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