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