]> icculus.org git repositories - mikachu/openbox.git/blob - src/Window.cc
that segfaulted. oops. added a workaround so setImageDither doesnt reconfig when...
[mikachu/openbox.git] / src / Window.cc
1 // Window.cc for Openbox
2 // Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
3 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a
6 // copy of this software and associated documentation files (the "Software"),
7 // to deal in the Software without restriction, including without limitation
8 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 // and/or sell copies of the Software, and to permit persons to whom the
10 // Software is furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 // DEALINGS IN THE SOFTWARE.
22
23 // stupid macros needed to access some functions in version 2 of the GNU C
24 // library
25 #ifndef   _GNU_SOURCE
26 #define   _GNU_SOURCE
27 #endif // _GNU_SOURCE
28
29 #ifdef    HAVE_CONFIG_H
30 #  include "../config.h"
31 #endif // HAVE_CONFIG_H
32
33 #include <X11/Xatom.h>
34 #include <X11/keysym.h>
35
36 #ifdef    HAVE_STRING_H
37 #  include <string.h>
38 #endif // HAVE_STRING_H
39
40 #ifdef    DEBUG
41 #  ifdef    HAVE_STDIO_H
42 #    include <stdio.h>
43 #  endif // HAVE_STDIO_H
44 #endif // DEBUG
45
46 #include "i18n.h"
47 #include "openbox.h"
48 #include "Iconmenu.h"
49 #include "Screen.h"
50 #include "Toolbar.h"
51 #include "Window.h"
52 #include "Windowmenu.h"
53 #include "Workspace.h"
54 #ifdef    SLIT
55 #  include "Slit.h"
56 #endif // SLIT
57 #include "Util.h"
58
59 /*
60  * Initializes the class with default values/the window's set initial values.
61  */
62 OpenboxWindow::OpenboxWindow(Openbox &o, Window w, BScreen *s) : openbox(o) {
63 #ifdef    DEBUG
64   fprintf(stderr, i18n->getMessage(WindowSet, WindowCreating,
65                      "OpenboxWindow::OpenboxWindow(): creating 0x%lx\n"),
66           w);
67 #endif // DEBUG
68
69   client.window = w;
70   display = openbox.getXDisplay();
71
72   openbox.grab();
73   if (! validateClient()) return;
74
75   // fetch client size and placement
76   XWindowAttributes wattrib;
77   if ((! XGetWindowAttributes(display, client.window, &wattrib)) ||
78       (! wattrib.screen) || wattrib.override_redirect) {
79 #ifdef    DEBUG
80     fprintf(stderr,
81             i18n->getMessage(WindowSet, WindowXGetWindowAttributesFail,
82                "OpenboxWindow::OpenboxWindow(): XGetWindowAttributes "
83                "failed\n"));
84 #endif // DEBUG
85
86     openbox.ungrab();
87     return;
88   }
89
90   if (s) {
91     screen = s;
92   } else {
93     screen = openbox.searchScreen(RootWindowOfScreen(wattrib.screen));
94     if (! screen) {
95 #ifdef    DEBUG
96       fprintf(stderr, i18n->getMessage(WindowSet, WindowCannotFindScreen,
97                       "OpenboxWindow::OpenboxWindow(): can't find screen\n"
98                       "\tfor root window 0x%lx\n"),
99                       RootWindowOfScreen(wattrib.screen));
100 #endif // DEBUG
101
102       openbox.ungrab();
103       return;
104     }
105   }
106
107   flags.moving = flags.resizing = flags.shaded = flags.visible =
108     flags.iconic = flags.transient = flags.focused =
109     flags.stuck = flags.modal =  flags.send_focus_message =
110     flags.shaped = flags.managed = False;
111   flags.maximized = 0;
112
113   openbox_attrib.workspace = workspace_number = window_number = -1;
114
115   openbox_attrib.flags = openbox_attrib.attrib = openbox_attrib.stack
116     = openbox_attrib.decoration = 0l;
117   openbox_attrib.premax_x = openbox_attrib.premax_y = 0;
118   openbox_attrib.premax_w = openbox_attrib.premax_h = 0;
119
120   frame.window = frame.plate = frame.title = frame.handle = None;
121   frame.close_button = frame.iconify_button = frame.maximize_button = None;
122   frame.right_grip = frame.left_grip = None;
123
124   frame.utitle = frame.ftitle = frame.uhandle = frame.fhandle = None;
125   frame.ulabel = frame.flabel = frame.ubutton = frame.fbutton = None;
126   frame.pbutton = frame.ugrip = frame.fgrip = None;
127
128   decorations.titlebar = decorations.border = decorations.handle = True;
129   decorations.iconify = decorations.maximize = decorations.menu = True;
130   functions.resize = functions.move = functions.iconify =
131     functions.maximize = True;
132   functions.close = decorations.close = False;
133
134   client.wm_hint_flags = client.normal_hint_flags = 0;
135   client.transient_for = client.transient = 0;
136   client.title = 0;
137   client.title_len = 0;
138   client.icon_title = 0;
139   client.mwm_hint = (MwmHints *) 0;
140   client.openbox_hint = (OpenboxHints *) 0;
141
142   // get the initial size and location of client window (relative to the
143   // _root window_). This position is the reference point used with the
144   // window's gravity to find the window's initial position.
145   client.x = wattrib.x;
146   client.y = wattrib.y;
147   client.width = wattrib.width;
148   client.height = wattrib.height;
149   client.old_bw = wattrib.border_width;
150
151   windowmenu = 0;
152   lastButtonPressTime = 0;
153   image_ctrl = screen->getImageControl();
154
155   timer = new BTimer(openbox, *this);
156   timer->setTimeout(openbox.getAutoRaiseDelay());
157   timer->fireOnce(True);
158
159   getOpenboxHints();
160   if (! client.openbox_hint)
161     getMWMHints();
162
163   // get size, aspect, minimum/maximum size and other hints set by the
164   // client
165   getWMProtocols();
166   getWMHints();
167   getWMNormalHints();
168
169 #ifdef    SLIT
170   if (client.initial_state == WithdrawnState) {
171     screen->getSlit()->addClient(client.window);
172     openbox.ungrab();
173     delete this;
174     return;
175   }
176 #endif // SLIT
177
178   flags.managed = True;
179   openbox.saveWindowSearch(client.window, this);
180
181   // determine if this is a transient window
182   Window win;
183   if (XGetTransientForHint(display, client.window, &win)) {
184     if (win && (win != client.window)) {
185       OpenboxWindow *tr;
186       if ((tr = openbox.searchWindow(win))) {
187         while (tr->client.transient) tr = tr->client.transient;
188         client.transient_for = tr;
189         tr->client.transient = this;
190         flags.stuck = client.transient_for->flags.stuck;
191         flags.transient = True;
192       } else if (win == client.window_group) {
193         if ((tr = openbox.searchGroup(win, this))) {
194           while (tr->client.transient) tr = tr->client.transient;
195           client.transient_for = tr;
196           tr->client.transient = this;
197           flags.stuck = client.transient_for->flags.stuck;
198           flags.transient = True;
199         }
200       }
201     }
202
203     if (win == screen->getRootWindow()) flags.modal = True;
204   }
205
206   // adjust the window decorations based on transience and window sizes
207   if (flags.transient)
208     decorations.maximize = decorations.handle = functions.maximize = False;
209
210   if ((client.normal_hint_flags & PMinSize) &&
211       (client.normal_hint_flags & PMaxSize) &&
212        client.max_width <= client.min_width &&
213       client.max_height <= client.min_height) {
214     decorations.maximize = decorations.handle =
215       functions.resize = functions.maximize = False;
216   }
217   upsize();
218
219   Bool place_window = True;
220   if (openbox.isStartup() || flags.transient ||
221       client.normal_hint_flags & (PPosition|USPosition)) {
222     setGravityOffsets();
223
224     if ((openbox.isStartup()) ||
225         (frame.x >= 0 &&
226          (signed) (frame.y + frame.y_border) >= 0 &&
227          frame.x <= (signed) screen->size().w() &&
228          frame.y <= (signed) screen->size().h()))
229       place_window = False;
230   }
231
232   frame.window = createToplevelWindow(frame.x, frame.y, frame.width,
233                                       frame.height,
234                                       frame.border_w);
235   openbox.saveWindowSearch(frame.window, this);
236
237   frame.plate = createChildWindow(frame.window);
238   openbox.saveWindowSearch(frame.plate, this);
239
240   if (decorations.titlebar) {
241     frame.title = createChildWindow(frame.window);
242     frame.label = createChildWindow(frame.title);
243     openbox.saveWindowSearch(frame.title, this);
244     openbox.saveWindowSearch(frame.label, this);
245   }
246
247   if (decorations.handle) {
248     frame.handle = createChildWindow(frame.window);
249     openbox.saveWindowSearch(frame.handle, this);
250
251     frame.left_grip =
252       createChildWindow(frame.handle, openbox.getLowerLeftAngleCursor());
253     openbox.saveWindowSearch(frame.left_grip, this);
254
255     frame.right_grip =
256       createChildWindow(frame.handle, openbox.getLowerRightAngleCursor());
257     openbox.saveWindowSearch(frame.right_grip, this);
258   }
259
260   associateClientWindow();
261
262   if (! screen->sloppyFocus())
263     openbox.grabButton(Button1, 0, frame.plate, True, ButtonPressMask,
264         GrabModeSync, GrabModeSync, None, None);
265
266   openbox.grabButton(Button1, Mod1Mask, frame.window, True,
267       ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
268       GrabModeAsync, None, openbox.getMoveCursor());
269   openbox.grabButton(Button2, Mod1Mask, frame.window, True,
270       ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None);
271   openbox.grabButton(Button3, Mod1Mask, frame.window, True,
272       ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
273       GrabModeAsync, None, None);
274
275   positionWindows();
276   XRaiseWindow(display, frame.plate);
277   XMapSubwindows(display, frame.plate);
278   if (decorations.titlebar) XMapSubwindows(display, frame.title);
279   XMapSubwindows(display, frame.window);
280
281   if (decorations.menu)
282     windowmenu = new Windowmenu(*this);
283
284   decorate();
285
286   if (workspace_number < 0 || workspace_number >= screen->getWorkspaceCount())
287     screen->getCurrentWorkspace()->addWindow(this, place_window);
288   else
289     screen->getWorkspace(workspace_number)->addWindow(this, place_window);
290
291   configure(frame.x, frame.y, frame.width, frame.height);
292
293   if (flags.shaded) {
294     flags.shaded = False;
295     shade();
296   }
297
298   if (flags.maximized && functions.maximize) {
299     unsigned int button = flags.maximized;
300     flags.maximized = 0;
301     maximize(button);
302   }
303
304   setFocusFlag(False);
305
306   openbox.ungrab();
307 }
308
309
310 OpenboxWindow::~OpenboxWindow(void) {
311   if (flags.moving || flags.resizing) {
312     screen->hideGeometry();
313     XUngrabPointer(display, CurrentTime);
314   }
315
316   if (workspace_number != -1 && window_number != -1)
317     screen->getWorkspace(workspace_number)->removeWindow(this);
318   else if (flags.iconic)
319     screen->removeIcon(this);
320
321   if (timer) {
322     if (timer->isTiming()) timer->stop();
323     delete timer;
324   }
325
326   if (windowmenu) delete windowmenu;
327
328   if (client.title)
329     delete [] client.title;
330
331   if (client.icon_title)
332     delete [] client.icon_title;
333
334   if (client.mwm_hint)
335     XFree(client.mwm_hint);
336
337   if (client.openbox_hint)
338     XFree(client.openbox_hint);
339
340   if (client.window_group)
341     openbox.removeGroupSearch(client.window_group);
342
343   if (flags.transient && client.transient_for)
344     client.transient_for->client.transient = client.transient;
345   if (client.transient)
346     client.transient->client.transient_for = client.transient_for;
347
348   if (frame.close_button) {
349     openbox.removeWindowSearch(frame.close_button);
350     XDestroyWindow(display, frame.close_button);
351   }
352
353   if (frame.iconify_button) {
354     openbox.removeWindowSearch(frame.iconify_button);
355     XDestroyWindow(display, frame.iconify_button);
356   }
357
358   if (frame.maximize_button) {
359     openbox.removeWindowSearch(frame.maximize_button);
360     XDestroyWindow(display, frame.maximize_button);
361   }
362
363   if (frame.title) {
364     if (frame.ftitle)
365       image_ctrl->removeImage(frame.ftitle);
366
367     if (frame.utitle)
368       image_ctrl->removeImage(frame.utitle);
369
370     if (frame.flabel)
371       image_ctrl->removeImage(frame.flabel);
372
373     if( frame.ulabel)
374       image_ctrl->removeImage(frame.ulabel);
375
376     openbox.removeWindowSearch(frame.label);
377     openbox.removeWindowSearch(frame.title);
378     XDestroyWindow(display, frame.label);
379     XDestroyWindow(display, frame.title);
380   }
381
382   if (frame.handle) {
383     if (frame.fhandle)
384       image_ctrl->removeImage(frame.fhandle);
385
386     if (frame.uhandle)
387       image_ctrl->removeImage(frame.uhandle);
388
389     if (frame.fgrip)
390       image_ctrl->removeImage(frame.fgrip);
391
392     if (frame.ugrip)
393       image_ctrl->removeImage(frame.ugrip);
394
395     openbox.removeWindowSearch(frame.handle);
396     openbox.removeWindowSearch(frame.right_grip);
397     openbox.removeWindowSearch(frame.left_grip);
398     XDestroyWindow(display, frame.right_grip);
399     XDestroyWindow(display, frame.left_grip);
400     XDestroyWindow(display, frame.handle);
401   }
402
403   if (frame.fbutton)
404     image_ctrl->removeImage(frame.fbutton);
405
406   if (frame.ubutton)
407     image_ctrl->removeImage(frame.ubutton);
408
409   if (frame.pbutton)
410     image_ctrl->removeImage(frame.pbutton);
411
412   if (frame.plate) {
413     openbox.removeWindowSearch(frame.plate);
414     XDestroyWindow(display, frame.plate);
415   }
416
417   if (frame.window) {
418     openbox.removeWindowSearch(frame.window);
419     XDestroyWindow(display, frame.window);
420   }
421
422   if (flags.managed) {
423     openbox.removeWindowSearch(client.window);
424     screen->removeNetizen(client.window);
425   }
426 }
427
428
429 /*
430  * Creates a new top level window, with a given location, size, and border
431  * width.
432  * Returns: the newly created window
433  */
434 Window OpenboxWindow::createToplevelWindow(int x, int y, unsigned int width,
435                                             unsigned int height,
436                                             unsigned int borderwidth)
437 {
438   XSetWindowAttributes attrib_create;
439   unsigned long create_mask = CWBackPixmap | CWBorderPixel | CWColormap |
440                               CWOverrideRedirect | CWEventMask;
441
442   attrib_create.background_pixmap = None;
443   attrib_create.colormap = screen->getColormap();
444   attrib_create.override_redirect = True;
445   attrib_create.event_mask = ButtonPressMask | ButtonReleaseMask |
446                              ButtonMotionMask | EnterWindowMask;
447
448   return XCreateWindow(display, screen->getRootWindow(), x, y, width, height,
449                         borderwidth, screen->getDepth(), InputOutput,
450                         screen->getVisual(), create_mask,
451                         &attrib_create);
452 }
453
454
455 /*
456  * Creates a child window, and optionally associates a given cursor with
457  * the new window.
458  */
459 Window OpenboxWindow::createChildWindow(Window parent, Cursor cursor) {
460   XSetWindowAttributes attrib_create;
461   unsigned long create_mask = CWBackPixmap | CWBorderPixel |
462                               CWEventMask;
463
464   attrib_create.background_pixmap = None;
465   attrib_create.event_mask = ButtonPressMask | ButtonReleaseMask |
466                              ButtonMotionMask | ExposureMask |
467                              EnterWindowMask | LeaveWindowMask;
468
469   if (cursor) {
470     create_mask |= CWCursor;
471     attrib_create.cursor = cursor;
472   }
473
474   return XCreateWindow(display, parent, 0, 0, 1, 1, 0, screen->getDepth(),
475                        InputOutput, screen->getVisual(), create_mask,
476                        &attrib_create);
477 }
478
479
480 void OpenboxWindow::associateClientWindow(void) {
481   XSetWindowBorderWidth(display, client.window, 0);
482   getWMName();
483   getWMIconName();
484
485   XChangeSaveSet(display, client.window, SetModeInsert);
486   XSetWindowAttributes attrib_set;
487
488   XSelectInput(display, frame.plate, NoEventMask);
489   XReparentWindow(display, client.window, frame.plate, 0, 0);
490   XSelectInput(display, frame.plate, SubstructureRedirectMask);
491
492   XFlush(display);
493
494   attrib_set.event_mask = PropertyChangeMask | StructureNotifyMask |
495                           FocusChangeMask;
496   attrib_set.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask |
497                                      ButtonMotionMask;
498
499   XChangeWindowAttributes(display, client.window, CWEventMask|CWDontPropagate,
500                           &attrib_set);
501
502 #ifdef    SHAPE
503   if (openbox.hasShapeExtensions()) {
504     XShapeSelectInput(display, client.window, ShapeNotifyMask);
505
506     int foo;
507     unsigned int ufoo;
508
509     XShapeQueryExtents(display, client.window, &flags.shaped, &foo, &foo,
510                        &ufoo, &ufoo, &foo, &foo, &foo, &ufoo, &ufoo);
511
512     if (flags.shaped) {
513       XShapeCombineShape(display, frame.window, ShapeBounding,
514                          frame.mwm_border_w, frame.y_border +
515                          frame.mwm_border_w, client.window,
516                          ShapeBounding, ShapeSet);
517
518       int num = 1;
519       XRectangle xrect[2];
520       xrect[0].x = xrect[0].y = 0;
521       xrect[0].width = frame.width;
522       xrect[0].height = frame.y_border;
523
524       if (decorations.handle) {
525         xrect[1].x = 0;
526         xrect[1].y = frame.y_handle;
527         xrect[1].width = frame.width;
528         xrect[1].height = frame.handle_h + frame.border_w;
529         num++;
530       }
531
532       XShapeCombineRectangles(display, frame.window, ShapeBounding, 0, 0,
533                               xrect, num, ShapeUnion, Unsorted);
534     }
535   }
536 #endif // SHAPE
537
538   if (decorations.iconify) createIconifyButton();
539   if (decorations.maximize) createMaximizeButton();
540   if (decorations.close) createCloseButton();
541
542   if (frame.ubutton) {
543     if (frame.close_button)
544       XSetWindowBackgroundPixmap(display, frame.close_button, frame.ubutton);
545     if (frame.maximize_button)
546       XSetWindowBackgroundPixmap(display, frame.maximize_button,
547                                  frame.ubutton);
548     if (frame.iconify_button)
549       XSetWindowBackgroundPixmap(display, frame.iconify_button, frame.ubutton);
550   } else {
551     if (frame.close_button)
552       XSetWindowBackground(display, frame.close_button, frame.ubutton_pixel);
553     if (frame.maximize_button)
554       XSetWindowBackground(display, frame.maximize_button,
555                            frame.ubutton_pixel);
556     if (frame.iconify_button)
557       XSetWindowBackground(display, frame.iconify_button, frame.ubutton_pixel);
558   }
559 }
560
561
562 void OpenboxWindow::decorate(void) {
563   Pixmap tmp = frame.fbutton;
564   BTexture *texture = &(screen->getWindowStyle()->b_focus);
565   if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
566     frame.fbutton = None;
567     frame.fbutton_pixel = texture->getColor()->getPixel();
568   } else {
569     frame.fbutton =
570       image_ctrl->renderImage(frame.button_w, frame.button_h, texture);
571   }
572   if (tmp) image_ctrl->removeImage(tmp);
573
574   tmp = frame.ubutton;
575   texture = &(screen->getWindowStyle()->b_unfocus);
576   if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
577     frame.ubutton = None;
578     frame.ubutton_pixel = texture->getColor()->getPixel();
579   } else {
580     frame.ubutton =
581       image_ctrl->renderImage(frame.button_w, frame.button_h, texture);
582   }
583   if (tmp) image_ctrl->removeImage(tmp);
584
585   tmp = frame.pbutton;
586   texture = &(screen->getWindowStyle()->b_pressed);
587   if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
588     frame.pbutton = None;
589     frame.pbutton_pixel = texture->getColor()->getPixel();
590   } else {
591     frame.pbutton =
592       image_ctrl->renderImage(frame.button_w, frame.button_h, texture);
593   }
594   if (tmp) image_ctrl->removeImage(tmp);
595
596   if (decorations.titlebar) {
597     tmp = frame.ftitle;
598     texture = &(screen->getWindowStyle()->t_focus);
599     if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
600       frame.ftitle = None;
601       frame.ftitle_pixel = texture->getColor()->getPixel();
602     } else {
603       frame.ftitle =
604         image_ctrl->renderImage(frame.width, frame.title_h, texture);
605     }
606     if (tmp) image_ctrl->removeImage(tmp);
607
608     tmp = frame.utitle;
609     texture = &(screen->getWindowStyle()->t_unfocus);
610     if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
611       frame.utitle = None;
612       frame.utitle_pixel = texture->getColor()->getPixel();
613     } else {
614       frame.utitle =
615         image_ctrl->renderImage(frame.width, frame.title_h, texture);
616     }
617     if (tmp) image_ctrl->removeImage(tmp);
618
619     XSetWindowBorder(display, frame.title,
620                      screen->getBorderColor()->getPixel());
621
622     decorateLabel();
623   }
624
625   if (decorations.border) {
626     frame.fborder_pixel = screen->getWindowStyle()->f_focus.getPixel();
627     frame.uborder_pixel = screen->getWindowStyle()->f_unfocus.getPixel();
628     openbox_attrib.flags |= AttribDecoration;
629     openbox_attrib.decoration = DecorNormal;
630   } else {
631     openbox_attrib.flags |= AttribDecoration;
632     openbox_attrib.decoration = DecorNone;
633   }
634
635   if (decorations.handle) {
636     tmp = frame.fhandle;
637     texture = &(screen->getWindowStyle()->h_focus);
638     if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
639       frame.fhandle = None;
640       frame.fhandle_pixel = texture->getColor()->getPixel();
641     } else {
642       frame.fhandle =
643         image_ctrl->renderImage(frame.width, frame.handle_h, texture);
644     }
645     if (tmp) image_ctrl->removeImage(tmp);
646
647     tmp = frame.uhandle;
648     texture = &(screen->getWindowStyle()->h_unfocus);
649     if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
650       frame.uhandle = None;
651       frame.uhandle_pixel = texture->getColor()->getPixel();
652     } else {
653       frame.uhandle =
654         image_ctrl->renderImage(frame.width, frame.handle_h, texture);
655     }
656     if (tmp) image_ctrl->removeImage(tmp);
657
658     tmp = frame.fgrip;
659     texture = &(screen->getWindowStyle()->g_focus);
660     if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
661       frame.fgrip = None;
662       frame.fgrip_pixel = texture->getColor()->getPixel();
663     } else {
664       frame.fgrip =
665         image_ctrl->renderImage(frame.grip_w, frame.grip_h, texture);
666     }
667     if (tmp) image_ctrl->removeImage(tmp);
668
669     tmp = frame.ugrip;
670     texture = &(screen->getWindowStyle()->g_unfocus);
671     if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
672       frame.ugrip = None;
673       frame.ugrip_pixel = texture->getColor()->getPixel();
674     } else {
675       frame.ugrip =
676         image_ctrl->renderImage(frame.grip_w, frame.grip_h, texture);
677     }
678     if (tmp) image_ctrl->removeImage(tmp);
679
680     XSetWindowBorder(display, frame.handle,
681                      screen->getBorderColor()->getPixel());
682     XSetWindowBorder(display, frame.left_grip,
683                      screen->getBorderColor()->getPixel());
684     XSetWindowBorder(display, frame.right_grip,
685                      screen->getBorderColor()->getPixel());
686   }
687
688   XSetWindowBorder(display, frame.window,
689                    screen->getBorderColor()->getPixel());
690 }
691
692
693 void OpenboxWindow::decorateLabel(void) {
694   Pixmap tmp = frame.flabel;
695   BTexture *texture = &(screen->getWindowStyle()->l_focus);
696   if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
697     frame.flabel = None;
698     frame.flabel_pixel = texture->getColor()->getPixel();
699   } else {
700     frame.flabel =
701       image_ctrl->renderImage(frame.label_w, frame.label_h, texture);
702   }
703   if (tmp) image_ctrl->removeImage(tmp);
704
705   tmp = frame.ulabel;
706   texture = &(screen->getWindowStyle()->l_unfocus);
707   if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
708     frame.ulabel = None;
709     frame.ulabel_pixel = texture->getColor()->getPixel();
710   } else {
711     frame.ulabel =
712       image_ctrl->renderImage(frame.label_w, frame.label_h, texture);
713   }
714   if (tmp) image_ctrl->removeImage(tmp);
715 }
716
717
718 void OpenboxWindow::createCloseButton(void) {
719   if (decorations.close && frame.title != None) {
720     frame.close_button = createChildWindow(frame.title);
721     openbox.saveWindowSearch(frame.close_button, this);
722   }
723 }
724
725
726 void OpenboxWindow::createIconifyButton(void) {
727   if (decorations.iconify && frame.title != None) {
728     frame.iconify_button = createChildWindow(frame.title);
729     openbox.saveWindowSearch(frame.iconify_button, this);
730   }
731 }
732
733
734 void OpenboxWindow::createMaximizeButton(void) {
735   if (decorations.maximize && frame.title != None) {
736     frame.maximize_button = createChildWindow(frame.title);
737     openbox.saveWindowSearch(frame.maximize_button, this);
738   }
739 }
740
741
742 void OpenboxWindow::positionButtons(Bool redecorate_label) {
743   const char *format = openbox.getTitleBarLayout();
744   const unsigned int bw = frame.bevel_w + 1;
745   const unsigned int by = frame.bevel_w + 1;
746   unsigned int bx = frame.bevel_w + 1;
747   unsigned int bcount = strlen(format) - 1;
748
749   if (!decorations.close)
750     bcount--;
751   if (!decorations.maximize)
752     bcount--;
753   if (!decorations.iconify)
754     bcount--;
755   frame.label_w = frame.width - bx * 2 - (frame.button_w + bw) * bcount;
756   
757   bool hasclose, hasiconify, hasmaximize;
758   hasclose = hasiconify = hasmaximize = false;
759  
760   for (int i = 0; format[i] != '\0' && i < 4; i++) {
761     switch(format[i]) {
762     case 'C':
763       if (decorations.close && frame.close_button != None) {
764         XMoveResizeWindow(display, frame.close_button, bx, by,
765                           frame.button_w, frame.button_h);
766         XMapWindow(display, frame.close_button);
767         XClearWindow(display, frame.close_button);
768         bx += frame.button_w + bw;
769         hasclose = true;
770       } else if (frame.close_button)
771         XUnmapWindow(display, frame.close_button);
772       break;
773     case 'I':
774       if (decorations.iconify && frame.iconify_button != None) {
775         XMoveResizeWindow(display, frame.iconify_button, bx, by,
776                           frame.button_w, frame.button_h);
777         XMapWindow(display, frame.iconify_button);
778         XClearWindow(display, frame.iconify_button);
779         bx += frame.button_w + bw;
780         hasiconify = true;
781       } else if (frame.close_button)
782         XUnmapWindow(display, frame.close_button);
783       break;
784     case 'M':
785       if (decorations.maximize && frame.maximize_button != None) {
786         XMoveResizeWindow(display, frame.maximize_button, bx, by,
787                           frame.button_w, frame.button_h);
788         XMapWindow(display, frame.maximize_button);
789         XClearWindow(display, frame.maximize_button);
790         bx += frame.button_w + bw;
791         hasmaximize = true;
792       } else if (frame.close_button)
793         XUnmapWindow(display, frame.close_button);
794       break;
795     case 'L':
796       XMoveResizeWindow(display, frame.label, bx, by - 1,
797                         frame.label_w, frame.label_h);
798       bx += frame.label_w + bw;
799       break;
800     }
801   }
802
803   if (!hasclose) {
804       openbox.removeWindowSearch(frame.close_button);
805       XDestroyWindow(display, frame.close_button);     
806   }
807   if (!hasiconify) {
808       openbox.removeWindowSearch(frame.iconify_button);
809       XDestroyWindow(display, frame.iconify_button);
810   }
811   if (!hasmaximize) {
812       openbox.removeWindowSearch(frame.maximize_button);
813       XDestroyWindow(display, frame.maximize_button);                 
814   }
815   if (redecorate_label)
816     decorateLabel();
817   redrawLabel();
818   redrawAllButtons();
819 }
820
821
822 void OpenboxWindow::reconfigure(void) {
823   upsize();
824
825   client.x = frame.x + frame.mwm_border_w + frame.border_w;
826   client.y = frame.y + frame.y_border + frame.mwm_border_w +
827              frame.border_w;
828
829   if (client.title) {
830     if (i18n->multibyte()) {
831       XRectangle ink, logical;
832       XmbTextExtents(screen->getWindowStyle()->fontset,
833                      client.title, client.title_len, &ink, &logical);
834       client.title_text_w = logical.width;
835     } else {
836       client.title_text_w = XTextWidth(screen->getWindowStyle()->font,
837                                        client.title, client.title_len);
838     }
839     client.title_text_w += (frame.bevel_w * 4);
840   }
841
842   positionWindows();
843   decorate();
844
845   XClearWindow(display, frame.window);
846   setFocusFlag(flags.focused);
847
848   configure(frame.x, frame.y, frame.width, frame.height);
849
850   if (! screen->sloppyFocus())
851     openbox.grabButton(Button1, 0, frame.plate, True, ButtonPressMask,
852         GrabModeSync, GrabModeSync, None, None);
853   else
854     openbox.ungrabButton(Button1, 0, frame.plate);
855
856   if (windowmenu) {
857     windowmenu->move(windowmenu->getX(), frame.y + frame.title_h);
858     windowmenu->reconfigure();
859   }
860 }
861
862
863 void OpenboxWindow::positionWindows(void) {
864   XResizeWindow(display, frame.window, frame.width,
865                 ((flags.shaded) ? frame.title_h : frame.height));
866   XSetWindowBorderWidth(display, frame.window, frame.border_w);
867   XSetWindowBorderWidth(display, frame.plate, frame.mwm_border_w);
868   XMoveResizeWindow(display, frame.plate, 0, frame.y_border,
869                     client.width, client.height);
870   XMoveResizeWindow(display, client.window, 0, 0, client.width, client.height);
871
872   if (decorations.titlebar) {
873     XSetWindowBorderWidth(display, frame.title, frame.border_w);
874     XMoveResizeWindow(display, frame.title, -frame.border_w,
875                       -frame.border_w, frame.width, frame.title_h);
876
877     positionButtons();
878   } else if (frame.title) {
879     XUnmapWindow(display, frame.title);
880   }
881   if (decorations.handle) {
882     XSetWindowBorderWidth(display, frame.handle, frame.border_w);
883     XSetWindowBorderWidth(display, frame.left_grip, frame.border_w);
884     XSetWindowBorderWidth(display, frame.right_grip, frame.border_w);
885
886     XMoveResizeWindow(display, frame.handle, -frame.border_w,
887                       frame.y_handle - frame.border_w,
888                       frame.width, frame.handle_h);
889     XMoveResizeWindow(display, frame.left_grip, -frame.border_w,
890                       -frame.border_w, frame.grip_w, frame.grip_h);
891     XMoveResizeWindow(display, frame.right_grip,
892                       frame.width - frame.grip_w - frame.border_w,
893                       -frame.border_w, frame.grip_w, frame.grip_h);
894     XMapSubwindows(display, frame.handle);
895   } else if (frame.handle) {
896     XUnmapWindow(display, frame.handle);
897   }
898 }
899
900
901 void OpenboxWindow::getWMName(void) {
902   if (client.title) {
903     delete [] client.title;
904     client.title = (char *) 0;
905   }
906
907   XTextProperty text_prop;
908   char **list;
909   int num;
910
911   if (XGetWMName(display, client.window, &text_prop)) {
912     if (text_prop.value && text_prop.nitems > 0) {
913       if (text_prop.encoding != XA_STRING) {
914         text_prop.nitems = strlen((char *) text_prop.value);
915
916         if ((XmbTextPropertyToTextList(display, &text_prop,
917                                        &list, &num) == Success) &&
918             (num > 0) && *list) {
919           client.title = bstrdup(*list);
920           XFreeStringList(list);
921         } else {
922           client.title = bstrdup((char *) text_prop.value);
923         }
924       } else {
925         client.title = bstrdup((char *) text_prop.value);
926       }
927       XFree((char *) text_prop.value);
928     } else {
929       client.title = bstrdup(i18n->getMessage(WindowSet, WindowUnnamed,
930                                               "Unnamed"));
931     }
932   } else {
933     client.title = bstrdup(i18n->getMessage(WindowSet, WindowUnnamed,
934                                             "Unnamed"));
935   }
936   client.title_len = strlen(client.title);
937
938   if (i18n->multibyte()) {
939     XRectangle ink, logical;
940     XmbTextExtents(screen->getWindowStyle()->fontset,
941                    client.title, client.title_len, &ink, &logical);
942     client.title_text_w = logical.width;
943   } else {
944     client.title_len = strlen(client.title);
945     client.title_text_w = XTextWidth(screen->getWindowStyle()->font,
946                                      client.title, client.title_len);
947   }
948
949   client.title_text_w += (frame.bevel_w * 4);
950 }
951
952
953 void OpenboxWindow::getWMIconName(void) {
954   if (client.icon_title) {
955     delete [] client.icon_title;
956     client.icon_title = (char *) 0;
957   }
958
959   XTextProperty text_prop;
960   char **list;
961   int num;
962
963   if (XGetWMIconName(display, client.window, &text_prop)) {
964     if (text_prop.value && text_prop.nitems > 0) {
965       if (text_prop.encoding != XA_STRING) {
966         text_prop.nitems = strlen((char *) text_prop.value);
967
968         if ((XmbTextPropertyToTextList(display, &text_prop,
969                                        &list, &num) == Success) &&
970             (num > 0) && *list) {
971           client.icon_title = bstrdup(*list);
972           XFreeStringList(list);
973         } else {
974           client.icon_title = bstrdup((char *) text_prop.value);
975         }
976       } else {
977         client.icon_title = bstrdup((char *) text_prop.value);
978       }
979       XFree((char *) text_prop.value);
980     } else {
981       client.icon_title = bstrdup(client.title);
982     }
983   } else {
984     client.icon_title = bstrdup(client.title);
985   }
986 }
987
988
989 /*
990  * Retrieve which WM Protocols are supported by the client window.
991  * If the WM_DELETE_WINDOW protocol is supported, add the close button to the
992  * window's decorations and allow the close behavior.
993  * If the WM_TAKE_FOCUS protocol is supported, save a value that indicates
994  * this.
995  */
996 void OpenboxWindow::getWMProtocols(void) {
997   Atom *proto;
998   int num_return = 0;
999
1000   if (XGetWMProtocols(display, client.window, &proto, &num_return)) {
1001     for (int i = 0; i < num_return; ++i) {
1002       if (proto[i] == openbox.getWMDeleteAtom())
1003         functions.close = decorations.close = True;
1004       else if (proto[i] == openbox.getWMTakeFocusAtom())
1005         flags.send_focus_message = True;
1006       else if (proto[i] == openbox.getOpenboxStructureMessagesAtom())
1007         screen->addNetizen(new Netizen(*screen, client.window));
1008     }
1009
1010     XFree(proto);
1011   }
1012 }
1013
1014
1015 /*
1016  * Gets the value of the WM_HINTS property.
1017  * If the property is not set, then use a set of default values.
1018  */
1019 void OpenboxWindow::getWMHints(void) {
1020   XWMHints *wmhint = XGetWMHints(display, client.window);
1021   if (! wmhint) {
1022     flags.visible = True;
1023     flags.iconic = False;
1024     focus_mode = F_Passive;
1025     client.window_group = None;
1026     client.initial_state = NormalState;
1027     return;
1028   }
1029   client.wm_hint_flags = wmhint->flags;
1030   if (wmhint->flags & InputHint) {
1031     if (wmhint->input == True) {
1032       if (flags.send_focus_message)
1033         focus_mode = F_LocallyActive;
1034       else
1035         focus_mode = F_Passive;
1036     } else {
1037       if (flags.send_focus_message)
1038         focus_mode = F_GloballyActive;
1039       else
1040         focus_mode = F_NoInput;
1041     }
1042   } else {
1043     focus_mode = F_Passive;
1044   }
1045
1046   if (wmhint->flags & StateHint)
1047     client.initial_state = wmhint->initial_state;
1048   else
1049     client.initial_state = NormalState;
1050
1051   if (wmhint->flags & WindowGroupHint) {
1052     if (! client.window_group) {
1053       client.window_group = wmhint->window_group;
1054       openbox.saveGroupSearch(client.window_group, this);
1055     }
1056   } else {
1057     client.window_group = None;
1058   }
1059   XFree(wmhint);
1060 }
1061
1062
1063 /*
1064  * Gets the value of the WM_NORMAL_HINTS property.
1065  * If the property is not set, then use a set of default values.
1066  */
1067 void OpenboxWindow::getWMNormalHints(void) {
1068   long icccm_mask;
1069   XSizeHints sizehint;
1070
1071   client.min_width = client.min_height =
1072     client.base_width = client.base_height =
1073     client.width_inc = client.height_inc = 1;
1074   client.max_width = screen->size().w();
1075   client.max_height = screen->size().h();
1076   client.min_aspect_x = client.min_aspect_y =
1077     client.max_aspect_x = client.max_aspect_y = 1;
1078   client.win_gravity = NorthWestGravity;
1079
1080   if (! XGetWMNormalHints(display, client.window, &sizehint, &icccm_mask))
1081     return;
1082
1083   client.normal_hint_flags = sizehint.flags;
1084
1085   if (sizehint.flags & PMinSize) {
1086     client.min_width = sizehint.min_width;
1087     client.min_height = sizehint.min_height;
1088   }
1089
1090   if (sizehint.flags & PMaxSize) {
1091     client.max_width = sizehint.max_width;
1092     client.max_height = sizehint.max_height;
1093   }
1094
1095   if (sizehint.flags & PResizeInc) {
1096     client.width_inc = sizehint.width_inc;
1097     client.height_inc = sizehint.height_inc;
1098   }
1099
1100   if (sizehint.flags & PAspect) {
1101     client.min_aspect_x = sizehint.min_aspect.x;
1102     client.min_aspect_y = sizehint.min_aspect.y;
1103     client.max_aspect_x = sizehint.max_aspect.x;
1104     client.max_aspect_y = sizehint.max_aspect.y;
1105   }
1106
1107   if (sizehint.flags & PBaseSize) {
1108     client.base_width = sizehint.base_width;
1109     client.base_height = sizehint.base_height;
1110   }
1111
1112   if (sizehint.flags & PWinGravity)
1113     client.win_gravity = sizehint.win_gravity;
1114 }
1115
1116
1117 /*
1118  * Gets the MWM hints for the class' contained window.
1119  * This is used while initializing the window to its first state, and not
1120  * thereafter.
1121  * Returns: true if the MWM hints are successfully retreived and applied; false
1122  * if they are not.
1123  */
1124 void OpenboxWindow::getMWMHints(void) {
1125   int format;
1126   Atom atom_return;
1127   unsigned long num, len;
1128
1129   int ret = XGetWindowProperty(display, client.window,
1130                                openbox.getMotifWMHintsAtom(), 0,
1131                                PropMwmHintsElements, False,
1132                                openbox.getMotifWMHintsAtom(), &atom_return,
1133                                &format, &num, &len,
1134                                (unsigned char **) &client.mwm_hint);
1135
1136   if (ret != Success || !client.mwm_hint || num != PropMwmHintsElements)
1137     return;
1138
1139   if (client.mwm_hint->flags & MwmHintsDecorations) {
1140     if (client.mwm_hint->decorations & MwmDecorAll) {
1141       decorations.titlebar = decorations.handle = decorations.border =
1142         decorations.iconify = decorations.maximize =
1143         decorations.close = decorations.menu = True;
1144     } else {
1145       decorations.titlebar = decorations.handle = decorations.border =
1146         decorations.iconify = decorations.maximize =
1147         decorations.close = decorations.menu = False;
1148
1149       if (client.mwm_hint->decorations & MwmDecorBorder)
1150         decorations.border = True;
1151       if (client.mwm_hint->decorations & MwmDecorHandle)
1152         decorations.handle = True;
1153       if (client.mwm_hint->decorations & MwmDecorTitle)
1154         decorations.titlebar = True;
1155       if (client.mwm_hint->decorations & MwmDecorMenu)
1156         decorations.menu = True;
1157       if (client.mwm_hint->decorations & MwmDecorIconify)
1158         decorations.iconify = True;
1159       if (client.mwm_hint->decorations & MwmDecorMaximize)
1160         decorations.maximize = True;
1161     }
1162   }
1163
1164   if (client.mwm_hint->flags & MwmHintsFunctions) {
1165     if (client.mwm_hint->functions & MwmFuncAll) {
1166       functions.resize = functions.move = functions.iconify =
1167         functions.maximize = functions.close = True;
1168     } else {
1169       functions.resize = functions.move = functions.iconify =
1170         functions.maximize = functions.close = False;
1171
1172       if (client.mwm_hint->functions & MwmFuncResize)
1173         functions.resize = True;
1174       if (client.mwm_hint->functions & MwmFuncMove)
1175         functions.move = True;
1176       if (client.mwm_hint->functions & MwmFuncIconify)
1177         functions.iconify = True;
1178       if (client.mwm_hint->functions & MwmFuncMaximize)
1179         functions.maximize = True;
1180       if (client.mwm_hint->functions & MwmFuncClose)
1181         functions.close = True;
1182     }
1183   }
1184 }
1185
1186
1187 /*
1188  * Gets the openbox hints from the class' contained window.
1189  * This is used while initializing the window to its first state, and not
1190  * thereafter.
1191  * Returns: true if the hints are successfully retreived and applied; false if
1192  * they are not.
1193  */
1194 void OpenboxWindow::getOpenboxHints(void) {
1195   int format;
1196   Atom atom_return;
1197   unsigned long num, len;
1198
1199   int ret = XGetWindowProperty(display, client.window,
1200                                openbox.getOpenboxHintsAtom(), 0,
1201                                PropOpenboxHintsElements, False,
1202                                openbox.getOpenboxHintsAtom(), &atom_return,
1203                                &format, &num, &len,
1204                                (unsigned char **) &client.openbox_hint);
1205   if (ret != Success || !client.openbox_hint ||
1206       num != PropOpenboxHintsElements)
1207     return;
1208
1209   if (client.openbox_hint->flags & AttribShaded)
1210     flags.shaded = (client.openbox_hint->attrib & AttribShaded);
1211
1212   if ((client.openbox_hint->flags & AttribMaxHoriz) &&
1213       (client.openbox_hint->flags & AttribMaxVert))
1214     flags.maximized = (client.openbox_hint->attrib &
1215                        (AttribMaxHoriz | AttribMaxVert)) ? 1 : 0;
1216   else if (client.openbox_hint->flags & AttribMaxVert)
1217     flags.maximized = (client.openbox_hint->attrib & AttribMaxVert) ? 2 : 0;
1218   else if (client.openbox_hint->flags & AttribMaxHoriz)
1219     flags.maximized = (client.openbox_hint->attrib & AttribMaxHoriz) ? 3 : 0;
1220
1221   if (client.openbox_hint->flags & AttribOmnipresent)
1222     flags.stuck = (client.openbox_hint->attrib & AttribOmnipresent);
1223
1224   if (client.openbox_hint->flags & AttribWorkspace)
1225     workspace_number = client.openbox_hint->workspace;
1226
1227   // if (client.openbox_hint->flags & AttribStack)
1228   //   don't yet have always on top/bottom for openbox yet... working
1229   //   on that
1230
1231   if (client.openbox_hint->flags & AttribDecoration) {
1232     switch (client.openbox_hint->decoration) {
1233     case DecorNone:
1234       decorations.titlebar = decorations.border = decorations.handle =
1235         decorations.iconify = decorations.maximize =
1236         decorations.menu = False;
1237       functions.resize = functions.move = functions.iconify =
1238         functions.maximize = False;
1239
1240       break;
1241
1242     case DecorTiny:
1243       decorations.titlebar = decorations.iconify = decorations.menu =
1244         functions.move = functions.iconify = True;
1245       decorations.border = decorations.handle = decorations.maximize =
1246         functions.resize = functions.maximize = False;
1247
1248       break;
1249
1250     case DecorTool:
1251       decorations.titlebar = decorations.menu = functions.move = True;
1252       decorations.iconify = decorations.border = decorations.handle =
1253         decorations.maximize = functions.resize = functions.maximize =
1254         functions.iconify = False;
1255
1256       break;
1257
1258     case DecorNormal:
1259     default:
1260       decorations.titlebar = decorations.border = decorations.handle =
1261         decorations.iconify = decorations.maximize =
1262         decorations.menu = True;
1263       functions.resize = functions.move = functions.iconify =
1264         functions.maximize = True;
1265
1266       break;
1267     }
1268
1269     reconfigure();
1270   }
1271 }
1272
1273
1274 void OpenboxWindow::configure(int dx, int dy,
1275                                unsigned int dw, unsigned int dh) {
1276   Bool send_event = (frame.x != dx || frame.y != dy);
1277
1278   if ((dw != frame.width) || (dh != frame.height)) {
1279     if ((((signed) frame.width) + dx) < 0) dx = 0;
1280     if ((((signed) frame.height) + dy) < 0) dy = 0;
1281
1282     frame.x = dx;
1283     frame.y = dy;
1284     frame.width = dw;
1285     frame.height = dh;
1286
1287     downsize();
1288
1289 #ifdef    SHAPE
1290     if (openbox.hasShapeExtensions() && flags.shaped) {
1291       XShapeCombineShape(display, frame.window, ShapeBounding,
1292                          frame.mwm_border_w, frame.y_border +
1293                          frame.mwm_border_w, client.window,
1294                          ShapeBounding, ShapeSet);
1295
1296       int num = 1;
1297       XRectangle xrect[2];
1298       xrect[0].x = xrect[0].y = 0;
1299       xrect[0].width = frame.width;
1300       xrect[0].height = frame.y_border;
1301
1302       if (decorations.handle) {
1303         xrect[1].x = 0;
1304         xrect[1].y = frame.y_handle;
1305         xrect[1].width = frame.width;
1306         xrect[1].height = frame.handle_h + frame.border_w;
1307         num++;
1308       }
1309
1310       XShapeCombineRectangles(display, frame.window, ShapeBounding, 0, 0,
1311                               xrect, num, ShapeUnion, Unsorted);
1312     }
1313 #endif // SHAPE
1314
1315     XMoveWindow(display, frame.window, frame.x, frame.y);
1316
1317     positionWindows();
1318     decorate();
1319     setFocusFlag(flags.focused);
1320     redrawAllButtons();
1321   } else {
1322     frame.x = dx;
1323     frame.y = dy;
1324
1325     XMoveWindow(display, frame.window, frame.x, frame.y);
1326
1327     if (! flags.moving) send_event = True;
1328   }
1329
1330   if (send_event && ! flags.moving) {
1331     client.x = dx + frame.mwm_border_w + frame.border_w;
1332     client.y = dy + frame.y_border + frame.mwm_border_w +
1333                frame.border_w;
1334
1335     XEvent event;
1336     event.type = ConfigureNotify;
1337
1338     event.xconfigure.display = display;
1339     event.xconfigure.event = client.window;
1340     event.xconfigure.window = client.window;
1341     event.xconfigure.x = client.x;
1342     event.xconfigure.y = client.y;
1343     event.xconfigure.width = client.width;
1344     event.xconfigure.height = client.height;
1345     event.xconfigure.border_width = client.old_bw;
1346     event.xconfigure.above = frame.window;
1347     event.xconfigure.override_redirect = False;
1348
1349     XSendEvent(display, client.window, True, NoEventMask, &event);
1350
1351     screen->updateNetizenConfigNotify(&event);
1352   }
1353 }
1354
1355
1356 Bool OpenboxWindow::setInputFocus(void) {
1357   if (((signed) (frame.x + frame.width)) < 0) {
1358     if (((signed) (frame.y + frame.y_border)) < 0)
1359       configure(frame.border_w, frame.border_w, frame.width, frame.height);
1360     else if (frame.y > (signed) screen->size().h())
1361       configure(frame.border_w, screen->size().h() - frame.height,
1362                 frame.width, frame.height);
1363     else
1364       configure(frame.border_w, frame.y + frame.border_w,
1365                 frame.width, frame.height);
1366   } else if (frame.x > (signed) screen->size().w()) {
1367     if (((signed) (frame.y + frame.y_border)) < 0)
1368       configure(screen->size().w() - frame.width, frame.border_w,
1369                 frame.width, frame.height);
1370     else if (frame.y > (signed) screen->size().h())
1371       configure(screen->size().w() - frame.width,
1372                 screen->size().h() - frame.height, frame.width, frame.height);
1373     else
1374       configure(screen->size().w() - frame.width,
1375                 frame.y + frame.border_w, frame.width, frame.height);
1376   }
1377
1378   openbox.grab();
1379   if (! validateClient()) return False;
1380
1381   Bool ret = False;
1382
1383   if (client.transient && flags.modal) {
1384     ret = client.transient->setInputFocus();
1385   } else if (! flags.focused) {
1386     if (focus_mode == F_LocallyActive || focus_mode == F_Passive)
1387       XSetInputFocus(display, client.window,
1388                      RevertToPointerRoot, CurrentTime);
1389     else
1390       XSetInputFocus(display, screen->getRootWindow(),
1391                      RevertToNone, CurrentTime);
1392
1393     openbox.setFocusedWindow(this);
1394
1395     if (flags.send_focus_message) {
1396       XEvent ce;
1397       ce.xclient.type = ClientMessage;
1398       ce.xclient.message_type = openbox.getWMProtocolsAtom();
1399       ce.xclient.display = display;
1400       ce.xclient.window = client.window;
1401       ce.xclient.format = 32;
1402       ce.xclient.data.l[0] = openbox.getWMTakeFocusAtom();
1403       ce.xclient.data.l[1] = openbox.getLastTime();
1404       ce.xclient.data.l[2] = 0l;
1405       ce.xclient.data.l[3] = 0l;
1406       ce.xclient.data.l[4] = 0l;
1407       XSendEvent(display, client.window, False, NoEventMask, &ce);
1408     }
1409
1410     if (screen->sloppyFocus() && screen->autoRaise())
1411       timer->start();
1412
1413     ret = True;
1414   }
1415
1416   openbox.ungrab();
1417
1418   return ret;
1419 }
1420
1421
1422 void OpenboxWindow::iconify(void) {
1423   if (flags.iconic) return;
1424
1425   if (windowmenu) windowmenu->hide();
1426
1427   setState(IconicState);
1428
1429   XSelectInput(display, client.window, NoEventMask);
1430   XUnmapWindow(display, client.window);
1431   XSelectInput(display, client.window,
1432                PropertyChangeMask | StructureNotifyMask | FocusChangeMask);
1433
1434   XUnmapWindow(display, frame.window);
1435   flags.visible = False;
1436   flags.iconic = True;
1437
1438   screen->getWorkspace(workspace_number)->removeWindow(this);
1439
1440   if (flags.transient && client.transient_for &&
1441       !client.transient_for->flags.iconic) {
1442     client.transient_for->iconify();
1443   }
1444   screen->addIcon(this);
1445
1446   if (client.transient && !client.transient->flags.iconic) {
1447     client.transient->iconify();
1448   }
1449 }
1450
1451
1452 void OpenboxWindow::deiconify(Bool reassoc, Bool raise) {
1453   if (flags.iconic || reassoc)
1454     screen->reassociateWindow(this, -1, False);
1455   else if (workspace_number != screen->getCurrentWorkspace()->getWorkspaceID())
1456     return;
1457
1458   setState(NormalState);
1459
1460   XSelectInput(display, client.window, NoEventMask);
1461   XMapWindow(display, client.window);
1462   XSelectInput(display, client.window,
1463                PropertyChangeMask | StructureNotifyMask | FocusChangeMask);
1464
1465   XMapSubwindows(display, frame.window);
1466   XMapWindow(display, frame.window);
1467
1468   if (flags.iconic && screen->focusNew()) setInputFocus();
1469
1470   flags.visible = True;
1471   flags.iconic = False;
1472
1473   if (reassoc && client.transient) client.transient->deiconify(True, False);
1474
1475   if (raise)
1476     screen->getWorkspace(workspace_number)->raiseWindow(this);
1477 }
1478
1479
1480 void OpenboxWindow::close(void) {
1481   XEvent ce;
1482   ce.xclient.type = ClientMessage;
1483   ce.xclient.message_type = openbox.getWMProtocolsAtom();
1484   ce.xclient.display = display;
1485   ce.xclient.window = client.window;
1486   ce.xclient.format = 32;
1487   ce.xclient.data.l[0] = openbox.getWMDeleteAtom();
1488   ce.xclient.data.l[1] = CurrentTime;
1489   ce.xclient.data.l[2] = 0l;
1490   ce.xclient.data.l[3] = 0l;
1491   ce.xclient.data.l[4] = 0l;
1492   XSendEvent(display, client.window, False, NoEventMask, &ce);
1493 }
1494
1495
1496 void OpenboxWindow::withdraw(void) {
1497   flags.visible = False;
1498   flags.iconic = False;
1499
1500   XUnmapWindow(display, frame.window);
1501
1502   XSelectInput(display, client.window, NoEventMask);
1503   XUnmapWindow(display, client.window);
1504   XSelectInput(display, client.window,
1505                PropertyChangeMask | StructureNotifyMask | FocusChangeMask);
1506
1507   if (windowmenu) windowmenu->hide();
1508 }
1509
1510
1511 void OpenboxWindow::maximize(unsigned int button) {
1512   // handle case where menu is open then the max button is used instead
1513   if (windowmenu && windowmenu->isVisible()) windowmenu->hide();
1514
1515   if (flags.maximized) {
1516     flags.maximized = 0;
1517
1518     openbox_attrib.flags &= ! (AttribMaxHoriz | AttribMaxVert);
1519     openbox_attrib.attrib &= ! (AttribMaxHoriz | AttribMaxVert);
1520
1521     // when a resize is begun, maximize(0) is called to clear any maximization
1522     // flags currently set.  Otherwise it still thinks it is maximized.
1523     // so we do not need to call configure() because resizing will handle it
1524     if (!flags.resizing)
1525       configure(openbox_attrib.premax_x, openbox_attrib.premax_y,
1526                 openbox_attrib.premax_w, openbox_attrib.premax_h);
1527
1528     openbox_attrib.premax_x = openbox_attrib.premax_y = 0;
1529     openbox_attrib.premax_w = openbox_attrib.premax_h = 0;
1530
1531     redrawAllButtons();
1532     setState(current_state);
1533     return;
1534   }
1535
1536   // the following code is temporary and will be taken care of by Screen in the
1537   // future (with the NETWM 'strut')
1538   Rect space(0, 0, screen->size().w(), screen->size().h());
1539   if (! screen->fullMax()) {
1540 #ifdef    SLIT
1541     Slit *slit = screen->getSlit();
1542     int slit_x = slit->autoHide() ? slit->hiddenOrigin().x() : slit->area().x(),
1543         slit_y = slit->autoHide() ? slit->hiddenOrigin().y() : slit->area().y();
1544     Toolbar *toolbar = screen->getToolbar();
1545     int tbarh = screen->hideToolbar() ? 0 :
1546       toolbar->getExposedHeight() + screen->getBorderWidth() * 2;
1547     bool tbartop;
1548     switch (toolbar->placement()) {
1549     case Toolbar::TopLeft:
1550     case Toolbar::TopCenter:
1551     case Toolbar::TopRight:
1552       tbartop = true;
1553       break;
1554     case Toolbar::BottomLeft:
1555     case Toolbar::BottomCenter:
1556     case Toolbar::BottomRight:
1557       tbartop = false;
1558       break;
1559     default:
1560       ASSERT(false);      // unhandled placement
1561     }
1562     if ((slit->direction() == Slit::Horizontal &&
1563          (slit->placement() == Slit::TopLeft ||
1564           slit->placement() == Slit::TopRight)) ||
1565         slit->placement() == Slit::TopCenter) {
1566       // exclude top
1567       if (tbartop && slit_y + slit->area().h() < tbarh) {
1568         space.setY(space.y() + tbarh);
1569         space.setH(space.h() - tbarh);
1570       } else {
1571         space.setY(space.y() + (slit_y + slit->area().h() +
1572                                 screen->getBorderWidth() * 2));
1573         space.setH(space.h() - (slit_y + slit->area().h() +
1574                                 screen->getBorderWidth() * 2));
1575         if (!tbartop)
1576           space.setH(space.h() - tbarh);
1577       }
1578     } else if ((slit->direction() == Slit::Vertical &&
1579               (slit->placement() == Slit::TopRight ||
1580                slit->placement() == Slit::BottomRight)) ||
1581              slit->placement() == Slit::CenterRight) {
1582       // exclude right
1583       space.setW(space.w() - (screen->size().w() - slit_x));
1584       if (tbartop)
1585         space.setY(space.y() + tbarh);
1586       space.setH(space.h() - tbarh);
1587     } else if ((slit->direction() == Slit::Horizontal &&
1588               (slit->placement() == Slit::BottomLeft ||
1589                slit->placement() == Slit::BottomRight)) ||
1590              slit->placement() == Slit::BottomCenter) {
1591       // exclude bottom
1592       if (!tbartop && (screen->size().h() - slit_y) < tbarh) {
1593         space.setH(space.h() - tbarh);
1594       } else {
1595         space.setH(space.h() - (screen->size().h() - slit_y));
1596         if (tbartop) {
1597           space.setY(space.y() + tbarh);
1598           space.setH(space.h() - tbarh);
1599         }
1600       }
1601     } else {// if ((slit->direction() == Slit::Vertical &&
1602       //      (slit->placement() == Slit::TopLeft ||
1603       //       slit->placement() == Slit::BottomLeft)) ||
1604       //     slit->placement() == Slit::CenterLeft)
1605       // exclude left
1606       space.setX(slit_x + slit->area().w() +
1607                  screen->getBorderWidth() * 2);
1608       space.setW(space.w() - (slit_x + slit->area().w() +
1609                               screen->getBorderWidth() * 2));
1610       if (tbartop)
1611         space.setY(space.y() + tbarh);
1612       space.setH(space.h() - tbarh);
1613     }
1614 #else // !SLIT
1615     Toolbar *toolbar = screen->getToolbar();
1616     int tbarh = screen->hideToolbar() ? 0 :
1617       toolbar->getExposedHeight() + screen->getBorderWidth() * 2;
1618     switch (toolbar->placement()) {
1619     case Toolbar::TopLeft:
1620     case Toolbar::TopCenter:
1621     case Toolbar::TopRight:
1622       space.setY(toolbar->getExposedHeight());
1623       space.setH(space.h() - toolbar->getExposedHeight());
1624       break;
1625     case Toolbar::BottomLeft:
1626     case Toolbar::BottomCenter:
1627     case Toolbar::BottomRight:
1628       space.setH(space.h() - tbarh);
1629       break;
1630     default:
1631       ASSERT(false);      // unhandled placement
1632     }
1633 #endif // SLIT
1634   }
1635
1636   openbox_attrib.premax_x = frame.x;
1637   openbox_attrib.premax_y = frame.y;
1638   openbox_attrib.premax_w = frame.width;
1639   openbox_attrib.premax_h = frame.height;
1640
1641   unsigned int dw = space.w(),
1642                dh = space.h();
1643   dw -= frame.border_w * 2;
1644   dw -= frame.mwm_border_w * 2;
1645   dw -= client.base_width;
1646
1647   dh -= frame.border_w * 2;
1648   dh -= frame.mwm_border_w * 2;
1649   dh -= ((frame.handle_h + frame.border_w) * decorations.handle);
1650   dh -= client.base_height;
1651   dh -= frame.y_border;
1652
1653   if (dw < client.min_width) dw = client.min_width;
1654   if (dh < client.min_height) dh = client.min_height;
1655   if (dw > client.max_width) dw = client.max_width;
1656   if (dh > client.max_height) dh = client.max_height;
1657
1658   dw -= (dw % client.width_inc);
1659   dw += client.base_width;
1660   dw += frame.mwm_border_w * 2;
1661
1662   dh -= (dh % client.height_inc);
1663   dh += client.base_height;
1664   dh += frame.y_border;
1665   dh += ((frame.handle_h + frame.border_w) * decorations.handle);
1666   dh += frame.mwm_border_w * 2;
1667
1668   int dx = space.x() + ((space.w() - dw) / 2) - frame.border_w,
1669       dy = space.y() + ((space.h() - dh) / 2) - frame.border_w;
1670
1671   switch(button) {
1672   case 1:
1673     openbox_attrib.flags |= AttribMaxHoriz | AttribMaxVert;
1674     openbox_attrib.attrib |= AttribMaxHoriz | AttribMaxVert;
1675     break;
1676
1677   case 2:
1678     openbox_attrib.flags |= AttribMaxVert;
1679     openbox_attrib.attrib |= AttribMaxVert;
1680
1681     dw = frame.width;
1682     dx = frame.x;
1683     break;
1684
1685   case 3:
1686     openbox_attrib.flags |= AttribMaxHoriz;
1687     openbox_attrib.attrib |= AttribMaxHoriz;
1688
1689     dh = frame.height;
1690     dy = frame.y;
1691     break;
1692   }
1693
1694   if (flags.shaded) {
1695     openbox_attrib.flags ^= AttribShaded;
1696     openbox_attrib.attrib ^= AttribShaded;
1697     flags.shaded = False;
1698   }
1699
1700   flags.maximized = button;
1701
1702   configure(dx, dy, dw, dh);
1703   screen->getWorkspace(workspace_number)->raiseWindow(this);
1704   redrawAllButtons();
1705   setState(current_state);
1706 }
1707
1708
1709 void OpenboxWindow::setWorkspace(int n) {
1710   workspace_number = n;
1711
1712   openbox_attrib.flags |= AttribWorkspace;
1713   openbox_attrib.workspace = workspace_number;
1714 }
1715
1716
1717 void OpenboxWindow::shade(void) {
1718   if (!decorations.titlebar)
1719     return;
1720
1721   if (flags.shaded) {
1722     XResizeWindow(display, frame.window, frame.width, frame.height);
1723     flags.shaded = False;
1724     openbox_attrib.flags ^= AttribShaded;
1725     openbox_attrib.attrib ^= AttribShaded;
1726
1727     setState(NormalState);
1728   } else {
1729     XResizeWindow(display, frame.window, frame.width, frame.title_h);
1730     flags.shaded = True;
1731     openbox_attrib.flags |= AttribShaded;
1732     openbox_attrib.attrib |= AttribShaded;
1733
1734     setState(IconicState);
1735   }
1736 }
1737
1738
1739 void OpenboxWindow::stick(void) {
1740   if (flags.stuck) {
1741     openbox_attrib.flags ^= AttribOmnipresent;
1742     openbox_attrib.attrib ^= AttribOmnipresent;
1743
1744     flags.stuck = False;
1745
1746     if (! flags.iconic)
1747       screen->reassociateWindow(this, -1, True);
1748
1749     setState(current_state);
1750   } else {
1751     flags.stuck = True;
1752
1753     openbox_attrib.flags |= AttribOmnipresent;
1754     openbox_attrib.attrib |= AttribOmnipresent;
1755
1756     setState(current_state);
1757   }
1758 }
1759
1760
1761 void OpenboxWindow::setFocusFlag(Bool focus) {
1762   flags.focused = focus;
1763
1764   if (decorations.titlebar) {
1765     if (flags.focused) {
1766       if (frame.ftitle)
1767         XSetWindowBackgroundPixmap(display, frame.title, frame.ftitle);
1768       else
1769         XSetWindowBackground(display, frame.title, frame.ftitle_pixel);
1770     } else {
1771       if (frame.utitle)
1772         XSetWindowBackgroundPixmap(display, frame.title, frame.utitle);
1773       else
1774         XSetWindowBackground(display, frame.title, frame.utitle_pixel);
1775     }
1776     XClearWindow(display, frame.title);
1777
1778     redrawLabel();
1779     redrawAllButtons();
1780   }
1781
1782   if (decorations.handle) {
1783     if (flags.focused) {
1784       if (frame.fhandle)
1785         XSetWindowBackgroundPixmap(display, frame.handle, frame.fhandle);
1786       else
1787         XSetWindowBackground(display, frame.handle, frame.fhandle_pixel);
1788
1789       if (frame.fgrip) {
1790         XSetWindowBackgroundPixmap(display, frame.right_grip, frame.fgrip);
1791         XSetWindowBackgroundPixmap(display, frame.left_grip, frame.fgrip);
1792       } else {
1793         XSetWindowBackground(display, frame.right_grip, frame.fgrip_pixel);
1794         XSetWindowBackground(display, frame.left_grip, frame.fgrip_pixel);
1795       }
1796     } else {
1797       if (frame.uhandle)
1798         XSetWindowBackgroundPixmap(display, frame.handle, frame.uhandle);
1799       else
1800         XSetWindowBackground(display, frame.handle, frame.uhandle_pixel);
1801
1802       if (frame.ugrip) {
1803         XSetWindowBackgroundPixmap(display, frame.right_grip, frame.ugrip);
1804         XSetWindowBackgroundPixmap(display, frame.left_grip, frame.ugrip);
1805       } else {
1806         XSetWindowBackground(display, frame.right_grip, frame.ugrip_pixel);
1807         XSetWindowBackground(display, frame.left_grip, frame.ugrip_pixel);
1808       }
1809     }
1810     XClearWindow(display, frame.handle);
1811     XClearWindow(display, frame.right_grip);
1812     XClearWindow(display, frame.left_grip);
1813   }
1814
1815   if (decorations.border) {
1816     if (flags.focused)
1817       XSetWindowBorder(display, frame.plate, frame.fborder_pixel);
1818     else
1819       XSetWindowBorder(display, frame.plate, frame.uborder_pixel);
1820   }
1821
1822   if (screen->sloppyFocus() && screen->autoRaise() && timer->isTiming())
1823     timer->stop();
1824 }
1825
1826
1827 void OpenboxWindow::installColormap(Bool install) {
1828   openbox.grab();
1829   if (! validateClient()) return;
1830
1831   int i = 0, ncmap = 0;
1832   Colormap *cmaps = XListInstalledColormaps(display, client.window, &ncmap);
1833   XWindowAttributes wattrib;
1834   if (cmaps) {
1835     if (XGetWindowAttributes(display, client.window, &wattrib)) {
1836       if (install) {
1837         // install the window's colormap
1838         for (i = 0; i < ncmap; i++) {
1839           if (*(cmaps + i) == wattrib.colormap)
1840             // this window is using an installed color map... do not install
1841             install = False;
1842         }
1843         // otherwise, install the window's colormap
1844         if (install)
1845           XInstallColormap(display, wattrib.colormap);
1846       } else {
1847         // uninstall the window's colormap
1848         for (i = 0; i < ncmap; i++) {
1849           if (*(cmaps + i) == wattrib.colormap)
1850             // we found the colormap to uninstall
1851             XUninstallColormap(display, wattrib.colormap);
1852         }
1853       }
1854     }
1855
1856     XFree(cmaps);
1857   }
1858
1859   openbox.ungrab();
1860 }
1861
1862
1863 void OpenboxWindow::setState(unsigned long new_state) {
1864   current_state = new_state;
1865
1866   unsigned long state[2];
1867   state[0] = (unsigned long) current_state;
1868   state[1] = (unsigned long) None;
1869   XChangeProperty(display, client.window, openbox.getWMStateAtom(),
1870                   openbox.getWMStateAtom(), 32, PropModeReplace,
1871                   (unsigned char *) state, 2);
1872
1873   XChangeProperty(display, client.window,
1874                   openbox.getOpenboxAttributesAtom(),
1875                   openbox.getOpenboxAttributesAtom(), 32, PropModeReplace,
1876                   (unsigned char *) &openbox_attrib,
1877                   PropOpenboxAttributesElements);
1878 }
1879
1880
1881 Bool OpenboxWindow::getState(void) {
1882   current_state = 0;
1883
1884   Atom atom_return;
1885   Bool ret = False;
1886   int foo;
1887   unsigned long *state, ulfoo, nitems;
1888
1889   if ((XGetWindowProperty(display, client.window, openbox.getWMStateAtom(),
1890                           0l, 2l, False, openbox.getWMStateAtom(),
1891                           &atom_return, &foo, &nitems, &ulfoo,
1892                           (unsigned char **) &state) != Success) ||
1893       (! state)) {
1894     openbox.ungrab();
1895     return False;
1896   }
1897
1898   if (nitems >= 1) {
1899     current_state = (unsigned long) state[0];
1900
1901     ret = True;
1902   }
1903
1904   XFree((void *) state);
1905
1906   return ret;
1907 }
1908
1909
1910 void OpenboxWindow::setGravityOffsets(void) {
1911   // x coordinates for each gravity type
1912   const int x_west = client.x;
1913   const int x_east = client.x + client.width - frame.width;
1914   const int x_center = client.x + client.width - frame.width/2;
1915   // y coordinates for each gravity type
1916   const int y_north = client.y;
1917   const int y_south = client.y + client.height - frame.height;
1918   const int y_center = client.y + client.height - frame.height/2;
1919
1920   switch (client.win_gravity) {
1921   case NorthWestGravity:
1922   default:
1923     frame.x = x_west;
1924     frame.y = y_north;
1925     break;
1926   case NorthGravity:
1927     frame.x = x_center;
1928     frame.y = y_north;
1929     break;
1930   case NorthEastGravity:
1931     frame.x = x_east;
1932     frame.y = y_north;
1933     break;
1934   case SouthWestGravity:
1935     frame.x = x_west;
1936     frame.y = y_south;
1937     break;
1938   case SouthGravity:
1939     frame.x = x_center;
1940     frame.y = y_south;
1941     break;
1942   case SouthEastGravity:
1943     frame.x = x_east;
1944     frame.y = y_south;
1945     break;
1946   case WestGravity:
1947     frame.x = x_west;
1948     frame.y = y_center;
1949     break;
1950   case EastGravity:
1951     frame.x = x_east;
1952     frame.y = y_center;
1953     break;
1954   case CenterGravity:
1955     frame.x = x_center;
1956     frame.y = y_center;
1957     break;
1958   case ForgetGravity:
1959   case StaticGravity:
1960     frame.x = client.x - frame.mwm_border_w + frame.border_w;
1961     frame.y = client.y - frame.y_border - frame.mwm_border_w - frame.border_w;
1962     break;
1963   }
1964 }
1965
1966
1967 void OpenboxWindow::restoreAttributes(void) {
1968   if (! getState()) current_state = NormalState;
1969
1970   Atom atom_return;
1971   int foo;
1972   unsigned long ulfoo, nitems;
1973
1974   OpenboxAttributes *net;
1975   int ret = XGetWindowProperty(display, client.window,
1976                                openbox.getOpenboxAttributesAtom(), 0l,
1977                                PropOpenboxAttributesElements, False,
1978                                openbox.getOpenboxAttributesAtom(),
1979                                &atom_return, &foo, &nitems, &ulfoo,
1980                                (unsigned char **) &net);
1981   if (ret != Success || !net || nitems != PropOpenboxAttributesElements)
1982     return;
1983
1984   openbox_attrib.flags = net->flags;
1985   openbox_attrib.attrib = net->attrib;
1986   openbox_attrib.decoration = net->decoration;
1987   openbox_attrib.workspace = net->workspace;
1988   openbox_attrib.stack = net->stack;
1989   openbox_attrib.premax_x = net->premax_x;
1990   openbox_attrib.premax_y = net->premax_y;
1991   openbox_attrib.premax_w = net->premax_w;
1992   openbox_attrib.premax_h = net->premax_h;
1993
1994   XFree((void *) net);
1995
1996   if (openbox_attrib.flags & AttribShaded &&
1997       openbox_attrib.attrib & AttribShaded) {
1998     int save_state =
1999       ((current_state == IconicState) ? NormalState : current_state);
2000
2001     flags.shaded = False;
2002     shade();
2003
2004     current_state = save_state;
2005   }
2006
2007   if (((int) openbox_attrib.workspace != screen->getCurrentWorkspaceID()) &&
2008       ((int) openbox_attrib.workspace < screen->getWorkspaceCount())) {
2009     screen->reassociateWindow(this, openbox_attrib.workspace, True);
2010
2011     if (current_state == NormalState) current_state = WithdrawnState;
2012   } else if (current_state == WithdrawnState) {
2013     current_state = NormalState;
2014   }
2015
2016   if (openbox_attrib.flags & AttribOmnipresent &&
2017       openbox_attrib.attrib & AttribOmnipresent) {
2018     flags.stuck = False;
2019     stick();
2020
2021     current_state = NormalState;
2022   }
2023
2024   if ((openbox_attrib.flags & AttribMaxHoriz) ||
2025       (openbox_attrib.flags & AttribMaxVert)) {
2026     int x = openbox_attrib.premax_x, y = openbox_attrib.premax_y;
2027     unsigned int w = openbox_attrib.premax_w, h = openbox_attrib.premax_h;
2028     flags.maximized = 0;
2029
2030     unsigned int m = False;
2031     if ((openbox_attrib.flags & AttribMaxHoriz) &&
2032         (openbox_attrib.flags & AttribMaxVert))
2033       m = (openbox_attrib.attrib & (AttribMaxHoriz | AttribMaxVert)) ? 1 : 0;
2034     else if (openbox_attrib.flags & AttribMaxVert)
2035       m = (openbox_attrib.attrib & AttribMaxVert) ? 2 : 0;
2036     else if (openbox_attrib.flags & AttribMaxHoriz)
2037       m = (openbox_attrib.attrib & AttribMaxHoriz) ? 3 : 0;
2038
2039     if (m) maximize(m);
2040
2041     openbox_attrib.premax_x = x;
2042     openbox_attrib.premax_y = y;
2043     openbox_attrib.premax_w = w;
2044     openbox_attrib.premax_h = h;
2045   }
2046
2047   setState(current_state);
2048 }
2049
2050
2051 /*
2052  * The reverse of the setGravityOffsets function. Uses the frame window's
2053  * position to find the window's reference point.
2054  */
2055 void OpenboxWindow::restoreGravity(void) {
2056   // x coordinates for each gravity type
2057   const int x_west = frame.x;
2058   const int x_east = frame.x + frame.width - client.width;
2059   const int x_center = frame.x + (frame.width/2) - client.width;
2060   // y coordinates for each gravity type
2061   const int y_north = frame.y;
2062   const int y_south = frame.y + frame.height - client.height;
2063   const int y_center = frame.y + (frame.height/2) - client.height;
2064
2065   switch(client.win_gravity) {
2066   default:
2067   case NorthWestGravity:
2068     client.x = x_west;
2069     client.y = y_north;
2070     break;
2071   case NorthGravity:
2072     client.x = x_center;
2073     client.y = y_north;
2074     break;
2075   case NorthEastGravity:
2076     client.x = x_east;
2077     client.y = y_north;
2078     break;
2079   case SouthWestGravity:
2080     client.x = x_west;
2081     client.y = y_south;
2082     break;
2083   case SouthGravity:
2084     client.x = x_center;
2085     client.y = y_south;
2086     break;
2087   case SouthEastGravity:
2088     client.x = x_east;
2089     client.y = y_south;
2090     break;
2091   case WestGravity:
2092     client.x = x_west;
2093     client.y = y_center;
2094     break;
2095   case EastGravity:
2096     client.x = x_east;
2097     client.y = y_center;
2098     break;
2099   case CenterGravity:
2100     client.x = x_center;
2101     client.y = y_center;
2102     break;
2103   case ForgetGravity:
2104   case StaticGravity:
2105     client.x = frame.x + frame.mwm_border_w + frame.border_w;
2106     client.y = frame.y + frame.y_border + frame.mwm_border_w +
2107       frame.border_w;
2108     break;
2109   }
2110 }
2111
2112
2113 void OpenboxWindow::redrawLabel(void) {
2114   int dx = frame.bevel_w * 2, dlen = client.title_len;
2115   unsigned int l = client.title_text_w;
2116
2117   if (flags.focused) {
2118     if (frame.flabel)
2119       XSetWindowBackgroundPixmap(display, frame.label, frame.flabel);
2120     else
2121       XSetWindowBackground(display, frame.label, frame.flabel_pixel);
2122   } else {
2123     if (frame.ulabel)
2124       XSetWindowBackgroundPixmap(display, frame.label, frame.ulabel);
2125     else
2126       XSetWindowBackground(display, frame.label, frame.ulabel_pixel);
2127   }
2128   XClearWindow(display, frame.label);
2129
2130   if (client.title_text_w > frame.label_w) {
2131     for (; dlen >= 0; dlen--) {
2132       if (i18n->multibyte()) {
2133         XRectangle ink, logical;
2134         XmbTextExtents(screen->getWindowStyle()->fontset, client.title, dlen,
2135                        &ink, &logical);
2136         l = logical.width;
2137       } else {
2138         l = XTextWidth(screen->getWindowStyle()->font, client.title, dlen);
2139       }
2140       l += (frame.bevel_w * 4);
2141
2142       if (l < frame.label_w)
2143         break;
2144     }
2145   }
2146
2147   switch (screen->getWindowStyle()->justify) {
2148   case BScreen::RightJustify:
2149     dx += frame.label_w - l;
2150     break;
2151
2152   case BScreen::CenterJustify:
2153     dx += (frame.label_w - l) / 2;
2154     break;
2155   }
2156
2157   WindowStyle *style = screen->getWindowStyle();
2158   GC text_gc = (flags.focused) ? style->l_text_focus_gc :
2159     style->l_text_unfocus_gc;
2160   if (i18n->multibyte())
2161     XmbDrawString(display, frame.label, style->fontset, text_gc, dx,
2162                   (1 - style->fontset_extents->max_ink_extent.y),
2163                   client.title, dlen);
2164   else
2165     XDrawString(display, frame.label, text_gc, dx,
2166                 (style->font->ascent + 1), client.title, dlen);
2167 }
2168
2169
2170 void OpenboxWindow::redrawAllButtons(void) {
2171   if (frame.iconify_button) redrawIconifyButton(False);
2172   if (frame.maximize_button) redrawMaximizeButton(flags.maximized);
2173   if (frame.close_button) redrawCloseButton(False);
2174 }
2175
2176
2177 void OpenboxWindow::redrawIconifyButton(Bool pressed) {
2178   if (! pressed) {
2179     if (flags.focused) {
2180       if (frame.fbutton)
2181         XSetWindowBackgroundPixmap(display, frame.iconify_button,
2182                                    frame.fbutton);
2183       else
2184         XSetWindowBackground(display, frame.iconify_button,
2185                              frame.fbutton_pixel);
2186     } else {
2187       if (frame.ubutton)
2188         XSetWindowBackgroundPixmap(display, frame.iconify_button,
2189                                    frame.ubutton);
2190       else
2191         XSetWindowBackground(display, frame.iconify_button,
2192                              frame.ubutton_pixel);
2193     }
2194   } else {
2195     if (frame.pbutton)
2196       XSetWindowBackgroundPixmap(display, frame.iconify_button, frame.pbutton);
2197     else
2198       XSetWindowBackground(display, frame.iconify_button, frame.pbutton_pixel);
2199   }
2200   XClearWindow(display, frame.iconify_button);
2201
2202   XDrawRectangle(display, frame.iconify_button,
2203                  ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc :
2204                   screen->getWindowStyle()->b_pic_unfocus_gc),
2205                  2, (frame.button_h - 5), (frame.button_w - 5), 2);
2206 }
2207
2208
2209 void OpenboxWindow::redrawMaximizeButton(Bool pressed) {
2210   if (! pressed) {
2211     if (flags.focused) {
2212       if (frame.fbutton)
2213         XSetWindowBackgroundPixmap(display, frame.maximize_button,
2214                                    frame.fbutton);
2215       else
2216         XSetWindowBackground(display, frame.maximize_button,
2217                              frame.fbutton_pixel);
2218     } else {
2219       if (frame.ubutton)
2220         XSetWindowBackgroundPixmap(display, frame.maximize_button,
2221                                    frame.ubutton);
2222       else
2223         XSetWindowBackground(display, frame.maximize_button,
2224                              frame.ubutton_pixel);
2225     }
2226   } else {
2227     if (frame.pbutton)
2228       XSetWindowBackgroundPixmap(display, frame.maximize_button,
2229                                  frame.pbutton);
2230     else
2231       XSetWindowBackground(display, frame.maximize_button,
2232                            frame.pbutton_pixel);
2233   }
2234   XClearWindow(display, frame.maximize_button);
2235
2236   XDrawRectangle(display, frame.maximize_button,
2237                  ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc :
2238                   screen->getWindowStyle()->b_pic_unfocus_gc),
2239                  2, 2, (frame.button_w - 5), (frame.button_h - 5));
2240   XDrawLine(display, frame.maximize_button,
2241             ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc :
2242              screen->getWindowStyle()->b_pic_unfocus_gc),
2243             2, 3, (frame.button_w - 3), 3);
2244 }
2245
2246
2247 void OpenboxWindow::redrawCloseButton(Bool pressed) {
2248   if (! pressed) {
2249     if (flags.focused) {
2250       if (frame.fbutton)
2251         XSetWindowBackgroundPixmap(display, frame.close_button,
2252                                    frame.fbutton);
2253       else
2254         XSetWindowBackground(display, frame.close_button,
2255                              frame.fbutton_pixel);
2256     } else {
2257       if (frame.ubutton)
2258         XSetWindowBackgroundPixmap(display, frame.close_button,
2259                                    frame.ubutton);
2260       else
2261         XSetWindowBackground(display, frame.close_button,
2262                              frame.ubutton_pixel);
2263     }
2264   } else {
2265     if (frame.pbutton)
2266       XSetWindowBackgroundPixmap(display, frame.close_button, frame.pbutton);
2267     else
2268       XSetWindowBackground(display, frame.close_button, frame.pbutton_pixel);
2269   }
2270   XClearWindow(display, frame.close_button);
2271
2272   XDrawLine(display, frame.close_button,
2273             ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc :
2274              screen->getWindowStyle()->b_pic_unfocus_gc), 2, 2,
2275             (frame.button_w - 3), (frame.button_h - 3));
2276   XDrawLine(display, frame.close_button,
2277             ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc :
2278              screen->getWindowStyle()->b_pic_unfocus_gc), 2,
2279             (frame.button_h - 3),
2280             (frame.button_w - 3), 2);
2281 }
2282
2283
2284 void OpenboxWindow::mapRequestEvent(XMapRequestEvent *re) {
2285   if (re->window == client.window) {
2286 #ifdef    DEBUG
2287     fprintf(stderr, i18n->getMessage(WindowSet, WindowMapRequest,
2288                              "OpenboxWindow::mapRequestEvent() for 0x%lx\n"),
2289             client.window);
2290 #endif // DEBUG
2291
2292     openbox.grab();
2293     if (! validateClient()) return;
2294
2295     Bool get_state_ret = getState();
2296     if (! (get_state_ret && openbox.isStartup())) {
2297       if ((client.wm_hint_flags & StateHint) &&
2298           (! (current_state == NormalState || current_state == IconicState)))
2299         current_state = client.initial_state;
2300       else
2301         current_state = NormalState;
2302     } else if (flags.iconic) {
2303       current_state = NormalState;
2304     }
2305
2306     switch (current_state) {
2307     case IconicState:
2308       iconify();
2309       break;
2310
2311     case WithdrawnState:
2312       withdraw();
2313       break;
2314
2315     case NormalState:
2316     case InactiveState:
2317     case ZoomState:
2318     default:
2319       deiconify(False);
2320       break;
2321     }
2322
2323     openbox.ungrab();
2324   }
2325 }
2326
2327
2328 void OpenboxWindow::mapNotifyEvent(XMapEvent *ne) {
2329   if ((ne->window == client.window) && (! ne->override_redirect)
2330       && (flags.visible)) {
2331     openbox.grab();
2332     if (! validateClient()) return;
2333
2334     if (decorations.titlebar) positionButtons();
2335
2336     setState(NormalState);
2337
2338     redrawAllButtons();
2339
2340     if (flags.transient || screen->focusNew())
2341       setInputFocus();
2342     else
2343       setFocusFlag(False);
2344
2345     flags.visible = True;
2346     flags.iconic = False;
2347
2348     openbox.ungrab();
2349   }
2350 }
2351
2352
2353 void OpenboxWindow::unmapNotifyEvent(XUnmapEvent *ue) {
2354   if (ue->window == client.window) {
2355 #ifdef    DEBUG
2356     fprintf(stderr, i18n->getMessage(WindowSet, WindowUnmapNotify,
2357                              "OpenboxWindow::unmapNotifyEvent() for 0x%lx\n"),
2358             client.window);
2359 #endif // DEBUG
2360
2361     openbox.grab();
2362     if (! validateClient()) return;
2363
2364     XChangeSaveSet(display, client.window, SetModeDelete);
2365     XSelectInput(display, client.window, NoEventMask);
2366
2367     XDeleteProperty(display, client.window, openbox.getWMStateAtom());
2368     XDeleteProperty(display, client.window,
2369                     openbox.getOpenboxAttributesAtom());
2370
2371     XUnmapWindow(display, frame.window);
2372     XUnmapWindow(display, client.window);
2373
2374     XEvent dummy;
2375     if (! XCheckTypedWindowEvent(display, client.window, ReparentNotify,
2376                                  &dummy)) {
2377 #ifdef    DEBUG
2378       fprintf(stderr, i18n->getMessage(WindowSet, WindowUnmapNotifyReparent,
2379                        "OpenboxWindow::unmapNotifyEvent(): reparent 0x%lx to "
2380                        "root.\n"), client.window);
2381 #endif // DEBUG
2382
2383       restoreGravity();
2384       XReparentWindow(display, client.window, screen->getRootWindow(),
2385                       client.x, client.y);
2386     }
2387
2388     XFlush(display);
2389
2390     openbox.ungrab();
2391
2392     delete this;
2393   }
2394 }
2395
2396
2397 void OpenboxWindow::destroyNotifyEvent(XDestroyWindowEvent *de) {
2398   if (de->window == client.window) {
2399     XUnmapWindow(display, frame.window);
2400
2401     delete this;
2402   }
2403 }
2404
2405
2406 void OpenboxWindow::propertyNotifyEvent(Atom atom) {
2407   openbox.grab();
2408   if (! validateClient()) return;
2409
2410   switch(atom) {
2411   case XA_WM_CLASS:
2412   case XA_WM_CLIENT_MACHINE:
2413   case XA_WM_COMMAND:
2414     break;
2415
2416   case XA_WM_TRANSIENT_FOR:
2417     // determine if this is a transient window
2418     Window win;
2419     if (XGetTransientForHint(display, client.window, &win)) {
2420       if (win && (win != client.window)) {
2421         if ((client.transient_for = openbox.searchWindow(win))) {
2422           client.transient_for->client.transient = this;
2423           flags.stuck = client.transient_for->flags.stuck;
2424           flags.transient = True;
2425         } else if (win == client.window_group) {
2426           //jr This doesn't look quite right...
2427           if ((client.transient_for = openbox.searchGroup(win, this))) {
2428             client.transient_for->client.transient = this;
2429             flags.stuck = client.transient_for->flags.stuck;
2430             flags.transient = True;
2431           }
2432         }
2433       }
2434
2435       if (win == screen->getRootWindow()) flags.modal = True;
2436     }
2437
2438     // adjust the window decorations based on transience
2439     if (flags.transient)
2440       decorations.maximize = decorations.handle = functions.maximize = False;
2441
2442     reconfigure();
2443
2444     break;
2445
2446   case XA_WM_HINTS:
2447     getWMHints();
2448     break;
2449
2450   case XA_WM_ICON_NAME:
2451     getWMIconName();
2452     if (flags.iconic) screen->iconUpdate();
2453     break;
2454
2455   case XA_WM_NAME:
2456     getWMName();
2457
2458     if (decorations.titlebar)
2459       redrawLabel();
2460
2461     if (! flags.iconic)
2462       screen->getWorkspace(workspace_number)->update();
2463
2464     break;
2465
2466   case XA_WM_NORMAL_HINTS: {
2467     getWMNormalHints();
2468
2469     if ((client.normal_hint_flags & PMinSize) &&
2470         (client.normal_hint_flags & PMaxSize)) {
2471       if (client.max_width <= client.min_width &&
2472           client.max_height <= client.min_height)
2473         decorations.maximize = decorations.handle =
2474             functions.resize = functions.maximize = False;
2475       else
2476         decorations.maximize = decorations.handle =
2477             functions.resize = functions.maximize = True;
2478     }
2479
2480     int x = frame.x, y = frame.y;
2481     unsigned int w = frame.width, h = frame.height;
2482
2483     upsize();
2484
2485     if ((x != frame.x) || (y != frame.y) ||
2486         (w != frame.width) || (h != frame.height))
2487       reconfigure();
2488
2489     break;
2490   }
2491
2492   default:
2493     if (atom == openbox.getWMProtocolsAtom()) {
2494       getWMProtocols();
2495
2496       if (decorations.close && (! frame.close_button)) {
2497         createCloseButton();
2498         if (decorations.titlebar) positionButtons(True);
2499         if (windowmenu) windowmenu->reconfigure();
2500       }
2501     }
2502
2503     break;
2504   }
2505
2506   openbox.ungrab();
2507 }
2508
2509
2510 void OpenboxWindow::exposeEvent(XExposeEvent *ee) {
2511   if (frame.label == ee->window && decorations.titlebar)
2512     redrawLabel();
2513   else if (frame.close_button == ee->window)
2514     redrawCloseButton(False);
2515   else if (frame.maximize_button == ee->window)
2516     redrawMaximizeButton(flags.maximized);
2517   else if (frame.iconify_button == ee->window)
2518     redrawIconifyButton(False);
2519 }
2520
2521
2522 void OpenboxWindow::configureRequestEvent(XConfigureRequestEvent *cr) {
2523   if (cr->window == client.window) {
2524     openbox.grab();
2525     if (! validateClient()) return;
2526
2527     int cx = frame.x, cy = frame.y;
2528     unsigned int cw = frame.width, ch = frame.height;
2529
2530     if (cr->value_mask & CWBorderWidth)
2531       client.old_bw = cr->border_width;
2532
2533     if (cr->value_mask & CWX)
2534       cx = cr->x - frame.mwm_border_w - frame.border_w;
2535
2536     if (cr->value_mask & CWY)
2537       cy = cr->y - frame.y_border - frame.mwm_border_w -
2538         frame.border_w;
2539
2540     if (cr->value_mask & CWWidth)
2541       cw = cr->width + (frame.mwm_border_w * 2);
2542
2543     if (cr->value_mask & CWHeight)
2544       ch = cr->height + frame.y_border + (frame.mwm_border_w * 2) +
2545         (frame.border_w * decorations.handle) + frame.handle_h;
2546
2547     if (frame.x != cx || frame.y != cy ||
2548         frame.width != cw || frame.height != ch)
2549       configure(cx, cy, cw, ch);
2550
2551     if (cr->value_mask & CWStackMode) {
2552       switch (cr->detail) {
2553       case Above:
2554       case TopIf:
2555       default:
2556         if (flags.iconic) deiconify();
2557         screen->getWorkspace(workspace_number)->raiseWindow(this);
2558         break;
2559
2560       case Below:
2561       case BottomIf:
2562         if (flags.iconic) deiconify();
2563         screen->getWorkspace(workspace_number)->lowerWindow(this);
2564         break;
2565       }
2566     }
2567
2568     openbox.ungrab();
2569   }
2570 }
2571
2572
2573 void OpenboxWindow::buttonPressEvent(XButtonEvent *be) {
2574   openbox.grab();
2575   if (! validateClient())
2576     return;
2577
2578   int stack_change = 1; // < 0 means to lower the window
2579                         // > 0 means to raise the window
2580                         // 0 means to leave it where it is
2581   
2582   // alt + left/right click begins interactively moving/resizing the window
2583   // when the mouse is moved
2584   if (be->state == Mod1Mask && (be->button == 1 || be->button == 3)) {
2585     frame.grab_x = be->x_root - frame.x - frame.border_w;
2586     frame.grab_y = be->y_root - frame.y - frame.border_w;
2587     if (be->button == 3) {
2588       if (screen->getWindowZones() == 4 &&
2589           be->y < (signed) frame.height / 2) {
2590         resize_zone = ZoneTop;
2591       } else {
2592         resize_zone = ZoneBottom;
2593       }
2594       if (screen->getWindowZones() >= 2 &&
2595           be->x < (signed) frame.width / 2) {
2596         resize_zone |= ZoneLeft;
2597       } else {
2598         resize_zone |= ZoneRight;
2599       }
2600     }
2601   // control + left click on the titlebar shades the window
2602   } else if (be->state == ControlMask && be->button == 1) {
2603     if (be->window == frame.title ||
2604         be->window == frame.label)
2605       shade();
2606   // left click
2607   } else if (be->state == 0 && be->button == 1) {
2608     if (windowmenu && windowmenu->isVisible())
2609         windowmenu->hide();
2610
2611     if (be->window == frame.maximize_button) {
2612       redrawMaximizeButton(True);
2613     } else if (be->window == frame.iconify_button) {
2614       redrawIconifyButton(True);
2615     } else if (be->window == frame.close_button) {
2616       redrawCloseButton(True);
2617     } else if (be->window == frame.plate) {
2618       XAllowEvents(display, ReplayPointer, be->time);
2619     } else if (be->window == frame.title ||
2620                be->window == frame.label) {
2621       // shade the window when the titlebar is double clicked
2622       if ( (be->time - lastButtonPressTime) <=
2623             openbox.getDoubleClickInterval()) {
2624         lastButtonPressTime = 0;
2625         shade();
2626       } else {
2627         lastButtonPressTime = be->time;
2628       }
2629       // clicking and dragging on the titlebar moves the window, so on a click
2630       // we need to save the coords of the click in case the user drags
2631       frame.grab_x = be->x_root - frame.x - frame.border_w;
2632       frame.grab_y = be->y_root - frame.y - frame.border_w;
2633     } else if (be->window == frame.handle ||
2634                be->window == frame.left_grip ||
2635                be->window == frame.right_grip ||
2636                be->window == frame.window) {
2637       // clicking and dragging on the window's frame moves the window, so on a
2638       // click we need to save the coords of the click in case the user drags
2639       frame.grab_x = be->x_root - frame.x - frame.border_w;
2640       frame.grab_y = be->y_root - frame.y - frame.border_w;
2641       if (be->window == frame.left_grip)
2642         resize_zone = ZoneBottom | ZoneLeft;
2643       else if (be->window == frame.right_grip)
2644         resize_zone = ZoneBottom | ZoneRight;
2645     }
2646   // middle click
2647   } else if (be->state == 0 && be->button == 2) {
2648     if (be->window == frame.maximize_button) {
2649       redrawMaximizeButton(True);
2650     // a middle click anywhere on the window's frame except for on the buttons
2651     // will lower the window
2652     } else if (! (be->window == frame.iconify_button ||
2653                   be->window == frame.close_button) ) {
2654       stack_change = -1;
2655     }
2656   // right click
2657   } else if (be->state == 0 && be->button == 3) {
2658     if (be->window == frame.maximize_button) {
2659       redrawMaximizeButton(True);
2660     // a right click on the window's frame will show or hide the window's
2661     // windowmenu
2662     } else if (be->window == frame.title ||
2663                be->window == frame.label ||
2664                be->window == frame.handle ||
2665                be->window == frame.window) {
2666       int mx, my;
2667       if (windowmenu) {
2668         if (windowmenu->isVisible()) {
2669           windowmenu->hide();
2670         } else {
2671           // get the coords for the menu
2672           mx = be->x_root - windowmenu->getWidth() / 2;
2673           if (be->window == frame.title || be->window == frame.label) {
2674             my = frame.y + frame.title_h;
2675           } else if (be->window = frame.handle) {
2676             my = frame.y + frame.y_handle - windowmenu->getHeight();
2677           } else { // (be->window == frame.window)
2678             if (be->y <= (signed) frame.bevel_w) {
2679               my = frame.y + frame.y_border;
2680             } else {
2681               my = be->y_root - (windowmenu->getHeight() / 2);
2682             }
2683           }
2684
2685           if (mx > (signed) (frame.x + frame.width -
2686               windowmenu->getWidth())) {
2687             mx = frame.x + frame.width - windowmenu->getWidth();
2688           } else if (mx < frame.x) {
2689             mx = frame.x;
2690           }
2691
2692           if (my > (signed) (frame.y + frame.y_handle -
2693                 windowmenu->getHeight())) {
2694             my = frame.y + frame.y_handle - windowmenu->getHeight();
2695           } else if (my < (signed) (frame.y +
2696               ((decorations.titlebar) ? frame.title_h : frame.y_border))) {
2697             my = frame.y +
2698               ((decorations.titlebar) ? frame.title_h : frame.y_border);
2699           }
2700
2701           windowmenu->move(mx, my);
2702           windowmenu->show();
2703           XRaiseWindow(display, windowmenu->getWindowID());
2704           XRaiseWindow(display, windowmenu->getSendToMenu()->getWindowID());
2705           stack_change = 0;  // dont raise the window overtop of the menu
2706         }
2707       }
2708     }
2709   // mouse wheel up
2710   } else if (be->state == 0 && be->button == 4) {
2711     if ((be->window == frame.label ||
2712         be->window == frame.title) &&
2713         !flags.shaded)
2714       shade();
2715   // mouse wheel down
2716   } else if (be->state == 0 && be->button == 5) {
2717     if ((be->window == frame.label ||
2718         be->window == frame.title) &&
2719         flags.shaded)
2720       shade();
2721   }
2722
2723   if (! (flags.focused || screen->sloppyFocus()) ) {
2724     setInputFocus();  // any click focus' the window in 'click to focus'
2725   }
2726   if (stack_change < 0) {
2727     screen->getWorkspace(workspace_number)->lowerWindow(this);
2728   } else if (stack_change > 0) {
2729     screen->getWorkspace(workspace_number)->raiseWindow(this);
2730   }
2731  
2732   openbox.ungrab();
2733 }
2734
2735
2736 void OpenboxWindow::buttonReleaseEvent(XButtonEvent *re) {
2737   openbox.grab();
2738   if (! validateClient())
2739     return;
2740
2741   // alt + middle button released
2742   if (re->state == (Mod1Mask & Button2Mask) && re->button == 2) {
2743     if (re->window == frame.window) {
2744       XUngrabPointer(display, CurrentTime); // why? i dont know
2745     }
2746   // left button released
2747   } else if (re->button == 1) {
2748     if (re->window == frame.maximize_button) {
2749       if (re->state == Button1Mask && // only the left button was depressed
2750           (re->x >= 0) && ((unsigned) re->x <= frame.button_w) &&
2751           (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) {
2752         maximize(re->button);
2753       } else {
2754         redrawMaximizeButton(False);
2755       }
2756     } else if (re->window == frame.iconify_button) {
2757       if (re->state == Button1Mask && // only the left button was depressed
2758           (re->x >= 0) && ((unsigned) re->x <= frame.button_w) &&
2759           (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) {
2760         iconify();
2761       } else {
2762         redrawIconifyButton(False);
2763       }
2764     } else if (re->window == frame.close_button) {
2765       if (re->state == Button1Mask && // only the left button was depressed
2766           (re->x >= 0) && ((unsigned) re->x <= frame.button_w) &&
2767           (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) {
2768           close();
2769       }
2770       //we should always redraw the close button. some applications
2771       //eg. acroread don't honour the close.
2772       redrawCloseButton(False);
2773     }
2774   // middle button released
2775   } else if (re->button == 2) {
2776     if (re->window == frame.maximize_button) {
2777       if (re->state == Button2Mask && // only the middle button was depressed
2778           (re->x >= 0) && ((unsigned) re->x <= frame.button_w) &&
2779           (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) {
2780         maximize(re->button);
2781       } else {
2782         redrawMaximizeButton(False);
2783       }
2784     }
2785   // right button released
2786   } else if (re->button == 3) {
2787     if (re->window == frame.maximize_button) {
2788       if (re->state == Button3Mask && // only the right button was depressed
2789           (re->x >= 0) && ((unsigned) re->x <= frame.button_w) &&
2790           (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) {
2791         maximize(re->button);
2792       } else {
2793         redrawMaximizeButton(False);
2794       }
2795     }
2796   }
2797   
2798   // when the window is being interactively moved, a button release stops the
2799   // move where it is
2800   if (flags.moving) {
2801     flags.moving = False;
2802
2803     openbox.maskWindowEvents(0, (OpenboxWindow *) 0);
2804     if (!screen->opaqueMove()) {
2805       XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
2806                      frame.move_x, frame.move_y, frame.resize_w - 1,
2807                      frame.resize_h - 1);
2808
2809       configure(frame.move_x, frame.move_y, frame.width, frame.height);
2810       openbox.ungrab();
2811     } else {
2812       configure(frame.x, frame.y, frame.width, frame.height);
2813     }
2814     screen->hideGeometry();
2815     XUngrabPointer(display, CurrentTime);
2816   // when the window is being interactively resized, a button release stops the
2817   // resizing
2818   } else if (flags.resizing) {
2819     flags.resizing = False;
2820     XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
2821                    frame.resize_x, frame.resize_y,
2822                    frame.resize_w - 1, frame.resize_h - 1);
2823     screen->hideGeometry();
2824     if (resize_zone & ZoneLeft) {
2825       left_fixsize();
2826     } else {  // when resizing with "Alt+Button3", the resize is the same as if
2827               // done with the right grip (the right side of the window is what
2828               // moves)
2829       right_fixsize();
2830     }
2831     // unset maximized state when resized after fully maximized
2832     if (flags.maximized == 1) {
2833         maximize(0);
2834     }
2835     configure(frame.resize_x, frame.resize_y,
2836               frame.resize_w - (frame.border_w * 2),
2837               frame.resize_h - (frame.border_w * 2));
2838     openbox.ungrab();
2839     XUngrabPointer(display, CurrentTime);
2840     resize_zone = 0;
2841   }
2842
2843   openbox.ungrab();
2844 }
2845
2846
2847 void OpenboxWindow::motionNotifyEvent(XMotionEvent *me) {
2848   if (!flags.resizing && (me->state & Button1Mask) && functions.move &&
2849       (frame.title == me->window || frame.label == me->window ||
2850        frame.handle == me->window || frame.window == me->window)) {
2851     if (! flags.moving) {
2852       XGrabPointer(display, me->window, False, Button1MotionMask |
2853                    ButtonReleaseMask, GrabModeAsync, GrabModeAsync,
2854                    None, openbox.getMoveCursor(), CurrentTime);
2855
2856       if (windowmenu && windowmenu->isVisible())
2857         windowmenu->hide();
2858
2859       flags.moving = True;
2860
2861       openbox.maskWindowEvents(client.window, this);
2862
2863       if (! screen->opaqueMove()) {
2864         openbox.grab();
2865
2866         frame.move_x = frame.x;
2867         frame.move_y = frame.y;
2868         frame.resize_w = frame.width + (frame.border_w * 2);
2869         frame.resize_h = ((flags.shaded) ? frame.title_h : frame.height) +
2870           (frame.border_w * 2);
2871
2872         screen->showPosition(frame.x, frame.y);
2873
2874         XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
2875                        frame.move_x, frame.move_y,
2876                        frame.resize_w - 1, frame.resize_h - 1);
2877       }
2878     } else {
2879       int dx = me->x_root - frame.grab_x, dy = me->y_root - frame.grab_y;
2880
2881       dx -= frame.border_w;
2882       dy -= frame.border_w;
2883
2884       int snap_distance = screen->edgeSnapThreshold();
2885       // width/height of the snapping window
2886       unsigned int snap_w = frame.width + (frame.border_w * 2);
2887       unsigned int snap_h = area().h() + (frame.border_w * 2);
2888       if (snap_distance) {
2889         int drx = screen->size().w() - (dx + snap_w);
2890
2891         if (dx < drx && (dx > 0 && dx < snap_distance) ||
2892                         (dx < 0 && dx > -snap_distance) )
2893           dx = 0;
2894         else if ( (drx > 0 && drx < snap_distance) ||
2895                   (drx < 0 && drx > -snap_distance) )
2896           dx = screen->size().w() - snap_w;
2897
2898         int dtty, dbby, dty, dby;
2899         switch (screen->getToolbar()->placement()) {
2900         case Toolbar::TopLeft:
2901         case Toolbar::TopCenter:
2902         case Toolbar::TopRight:
2903           dtty = screen->getToolbar()->getExposedHeight() +
2904                  frame.border_w;
2905           dbby = screen->size().h();
2906           break;
2907
2908         default:
2909           dtty = 0;
2910           dbby = screen->getToolbar()->area().y();
2911           break;
2912         }
2913
2914         dty = dy - dtty;
2915         dby = dbby - (dy + snap_h);
2916
2917         if ( (dy > 0 && dty < snap_distance) ||
2918             (dy < 0 && dty > -snap_distance) )
2919           dy = dtty;
2920         else if ( (dby > 0 && dby < snap_distance) ||
2921                  (dby < 0 && dby > -snap_distance) )
2922           dy = dbby - snap_h;
2923       }
2924
2925       if (screen->opaqueMove()) {
2926         configure(dx, dy, frame.width, frame.height);
2927       } else {
2928         XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
2929                        frame.move_x, frame.move_y, frame.resize_w - 1,
2930                        frame.resize_h - 1);
2931
2932         frame.move_x = dx;
2933         frame.move_y = dy;
2934
2935         XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
2936                        frame.move_x, frame.move_y, frame.resize_w - 1,
2937                        frame.resize_h - 1);
2938       }
2939
2940       screen->showPosition(dx, dy);
2941     }
2942   } else if (functions.resize &&
2943              (((me->state & Button1Mask) && (me->window == frame.right_grip ||
2944                                              me->window == frame.left_grip)) ||
2945               (me->state & (Mod1Mask | Button3Mask) &&
2946                                              me->window == frame.window))) {
2947     Bool left = resize_zone & ZoneLeft;
2948
2949     if (! flags.resizing) {
2950       Cursor cursor;
2951       if (resize_zone & ZoneTop)
2952         cursor = (resize_zone & ZoneLeft) ?
2953           openbox.getUpperLeftAngleCursor() :
2954           openbox.getUpperRightAngleCursor();
2955       else
2956         cursor = (resize_zone & ZoneLeft) ?
2957           openbox.getLowerLeftAngleCursor() :
2958           openbox.getLowerRightAngleCursor();
2959       XGrabPointer(display, me->window, False, ButtonMotionMask |
2960                    ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None,
2961                    cursor, CurrentTime);
2962
2963       flags.resizing = True;
2964
2965       openbox.grab();
2966
2967       int gx, gy;
2968       if (resize_zone & ZoneRight)
2969         frame.grab_x = me->x - screen->getBorderWidth();
2970       else
2971         frame.grab_x = me->x + screen->getBorderWidth();
2972       if (resize_zone & ZoneTop)
2973         frame.grab_y = me->y + screen->getBorderWidth() * 2;
2974       else
2975         frame.grab_y = me->y - screen->getBorderWidth() * 2;
2976       frame.resize_x = frame.x;
2977       frame.resize_y = frame.y;
2978       frame.resize_w = frame.width + (frame.border_w * 2);
2979       frame.resize_h = frame.height + (frame.border_w * 2);
2980
2981       if (left)
2982         left_fixsize(&gx, &gy);
2983       else
2984         right_fixsize(&gx, &gy);
2985
2986       screen->showGeometry(gx, gy);
2987
2988       XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
2989                      frame.resize_x, frame.resize_y,
2990                      frame.resize_w - 1, frame.resize_h - 1);
2991     } else {
2992       XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
2993                      frame.resize_x, frame.resize_y,
2994                      frame.resize_w - 1, frame.resize_h - 1);
2995
2996       int gx, gy;
2997
2998       if (resize_zone & ZoneTop)
2999         frame.resize_h = frame.height - (me->y - frame.grab_y);
3000       else
3001         frame.resize_h = frame.height + (me->y - frame.grab_y);
3002       if (frame.resize_h < 1) frame.resize_h = 1;
3003
3004       if (left) {
3005         frame.resize_x = me->x_root - frame.grab_x;
3006         if (frame.resize_x > (signed) (frame.x + frame.width))
3007           frame.resize_x = frame.resize_x + frame.width - 1;
3008
3009         left_fixsize(&gx, &gy);
3010       } else {
3011         frame.resize_w = frame.width + (me->x - frame.grab_x);
3012         if (frame.resize_w < 1) frame.resize_w = 1;
3013
3014         right_fixsize(&gx, &gy);
3015       }
3016
3017       XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
3018                      frame.resize_x, frame.resize_y,
3019                      frame.resize_w - 1, frame.resize_h - 1);
3020
3021       screen->showGeometry(gx, gy);
3022     }
3023   }
3024 }
3025
3026
3027 #ifdef    SHAPE
3028 void OpenboxWindow::shapeEvent(XShapeEvent *) {
3029   if (openbox.hasShapeExtensions()) {
3030     if (flags.shaped) {
3031       openbox.grab();
3032       if (! validateClient()) return;
3033       XShapeCombineShape(display, frame.window, ShapeBounding,
3034                          frame.mwm_border_w, frame.y_border +
3035                          frame.mwm_border_w, client.window,
3036                          ShapeBounding, ShapeSet);
3037
3038       int num = 1;
3039       XRectangle xrect[2];
3040       xrect[0].x = xrect[0].y = 0;
3041       xrect[0].width = frame.width;
3042       xrect[0].height = frame.y_border;
3043
3044       if (decorations.handle) {
3045         xrect[1].x = 0;
3046         xrect[1].y = frame.y_handle;
3047         xrect[1].width = frame.width;
3048         xrect[1].height = frame.handle_h + frame.border_w;
3049         num++;
3050       }
3051
3052       XShapeCombineRectangles(display, frame.window, ShapeBounding, 0, 0,
3053                               xrect, num, ShapeUnion, Unsorted);
3054       openbox.ungrab();
3055     }
3056   }
3057 }
3058 #endif // SHAPE
3059
3060
3061 Bool OpenboxWindow::validateClient(void) {
3062   XSync(display, False);
3063
3064   XEvent e;
3065   if (XCheckTypedWindowEvent(display, client.window, DestroyNotify, &e) ||
3066       XCheckTypedWindowEvent(display, client.window, UnmapNotify, &e)) {
3067     XPutBackEvent(display, &e);
3068     openbox.ungrab();
3069
3070     return False;
3071   }
3072
3073   return True;
3074 }
3075
3076
3077 void OpenboxWindow::restore(void) {
3078   XChangeSaveSet(display, client.window, SetModeDelete);
3079   XSelectInput(display, client.window, NoEventMask);
3080
3081   restoreGravity();
3082
3083   XUnmapWindow(display, frame.window);
3084   XUnmapWindow(display, client.window);
3085
3086   XSetWindowBorderWidth(display, client.window, client.old_bw);
3087   XReparentWindow(display, client.window, screen->getRootWindow(),
3088                   client.x, client.y);
3089   XMapWindow(display, client.window);
3090
3091   XFlush(display);
3092 }
3093
3094
3095 void OpenboxWindow::timeout(void) {
3096   screen->getWorkspace(workspace_number)->raiseWindow(this);
3097 }
3098
3099
3100 void OpenboxWindow::changeOpenboxHints(OpenboxHints *net) {
3101   if ((net->flags & AttribShaded) &&
3102       ((openbox_attrib.attrib & AttribShaded) !=
3103        (net->attrib & AttribShaded)))
3104     shade();
3105
3106   if (flags.visible && // watch out for requests when we can not be seen
3107       (net->flags & (AttribMaxVert | AttribMaxHoriz)) &&
3108       ((openbox_attrib.attrib & (AttribMaxVert | AttribMaxHoriz)) !=
3109        (net->attrib & (AttribMaxVert | AttribMaxHoriz)))) {
3110     if (flags.maximized) {
3111       maximize(0);
3112     } else {
3113       int button = 0;
3114
3115       if ((net->flags & AttribMaxHoriz) && (net->flags & AttribMaxVert))
3116         button = ((net->attrib & (AttribMaxHoriz | AttribMaxVert)) ?  1 : 0);
3117       else if (net->flags & AttribMaxVert)
3118         button = ((net->attrib & AttribMaxVert) ? 2 : 0);
3119       else if (net->flags & AttribMaxHoriz)
3120         button = ((net->attrib & AttribMaxHoriz) ? 3 : 0);
3121
3122       maximize(button);
3123     }
3124   }
3125
3126   if ((net->flags & AttribOmnipresent) &&
3127       ((openbox_attrib.attrib & AttribOmnipresent) !=
3128        (net->attrib & AttribOmnipresent)))
3129     stick();
3130
3131   if ((net->flags & AttribWorkspace) &&
3132       (workspace_number != (signed) net->workspace)) {
3133     screen->reassociateWindow(this, net->workspace, True);
3134
3135     if (screen->getCurrentWorkspaceID() != (signed) net->workspace) withdraw();
3136     else deiconify();
3137   }
3138
3139   if (net->flags & AttribDecoration) {
3140     switch (net->decoration) {
3141     case DecorNone:
3142       decorations.titlebar = decorations.border = decorations.handle =
3143        decorations.iconify = decorations.maximize = decorations.menu = False;
3144
3145       break;
3146
3147     default:
3148     case DecorNormal:
3149       decorations.titlebar = decorations.border = decorations.handle =
3150        decorations.iconify = decorations.maximize = decorations.menu = True;
3151
3152       break;
3153
3154     case DecorTiny:
3155       decorations.titlebar = decorations.iconify = decorations.menu = True;
3156       decorations.border = decorations.handle = decorations.maximize = False;
3157  
3158       break;
3159
3160     case DecorTool:
3161       decorations.titlebar = decorations.menu = functions.move = True;
3162       decorations.iconify = decorations.border = decorations.handle =
3163         decorations.maximize = False;
3164
3165       break;
3166     }
3167     if (frame.window) {
3168       XMapSubwindows(display, frame.window);
3169       XMapWindow(display, frame.window);
3170     }
3171
3172     reconfigure();
3173     setState(current_state);
3174   }
3175 }
3176
3177
3178 /*
3179  * Set the sizes of all components of the window frame
3180  * (the window decorations).
3181  * These values are based upon the current style settings and the client
3182  * window's dimentions.
3183  */
3184 void OpenboxWindow::upsize(void) {
3185   frame.bevel_w = screen->getBevelWidth();
3186
3187   if (decorations.border) {
3188     frame.border_w = screen->getBorderWidth();
3189     if (!flags.transient)
3190       frame.mwm_border_w = screen->getFrameWidth();
3191     else
3192       frame.mwm_border_w = 0;
3193   } else {
3194     frame.mwm_border_w = frame.border_w = 0;
3195   }
3196
3197   if (decorations.titlebar) {
3198     // the height of the titlebar is based upon the height of the font being
3199     // used to display the window's title
3200     WindowStyle *style = screen->getWindowStyle();
3201     if (i18n->multibyte())
3202       frame.title_h = (style->fontset_extents->max_ink_extent.height +
3203                        (frame.bevel_w * 2) + 2);
3204     else
3205       frame.title_h = (style->font->ascent + style->font->descent +
3206                        (frame.bevel_w * 2) + 2);
3207
3208     frame.label_h = frame.title_h - (frame.bevel_w * 2);
3209     frame.button_w = frame.button_h = (frame.label_h - 2);
3210     frame.y_border = frame.title_h + frame.border_w;
3211   } else {
3212     frame.title_h = 0;
3213     frame.label_h = 0;
3214     frame.button_w = frame.button_h = 0;
3215     frame.y_border = 0;
3216   }
3217
3218   frame.border_h = client.height + frame.mwm_border_w * 2;
3219
3220   if (decorations.handle) {
3221     frame.y_handle = frame.y_border + frame.border_h + frame.border_w;
3222     frame.grip_w = frame.button_w * 2;
3223     frame.grip_h = frame.handle_h = screen->getHandleWidth();
3224   } else {
3225     frame.y_handle = frame.y_border + frame.border_h;
3226     frame.handle_h = 0;
3227     frame.grip_w = frame.grip_h = 0;
3228   }
3229   
3230   frame.width = client.width + (frame.mwm_border_w * 2);
3231   frame.height = frame.y_handle + frame.handle_h;
3232 }
3233
3234
3235 /*
3236  * Set the size and position of the client window.
3237  * These values are based upon the current style settings and the frame
3238  * window's dimensions.
3239  */
3240 void OpenboxWindow::downsize(void) {
3241   frame.y_handle = frame.height - frame.handle_h;
3242   frame.border_h = frame.y_handle - frame.y_border -
3243     (decorations.handle ? frame.border_w : 0);
3244
3245   client.x = frame.x + frame.mwm_border_w + frame.border_w;
3246   client.y = frame.y + frame.y_border + frame.mwm_border_w + frame.border_w;
3247
3248   client.width = frame.width - (frame.mwm_border_w * 2);
3249   client.height = frame.height - frame.y_border - (frame.mwm_border_w * 2)
3250     - frame.handle_h - (decorations.handle ? frame.border_w : 0);
3251
3252   frame.y_handle = frame.border_h + frame.y_border + frame.border_w;
3253 }
3254
3255
3256 void OpenboxWindow::right_fixsize(int *gx, int *gy) {
3257   // calculate the size of the client window and conform it to the
3258   // size specified by the size hints of the client window...
3259   int dx = frame.resize_w - client.base_width - (frame.mwm_border_w * 2) -
3260     (frame.border_w * 2) + (client.width_inc / 2);
3261   int dy = frame.resize_h - frame.y_border - client.base_height -
3262     frame.handle_h - (frame.border_w * 3) - (frame.mwm_border_w * 2)
3263     + (client.height_inc / 2);
3264
3265   if (dx < (signed) client.min_width) dx = client.min_width;
3266   if (dy < (signed) client.min_height) dy = client.min_height;
3267   if ((unsigned) dx > client.max_width) dx = client.max_width;
3268   if ((unsigned) dy > client.max_height) dy = client.max_height;
3269
3270   dx /= client.width_inc;
3271   dy /= client.height_inc;
3272
3273   if (gx) *gx = dx;
3274   if (gy) *gy = dy;
3275
3276   dx = (dx * client.width_inc) + client.base_width;
3277   dy = (dy * client.height_inc) + client.base_height;
3278
3279   frame.resize_w = dx + (frame.mwm_border_w * 2) + (frame.border_w * 2);
3280   frame.resize_h = dy + frame.y_border + frame.handle_h +
3281                    (frame.mwm_border_w * 2) +  (frame.border_w * 3);
3282   if (resize_zone & ZoneTop)
3283     frame.resize_y = frame.y + frame.height - frame.resize_h +
3284       screen->getBorderWidth() * 2;
3285 }
3286
3287
3288 void OpenboxWindow::left_fixsize(int *gx, int *gy) {
3289   // calculate the size of the client window and conform it to the
3290   // size specified by the size hints of the client window...
3291   int dx = frame.x + frame.width - frame.resize_x - client.base_width -
3292     (frame.mwm_border_w * 2) + (client.width_inc / 2);
3293   int dy = frame.resize_h - frame.y_border - client.base_height -
3294     frame.handle_h - (frame.border_w * 3) - (frame.mwm_border_w * 2)
3295     + (client.height_inc / 2);
3296
3297   if (dx < (signed) client.min_width) dx = client.min_width;
3298   if (dy < (signed) client.min_height) dy = client.min_height;
3299   if ((unsigned) dx > client.max_width) dx = client.max_width;
3300   if ((unsigned) dy > client.max_height) dy = client.max_height;
3301
3302   dx /= client.width_inc;
3303   dy /= client.height_inc;
3304
3305   if (gx) *gx = dx;
3306   if (gy) *gy = dy;
3307
3308   dx = (dx * client.width_inc) + client.base_width;
3309   dy = (dy * client.height_inc) + client.base_height;
3310
3311   frame.resize_w = dx + (frame.mwm_border_w * 2) + (frame.border_w * 2);
3312   frame.resize_x = frame.x + frame.width - frame.resize_w +
3313                    (frame.border_w * 2);
3314   frame.resize_h = dy + frame.y_border + frame.handle_h +
3315                    (frame.mwm_border_w * 2) + (frame.border_w * 3);
3316   if (resize_zone & ZoneTop)
3317     frame.resize_y = frame.y + frame.height - frame.resize_h +
3318       screen->getBorderWidth() * 2;
3319   
3320 }