]> Pileus Git - ~andy/gtk/blob - gtk/gtkwindow-decorate.c
Updated galician translations
[~andy/gtk] / gtk / gtkwindow-decorate.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2001 Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /* 
21  * Authors: Alexander Larsson <alexl@redhat.com>
22  */
23
24 #include "config.h"
25 #include "gtkprivate.h"
26 #include "gtkwindow.h"
27 #include "gtkmain.h"
28 #include "gtkwindow-decorate.h"
29 #include "gtkintl.h"
30
31
32 #ifdef DECORATE_WINDOWS
33
34 typedef enum
35 {
36   GTK_WINDOW_REGION_TITLE,
37   GTK_WINDOW_REGION_MAXIMIZE,
38   GTK_WINDOW_REGION_CLOSE,
39   GTK_WINDOW_REGION_BR_RESIZE
40 } GtkWindowRegionType;
41
42 typedef struct _GtkWindowRegion GtkWindowRegion;
43 typedef struct _GtkWindowDecoration GtkWindowDecoration;
44
45 struct _GtkWindowRegion
46 {
47   GdkRectangle rect;
48   GtkWindowRegionType type;
49 };
50
51 typedef enum
52 {
53   RESIZE_TOP_LEFT,
54   RESIZE_TOP,
55   RESIZE_TOP_RIGHT,
56   RESIZE_RIGHT,
57   RESIZE_BOTTOM_RIGHT,
58   RESIZE_BOTTOM,
59   RESIZE_BOTTOM_LEFT,
60   RESIZE_LEFT,
61   RESIZE_NONE,
62 } GtkWindowResizeType;
63
64 struct _GtkWindowDecoration
65 {
66   gint n_regions;
67   GtkWindowRegion *regions;
68
69   gint last_x, last_y;
70   gint last_w, last_h;
71   
72   PangoLayout *title_layout;
73
74   GtkWindowResizeType resize;
75   
76   guint moving : 1;
77   guint closing : 1;
78   guint maximizing : 1;
79   guint maximized : 1;
80   guint maximizable : 1;
81   guint decorated : 1;
82   guint real_inner_move : 1;
83   guint focused : 1;
84 };
85
86 #define DECORATION_BORDER_TOP 15
87 #define DECORATION_BORDER_LEFT 3
88 #define DECORATION_BORDER_RIGHT 3
89 #define DECORATION_BORDER_BOTTOM 3
90 #define DECORATION_BORDER_TOT_X (DECORATION_BORDER_LEFT + DECORATION_BORDER_RIGHT)
91 #define DECORATION_BORDER_TOT_Y (DECORATION_BORDER_TOP + DECORATION_BORDER_BOTTOM)
92 #define DECORATION_BUTTON_SIZE 9
93 #define DECORATION_BUTTON_Y_OFFSET 2
94 #define DECORATION_TITLE_FONT "Sans 9"
95
96 static void gtk_decorated_window_recalculate_regions      (GtkWindow      *window);
97 static GtkWindowRegionType gtk_decorated_window_region_type    (GtkWindow      *window,
98                                                  gint            x,
99                                                  gint            y);
100 static gint gtk_decorated_window_frame_event    (GtkWindow *window,
101                                                  GdkEvent *event);
102 static gint gtk_decorated_window_button_press   (GtkWidget      *widget,
103                                                  GdkEventButton *event);
104 static gint gtk_decorated_window_button_release (GtkWidget      *widget,
105                                                  GdkEventButton *event);
106 static gint gtk_decorated_window_motion_notify  (GtkWidget      *widget,
107                                                  GdkEventMotion *event);
108 static gint gtk_decorated_window_window_state   (GtkWidget           *widget,
109                                                  GdkEventWindowState *event);
110 static void gtk_decorated_window_paint          (GtkWidget      *widget,
111                                                  GdkRectangle   *area);
112 static gint gtk_decorated_window_focus_change   (GtkWidget         *widget,
113                                                  GdkEventFocus     *event);
114 static void gtk_decorated_window_realize        (GtkWindow   *window);
115 static void gtk_decorated_window_unrealize      (GtkWindow   *window);
116
117 static void
118 gtk_decoration_free (GtkWindowDecoration *deco)
119 {
120   g_free (deco->regions);
121   deco->regions = NULL;
122   deco->n_regions = 0;
123
124   g_free (deco);
125 }
126
127 void
128 gtk_decorated_window_init (GtkWindow   *window)
129 {
130   GtkWindowDecoration *deco;
131
132   deco = g_new (GtkWindowDecoration, 1);
133
134   deco->n_regions = 0;
135   deco->regions = NULL;
136   deco->title_layout = NULL;
137   deco->resize = RESIZE_NONE;
138   deco->moving = FALSE;
139   deco->decorated = TRUE;
140   deco->closing = FALSE;
141   deco->maximizing = FALSE;
142   deco->maximized = FALSE;
143   deco->maximizable = FALSE;
144   deco->real_inner_move = FALSE;
145  
146   g_object_set_data_full (G_OBJECT (window), I_("gtk-window-decoration"), deco,
147                           (GDestroyNotify) gtk_decoration_free);
148   
149   gtk_window_set_has_frame (window, TRUE);
150
151   g_signal_connect (window,
152                     "frame-event",
153                     G_CALLBACK (gtk_decorated_window_frame_event),
154                     window);
155   g_signal_connect (window,
156                     "focus-in-event",
157                     G_CALLBACK (gtk_decorated_window_focus_change),
158                     window);
159   g_signal_connect (window,
160                     "focus-out-event",
161                     G_CALLBACK (gtk_decorated_window_focus_change),
162                     window);
163   g_signal_connect (window,
164                     "realize",
165                     G_CALLBACK (gtk_decorated_window_realize),
166                     window);
167   g_signal_connect (window,
168                     "unrealize",
169                     G_CALLBACK (gtk_decorated_window_unrealize),
170                     window);
171 }
172
173 static inline GtkWindowDecoration *
174 get_decoration (GtkWindow *window)
175 {
176   return (GtkWindowDecoration *)g_object_get_data (G_OBJECT (window), "gtk-window-decoration");
177 }
178
179 void
180 gtk_decorated_window_set_title (GtkWindow   *window,
181                                 const gchar *title)
182 {
183   GtkWindowDecoration *deco = get_decoration (window);
184   
185   if (deco->title_layout)
186     pango_layout_set_text (deco->title_layout, title, -1);
187 }
188
189 void 
190 gtk_decorated_window_calculate_frame_size (GtkWindow *window)
191 {
192   GdkWMDecoration decorations;
193   GtkWindowDecoration *deco = get_decoration (window);
194   
195   if (gdk_window_get_decorations (GTK_WIDGET (window)->window,
196                                   &decorations))
197     {
198       if ((decorations & GDK_DECOR_BORDER) &&
199           (decorations & GDK_DECOR_TITLE))
200         {
201           deco->decorated = TRUE;
202           if ((decorations & GDK_DECOR_MAXIMIZE) &&
203               (gtk_window_get_type_hint (window) == GDK_WINDOW_TYPE_HINT_NORMAL))
204             deco->maximizable = TRUE;
205         }
206       else
207         deco->decorated = FALSE;
208     }
209   else
210     {
211       deco->decorated = (window->type != GTK_WINDOW_POPUP);
212       deco->maximizable = (gtk_window_get_type_hint (window) == GDK_WINDOW_TYPE_HINT_NORMAL);
213     }
214
215   if (deco->decorated)
216     gtk_window_set_frame_dimensions (window,
217                                      DECORATION_BORDER_LEFT,
218                                      DECORATION_BORDER_TOP,
219                                      DECORATION_BORDER_RIGHT,
220                                      DECORATION_BORDER_BOTTOM);
221   else
222     gtk_window_set_frame_dimensions (window, 0, 0, 0, 0);
223
224   gtk_decorated_window_recalculate_regions (window);
225 }
226
227 static gboolean
228 gtk_decorated_window_inner_change (GdkWindow *win,
229                                    gint x, gint y,
230                                    gint width, gint height,
231                                    gpointer user_data)
232 {
233   GtkWindow *window = (GtkWindow *)user_data;
234   GtkWidget *widget = GTK_WIDGET (window);
235   GtkWindowDecoration *deco = get_decoration (window);
236
237   if (deco->real_inner_move)
238     {
239       deco->real_inner_move = FALSE;
240       return FALSE;
241     }
242
243   deco->real_inner_move = TRUE;
244   gdk_window_move_resize (widget->window,
245                           window->frame_left, window->frame_top,
246                           width, height);
247
248   gdk_window_move_resize (window->frame,
249                           x - window->frame_left, y - window->frame_top,
250                           width + window->frame_left + window->frame_right,
251                           height + window->frame_top + window->frame_bottom);
252   return TRUE;
253 }
254
255 static void
256 gtk_decorated_window_inner_get_pos (GdkWindow *win,
257                                     gint *x, gint *y,
258                                     gpointer user_data)
259 {
260   GtkWindow *window = (GtkWindow *)user_data;
261
262   gdk_window_get_position (window->frame, x, y);
263   
264   *x += window->frame_left;
265   *y += window->frame_top;
266 }
267
268 static void
269 gtk_decorated_window_realize (GtkWindow   *window)
270 {
271   GtkWindowDecoration *deco = get_decoration (window);
272   GtkWidget *widget = GTK_WIDGET (window);
273   PangoFontDescription *font_desc;
274
275   deco->title_layout = gtk_widget_create_pango_layout (widget,
276                                                        (window->title)?window->title:"");
277
278   font_desc = pango_font_description_from_string(DECORATION_TITLE_FONT);
279   pango_layout_set_font_description (deco->title_layout, font_desc);
280   pango_font_description_free (font_desc);
281 }
282
283
284 static void
285 gtk_decorated_window_unrealize (GtkWindow   *window)
286 {
287   GtkWindowDecoration *deco = get_decoration (window);
288
289   if (deco->title_layout)
290     {
291       g_object_unref (deco->title_layout);
292       deco->title_layout = NULL;
293     }
294 }
295
296 static gint
297 gtk_decorated_window_frame_event (GtkWindow *window, GdkEvent *event)
298 {
299   GtkWindowDecoration *deco = get_decoration (window);
300   GtkWidget *widget = GTK_WIDGET (window);
301   GdkEventExpose *expose_event;
302
303   switch (event->type)
304     {
305     case GDK_EXPOSE:
306       expose_event = (GdkEventExpose *)event;
307       if (deco->decorated)
308         gtk_decorated_window_paint (widget, &expose_event->area);
309       return TRUE;
310       break;
311     case GDK_CONFIGURE:
312       gtk_decorated_window_recalculate_regions (window);
313       break;
314     case GDK_MOTION_NOTIFY:
315       return gtk_decorated_window_motion_notify (widget, (GdkEventMotion *)event);
316       break;
317     case GDK_BUTTON_PRESS:
318       return gtk_decorated_window_button_press (widget, (GdkEventButton *)event);
319       break;
320     case GDK_BUTTON_RELEASE:
321       return gtk_decorated_window_button_release (widget, (GdkEventButton *)event);
322     case GDK_WINDOW_STATE:
323       return gtk_decorated_window_window_state (widget, (GdkEventWindowState *)event);
324     default:
325       break;
326     }
327   return FALSE;
328 }
329
330 static gint
331 gtk_decorated_window_focus_change (GtkWidget         *widget,
332                                    GdkEventFocus     *event)
333 {
334   GtkWindow *window = GTK_WINDOW(widget);
335   GtkWindowDecoration *deco = get_decoration (window);
336   deco->focused = event->in;
337   gdk_window_invalidate_rect (window->frame, NULL, FALSE);
338   return FALSE;
339 }
340
341 static gint
342 gtk_decorated_window_motion_notify (GtkWidget       *widget,
343                                     GdkEventMotion  *event)
344 {
345   GtkWindow *window;
346   GtkWindowDecoration *deco;
347   GdkModifierType mask;
348   GdkWindow *win;
349   gint x, y;
350   gint win_x, win_y, win_w, win_h;
351   
352   window = GTK_WINDOW (widget);
353   deco = get_decoration (window);
354   
355   if (!deco->decorated)
356     return TRUE;
357   
358   win = widget->window;
359   gdk_window_get_pointer (window->frame, &x, &y, &mask);
360   
361   gdk_window_get_position (window->frame, &win_x, &win_y);
362   win_x += DECORATION_BORDER_LEFT;
363   win_y += DECORATION_BORDER_TOP;
364   
365   gdk_window_get_geometry (win, NULL, NULL, &win_w, &win_h, NULL);
366
367   if (deco->moving)
368     {
369       int dx, dy;
370       dx = x - deco->last_x;
371       dy = y - deco->last_y;
372
373       gtk_window_move (window, win_x + dx, win_y + dy);
374     }
375
376   if (deco->resize != RESIZE_NONE)
377     {
378       int w, h;
379       
380       w = win_w;
381       h = win_h;
382       
383       switch(deco->resize) {
384       case RESIZE_BOTTOM_RIGHT:
385         w = x - DECORATION_BORDER_TOT_X;
386         h = y - DECORATION_BORDER_TOT_Y;
387         break;
388       case RESIZE_RIGHT:
389         w = x - DECORATION_BORDER_TOT_X;
390         break;
391       case RESIZE_BOTTOM:
392         h = y - DECORATION_BORDER_TOT_Y;
393         break;
394       case RESIZE_TOP_LEFT:
395       case RESIZE_TOP:
396       case RESIZE_TOP_RIGHT:
397       case RESIZE_BOTTOM_LEFT:
398       case RESIZE_LEFT:
399       default:
400         g_warning ("Resize mode %d not handled yet.\n", deco->resize);
401         break;
402       }
403       
404       if ((w > 0) && (h > 0))
405         {
406           _gtk_window_constrain_size (window, w,h, &w, &h);
407           
408           if ((w != win_w) || (h != win_h))
409             gdk_window_resize (widget->window, w, h);
410         }
411     }
412
413   return TRUE;
414 }
415
416 static GtkWindowRegionType
417 gtk_decorated_window_region_type (GtkWindow *window, gint x, gint y)
418 {
419   GtkWindowDecoration *deco = get_decoration (window);
420   int i;
421
422   for (i=0;i<deco->n_regions;i++)
423     {
424       if ((x > deco->regions[i].rect.x) &&
425           (x - deco->regions[i].rect.x < deco->regions[i].rect.width) &&
426           (y > deco->regions[i].rect.y) &&
427           (y - deco->regions[i].rect.y < deco->regions[i].rect.height))
428         return deco->regions[i].type;
429     }
430   return -1;
431 }
432
433 static gint
434 gtk_decorated_window_button_press (GtkWidget       *widget,
435                                    GdkEventButton  *event)
436 {
437   GtkWindow *window;
438   GtkWindowRegionType type;
439   GtkWindowDecoration *deco;
440   gint x, y; 
441
442   window = GTK_WINDOW (widget);
443   deco = get_decoration (window);
444
445   if (!deco->decorated)
446     return TRUE;
447
448   x = event->x;
449   y = event->y;
450   
451   type = gtk_decorated_window_region_type (window, x, y);
452
453   switch (type)
454     {
455     case GTK_WINDOW_REGION_TITLE:
456       if (!deco->maximized && event->state & GDK_BUTTON1_MASK)
457         {
458           deco->last_x = x;
459           deco->last_y = y;
460           deco->moving = TRUE;
461         }
462       break;
463     case GTK_WINDOW_REGION_MAXIMIZE:
464       if (event->state & GDK_BUTTON1_MASK)
465         deco->maximizing = TRUE;
466       break;
467     case GTK_WINDOW_REGION_CLOSE:
468       if (event->state & GDK_BUTTON1_MASK)
469         deco->closing = TRUE;
470       break;
471     case GTK_WINDOW_REGION_BR_RESIZE:
472       if (!deco->maximized)
473         {
474           if (event->state & GDK_BUTTON1_MASK)
475             deco->resize = RESIZE_BOTTOM_RIGHT;
476           deco->last_x = x;
477           deco->last_y = y;
478         }
479       break;
480     default:
481       break;
482     }
483   
484   return TRUE;
485 }
486
487 static gint
488 gtk_decorated_window_button_release (GtkWidget      *widget,
489                                      GdkEventButton *event)
490 {
491   GtkWindow *window;
492   GtkWindowRegionType type;
493   GtkWindowDecoration *deco;
494       
495   window = GTK_WINDOW (widget);
496   deco = get_decoration (window);
497
498   if (deco->closing)
499     {
500       type = gtk_decorated_window_region_type (window, event->x, event->y);
501       if (type == GTK_WINDOW_REGION_CLOSE)
502         {
503           GdkEvent *event = gdk_event_new (GDK_DELETE);
504
505           event->any.type = GDK_DELETE;
506           event->any.window = g_object_ref (widget->window);
507           event->any.send_event = TRUE;
508
509           gtk_main_do_event (event);
510           gdk_event_free (event);
511         }
512     }
513   else if (deco->maximizing)
514     {
515       type = gtk_decorated_window_region_type (window, event->x, event->y);
516       if (type == GTK_WINDOW_REGION_MAXIMIZE)
517         {
518           if (deco->maximized)
519             gtk_window_unmaximize (window);
520           else
521             gtk_window_maximize (window);
522         }
523     }
524   
525   deco->closing = FALSE;
526   deco->maximizing = FALSE;
527   deco->moving = FALSE;
528   deco->resize = RESIZE_NONE;
529   return TRUE;
530 }
531
532 static gint
533 gtk_decorated_window_window_state (GtkWidget           *widget,
534                                    GdkEventWindowState *event)
535 {
536   GtkWindow *window;
537   GtkWindowDecoration *deco;
538   GdkWindowObject *priv;
539       
540   window = GTK_WINDOW (widget);
541   deco = get_decoration (window);
542   priv = GDK_WINDOW_OBJECT (window->frame);
543
544   if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED)
545     {
546       if (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED)
547         {
548           int w, h;
549           gdk_window_get_geometry (widget->window, NULL, NULL,
550                                    &deco->last_w, &deco->last_h, NULL);
551           gdk_window_get_origin (widget->window, &deco->last_x, &deco->last_y);
552           w = gdk_screen_get_width(gdk_screen_get_default()) - DECORATION_BORDER_TOT_X;
553           h = gdk_screen_get_height(gdk_screen_get_default()) - DECORATION_BORDER_TOT_Y;
554           _gtk_window_constrain_size (window, w, h, &w, &h);
555           if (w != deco->last_w || h != deco->last_h)
556             {
557               gtk_window_move (window, DECORATION_BORDER_LEFT, DECORATION_BORDER_TOP);
558               gdk_window_resize (widget->window, w, h);
559               deco->maximized = TRUE;
560             }
561         }
562       else
563         {
564           gtk_window_move (window, deco->last_x, deco->last_y);
565           _gtk_window_constrain_size (window, deco->last_w, deco->last_h,
566                                       &deco->last_w, &deco->last_h);
567           gdk_window_resize (widget->window, deco->last_w, deco->last_h);
568           deco->maximized = FALSE;
569         }
570     }
571   return TRUE;
572 }
573
574 static void
575 gtk_decorated_window_paint (GtkWidget    *widget,
576                             GdkRectangle *area)
577 {
578   GtkWindow *window = GTK_WINDOW (widget);
579   GtkWindowDecoration *deco = get_decoration (window);
580   gint x1, y1, x2, y2;
581   GtkStateType border_state;
582   cairo_t *cr;
583
584   if (deco->decorated)
585     {
586       GdkWindow *frame;
587       gint width, height;
588
589       frame = window->frame;
590       gdk_drawable_get_size (frame, &width, &height);
591
592       /* Top */
593       gtk_paint_flat_box (widget->style, frame, GTK_STATE_NORMAL,
594                           GTK_SHADOW_NONE, area, widget, "base",
595                           0, 0,
596                           width, DECORATION_BORDER_TOP);
597       /* Bottom */
598       gtk_paint_flat_box (widget->style, frame, GTK_STATE_NORMAL,
599                           GTK_SHADOW_NONE, area, widget, "base",
600                           0, height - DECORATION_BORDER_BOTTOM,
601                           width, DECORATION_BORDER_BOTTOM);
602       /* Left */
603       gtk_paint_flat_box (widget->style, frame, GTK_STATE_NORMAL,
604                           GTK_SHADOW_NONE, area, widget, "base",
605                           0, DECORATION_BORDER_TOP,
606                           DECORATION_BORDER_LEFT, height - DECORATION_BORDER_TOT_Y);
607       /* Right */
608       gtk_paint_flat_box (widget->style, frame, GTK_STATE_NORMAL,
609                           GTK_SHADOW_NONE, area, widget, "base",
610                           width - DECORATION_BORDER_RIGHT, DECORATION_BORDER_TOP,
611                           DECORATION_BORDER_RIGHT, height - DECORATION_BORDER_TOT_Y);
612       
613       /* Border: */
614       if (deco->focused)
615         border_state = GTK_STATE_SELECTED;
616       else 
617         border_state = GTK_STATE_PRELIGHT;
618
619       gtk_paint_box (widget->style, frame, border_state, 
620                      GTK_SHADOW_OUT, area, widget, "base",
621                      0, 0, width, height);
622       
623       gtk_paint_box (widget->style, frame, border_state, 
624                      GTK_SHADOW_IN, area, widget, "base",
625                      DECORATION_BORDER_LEFT - 2, DECORATION_BORDER_TOP - 2,
626                      width - (DECORATION_BORDER_LEFT + DECORATION_BORDER_RIGHT) + 3,
627                      height - (DECORATION_BORDER_TOP + DECORATION_BORDER_BOTTOM) + 3);
628       
629       cr = gdk_cairo_create (frame);
630       cairo_set_line_width (cr, 1.0);
631       cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
632
633       if (area)
634         {
635           gdk_cairo_rectangle (cr, &area);
636           cairo_clip (cr);
637         }
638
639       if (deco->maximizable)
640         {
641           /* Maximize button: */
642
643           x1 = width - (DECORATION_BORDER_LEFT * 2) - (DECORATION_BUTTON_SIZE * 2);
644           y1 = DECORATION_BUTTON_Y_OFFSET;
645           x2 = x1 + DECORATION_BUTTON_SIZE;
646           y2 = y1 + DECORATION_BUTTON_SIZE;
647
648           gdk_cairo_set_source_color (cr, &widget->style->bg[widget->state]);
649           cairo_rectangle (cr, x1, y1, x2 - x1, y2 - y1);
650           cairo_fill (cr);
651
652           gdk_cairo_set_source_rgb (cr, 0, 0, 0);
653           cairo_rectangle (cr, x1 + 1, y1 + 1, x2 - x1 - 3, 1);
654           cairo_move_to (cr, x1 + 1.5, y1 + 1.5);
655           cairo_line_to (cr, x2 - 1.5, y1 + 1.5);
656           cairo_rectangle (cr, x1 + 1.5, y1 + 2.5, DECORATION_BUTTON_SIZE - 3, DECORATION_BUTTON_SIZE - 4);
657           cairo_stroke (cr);
658         }
659       
660       /* Close button: */
661       
662       x1 = width - DECORATION_BORDER_LEFT - DECORATION_BUTTON_SIZE;
663       y1 = DECORATION_BUTTON_Y_OFFSET;
664       x2 = width - DECORATION_BORDER_LEFT;
665       y2 = DECORATION_BUTTON_Y_OFFSET + DECORATION_BUTTON_SIZE;
666
667       gdk_cairo_set_source_color (cr, &widget->style->bg[widget->state]);
668       cairo_rectangle (cr, x1, y1, x2 - x1, y2 - y1);
669       cairo_fill (cr);
670
671       /* draw an X */
672       cairo_move_to (cr, x1 + 0.5, y1 + 0.5);
673       cairo_line_to (cr, x2 - 0.5, y2 - 0.5);
674       cairo_move_to (cr, x1 + 0.5, y2 - 0.5);
675       cairo_line_to (cr, x2 - 0.5, y1 + 0.5);
676       cairo_stroke (cr);
677
678       /* Title */
679       if (deco->title_layout)
680         {
681           gdk_cairo_set_source_color (cr, widget->style->fg [border_state]);
682           pango_cairo_show_layout (cr, deco->title_layout);
683         }
684
685       cairo_destroy (cr);
686     }
687 }
688
689
690 static void
691 gtk_decorated_window_recalculate_regions (GtkWindow *window)
692 {
693   gint n_regions;
694   gint width, height;
695   GtkWindowRegion *region;
696   GtkWindowDecoration *deco = get_decoration (window);
697       
698   n_regions = 0;
699
700   if (!deco->decorated)
701     return;
702   
703   n_regions += 2; /* close, Title */
704   if (deco->maximizable)
705     n_regions += 1;
706   if (gtk_window_get_resizable (window))
707     n_regions += 2;
708
709   if (deco->n_regions != n_regions)
710     {
711       g_free (deco->regions);
712       deco->regions = g_new (GtkWindowRegion, n_regions);
713       deco->n_regions = n_regions;
714     }
715
716   width = GTK_WIDGET (window)->allocation.width + DECORATION_BORDER_TOT_X;
717   height = GTK_WIDGET (window)->allocation.height + DECORATION_BORDER_TOT_Y;
718
719   region = deco->regions;
720
721   /* Maximize button */
722   if (deco->maximizable)
723     {
724       region->rect.x = width - (DECORATION_BORDER_LEFT * 2) - (DECORATION_BUTTON_SIZE * 2);
725       region->rect.y = DECORATION_BUTTON_Y_OFFSET;
726       region->rect.width = DECORATION_BUTTON_SIZE;
727       region->rect.height = DECORATION_BUTTON_SIZE;
728       region->type = GTK_WINDOW_REGION_MAXIMIZE;
729       region++;
730     }
731
732   /* Close button */
733   region->rect.x = width - DECORATION_BORDER_LEFT - DECORATION_BUTTON_SIZE;
734   region->rect.y = DECORATION_BUTTON_Y_OFFSET;
735   region->rect.width = DECORATION_BUTTON_SIZE;
736   region->rect.height = DECORATION_BUTTON_SIZE;
737   region->type = GTK_WINDOW_REGION_CLOSE;
738   region++;
739     
740   /* title bar */
741   region->rect.x = 0;
742   region->rect.y = 0;
743   region->rect.width = width;
744   region->rect.height = DECORATION_BORDER_TOP;
745   region->type = GTK_WINDOW_REGION_TITLE;
746   region++;
747   
748   if (gtk_window_get_resizable (window))
749     {
750       region->rect.x = width - (DECORATION_BORDER_RIGHT + 10);
751       region->rect.y = height - DECORATION_BORDER_BOTTOM;
752       region->rect.width = DECORATION_BORDER_RIGHT + 10;
753       region->rect.height = DECORATION_BORDER_BOTTOM;
754       region->type = GTK_WINDOW_REGION_BR_RESIZE;
755       region++;
756
757       region->rect.x = width - DECORATION_BORDER_RIGHT;
758       region->rect.y = height - (DECORATION_BORDER_BOTTOM + 10);
759       region->rect.width = DECORATION_BORDER_RIGHT;
760       region->rect.height = DECORATION_BORDER_BOTTOM + 10;
761       region->type = GTK_WINDOW_REGION_BR_RESIZE;
762       region++;
763     }
764 }
765
766 void
767 gtk_decorated_window_move_resize_window (GtkWindow   *window,
768                                          gint         x,
769                                          gint         y,
770                                          gint         width,
771                                          gint         height)
772 {
773   GtkWidget *widget = GTK_WIDGET (window);
774   GtkWindowDecoration *deco = get_decoration (window);
775   
776   deco->real_inner_move = TRUE;
777   gdk_window_move_resize (widget->window,
778                           x, y, width, height);
779 }
780 #else
781
782 void
783 gtk_decorated_window_init (GtkWindow  *window)
784 {
785 }
786
787 void 
788 gtk_decorated_window_calculate_frame_size (GtkWindow *window)
789 {
790 }
791
792 void
793 gtk_decorated_window_set_title (GtkWindow   *window,
794                                 const gchar *title)
795 {
796 }
797
798 void
799 gtk_decorated_window_move_resize_window (GtkWindow   *window,
800                                          gint         x,
801                                          gint         y,
802                                          gint         width,
803                                          gint         height)
804 {
805   gdk_window_move_resize (gtk_widget_get_window (GTK_WIDGET (window)),
806                           x, y, width, height);
807 }
808 #endif