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