1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 
3 /* Marco Theme Rendering */
4 
5 /*
6  * Copyright (C) 2001 Havoc Pennington
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of the
11  * License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301, USA.
22  */
23 
24 #ifndef META_THEME_H
25 #define META_THEME_H
26 
27 #include "boxes.h"
28 #include "gradient.h"
29 #include "common.h"
30 #include <gtk/gtk.h>
31 
32 typedef struct _MetaFrameStyle MetaFrameStyle;
33 typedef struct _MetaFrameStyleSet MetaFrameStyleSet;
34 typedef struct _MetaDrawOp MetaDrawOp;
35 typedef struct _MetaDrawOpList MetaDrawOpList;
36 typedef struct _MetaGradientSpec MetaGradientSpec;
37 typedef struct _MetaAlphaGradientSpec MetaAlphaGradientSpec;
38 typedef struct _MetaColorSpec MetaColorSpec;
39 typedef struct _MetaFrameLayout MetaFrameLayout;
40 typedef struct _MetaButtonSpace MetaButtonSpace;
41 typedef struct _MetaFrameGeometry MetaFrameGeometry;
42 typedef struct _MetaTheme MetaTheme;
43 typedef struct _MetaPositionExprEnv MetaPositionExprEnv;
44 typedef struct _MetaDrawInfo MetaDrawInfo;
45 
46 #define META_THEME_ERROR (g_quark_from_static_string ("meta-theme-error"))
47 
48 typedef enum
49 {
50   META_THEME_ERROR_FRAME_GEOMETRY,
51   META_THEME_ERROR_BAD_CHARACTER,
52   META_THEME_ERROR_BAD_PARENS,
53   META_THEME_ERROR_UNKNOWN_VARIABLE,
54   META_THEME_ERROR_DIVIDE_BY_ZERO,
55   META_THEME_ERROR_MOD_ON_FLOAT,
56   META_THEME_ERROR_FAILED
57 } MetaThemeError;
58 
59 /**
60  * Whether a button's size is calculated from the area around it (aspect
61  * sizing) or is given as a fixed height and width in pixels (fixed sizing).
62  *
63  * \bug This could be done away with; see the comment at the top of
64  * MetaFrameLayout.
65  */
66 typedef enum
67 {
68   META_BUTTON_SIZING_ASPECT,
69   META_BUTTON_SIZING_FIXED,
70   META_BUTTON_SIZING_LAST
71 } MetaButtonSizing;
72 
73 /**
74  * Various parameters used to calculate the geometry of a frame.
75  * They are used inside a MetaFrameStyle.
76  * This corresponds closely to the <frame_geometry> tag in a theme file.
77  *
78  * \bug button_sizing isn't really necessary, because we could easily say
79  * that if button_aspect is zero, the height and width are fixed values.
80  * This would also mean that MetaButtonSizing didn't need to exist, and
81  * save code.
82  **/
83 struct _MetaFrameLayout
84 {
85   /** Reference count. */
86   int refcount;
87 
88   /** Size of left side */
89   int left_width;
90   /** Size of right side */
91   int right_width;
92   /** Size of bottom side */
93   int bottom_height;
94 
95   /** Invisible border */
96   GtkBorder invisible_border;
97 
98   /** Border of blue title region
99    * \bug (blue?!)
100    **/
101   GtkBorder title_border;
102 
103   /** Extra height for inside of title region, above the font height */
104   int title_vertical_pad;
105 
106   /** Right indent of buttons from edges of frame */
107   int right_titlebar_edge;
108   /** Left indent of buttons from edges of frame */
109   int left_titlebar_edge;
110 
111   /**
112    * Sizing rule of buttons, either META_BUTTON_SIZING_ASPECT
113    * (in which case button_aspect will be honoured, and
114    * button_width and button_height set from it), or
115    * META_BUTTON_SIZING_FIXED (in which case we read the width
116    * and height directly).
117    */
118   MetaButtonSizing button_sizing;
119 
120   /**
121    * Ratio of height/width. Honoured only if
122    * button_sizing==META_BUTTON_SIZING_ASPECT.
123    * Otherwise we figure out the height from the button_border.
124    */
125   double button_aspect;
126 
127   /** Width of a button; set even when we are using aspect sizing */
128   int button_width;
129 
130   /** Height of a button; set even when we are using aspect sizing */
131   int button_height;
132 
133   /** Space around buttons */
134   GtkBorder button_border;
135 
136   /** scale factor for title text */
137   double title_scale;
138 
139   /** Whether title text will be displayed */
140   guint has_title : 1;
141 
142   /** Whether we should hide the buttons */
143   guint hide_buttons : 1;
144 
145   /** Radius of the top left-hand corner; 0 if not rounded */
146   guint top_left_corner_rounded_radius;
147   /** Radius of the top right-hand corner; 0 if not rounded */
148   guint top_right_corner_rounded_radius;
149   /** Radius of the bottom left-hand corner; 0 if not rounded */
150   guint bottom_left_corner_rounded_radius;
151   /** Radius of the bottom right-hand corner; 0 if not rounded */
152   guint bottom_right_corner_rounded_radius;
153 };
154 
155 /**
156  * The computed size of a button (really just a way of tying its
157  * visible and clickable areas together).
158  * The reason for two different rectangles here is Fitts' law & maximized
159  * windows; see bug #97703 for more details.
160  */
161 struct _MetaButtonSpace
162 {
163   /** The screen area where the button's image is drawn */
164   GdkRectangle visible;
165   /** The screen area where the button can be activated by clicking */
166   GdkRectangle clickable;
167 };
168 
169 /**
170  * Calculated actual geometry of the frame
171  */
172 struct _MetaFrameGeometry
173 {
174   MetaFrameBorders borders;
175 
176   int width;
177   int height;
178 
179   GdkRectangle title_rect;
180 
181   int left_titlebar_edge;
182   int right_titlebar_edge;
183   int top_titlebar_edge;
184   int bottom_titlebar_edge;
185 
186   /* used for a memset hack */
187 #define ADDRESS_OF_BUTTON_RECTS(fgeom) (((char*)(fgeom)) + G_STRUCT_OFFSET (MetaFrameGeometry, close_rect))
188 #define LENGTH_OF_BUTTON_RECTS (G_STRUCT_OFFSET (MetaFrameGeometry, right_single_background) + sizeof (GdkRectangle) - G_STRUCT_OFFSET (MetaFrameGeometry, close_rect))
189 
190   /* The button rects (if changed adjust memset hack) */
191   MetaButtonSpace close_rect;
192   MetaButtonSpace max_rect;
193   MetaButtonSpace min_rect;
194   MetaButtonSpace menu_rect;
195   MetaButtonSpace appmenu_rect;
196   MetaButtonSpace shade_rect;
197   MetaButtonSpace above_rect;
198   MetaButtonSpace stick_rect;
199   MetaButtonSpace unshade_rect;
200   MetaButtonSpace unabove_rect;
201   MetaButtonSpace unstick_rect;
202 
203 #define MAX_MIDDLE_BACKGROUNDS (MAX_BUTTONS_PER_CORNER - 2)
204   GdkRectangle left_left_background;
205   GdkRectangle left_middle_backgrounds[MAX_MIDDLE_BACKGROUNDS];
206   GdkRectangle left_right_background;
207   GdkRectangle left_single_background;
208   GdkRectangle right_left_background;
209   GdkRectangle right_middle_backgrounds[MAX_MIDDLE_BACKGROUNDS];
210   GdkRectangle right_right_background;
211   GdkRectangle right_single_background;
212   /* End of button rects (if changed adjust memset hack) */
213 
214   /* Saved button layout */
215   MetaButtonLayout button_layout;
216   int n_left_buttons;
217   int n_right_buttons;
218 
219   /* Round corners */
220   guint top_left_corner_rounded_radius;
221   guint top_right_corner_rounded_radius;
222   guint bottom_left_corner_rounded_radius;
223   guint bottom_right_corner_rounded_radius;
224 };
225 
226 typedef enum
227 {
228   META_IMAGE_FILL_SCALE, /* default, needs to be all-bits-zero for g_new0 */
229   META_IMAGE_FILL_TILE
230 } MetaImageFillType;
231 
232 typedef enum
233 {
234   META_COLOR_SPEC_BASIC,
235   META_COLOR_SPEC_GTK,
236   META_COLOR_SPEC_GTK_CUSTOM,
237   META_COLOR_SPEC_BLEND,
238   META_COLOR_SPEC_SHADE
239 } MetaColorSpecType;
240 
241 typedef enum
242 {
243   META_GTK_COLOR_FG,
244   META_GTK_COLOR_BG,
245   META_GTK_COLOR_LIGHT,
246   META_GTK_COLOR_DARK,
247   META_GTK_COLOR_MID,
248   META_GTK_COLOR_TEXT,
249   META_GTK_COLOR_BASE,
250   META_GTK_COLOR_TEXT_AA,
251   META_GTK_COLOR_LAST
252 } MetaGtkColorComponent;
253 
254 struct _MetaColorSpec
255 {
256   MetaColorSpecType type;
257   union
258   {
259     struct {
260       GdkRGBA color;
261     } basic;
262     struct {
263       MetaGtkColorComponent component;
264       GtkStateFlags state;
265     } gtk;
266     struct {
267       char *color_name;
268       MetaColorSpec *fallback;
269     } gtkcustom;
270     struct {
271       MetaColorSpec *foreground;
272       MetaColorSpec *background;
273       double alpha;
274       GdkRGBA color;
275     } blend;
276     struct {
277       MetaColorSpec *base;
278       double factor;
279       GdkRGBA color;
280     } shade;
281   } data;
282 };
283 
284 struct _MetaGradientSpec
285 {
286   MetaGradientType type;
287   GSList *color_specs;
288 };
289 
290 struct _MetaAlphaGradientSpec
291 {
292   MetaGradientType type;
293   unsigned char *alphas;
294   int n_alphas;
295 };
296 
297 struct _MetaDrawInfo
298 {
299   GdkPixbuf   *mini_icon;
300   GdkPixbuf   *icon;
301   PangoLayout *title_layout;
302   int title_layout_width;
303   int title_layout_height;
304   const MetaFrameGeometry *fgeom;
305 };
306 
307 /**
308  * A drawing operation in our simple vector drawing language.
309  */
310 typedef enum
311 {
312   /** Basic drawing-- line */
313   META_DRAW_LINE,
314   /** Basic drawing-- rectangle */
315   META_DRAW_RECTANGLE,
316   /** Basic drawing-- arc */
317   META_DRAW_ARC,
318 
319   /** Clip to a rectangle */
320   META_DRAW_CLIP,
321 
322   /* Texture thingies */
323 
324   /** Just a filled rectangle with alpha */
325   META_DRAW_TINT,
326   META_DRAW_GRADIENT,
327   META_DRAW_IMAGE,
328 
329   /** GTK theme engine stuff */
330   META_DRAW_GTK_ARROW,
331   META_DRAW_GTK_BOX,
332   META_DRAW_GTK_VLINE,
333 
334   /** App's window icon */
335   META_DRAW_ICON,
336   /** App's window title */
337   META_DRAW_TITLE,
338   /** a draw op list */
339   META_DRAW_OP_LIST,
340   /** tiled draw op list */
341   META_DRAW_TILE
342 } MetaDrawType;
343 
344 typedef enum
345 {
346   POS_TOKEN_INT,
347   POS_TOKEN_DOUBLE,
348   POS_TOKEN_OPERATOR,
349   POS_TOKEN_VARIABLE,
350   POS_TOKEN_OPEN_PAREN,
351   POS_TOKEN_CLOSE_PAREN
352 } PosTokenType;
353 
354 typedef enum
355 {
356   POS_OP_NONE,
357   POS_OP_ADD,
358   POS_OP_SUBTRACT,
359   POS_OP_MULTIPLY,
360   POS_OP_DIVIDE,
361   POS_OP_MOD,
362   POS_OP_MAX,
363   POS_OP_MIN
364 } PosOperatorType;
365 
366 /**
367  * A token, as output by the tokeniser.
368  *
369  * \ingroup tokenizer
370  */
371 typedef struct
372 {
373   PosTokenType type;
374 
375   union
376   {
377     struct {
378       int val;
379     } i;
380 
381     struct {
382       double val;
383     } d;
384 
385     struct {
386       PosOperatorType op;
387     } o;
388 
389     struct {
390       char *name;
391       GQuark name_quark;
392     } v;
393 
394   } d;
395 } PosToken;
396 
397 /**
398  * A computed expression in our simple vector drawing language.
399  * While it appears to take the form of a tree, this is actually
400  * merely a list; concerns such as precedence of operators are
401  * currently recomputed on every recalculation.
402  *
403  * Created by meta_draw_spec_new(), destroyed by meta_draw_spec_free().
404  * pos_eval() fills this with ...FIXME. Are tokens a tree or a list?
405  * \ingroup parser
406  */
407 typedef struct _MetaDrawSpec
408 {
409   /**
410    * If this spec is constant, this is the value of the constant;
411    * otherwise it is zero.
412    */
413   int value;
414 
415   /** A list of tokens in the expression. */
416   PosToken *tokens;
417 
418   /** How many tokens are in the tokens list. */
419   int n_tokens;
420 
421   /** Does the expression contain any variables? */
422   gboolean constant : 1;
423 } MetaDrawSpec;
424 
425 /**
426  * A single drawing operation in our simple vector drawing language.
427  */
428 struct _MetaDrawOp
429 {
430   MetaDrawType type;
431 
432   /* Positions are strings because they can be expressions */
433   union
434   {
435     struct {
436       MetaColorSpec *color_spec;
437       int dash_on_length;
438       int dash_off_length;
439       int width;
440       MetaDrawSpec *x1;
441       MetaDrawSpec *y1;
442       MetaDrawSpec *x2;
443       MetaDrawSpec *y2;
444     } line;
445 
446     struct {
447       MetaColorSpec *color_spec;
448       gboolean filled;
449       MetaDrawSpec *x;
450       MetaDrawSpec *y;
451       MetaDrawSpec *width;
452       MetaDrawSpec *height;
453     } rectangle;
454 
455     struct {
456       MetaColorSpec *color_spec;
457       gboolean filled;
458       MetaDrawSpec *x;
459       MetaDrawSpec *y;
460       MetaDrawSpec *width;
461       MetaDrawSpec *height;
462       double start_angle;
463       double extent_angle;
464     } arc;
465 
466     struct {
467       MetaDrawSpec *x;
468       MetaDrawSpec *y;
469       MetaDrawSpec *width;
470       MetaDrawSpec *height;
471     } clip;
472 
473     struct {
474       MetaColorSpec *color_spec;
475       MetaAlphaGradientSpec *alpha_spec;
476       MetaDrawSpec *x;
477       MetaDrawSpec *y;
478       MetaDrawSpec *width;
479       MetaDrawSpec *height;
480     } tint;
481 
482     struct {
483       MetaGradientSpec *gradient_spec;
484       MetaAlphaGradientSpec *alpha_spec;
485       MetaDrawSpec *x;
486       MetaDrawSpec *y;
487       MetaDrawSpec *width;
488       MetaDrawSpec *height;
489     } gradient;
490 
491     struct {
492       MetaColorSpec *colorize_spec;
493       MetaAlphaGradientSpec *alpha_spec;
494       GdkPixbuf *pixbuf;
495       MetaDrawSpec *x;
496       MetaDrawSpec *y;
497       MetaDrawSpec *width;
498       MetaDrawSpec *height;
499 
500       guint32 colorize_cache_pixel;
501       GdkPixbuf *colorize_cache_pixbuf;
502       MetaImageFillType fill_type;
503       unsigned int vertical_stripes : 1;
504       unsigned int horizontal_stripes : 1;
505     } image;
506 
507     struct {
508       GtkStateFlags state;
509       GtkShadowType shadow;
510       GtkArrowType arrow;
511       gboolean filled;
512 
513       MetaDrawSpec *x;
514       MetaDrawSpec *y;
515       MetaDrawSpec *width;
516       MetaDrawSpec *height;
517     } gtk_arrow;
518 
519     struct {
520       GtkStateFlags state;
521       GtkShadowType shadow;
522       MetaDrawSpec *x;
523       MetaDrawSpec *y;
524       MetaDrawSpec *width;
525       MetaDrawSpec *height;
526     } gtk_box;
527 
528     struct {
529       GtkStateFlags state;
530       MetaDrawSpec *x;
531       MetaDrawSpec *y1;
532       MetaDrawSpec *y2;
533     } gtk_vline;
534 
535     struct {
536       MetaAlphaGradientSpec *alpha_spec;
537       MetaDrawSpec *x;
538       MetaDrawSpec *y;
539       MetaDrawSpec *width;
540       MetaDrawSpec *height;
541       MetaImageFillType fill_type;
542     } icon;
543 
544     struct {
545       MetaColorSpec *color_spec;
546       MetaDrawSpec *x;
547       MetaDrawSpec *y;
548       MetaDrawSpec *ellipsize_width;
549     } title;
550 
551     struct {
552       MetaDrawOpList *op_list;
553       MetaDrawSpec *x;
554       MetaDrawSpec *y;
555       MetaDrawSpec *width;
556       MetaDrawSpec *height;
557     } op_list;
558 
559     struct {
560       MetaDrawOpList *op_list;
561       MetaDrawSpec *x;
562       MetaDrawSpec *y;
563       MetaDrawSpec *width;
564       MetaDrawSpec *height;
565       MetaDrawSpec *tile_xoffset;
566       MetaDrawSpec *tile_yoffset;
567       MetaDrawSpec *tile_width;
568       MetaDrawSpec *tile_height;
569     } tile;
570 
571   } data;
572 };
573 
574 /**
575  * A list of MetaDrawOp objects. Maintains a reference count.
576  * Grows as necessary and allows the allocation of unused spaces
577  * to keep reallocations to a minimum.
578  *
579  * \bug Do we really win anything from not using the equivalent
580  * GLib structures?
581  */
582 struct _MetaDrawOpList
583 {
584   int refcount;
585   MetaDrawOp **ops;
586   int n_ops;
587   int n_allocated;
588 };
589 
590 typedef enum
591 {
592   META_BUTTON_STATE_NORMAL,
593   META_BUTTON_STATE_PRESSED,
594   META_BUTTON_STATE_PRELIGHT,
595   META_BUTTON_STATE_LAST
596 } MetaButtonState;
597 
598 typedef enum
599 {
600   /* Ordered so that background is drawn first */
601   META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND,
602   META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND,
603   META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND,
604   META_BUTTON_TYPE_LEFT_SINGLE_BACKGROUND,
605   META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND,
606   META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND,
607   META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND,
608   META_BUTTON_TYPE_RIGHT_SINGLE_BACKGROUND,
609   META_BUTTON_TYPE_CLOSE,
610   META_BUTTON_TYPE_MAXIMIZE,
611   META_BUTTON_TYPE_MINIMIZE,
612   META_BUTTON_TYPE_MENU,
613   META_BUTTON_TYPE_APPMENU,
614   META_BUTTON_TYPE_SHADE,
615   META_BUTTON_TYPE_ABOVE,
616   META_BUTTON_TYPE_STICK,
617   META_BUTTON_TYPE_UNSHADE,
618   META_BUTTON_TYPE_UNABOVE,
619   META_BUTTON_TYPE_UNSTICK,
620   META_BUTTON_TYPE_LAST
621 } MetaButtonType;
622 
623 typedef enum
624 {
625   META_MENU_ICON_TYPE_CLOSE,
626   META_MENU_ICON_TYPE_MAXIMIZE,
627   META_MENU_ICON_TYPE_UNMAXIMIZE,
628   META_MENU_ICON_TYPE_MINIMIZE,
629   META_MENU_ICON_TYPE_LAST
630 } MetaMenuIconType;
631 
632 typedef enum
633 {
634   /* Listed in the order in which the textures are drawn.
635    * (though this only matters for overlaps of course.)
636    * Buttons are drawn after the frame textures.
637    *
638    * On the corners, horizontal pieces are arbitrarily given the
639    * corner area:
640    *
641    *   =====                 |====
642    *   |                     |
643    *   |       rather than   |
644    *
645    */
646 
647   /* entire frame */
648   META_FRAME_PIECE_ENTIRE_BACKGROUND,
649   /* entire titlebar background */
650   META_FRAME_PIECE_TITLEBAR,
651   /* portion of the titlebar background inside the titlebar
652    * background edges
653    */
654   META_FRAME_PIECE_TITLEBAR_MIDDLE,
655   /* left end of titlebar */
656   META_FRAME_PIECE_LEFT_TITLEBAR_EDGE,
657   /* right end of titlebar */
658   META_FRAME_PIECE_RIGHT_TITLEBAR_EDGE,
659   /* top edge of titlebar */
660   META_FRAME_PIECE_TOP_TITLEBAR_EDGE,
661   /* bottom edge of titlebar */
662   META_FRAME_PIECE_BOTTOM_TITLEBAR_EDGE,
663   /* render over title background (text area) */
664   META_FRAME_PIECE_TITLE,
665   /* left edge of the frame */
666   META_FRAME_PIECE_LEFT_EDGE,
667   /* right edge of the frame */
668   META_FRAME_PIECE_RIGHT_EDGE,
669   /* bottom edge of the frame */
670   META_FRAME_PIECE_BOTTOM_EDGE,
671   /* place over entire frame, after drawing everything else */
672   META_FRAME_PIECE_OVERLAY,
673   /* Used to get size of the enum */
674   META_FRAME_PIECE_LAST
675 } MetaFramePiece;
676 
677 /**
678  * How to draw a frame in a particular state (say, a focussed, non-maximised,
679  * resizable frame). This corresponds closely to the <frame_style> tag
680  * in a theme file.
681  */
682 struct _MetaFrameStyle
683 {
684   /** Reference count. */
685   int refcount;
686   /**
687    * Parent style.
688    * Settings which are unspecified here will be taken from there.
689    */
690   MetaFrameStyle *parent;
691   /** Operations for drawing each kind of button in each state. */
692   MetaDrawOpList *buttons[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST];
693   /** Operations for drawing each piece of the frame. */
694   MetaDrawOpList *pieces[META_FRAME_PIECE_LAST];
695   /**
696    * Details such as the height and width of each edge, the corner rounding,
697    * and the aspect ratio of the buttons.
698    */
699   MetaFrameLayout *layout;
700   /**
701    * Background colour of the window. Only present in theme formats
702    * 2 and above. Can be NULL to use the standard GTK theme engine.
703    */
704   MetaColorSpec *window_background_color;
705   /**
706    * Transparency of the window background. 0=transparent; 255=opaque.
707    */
708   guint8 window_background_alpha;
709 };
710 
711 /* Kinds of frame...
712  *
713  *  normal ->   noresize / vert only / horz only / both
714  *              focused / unfocused
715  *  max    ->   focused / unfocused
716  *  shaded ->   focused / unfocused
717  *  max/shaded -> focused / unfocused
718  *
719  *  so 4 states with 8 sub-states in one, 2 sub-states in the other 3,
720  *  meaning 14 total
721  *
722  * 14 window states times 7 or 8 window types. Except some
723  * window types never get a frame so that narrows it down a bit.
724  *
725  */
726 typedef enum
727 {
728   META_FRAME_STATE_NORMAL,
729   META_FRAME_STATE_MAXIMIZED,
730   META_FRAME_STATE_TILED_LEFT,
731   META_FRAME_STATE_TILED_RIGHT,
732   META_FRAME_STATE_SHADED,
733   META_FRAME_STATE_MAXIMIZED_AND_SHADED,
734   META_FRAME_STATE_TILED_LEFT_AND_SHADED,
735   META_FRAME_STATE_TILED_RIGHT_AND_SHADED,
736   META_FRAME_STATE_LAST
737 } MetaFrameState;
738 
739 typedef enum
740 {
741   META_FRAME_RESIZE_NONE,
742   META_FRAME_RESIZE_VERTICAL,
743   META_FRAME_RESIZE_HORIZONTAL,
744   META_FRAME_RESIZE_BOTH,
745   META_FRAME_RESIZE_LAST
746 } MetaFrameResize;
747 
748 typedef enum
749 {
750   META_FRAME_FOCUS_NO,
751   META_FRAME_FOCUS_YES,
752   META_FRAME_FOCUS_LAST
753 } MetaFrameFocus;
754 
755 /**
756  * How to draw frames at different times: when it's maximised or not, shaded
757  * or not, when it's focussed or not, and (for non-maximised windows), when
758  * it can be horizontally or vertically resized, both, or neither.
759  * Not all window types actually get a frame.
760  *
761  * A theme contains one of these objects for each type of window (each
762  * MetaFrameType), that is, normal, dialogue (modal and non-modal), etc.
763  *
764  * This corresponds closely to the <frame_style_set> tag in a theme file.
765  */
766 struct _MetaFrameStyleSet
767 {
768   int refcount;
769   MetaFrameStyleSet *parent;
770   MetaFrameStyle *normal_styles[META_FRAME_RESIZE_LAST][META_FRAME_FOCUS_LAST];
771   MetaFrameStyle *maximized_styles[META_FRAME_FOCUS_LAST];
772   MetaFrameStyle *tiled_left_styles[META_FRAME_FOCUS_LAST];
773   MetaFrameStyle *tiled_right_styles[META_FRAME_FOCUS_LAST];
774   MetaFrameStyle *shaded_styles[META_FRAME_RESIZE_LAST][META_FRAME_FOCUS_LAST];
775   MetaFrameStyle *maximized_and_shaded_styles[META_FRAME_FOCUS_LAST];
776   MetaFrameStyle *tiled_left_and_shaded_styles[META_FRAME_FOCUS_LAST];
777   MetaFrameStyle *tiled_right_and_shaded_styles[META_FRAME_FOCUS_LAST];
778 };
779 
780 /**
781  * A theme. This is a singleton class which groups all settings from a theme
782  * on disk together.
783  *
784  * \bug It is rather useless to keep the metadata fields in core, I think.
785  */
786 struct _MetaTheme
787 {
788   /** Name of the theme (on disk), e.g. "Crux" */
789   char *name;
790   /** Path to the files associated with the theme */
791   char *dirname;
792   /**
793    * Filename of the XML theme file.
794    * \bug Kept lying around for no discernable reason.
795    */
796   char *filename;
797   /** Metadata: Human-readable name of the theme. */
798   char *readable_name;
799   /** Metadata: Author of the theme. */
800   char *author;
801   /** Metadata: Copyright holder. */
802   char *copyright;
803   /** Metadata: Date of the theme. */
804   char *date;
805   /** Metadata: Description of the theme. */
806   char *description;
807   /** Version of the theme format. Older versions cannot use the features
808    * of newer versions even if they think they can (this is to allow forward
809    * and backward compatibility.
810    */
811   guint format_version;
812 
813   /** Symbol table of integer constants. */
814   GHashTable *integer_constants;
815   /** Symbol table of float constants. */
816   GHashTable *float_constants;
817   /**
818    * Symbol table of colour constants (hex triples, and triples
819    * plus alpha).
820    * */
821   GHashTable *color_constants;
822   GHashTable *images_by_filename;
823   GHashTable *layouts_by_name;
824   GHashTable *draw_op_lists_by_name;
825   GHashTable *styles_by_name;
826   GHashTable *style_sets_by_name;
827   MetaFrameStyleSet *style_sets_by_type[META_FRAME_TYPE_LAST];
828 
829   GQuark quark_width;
830   GQuark quark_height;
831   GQuark quark_object_width;
832   GQuark quark_object_height;
833   GQuark quark_left_width;
834   GQuark quark_right_width;
835   GQuark quark_top_height;
836   GQuark quark_bottom_height;
837   GQuark quark_mini_icon_width;
838   GQuark quark_mini_icon_height;
839   GQuark quark_icon_width;
840   GQuark quark_icon_height;
841   GQuark quark_title_width;
842   GQuark quark_title_height;
843   GQuark quark_frame_x_center;
844   GQuark quark_frame_y_center;
845 };
846 
847 struct _MetaPositionExprEnv
848 {
849   MetaRectangle rect;
850   /* size of an object being drawn, if it has a natural size */
851   int object_width;
852   int object_height;
853   /* global object sizes, always available */
854   int left_width;
855   int right_width;
856   int top_height;
857   int bottom_height;
858   int title_width;
859   int title_height;
860   int frame_x_center;
861   int frame_y_center;
862   int mini_icon_width;
863   int mini_icon_height;
864   int icon_width;
865   int icon_height;
866   /* Theme so we can look up constants */
867   MetaTheme *theme;
868 };
869 
870 MetaFrameLayout* meta_frame_layout_new           (void);
871 MetaFrameLayout* meta_frame_layout_copy          (const MetaFrameLayout *src);
872 void             meta_frame_layout_ref           (MetaFrameLayout       *layout);
873 void             meta_frame_layout_unref         (MetaFrameLayout       *layout);
874 void             meta_frame_layout_get_borders   (const MetaFrameLayout *layout,
875                                                   int                    text_height,
876                                                   MetaFrameFlags         flags,
877                                                   MetaFrameBorders      *borders);
878 void             meta_frame_layout_calc_geometry (const MetaFrameLayout  *layout,
879                                                   int                     text_height,
880                                                   MetaFrameFlags          flags,
881                                                   int                     client_width,
882                                                   int                     client_height,
883                                                   const MetaButtonLayout *button_layout,
884                                                   MetaFrameGeometry      *fgeom,
885                                                   MetaTheme              *theme);
886 
887 gboolean         meta_frame_layout_validate      (const MetaFrameLayout *layout,
888                                                   GError               **error);
889 
890 gboolean meta_parse_position_expression (MetaDrawSpec               *spec,
891                                          const MetaPositionExprEnv  *env,
892                                          int                        *x_return,
893                                          int                        *y_return,
894                                          GError                    **err);
895 gboolean meta_parse_size_expression     (MetaDrawSpec               *spec,
896                                          const MetaPositionExprEnv  *env,
897                                          int                        *val_return,
898                                          GError                    **err);
899 
900 MetaDrawSpec* meta_draw_spec_new (MetaTheme  *theme,
901                                   const char *expr,
902                                   GError    **error);
903 void          meta_draw_spec_free (MetaDrawSpec *spec);
904 
905 MetaColorSpec* meta_color_spec_new             (MetaColorSpecType  type);
906 MetaColorSpec* meta_color_spec_new_from_string (const char        *str,
907                                                 GError           **err);
908 MetaColorSpec* meta_color_spec_new_gtk         (MetaGtkColorComponent component,
909                                                 GtkStateFlags         state);
910 void           meta_color_spec_free            (MetaColorSpec     *spec);
911 void           meta_color_spec_render          (MetaColorSpec     *spec,
912                                                 GtkStyleContext   *style_gtk,
913                                                 GdkRGBA           *color);
914 
915 MetaDrawOp*    meta_draw_op_new  (MetaDrawType        type);
916 void           meta_draw_op_free (MetaDrawOp          *op);
917 void           meta_draw_op_draw (const MetaDrawOp    *op,
918                                   GtkWidget           *widget,
919                                   cairo_t             *cr,
920                                   const MetaDrawInfo  *info,
921                                   /* logical region being drawn */
922                                   MetaRectangle        logical_region);
923 
924 void           meta_draw_op_draw_with_style (const MetaDrawOp    *op,
925                                              GtkStyleContext     *style_gtk,
926                                              cairo_t             *cr,
927                                              const MetaDrawInfo  *info,
928                                              /* logical region being drawn */
929                                              MetaRectangle        logical_region);
930 
931 MetaDrawOpList* meta_draw_op_list_new   (int                   n_preallocs);
932 void            meta_draw_op_list_ref   (MetaDrawOpList       *op_list);
933 void            meta_draw_op_list_unref (MetaDrawOpList       *op_list);
934 void            meta_draw_op_list_draw  (const MetaDrawOpList *op_list,
935                                          GtkWidget            *widget,
936                                          cairo_t              *cr,
937                                          const MetaDrawInfo   *info,
938                                          MetaRectangle         rect);
939 void            meta_draw_op_list_draw_with_style  (const MetaDrawOpList *op_list,
940                                                     GtkStyleContext      *style_gtk,
941                                                     cairo_t              *cr,
942                                                     const MetaDrawInfo   *info,
943                                                     MetaRectangle         rect);
944 void           meta_draw_op_list_append (MetaDrawOpList       *op_list,
945                                          MetaDrawOp           *op);
946 gboolean       meta_draw_op_list_validate (MetaDrawOpList    *op_list,
947                                            GError           **error);
948 gboolean       meta_draw_op_list_contains (MetaDrawOpList    *op_list,
949                                            MetaDrawOpList    *child);
950 
951 MetaGradientSpec* meta_gradient_spec_new    (MetaGradientType        type);
952 void              meta_gradient_spec_free   (MetaGradientSpec       *desc);
953 void              meta_gradient_spec_render (const MetaGradientSpec      *spec,
954                                              const MetaAlphaGradientSpec *alpha_spec,
955                                              cairo_t                     *cr,
956                                              GtkStyleContext             *context,
957                                              gint                         x,
958                                              gint                         y,
959                                              gint                         width,
960                                              gint                         height);
961 gboolean          meta_gradient_spec_validate (MetaGradientSpec     *spec,
962                                                GError              **error);
963 
964 MetaAlphaGradientSpec* meta_alpha_gradient_spec_new  (MetaGradientType       type,
965                                                       int                    n_alphas);
966 void                   meta_alpha_gradient_spec_free (MetaAlphaGradientSpec *spec);
967 cairo_pattern_t *      meta_alpha_gradient_spec_get_mask (const MetaAlphaGradientSpec *spec);
968 
969 MetaFrameStyle* meta_frame_style_new   (MetaFrameStyle *parent);
970 void            meta_frame_style_ref   (MetaFrameStyle *style);
971 void            meta_frame_style_unref (MetaFrameStyle *style);
972 
973 void meta_frame_style_draw (MetaFrameStyle          *style,
974                             GtkWidget               *widget,
975                             cairo_t                 *cr,
976                             const MetaFrameGeometry *fgeom,
977                             int                      client_width,
978                             int                      client_height,
979                             PangoLayout             *title_layout,
980                             int                      text_height,
981                             MetaButtonState          button_states[META_BUTTON_TYPE_LAST],
982                             GdkPixbuf               *mini_icon,
983                             GdkPixbuf               *icon);
984 
985 void meta_frame_style_draw_with_style (MetaFrameStyle          *style,
986                                        GtkStyleContext         *style_gtk,
987                                        cairo_t                 *cr,
988                                        const MetaFrameGeometry *fgeom,
989                                        int                      client_width,
990                                        int                      client_height,
991                                        PangoLayout             *title_layout,
992                                        int                      text_height,
993                                        MetaButtonState          button_states[META_BUTTON_TYPE_LAST],
994                                        GdkPixbuf               *mini_icon,
995                                        GdkPixbuf               *icon);
996 
997 gboolean       meta_frame_style_validate (MetaFrameStyle    *style,
998                                           guint              current_theme_version,
999                                           GError           **error);
1000 
1001 MetaFrameStyleSet* meta_frame_style_set_new   (MetaFrameStyleSet *parent);
1002 void               meta_frame_style_set_ref   (MetaFrameStyleSet *style_set);
1003 void               meta_frame_style_set_unref (MetaFrameStyleSet *style_set);
1004 
1005 gboolean       meta_frame_style_set_validate  (MetaFrameStyleSet *style_set,
1006                                                GError           **error);
1007 
1008 MetaTheme* meta_theme_get_current (void);
1009 void       meta_theme_set_current (const char *name,
1010                                    gboolean    force_reload);
1011 
1012 MetaTheme* meta_theme_new      (void);
1013 void       meta_theme_free     (MetaTheme *theme);
1014 gboolean   meta_theme_validate (MetaTheme *theme,
1015                                 GError   **error);
1016 GdkPixbuf* meta_theme_load_image (MetaTheme  *theme,
1017                                   const char *filename,
1018                                   guint       size_of_theme_icons,
1019                                   GError    **error);
1020 
1021 MetaFrameStyle* meta_theme_get_frame_style (MetaTheme     *theme,
1022                                             MetaFrameType  type,
1023                                             MetaFrameFlags flags);
1024 
1025 double meta_theme_get_title_scale (MetaTheme     *theme,
1026                                    MetaFrameType  type,
1027                                    MetaFrameFlags flags);
1028 
1029 void meta_theme_draw_frame (MetaTheme              *theme,
1030                             GtkStyleContext        *style_gtk,
1031                             cairo_t                *cr,
1032                             MetaFrameType           type,
1033                             MetaFrameFlags          flags,
1034                             int                     client_width,
1035                             int                     client_height,
1036                             PangoLayout            *title_layout,
1037                             int                     text_height,
1038                             const MetaButtonLayout *button_layout,
1039                             MetaButtonState         button_states[META_BUTTON_TYPE_LAST],
1040                             GdkPixbuf              *mini_icon,
1041                             GdkPixbuf              *icon);
1042 
1043 void meta_theme_draw_frame_by_name (MetaTheme              *theme,
1044                                     GtkWidget              *widget,
1045                                     cairo_t                *cr,
1046                                     const gchar             *style_name,
1047                                     MetaFrameFlags          flags,
1048                                     int                     client_width,
1049                                     int                     client_height,
1050                                     PangoLayout            *title_layout,
1051                                     int                     text_height,
1052                                     const MetaButtonLayout *button_layout,
1053                                     MetaButtonState         button_states[META_BUTTON_TYPE_LAST],
1054                                     GdkPixbuf              *mini_icon,
1055                                     GdkPixbuf              *icon);
1056 
1057 void meta_theme_get_frame_borders (MetaTheme         *theme,
1058                                    MetaFrameType      type,
1059                                    int                text_height,
1060                                    MetaFrameFlags     flags,
1061                                    MetaFrameBorders  *borders);
1062 void meta_theme_calc_geometry (MetaTheme              *theme,
1063                                MetaFrameType           type,
1064                                int                     text_height,
1065                                MetaFrameFlags          flags,
1066                                int                     client_width,
1067                                int                     client_height,
1068                                const MetaButtonLayout *button_layout,
1069                                MetaFrameGeometry      *fgeom);
1070 
1071 MetaFrameLayout*   meta_theme_lookup_layout       (MetaTheme         *theme,
1072                                                    const char        *name);
1073 void               meta_theme_insert_layout       (MetaTheme         *theme,
1074                                                    const char        *name,
1075                                                    MetaFrameLayout   *layout);
1076 MetaDrawOpList*    meta_theme_lookup_draw_op_list (MetaTheme         *theme,
1077                                                    const char        *name);
1078 void               meta_theme_insert_draw_op_list (MetaTheme         *theme,
1079                                                    const char        *name,
1080                                                    MetaDrawOpList    *op_list);
1081 MetaFrameStyle*    meta_theme_lookup_style        (MetaTheme         *theme,
1082                                                    const char        *name);
1083 void               meta_theme_insert_style        (MetaTheme         *theme,
1084                                                    const char        *name,
1085                                                    MetaFrameStyle    *style);
1086 MetaFrameStyleSet* meta_theme_lookup_style_set    (MetaTheme         *theme,
1087                                                    const char        *name);
1088 void               meta_theme_insert_style_set    (MetaTheme         *theme,
1089                                                    const char        *name,
1090                                                    MetaFrameStyleSet *style_set);
1091 gboolean meta_theme_define_int_constant   (MetaTheme   *theme,
1092                                            const char  *name,
1093                                            int          value,
1094                                            GError     **error);
1095 gboolean meta_theme_lookup_int_constant   (MetaTheme   *theme,
1096                                            const char  *name,
1097                                            int         *value);
1098 gboolean meta_theme_define_float_constant (MetaTheme   *theme,
1099                                            const char  *name,
1100                                            double       value,
1101                                            GError     **error);
1102 gboolean meta_theme_lookup_float_constant (MetaTheme   *theme,
1103                                            const char  *name,
1104                                            double      *value);
1105 
1106 gboolean meta_theme_define_color_constant (MetaTheme   *theme,
1107                                            const char  *name,
1108                                            const char  *value,
1109                                            GError     **error);
1110 gboolean meta_theme_lookup_color_constant (MetaTheme   *theme,
1111                                            const char  *name,
1112                                            char       **value);
1113 
1114 gboolean     meta_theme_replace_constants     (MetaTheme    *theme,
1115                                                PosToken     *tokens,
1116                                                int           n_tokens,
1117                                                GError      **err);
1118 
1119 /* random stuff */
1120 
1121 PangoFontDescription* meta_gtk_widget_get_font_desc        (GtkWidget            *widget,
1122                                                             double                scale,
1123 							    const PangoFontDescription *override);
1124 int                   meta_pango_font_desc_get_text_height (const PangoFontDescription *font_desc,
1125                                                             PangoContext         *context);
1126 
1127 /* Enum converters */
1128 MetaGtkColorComponent meta_color_component_from_string (const char            *str);
1129 const char*           meta_color_component_to_string   (MetaGtkColorComponent  component);
1130 MetaButtonState       meta_button_state_from_string    (const char            *str);
1131 const char*           meta_button_state_to_string      (MetaButtonState        state);
1132 MetaButtonType        meta_button_type_from_string     (const char            *str,
1133                                                         MetaTheme             *theme);
1134 const char*           meta_button_type_to_string       (MetaButtonType         type);
1135 MetaFramePiece        meta_frame_piece_from_string     (const char            *str);
1136 const char*           meta_frame_piece_to_string       (MetaFramePiece         piece);
1137 MetaFrameState        meta_frame_state_from_string     (const char            *str);
1138 const char*           meta_frame_state_to_string       (MetaFrameState         state);
1139 MetaFrameResize       meta_frame_resize_from_string    (const char            *str);
1140 const char*           meta_frame_resize_to_string      (MetaFrameResize        resize);
1141 MetaFrameFocus        meta_frame_focus_from_string     (const char            *str);
1142 const char*           meta_frame_focus_to_string       (MetaFrameFocus         focus);
1143 MetaFrameType         meta_frame_type_from_string      (const char            *str);
1144 const char*           meta_frame_type_to_string        (MetaFrameType          type);
1145 MetaGradientType      meta_gradient_type_from_string   (const char            *str);
1146 const char*           meta_gradient_type_to_string     (MetaGradientType       type);
1147 GtkStateFlags         meta_gtk_state_from_string       (const char            *str);
1148 GtkShadowType         meta_gtk_shadow_from_string      (const char            *str);
1149 const char*           meta_gtk_shadow_to_string        (GtkShadowType          shadow);
1150 GtkArrowType          meta_gtk_arrow_from_string       (const char            *str);
1151 const char*           meta_gtk_arrow_to_string         (GtkArrowType           arrow);
1152 MetaImageFillType     meta_image_fill_type_from_string (const char            *str);
1153 const char*           meta_image_fill_type_to_string   (MetaImageFillType      fill_type);
1154 void                  meta_gtk_style_get_light_color   (GtkStyleContext      *style,
1155                                                         GtkStateFlags         state,
1156                                                         GdkRGBA              *color);
1157 void                  meta_gtk_style_get_dark_color    (GtkStyleContext      *style,
1158                                                         GtkStateFlags         state,
1159                                                         GdkRGBA              *color);
1160 
1161 guint meta_theme_earliest_version_with_button (MetaButtonType type);
1162 
1163 #define META_THEME_ALLOWS(theme, feature) (theme->format_version >= feature)
1164 
1165 /* What version of the theme file format were various features introduced in? */
1166 #define META_THEME_SHADE_STICK_ABOVE_BUTTONS 2
1167 #define META_THEME_UBIQUITOUS_CONSTANTS 2
1168 #define META_THEME_VARIED_ROUND_CORNERS 2
1169 #define META_THEME_IMAGES_FROM_ICON_THEMES 2
1170 #define META_THEME_UNRESIZABLE_SHADED_STYLES 2
1171 #define META_THEME_DEGREES_IN_ARCS 2
1172 #define META_THEME_HIDDEN_BUTTONS 2
1173 #define META_THEME_COLOR_CONSTANTS 2
1174 #define META_THEME_FRAME_BACKGROUNDS 2
1175 
1176 #endif
1177