1 // Window.cc for Openbox
2 // Copyright (c) 2002 - 2002 Ben Jansens (ben at orodu.net)
3 // Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry (shaleh at debian.org)
4 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net)
6 // Permission is hereby granted, free of charge, to any person obtaining a
7 // copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the
11 // Software is furnished to do so, subject to the following conditions:
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 // DEALINGS IN THE SOFTWARE.
24 // stupid macros needed to access some functions in version 2 of the GNU C
31 # include "../config.h"
32 #endif // HAVE_CONFIG_H
34 #include <X11/Xatom.h>
35 #include <X11/keysym.h>
39 #endif // HAVE_STRING_H
44 # endif // HAVE_STDIO_H
53 #include "Windowmenu.h"
54 #include "Workspace.h"
61 * Initializes the class with default values/the window's set initial values.
63 OpenboxWindow::OpenboxWindow(Openbox &o, Window w, BScreen *s) : openbox(o) {
65 fprintf(stderr, i18n->getMessage(WindowSet, WindowCreating,
66 "OpenboxWindow::OpenboxWindow(): creating 0x%lx\n"),
71 display = openbox.getXDisplay();
74 if (! validateClient()) return;
76 // fetch client size and placement
77 XWindowAttributes wattrib;
78 if ((! XGetWindowAttributes(display, client.window, &wattrib)) ||
79 (! wattrib.screen) || wattrib.override_redirect) {
82 i18n->getMessage(WindowSet, WindowXGetWindowAttributesFail,
83 "OpenboxWindow::OpenboxWindow(): XGetWindowAttributes "
94 screen = openbox.searchScreen(RootWindowOfScreen(wattrib.screen));
97 fprintf(stderr, i18n->getMessage(WindowSet, WindowCannotFindScreen,
98 "OpenboxWindow::OpenboxWindow(): can't find screen\n"
99 "\tfor root window 0x%lx\n"),
100 RootWindowOfScreen(wattrib.screen));
110 flags.moving = flags.resizing = flags.shaded = flags.visible =
111 flags.iconic = flags.transient = flags.focused =
112 flags.stuck = flags.modal = flags.send_focus_message =
113 flags.shaped = flags.managed = False;
116 openbox_attrib.workspace = workspace_number = window_number = -1;
118 openbox_attrib.flags = openbox_attrib.attrib = openbox_attrib.stack
119 = openbox_attrib.decoration = 0l;
120 openbox_attrib.premax_x = openbox_attrib.premax_y = 0;
121 openbox_attrib.premax_w = openbox_attrib.premax_h = 0;
123 frame.window = frame.plate = frame.title = frame.handle = None;
124 frame.close_button = frame.iconify_button = frame.maximize_button = None;
125 frame.right_grip = frame.left_grip = None;
127 frame.utitle = frame.ftitle = frame.uhandle = frame.fhandle = None;
128 frame.ulabel = frame.flabel = frame.ubutton = frame.fbutton = None;
129 frame.pbutton = frame.ugrip = frame.fgrip = None;
131 decorations.titlebar = decorations.border = decorations.handle = True;
132 decorations.iconify = decorations.maximize = decorations.menu = True;
133 functions.resize = functions.move = functions.iconify =
134 functions.maximize = True;
135 functions.close = decorations.close = False;
137 client.wm_hint_flags = client.normal_hint_flags = 0;
138 client.transient_for = client.transient = 0;
140 client.title_len = 0;
141 client.icon_title = 0;
142 client.mwm_hint = (MwmHints *) 0;
143 client.openbox_hint = (OpenboxHints *) 0;
145 // get the initial size and location of client window (relative to the
146 // _root window_). This position is the reference point used with the
147 // window's gravity to find the window's initial position.
148 client.x = wattrib.x;
149 client.y = wattrib.y;
150 client.width = wattrib.width;
151 client.height = wattrib.height;
152 client.old_bw = wattrib.border_width;
155 lastButtonPressTime = 0;
156 image_ctrl = screen->getImageControl();
158 current_state = WithdrawnState;
160 timer = new BTimer(openbox, *this);
161 timer->setTimeout(openbox.getAutoRaiseDelay());
162 timer->fireOnce(True);
165 if (! client.openbox_hint)
168 // get size, aspect, minimum/maximum size and other hints set by the
175 if (client.initial_state == WithdrawnState) {
176 screen->getSlit()->addClient(client.window);
183 flags.managed = True;
184 openbox.saveWindowSearch(client.window, this);
186 // determine if this is a transient window
188 if (XGetTransientForHint(display, client.window, &win)) {
189 if (win && (win != client.window)) {
191 if ((tr = openbox.searchWindow(win))) {
192 while (tr->client.transient) tr = tr->client.transient;
193 client.transient_for = tr;
194 tr->client.transient = this;
195 flags.stuck = client.transient_for->flags.stuck;
196 flags.transient = True;
197 } else if (win == client.window_group) {
198 if ((tr = openbox.searchGroup(win, this))) {
199 while (tr->client.transient) tr = tr->client.transient;
200 client.transient_for = tr;
201 tr->client.transient = this;
202 flags.stuck = client.transient_for->flags.stuck;
203 flags.transient = True;
208 if (win == screen->getRootWindow()) flags.modal = True;
211 // adjust the window decorations based on transience and window sizes
213 decorations.maximize = decorations.handle = functions.maximize = False;
215 if ((client.normal_hint_flags & PMinSize) &&
216 (client.normal_hint_flags & PMaxSize) &&
217 client.max_width <= client.min_width &&
218 client.max_height <= client.min_height) {
219 decorations.maximize = decorations.handle =
220 functions.resize = functions.maximize = False;
225 if (openbox.isStartup() || flags.transient ||
226 client.normal_hint_flags & (PPosition|USPosition)) {
229 if ((openbox.isStartup()) ||
231 (signed) (frame.y + frame.y_border) >= 0 &&
232 frame.x <= (signed) screen->size().w() &&
233 frame.y <= (signed) screen->size().h()))
234 place_window = false;
237 frame.window = createToplevelWindow(frame.x, frame.y, frame.width,
240 openbox.saveWindowSearch(frame.window, this);
242 frame.plate = createChildWindow(frame.window);
243 openbox.saveWindowSearch(frame.plate, this);
245 if (decorations.titlebar) {
246 frame.title = createChildWindow(frame.window);
247 frame.label = createChildWindow(frame.title);
248 openbox.saveWindowSearch(frame.title, this);
249 openbox.saveWindowSearch(frame.label, this);
252 if (decorations.handle) {
253 frame.handle = createChildWindow(frame.window);
254 openbox.saveWindowSearch(frame.handle, this);
257 createChildWindow(frame.handle, openbox.getLowerLeftAngleCursor());
258 openbox.saveWindowSearch(frame.left_grip, this);
261 createChildWindow(frame.handle, openbox.getLowerRightAngleCursor());
262 openbox.saveWindowSearch(frame.right_grip, this);
265 associateClientWindow();
267 if (! screen->sloppyFocus())
268 openbox.grabButton(Button1, 0, frame.plate, True, ButtonPressMask,
269 GrabModeSync, GrabModeSync, frame.plate, None);
271 openbox.grabButton(Button1, Mod1Mask, frame.window, True,
272 ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
273 GrabModeAsync, frame.window, openbox.getMoveCursor());
274 openbox.grabButton(Button2, Mod1Mask, frame.window, True,
275 ButtonReleaseMask, GrabModeAsync, GrabModeAsync, frame.window, None);
276 openbox.grabButton(Button3, Mod1Mask, frame.window, True,
277 ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
278 GrabModeAsync, frame.window, None);
281 XRaiseWindow(display, frame.plate);
282 XMapSubwindows(display, frame.plate);
283 if (decorations.titlebar) XMapSubwindows(display, frame.title);
284 XMapSubwindows(display, frame.window);
286 if (decorations.menu)
287 windowmenu = new Windowmenu(*this);
291 if (workspace_number < 0 || workspace_number >= screen->getWorkspaceCount())
292 screen->getCurrentWorkspace()->addWindow(this, place_window);
294 screen->getWorkspace(workspace_number)->addWindow(this, place_window);
296 configure(frame.x, frame.y, frame.width, frame.height);
299 flags.shaded = False;
308 if (flags.maximized && functions.maximize) {
309 unsigned int button = flags.maximized;
320 OpenboxWindow::~OpenboxWindow(void) {
321 if (flags.moving || flags.resizing) {
322 screen->hideGeometry();
323 XUngrabPointer(display, CurrentTime);
326 if (workspace_number != -1 && window_number != -1) {
328 // make sure no other workspaces think that we're focused
329 for (int i=0; i < screen->getWorkspaceCount(); i++)
330 screen->getWorkspace(i)->removeWindow(this);
332 screen->getWorkspace(workspace_number)->removeWindow(this);
333 } else if (flags.iconic)
334 screen->removeIcon(this);
337 if (timer->isTiming()) timer->stop();
341 if (windowmenu) delete windowmenu;
344 delete [] client.title;
346 if (client.icon_title)
347 delete [] client.icon_title;
350 XFree(client.mwm_hint);
352 if (client.openbox_hint)
353 XFree(client.openbox_hint);
355 if (client.window_group)
356 openbox.removeGroupSearch(client.window_group);
358 if (flags.transient && client.transient_for)
359 client.transient_for->client.transient = client.transient;
360 if (client.transient)
361 client.transient->client.transient_for = client.transient_for;
363 if (frame.close_button) {
364 openbox.removeWindowSearch(frame.close_button);
365 XDestroyWindow(display, frame.close_button);
368 if (frame.iconify_button) {
369 openbox.removeWindowSearch(frame.iconify_button);
370 XDestroyWindow(display, frame.iconify_button);
373 if (frame.maximize_button) {
374 openbox.removeWindowSearch(frame.maximize_button);
375 XDestroyWindow(display, frame.maximize_button);
380 image_ctrl->removeImage(frame.ftitle);
383 image_ctrl->removeImage(frame.utitle);
386 image_ctrl->removeImage(frame.flabel);
389 image_ctrl->removeImage(frame.ulabel);
391 openbox.removeWindowSearch(frame.label);
392 openbox.removeWindowSearch(frame.title);
393 XDestroyWindow(display, frame.label);
394 XDestroyWindow(display, frame.title);
399 image_ctrl->removeImage(frame.fhandle);
402 image_ctrl->removeImage(frame.uhandle);
405 image_ctrl->removeImage(frame.fgrip);
408 image_ctrl->removeImage(frame.ugrip);
410 openbox.removeWindowSearch(frame.handle);
411 openbox.removeWindowSearch(frame.right_grip);
412 openbox.removeWindowSearch(frame.left_grip);
413 XDestroyWindow(display, frame.right_grip);
414 XDestroyWindow(display, frame.left_grip);
415 XDestroyWindow(display, frame.handle);
419 image_ctrl->removeImage(frame.fbutton);
422 image_ctrl->removeImage(frame.ubutton);
425 image_ctrl->removeImage(frame.pbutton);
428 openbox.removeWindowSearch(frame.plate);
429 XDestroyWindow(display, frame.plate);
433 openbox.removeWindowSearch(frame.window);
434 XDestroyWindow(display, frame.window);
438 openbox.removeWindowSearch(client.window);
439 screen->removeNetizen(client.window);
445 * Creates a new top level window, with a given location, size, and border
447 * Returns: the newly created window
449 Window OpenboxWindow::createToplevelWindow(int x, int y, unsigned int width,
451 unsigned int borderwidth)
453 XSetWindowAttributes attrib_create;
454 unsigned long create_mask = CWBackPixmap | CWBorderPixel | CWColormap |
455 CWOverrideRedirect | CWEventMask;
457 attrib_create.background_pixmap = None;
458 attrib_create.colormap = screen->getColormap();
459 attrib_create.override_redirect = True;
460 attrib_create.event_mask = ButtonPressMask | ButtonReleaseMask |
461 ButtonMotionMask | EnterWindowMask;
463 return XCreateWindow(display, screen->getRootWindow(), x, y, width, height,
464 borderwidth, screen->getDepth(), InputOutput,
465 screen->getVisual(), create_mask,
471 * Creates a child window, and optionally associates a given cursor with
474 Window OpenboxWindow::createChildWindow(Window parent, Cursor cursor) {
475 XSetWindowAttributes attrib_create;
476 unsigned long create_mask = CWBackPixmap | CWBorderPixel |
479 attrib_create.background_pixmap = None;
480 attrib_create.event_mask = ButtonPressMask | ButtonReleaseMask |
481 ButtonMotionMask | ExposureMask |
482 EnterWindowMask | LeaveWindowMask;
485 create_mask |= CWCursor;
486 attrib_create.cursor = cursor;
489 return XCreateWindow(display, parent, 0, 0, 1, 1, 0, screen->getDepth(),
490 InputOutput, screen->getVisual(), create_mask,
495 void OpenboxWindow::associateClientWindow(void) {
496 XSetWindowBorderWidth(display, client.window, 0);
500 XChangeSaveSet(display, client.window, SetModeInsert);
501 XSetWindowAttributes attrib_set;
503 XSelectInput(display, frame.plate, NoEventMask);
504 XReparentWindow(display, client.window, frame.plate, 0, 0);
505 XSelectInput(display, frame.plate, SubstructureRedirectMask);
509 attrib_set.event_mask = PropertyChangeMask | StructureNotifyMask |
511 attrib_set.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask |
514 XChangeWindowAttributes(display, client.window, CWEventMask|CWDontPropagate,
518 if (openbox.hasShapeExtensions()) {
519 XShapeSelectInput(display, client.window, ShapeNotifyMask);
524 XShapeQueryExtents(display, client.window, &flags.shaped, &foo, &foo,
525 &ufoo, &ufoo, &foo, &foo, &foo, &ufoo, &ufoo);
528 XShapeCombineShape(display, frame.window, ShapeBounding,
529 frame.mwm_border_w, frame.y_border +
530 frame.mwm_border_w, client.window,
531 ShapeBounding, ShapeSet);
535 xrect[0].x = xrect[0].y = 0;
536 xrect[0].width = frame.width;
537 xrect[0].height = frame.y_border;
539 if (decorations.handle) {
541 xrect[1].y = frame.y_handle;
542 xrect[1].width = frame.width;
543 xrect[1].height = frame.handle_h + frame.border_w;
547 XShapeCombineRectangles(display, frame.window, ShapeBounding, 0, 0,
548 xrect, num, ShapeUnion, Unsorted);
553 if (decorations.iconify) createIconifyButton();
554 if (decorations.maximize) createMaximizeButton();
555 if (decorations.close) createCloseButton();
559 void OpenboxWindow::decorate(void) {
560 Pixmap tmp = frame.fbutton;
561 BTexture *texture = &(screen->getWindowStyle()->b_focus);
562 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
563 frame.fbutton = None;
564 frame.fbutton_pixel = texture->getColor()->getPixel();
567 image_ctrl->renderImage(frame.button_w, frame.button_h, texture);
569 if (tmp) image_ctrl->removeImage(tmp);
572 texture = &(screen->getWindowStyle()->b_unfocus);
573 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
574 frame.ubutton = None;
575 frame.ubutton_pixel = texture->getColor()->getPixel();
578 image_ctrl->renderImage(frame.button_w, frame.button_h, texture);
580 if (tmp) image_ctrl->removeImage(tmp);
583 texture = &(screen->getWindowStyle()->b_pressed);
584 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
585 frame.pbutton = None;
586 frame.pbutton_pixel = texture->getColor()->getPixel();
589 image_ctrl->renderImage(frame.button_w, frame.button_h, texture);
591 if (tmp) image_ctrl->removeImage(tmp);
593 if (decorations.titlebar) {
595 texture = &(screen->getWindowStyle()->t_focus);
596 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
598 frame.ftitle_pixel = texture->getColor()->getPixel();
601 image_ctrl->renderImage(frame.width, frame.title_h, texture);
603 if (tmp) image_ctrl->removeImage(tmp);
606 texture = &(screen->getWindowStyle()->t_unfocus);
607 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
609 frame.utitle_pixel = texture->getColor()->getPixel();
612 image_ctrl->renderImage(frame.width, frame.title_h, texture);
614 if (tmp) image_ctrl->removeImage(tmp);
616 XSetWindowBorder(display, frame.title,
617 screen->getBorderColor()->getPixel());
622 if (decorations.border) {
623 frame.fborder_pixel = screen->getWindowStyle()->f_focus.getPixel();
624 frame.uborder_pixel = screen->getWindowStyle()->f_unfocus.getPixel();
625 openbox_attrib.flags |= AttribDecoration;
626 openbox_attrib.decoration = DecorNormal;
628 openbox_attrib.flags |= AttribDecoration;
629 openbox_attrib.decoration = DecorNone;
632 if (decorations.handle) {
634 texture = &(screen->getWindowStyle()->h_focus);
635 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
636 frame.fhandle = None;
637 frame.fhandle_pixel = texture->getColor()->getPixel();
640 image_ctrl->renderImage(frame.width, frame.handle_h, texture);
642 if (tmp) image_ctrl->removeImage(tmp);
645 texture = &(screen->getWindowStyle()->h_unfocus);
646 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
647 frame.uhandle = None;
648 frame.uhandle_pixel = texture->getColor()->getPixel();
651 image_ctrl->renderImage(frame.width, frame.handle_h, texture);
653 if (tmp) image_ctrl->removeImage(tmp);
656 texture = &(screen->getWindowStyle()->g_focus);
657 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
659 frame.fgrip_pixel = texture->getColor()->getPixel();
662 image_ctrl->renderImage(frame.grip_w, frame.grip_h, texture);
664 if (tmp) image_ctrl->removeImage(tmp);
667 texture = &(screen->getWindowStyle()->g_unfocus);
668 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
670 frame.ugrip_pixel = texture->getColor()->getPixel();
673 image_ctrl->renderImage(frame.grip_w, frame.grip_h, texture);
675 if (tmp) image_ctrl->removeImage(tmp);
677 XSetWindowBorder(display, frame.handle,
678 screen->getBorderColor()->getPixel());
679 XSetWindowBorder(display, frame.left_grip,
680 screen->getBorderColor()->getPixel());
681 XSetWindowBorder(display, frame.right_grip,
682 screen->getBorderColor()->getPixel());
685 XSetWindowBorder(display, frame.window,
686 screen->getBorderColor()->getPixel());
690 void OpenboxWindow::decorateLabel(void) {
691 Pixmap tmp = frame.flabel;
692 BTexture *texture = &(screen->getWindowStyle()->l_focus);
693 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
695 frame.flabel_pixel = texture->getColor()->getPixel();
698 image_ctrl->renderImage(frame.label_w, frame.label_h, texture);
700 if (tmp) image_ctrl->removeImage(tmp);
703 texture = &(screen->getWindowStyle()->l_unfocus);
704 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
706 frame.ulabel_pixel = texture->getColor()->getPixel();
709 image_ctrl->renderImage(frame.label_w, frame.label_h, texture);
711 if (tmp) image_ctrl->removeImage(tmp);
715 void OpenboxWindow::createCloseButton(void) {
716 if (decorations.close && frame.title != None) {
717 frame.close_button = createChildWindow(frame.title);
718 openbox.saveWindowSearch(frame.close_button, this);
723 void OpenboxWindow::createIconifyButton(void) {
724 if (decorations.iconify && frame.title != None) {
725 frame.iconify_button = createChildWindow(frame.title);
726 openbox.saveWindowSearch(frame.iconify_button, this);
731 void OpenboxWindow::createMaximizeButton(void) {
732 if (decorations.maximize && frame.title != None) {
733 frame.maximize_button = createChildWindow(frame.title);
734 openbox.saveWindowSearch(frame.maximize_button, this);
739 void OpenboxWindow::positionButtons() {
740 const char *format = openbox.getTitleBarLayout();
741 const unsigned int bw = frame.bevel_w + 1;
742 const unsigned int by = frame.bevel_w + 1;
743 unsigned int bx = frame.bevel_w + 1;
744 unsigned int bcount = strlen(format) - 1;
746 if (!decorations.close)
748 if (!decorations.maximize)
750 if (!decorations.iconify)
752 frame.label_w = frame.width - bx * 2 - (frame.button_w + bw) * bcount;
754 bool hasclose, hasiconify, hasmaximize;
755 hasclose = hasiconify = hasmaximize = false;
757 for (int i = 0; format[i] != '\0' && i < 4; i++) {
760 if (decorations.close) {
761 if (frame.close_button == None)
763 XMoveResizeWindow(display, frame.close_button, bx, by,
764 frame.button_w, frame.button_h);
765 XMapWindow(display, frame.close_button);
766 XClearWindow(display, frame.close_button);
767 bx += frame.button_w + bw;
772 if (decorations.iconify) {
773 if (frame.iconify_button == None)
774 createIconifyButton();
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;
784 if (decorations.maximize) {
785 if (frame.maximize_button == None)
786 createMaximizeButton();
787 XMoveResizeWindow(display, frame.maximize_button, bx, by,
788 frame.button_w, frame.button_h);
789 XMapWindow(display, frame.maximize_button);
790 XClearWindow(display, frame.maximize_button);
791 bx += frame.button_w + bw;
796 XMoveResizeWindow(display, frame.label, bx, by - 1,
797 frame.label_w, frame.label_h);
798 bx += frame.label_w + bw;
803 if (!hasclose && frame.close_button) {
804 openbox.removeWindowSearch(frame.close_button);
805 XDestroyWindow(display, frame.close_button);
806 frame.close_button = None;
808 if (!hasiconify && frame.iconify_button) {
809 openbox.removeWindowSearch(frame.iconify_button);
810 XDestroyWindow(display, frame.iconify_button);
811 frame.iconify_button = None;
813 if (!hasmaximize && frame.iconify_button) {
814 openbox.removeWindowSearch(frame.maximize_button);
815 XDestroyWindow(display, frame.maximize_button);
816 frame.maximize_button = None;
824 void OpenboxWindow::reconfigure(void) {
827 client.x = frame.x + frame.mwm_border_w + frame.border_w;
828 client.y = frame.y + frame.y_border + frame.mwm_border_w +
832 if (i18n->multibyte()) {
833 XRectangle ink, logical;
834 XmbTextExtents(screen->getWindowStyle()->fontset,
835 client.title, client.title_len, &ink, &logical);
836 client.title_text_w = logical.width;
838 client.title_text_w = XTextWidth(screen->getWindowStyle()->font,
839 client.title, client.title_len);
841 client.title_text_w += (frame.bevel_w * 4);
847 XClearWindow(display, frame.window);
848 setFocusFlag(flags.focused);
850 configure(frame.x, frame.y, frame.width, frame.height);
852 if (! screen->sloppyFocus())
853 openbox.grabButton(Button1, 0, frame.plate, True, ButtonPressMask,
854 GrabModeSync, GrabModeSync, None, None);
856 openbox.ungrabButton(Button1, 0, frame.plate);
859 windowmenu->move(windowmenu->getX(), frame.y + frame.title_h);
860 windowmenu->reconfigure();
863 // re-get the timeout delay
864 timer->setTimeout(openbox.getAutoRaiseDelay());
868 void OpenboxWindow::positionWindows(void) {
869 XResizeWindow(display, frame.window, frame.width,
870 ((flags.shaded) ? frame.title_h : frame.height));
871 XSetWindowBorderWidth(display, frame.window, frame.border_w);
872 XSetWindowBorderWidth(display, frame.plate, frame.mwm_border_w);
873 XMoveResizeWindow(display, frame.plate, 0, frame.y_border,
874 client.width, client.height);
875 XMoveResizeWindow(display, client.window, 0, 0, client.width, client.height);
877 if (decorations.titlebar) {
878 XSetWindowBorderWidth(display, frame.title, frame.border_w);
879 XMoveResizeWindow(display, frame.title, -frame.border_w,
880 -frame.border_w, frame.width, frame.title_h);
883 } else if (frame.title) {
884 XUnmapWindow(display, frame.title);
886 if (decorations.handle) {
887 XSetWindowBorderWidth(display, frame.handle, frame.border_w);
888 XSetWindowBorderWidth(display, frame.left_grip, frame.border_w);
889 XSetWindowBorderWidth(display, frame.right_grip, frame.border_w);
891 XMoveResizeWindow(display, frame.handle, -frame.border_w,
892 frame.y_handle - frame.border_w,
893 frame.width, frame.handle_h);
894 XMoveResizeWindow(display, frame.left_grip, -frame.border_w,
895 -frame.border_w, frame.grip_w, frame.grip_h);
896 XMoveResizeWindow(display, frame.right_grip,
897 frame.width - frame.grip_w - frame.border_w,
898 -frame.border_w, frame.grip_w, frame.grip_h);
899 XMapSubwindows(display, frame.handle);
900 } else if (frame.handle) {
901 XUnmapWindow(display, frame.handle);
906 void OpenboxWindow::getWMName(void) {
908 delete [] client.title;
909 client.title = (char *) 0;
912 XTextProperty text_prop;
916 if (XGetWMName(display, client.window, &text_prop)) {
917 if (text_prop.value && text_prop.nitems > 0) {
918 if (text_prop.encoding != XA_STRING) {
919 text_prop.nitems = strlen((char *) text_prop.value);
921 if ((XmbTextPropertyToTextList(display, &text_prop,
922 &list, &num) == Success) &&
923 (num > 0) && *list) {
924 client.title = bstrdup(*list);
925 XFreeStringList(list);
927 client.title = bstrdup((char *) text_prop.value);
930 client.title = bstrdup((char *) text_prop.value);
932 XFree((char *) text_prop.value);
934 client.title = bstrdup(i18n->getMessage(WindowSet, WindowUnnamed,
938 client.title = bstrdup(i18n->getMessage(WindowSet, WindowUnnamed,
941 client.title_len = strlen(client.title);
943 if (i18n->multibyte()) {
944 XRectangle ink, logical;
945 XmbTextExtents(screen->getWindowStyle()->fontset,
946 client.title, client.title_len, &ink, &logical);
947 client.title_text_w = logical.width;
949 client.title_len = strlen(client.title);
950 client.title_text_w = XTextWidth(screen->getWindowStyle()->font,
951 client.title, client.title_len);
954 client.title_text_w += (frame.bevel_w * 4);
958 void OpenboxWindow::getWMIconName(void) {
959 if (client.icon_title) {
960 delete [] client.icon_title;
961 client.icon_title = (char *) 0;
964 XTextProperty text_prop;
968 if (XGetWMIconName(display, client.window, &text_prop)) {
969 if (text_prop.value && text_prop.nitems > 0) {
970 if (text_prop.encoding != XA_STRING) {
971 text_prop.nitems = strlen((char *) text_prop.value);
973 if ((XmbTextPropertyToTextList(display, &text_prop,
974 &list, &num) == Success) &&
975 (num > 0) && *list) {
976 client.icon_title = bstrdup(*list);
977 XFreeStringList(list);
979 client.icon_title = bstrdup((char *) text_prop.value);
982 client.icon_title = bstrdup((char *) text_prop.value);
984 XFree((char *) text_prop.value);
986 client.icon_title = bstrdup(client.title);
989 client.icon_title = bstrdup(client.title);
995 * Retrieve which WM Protocols are supported by the client window.
996 * If the WM_DELETE_WINDOW protocol is supported, add the close button to the
997 * window's decorations and allow the close behavior.
998 * If the WM_TAKE_FOCUS protocol is supported, save a value that indicates
1001 void OpenboxWindow::getWMProtocols(void) {
1005 if (XGetWMProtocols(display, client.window, &proto, &num_return)) {
1006 for (int i = 0; i < num_return; ++i) {
1007 if (proto[i] == openbox.getWMDeleteAtom())
1008 functions.close = decorations.close = True;
1009 else if (proto[i] == openbox.getWMTakeFocusAtom())
1010 flags.send_focus_message = True;
1011 else if (proto[i] == openbox.getOpenboxStructureMessagesAtom())
1012 screen->addNetizen(new Netizen(*screen, client.window));
1021 * Gets the value of the WM_HINTS property.
1022 * If the property is not set, then use a set of default values.
1024 void OpenboxWindow::getWMHints(void) {
1025 XWMHints *wmhint = XGetWMHints(display, client.window);
1027 flags.visible = True;
1028 flags.iconic = False;
1029 focus_mode = F_Passive;
1030 client.window_group = None;
1031 client.initial_state = NormalState;
1034 client.wm_hint_flags = wmhint->flags;
1035 if (wmhint->flags & InputHint) {
1036 if (wmhint->input == True) {
1037 if (flags.send_focus_message)
1038 focus_mode = F_LocallyActive;
1040 focus_mode = F_Passive;
1042 if (flags.send_focus_message)
1043 focus_mode = F_GloballyActive;
1045 focus_mode = F_NoInput;
1048 focus_mode = F_Passive;
1051 if (wmhint->flags & StateHint)
1052 client.initial_state = wmhint->initial_state;
1054 client.initial_state = NormalState;
1056 if (wmhint->flags & WindowGroupHint) {
1057 if (! client.window_group) {
1058 client.window_group = wmhint->window_group;
1059 openbox.saveGroupSearch(client.window_group, this);
1062 client.window_group = None;
1069 * Gets the value of the WM_NORMAL_HINTS property.
1070 * If the property is not set, then use a set of default values.
1072 void OpenboxWindow::getWMNormalHints(void) {
1074 XSizeHints sizehint;
1076 client.min_width = client.min_height =
1077 client.width_inc = client.height_inc = 1;
1078 client.base_width = client.base_height = 0;
1079 client.max_width = screen->size().w();
1080 client.max_height = screen->size().h();
1081 client.min_aspect_x = client.min_aspect_y =
1082 client.max_aspect_x = client.max_aspect_y = 1;
1083 client.win_gravity = NorthWestGravity;
1085 if (! XGetWMNormalHints(display, client.window, &sizehint, &icccm_mask))
1088 client.normal_hint_flags = sizehint.flags;
1090 if (sizehint.flags & PMinSize) {
1091 client.min_width = sizehint.min_width;
1092 client.min_height = sizehint.min_height;
1095 if (sizehint.flags & PMaxSize) {
1096 client.max_width = sizehint.max_width;
1097 client.max_height = sizehint.max_height;
1100 if (sizehint.flags & PResizeInc) {
1101 client.width_inc = sizehint.width_inc;
1102 client.height_inc = sizehint.height_inc;
1105 if (sizehint.flags & PAspect) {
1106 client.min_aspect_x = sizehint.min_aspect.x;
1107 client.min_aspect_y = sizehint.min_aspect.y;
1108 client.max_aspect_x = sizehint.max_aspect.x;
1109 client.max_aspect_y = sizehint.max_aspect.y;
1112 if (sizehint.flags & PBaseSize) {
1113 client.base_width = sizehint.base_width;
1114 client.base_height = sizehint.base_height;
1117 if (sizehint.flags & PWinGravity)
1118 client.win_gravity = sizehint.win_gravity;
1123 * Gets the MWM hints for the class' contained window.
1124 * This is used while initializing the window to its first state, and not
1126 * Returns: true if the MWM hints are successfully retreived and applied; false
1129 void OpenboxWindow::getMWMHints(void) {
1132 unsigned long num, len;
1134 int ret = XGetWindowProperty(display, client.window,
1135 openbox.getMotifWMHintsAtom(), 0,
1136 PropMwmHintsElements, False,
1137 openbox.getMotifWMHintsAtom(), &atom_return,
1138 &format, &num, &len,
1139 (unsigned char **) &client.mwm_hint);
1141 if (ret != Success || !client.mwm_hint || num != PropMwmHintsElements)
1144 if (client.mwm_hint->flags & MwmHintsDecorations) {
1145 if (client.mwm_hint->decorations & MwmDecorAll) {
1146 decorations.titlebar = decorations.handle = decorations.border =
1147 decorations.iconify = decorations.maximize =
1148 decorations.close = decorations.menu = True;
1150 decorations.titlebar = decorations.handle = decorations.border =
1151 decorations.iconify = decorations.maximize =
1152 decorations.close = decorations.menu = False;
1154 if (client.mwm_hint->decorations & MwmDecorBorder)
1155 decorations.border = True;
1156 if (client.mwm_hint->decorations & MwmDecorHandle)
1157 decorations.handle = True;
1158 if (client.mwm_hint->decorations & MwmDecorTitle)
1159 decorations.titlebar = True;
1160 if (client.mwm_hint->decorations & MwmDecorMenu)
1161 decorations.menu = True;
1162 if (client.mwm_hint->decorations & MwmDecorIconify)
1163 decorations.iconify = True;
1164 if (client.mwm_hint->decorations & MwmDecorMaximize)
1165 decorations.maximize = True;
1169 if (client.mwm_hint->flags & MwmHintsFunctions) {
1170 if (client.mwm_hint->functions & MwmFuncAll) {
1171 functions.resize = functions.move = functions.iconify =
1172 functions.maximize = functions.close = True;
1174 functions.resize = functions.move = functions.iconify =
1175 functions.maximize = functions.close = False;
1177 if (client.mwm_hint->functions & MwmFuncResize)
1178 functions.resize = True;
1179 if (client.mwm_hint->functions & MwmFuncMove)
1180 functions.move = True;
1181 if (client.mwm_hint->functions & MwmFuncIconify)
1182 functions.iconify = True;
1183 if (client.mwm_hint->functions & MwmFuncMaximize)
1184 functions.maximize = True;
1185 if (client.mwm_hint->functions & MwmFuncClose)
1186 functions.close = True;
1193 * Gets the openbox hints from the class' contained window.
1194 * This is used while initializing the window to its first state, and not
1196 * Returns: true if the hints are successfully retreived and applied; false if
1199 void OpenboxWindow::getOpenboxHints(void) {
1202 unsigned long num, len;
1204 int ret = XGetWindowProperty(display, client.window,
1205 openbox.getOpenboxHintsAtom(), 0,
1206 PropOpenboxHintsElements, False,
1207 openbox.getOpenboxHintsAtom(), &atom_return,
1208 &format, &num, &len,
1209 (unsigned char **) &client.openbox_hint);
1210 if (ret != Success || !client.openbox_hint ||
1211 num != PropOpenboxHintsElements)
1214 if (client.openbox_hint->flags & AttribShaded)
1215 flags.shaded = (client.openbox_hint->attrib & AttribShaded);
1217 if ((client.openbox_hint->flags & AttribMaxHoriz) &&
1218 (client.openbox_hint->flags & AttribMaxVert))
1219 flags.maximized = (client.openbox_hint->attrib &
1220 (AttribMaxHoriz | AttribMaxVert)) ? 1 : 0;
1221 else if (client.openbox_hint->flags & AttribMaxVert)
1222 flags.maximized = (client.openbox_hint->attrib & AttribMaxVert) ? 2 : 0;
1223 else if (client.openbox_hint->flags & AttribMaxHoriz)
1224 flags.maximized = (client.openbox_hint->attrib & AttribMaxHoriz) ? 3 : 0;
1226 if (client.openbox_hint->flags & AttribOmnipresent)
1227 flags.stuck = (client.openbox_hint->attrib & AttribOmnipresent);
1229 if (client.openbox_hint->flags & AttribWorkspace)
1230 workspace_number = client.openbox_hint->workspace;
1232 // if (client.openbox_hint->flags & AttribStack)
1233 // don't yet have always on top/bottom for openbox yet... working
1236 if (client.openbox_hint->flags & AttribDecoration) {
1237 switch (client.openbox_hint->decoration) {
1239 decorations.titlebar = decorations.border = decorations.handle =
1240 decorations.iconify = decorations.maximize =
1241 decorations.menu = False;
1242 functions.resize = functions.move = functions.iconify =
1243 functions.maximize = False;
1248 decorations.titlebar = decorations.iconify = decorations.menu =
1249 functions.move = functions.iconify = True;
1250 decorations.border = decorations.handle = decorations.maximize =
1251 functions.resize = functions.maximize = False;
1256 decorations.titlebar = decorations.menu = functions.move = True;
1257 decorations.iconify = decorations.border = decorations.handle =
1258 decorations.maximize = functions.resize = functions.maximize =
1259 functions.iconify = False;
1265 decorations.titlebar = decorations.border = decorations.handle =
1266 decorations.iconify = decorations.maximize =
1267 decorations.menu = True;
1268 functions.resize = functions.move = functions.iconify =
1269 functions.maximize = True;
1279 void OpenboxWindow::configure(int dx, int dy,
1280 unsigned int dw, unsigned int dh) {
1281 Bool send_event = (frame.x != dx || frame.y != dy);
1283 if ((dw != frame.width) || (dh != frame.height)) {
1284 if ((((signed) frame.width) + dx) < 0) dx = 0;
1285 if ((((signed) frame.height) + dy) < 0) dy = 0;
1295 if (openbox.hasShapeExtensions() && flags.shaped) {
1296 XShapeCombineShape(display, frame.window, ShapeBounding,
1297 frame.mwm_border_w, frame.y_border +
1298 frame.mwm_border_w, client.window,
1299 ShapeBounding, ShapeSet);
1302 XRectangle xrect[2];
1303 xrect[0].x = xrect[0].y = 0;
1304 xrect[0].width = frame.width;
1305 xrect[0].height = frame.y_border;
1307 if (decorations.handle) {
1309 xrect[1].y = frame.y_handle;
1310 xrect[1].width = frame.width;
1311 xrect[1].height = frame.handle_h + frame.border_w;
1315 XShapeCombineRectangles(display, frame.window, ShapeBounding, 0, 0,
1316 xrect, num, ShapeUnion, Unsorted);
1320 XMoveWindow(display, frame.window, frame.x, frame.y);
1324 setFocusFlag(flags.focused);
1329 XMoveWindow(display, frame.window, frame.x, frame.y);
1331 if (! flags.moving) send_event = True;
1334 if (send_event && ! flags.moving) {
1335 client.x = dx + frame.mwm_border_w + frame.border_w;
1336 client.y = dy + frame.y_border + frame.mwm_border_w +
1340 event.type = ConfigureNotify;
1342 event.xconfigure.display = display;
1343 event.xconfigure.event = client.window;
1344 event.xconfigure.window = client.window;
1345 event.xconfigure.x = client.x;
1346 event.xconfigure.y = client.y;
1347 event.xconfigure.width = client.width;
1348 event.xconfigure.height = client.height;
1349 event.xconfigure.border_width = client.old_bw;
1350 event.xconfigure.above = frame.window;
1351 event.xconfigure.override_redirect = False;
1353 XSendEvent(display, client.window, True, NoEventMask, &event);
1355 screen->updateNetizenConfigNotify(&event);
1360 bool OpenboxWindow::setInputFocus(void) {
1361 if (((signed) (frame.x + frame.width)) < 0) {
1362 if (((signed) (frame.y + frame.y_border)) < 0)
1363 configure(frame.border_w, frame.border_w, frame.width, frame.height);
1364 else if (frame.y > (signed) screen->size().h())
1365 configure(frame.border_w, screen->size().h() - frame.height,
1366 frame.width, frame.height);
1368 configure(frame.border_w, frame.y + frame.border_w,
1369 frame.width, frame.height);
1370 } else if (frame.x > (signed) screen->size().w()) {
1371 if (((signed) (frame.y + frame.y_border)) < 0)
1372 configure(screen->size().w() - frame.width, frame.border_w,
1373 frame.width, frame.height);
1374 else if (frame.y > (signed) screen->size().h())
1375 configure(screen->size().w() - frame.width,
1376 screen->size().h() - frame.height, frame.width, frame.height);
1378 configure(screen->size().w() - frame.width,
1379 frame.y + frame.border_w, frame.width, frame.height);
1383 if (! validateClient()) return False;
1387 if (client.transient && flags.modal) {
1388 ret = client.transient->setInputFocus();
1389 } else if (! flags.focused) {
1390 if (focus_mode == F_LocallyActive || focus_mode == F_Passive) {
1391 XSetInputFocus(display, client.window,
1392 RevertToPointerRoot, CurrentTime);
1393 openbox.focusWindow(this);
1395 if (flags.send_focus_message) {
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);
1410 if (screen->sloppyFocus() && screen->autoRaise())
1423 void OpenboxWindow::iconify(void) {
1424 if (flags.iconic) return;
1429 if (windowmenu) windowmenu->hide();
1431 setState(IconicState);
1433 XSelectInput(display, client.window, NoEventMask);
1434 XUnmapWindow(display, client.window);
1435 XSelectInput(display, client.window,
1436 PropertyChangeMask | StructureNotifyMask | FocusChangeMask);
1438 XUnmapWindow(display, frame.window);
1439 flags.visible = False;
1440 flags.iconic = True;
1442 screen->getWorkspace(workspace_number)->removeWindow(this);
1444 if (flags.transient && client.transient_for &&
1445 !client.transient_for->flags.iconic) {
1446 client.transient_for->iconify();
1448 screen->addIcon(this);
1450 if (client.transient && !client.transient->flags.iconic) {
1451 client.transient->iconify();
1456 void OpenboxWindow::deiconify(bool reassoc, bool raise, bool initial) {
1457 if (flags.iconic || reassoc)
1458 screen->reassociateWindow(this, -1, False);
1459 else if (workspace_number != screen->getCurrentWorkspace()->getWorkspaceID())
1462 setState(NormalState);
1464 XSelectInput(display, client.window, NoEventMask);
1465 XMapWindow(display, client.window);
1466 XSelectInput(display, client.window,
1467 PropertyChangeMask | StructureNotifyMask | FocusChangeMask);
1469 XMapSubwindows(display, frame.window);
1470 XMapWindow(display, frame.window);
1472 // if we're using the click to place placement type, then immediately
1473 // after the window is mapped, we need to start interactively moving it
1474 if (initial && place_window &&
1475 screen->placementPolicy() == BScreen::ClickMousePlacement) {
1479 XQueryPointer(openbox.getXDisplay(), screen->getRootWindow(),
1480 &r, &c, &rx, &ry, &x, &y, &m);
1484 if (flags.iconic && screen->focusNew()) setInputFocus();
1486 flags.visible = True;
1487 flags.iconic = False;
1489 if (reassoc && client.transient) client.transient->deiconify(True, False);
1492 screen->getWorkspace(workspace_number)->raiseWindow(this);
1496 void OpenboxWindow::close(void) {
1498 ce.xclient.type = ClientMessage;
1499 ce.xclient.message_type = openbox.getWMProtocolsAtom();
1500 ce.xclient.display = display;
1501 ce.xclient.window = client.window;
1502 ce.xclient.format = 32;
1503 ce.xclient.data.l[0] = openbox.getWMDeleteAtom();
1504 ce.xclient.data.l[1] = CurrentTime;
1505 ce.xclient.data.l[2] = 0l;
1506 ce.xclient.data.l[3] = 0l;
1507 ce.xclient.data.l[4] = 0l;
1508 XSendEvent(display, client.window, False, NoEventMask, &ce);
1512 void OpenboxWindow::withdraw(void) {
1516 flags.visible = False;
1517 flags.iconic = False;
1519 XUnmapWindow(display, frame.window);
1521 XSelectInput(display, client.window, NoEventMask);
1522 XUnmapWindow(display, client.window);
1523 XSelectInput(display, client.window,
1524 PropertyChangeMask | StructureNotifyMask | FocusChangeMask);
1526 if (windowmenu) windowmenu->hide();
1530 void OpenboxWindow::maximize(unsigned int button) {
1534 // handle case where menu is open then the max button is used instead
1535 if (windowmenu && windowmenu->isVisible()) windowmenu->hide();
1537 if (flags.maximized) {
1538 flags.maximized = 0;
1540 openbox_attrib.flags &= ! (AttribMaxHoriz | AttribMaxVert);
1541 openbox_attrib.attrib &= ! (AttribMaxHoriz | AttribMaxVert);
1543 // when a resize is begun, maximize(0) is called to clear any maximization
1544 // flags currently set. Otherwise it still thinks it is maximized.
1545 // so we do not need to call configure() because resizing will handle it
1546 if (!flags.resizing)
1547 configure(openbox_attrib.premax_x, openbox_attrib.premax_y,
1548 openbox_attrib.premax_w, openbox_attrib.premax_h);
1550 openbox_attrib.premax_x = openbox_attrib.premax_y = 0;
1551 openbox_attrib.premax_w = openbox_attrib.premax_h = 0;
1553 redrawMaximizeButton(flags.maximized);
1554 setState(current_state);
1558 openbox_attrib.premax_x = frame.x;
1559 openbox_attrib.premax_y = frame.y;
1560 openbox_attrib.premax_w = frame.width;
1561 openbox_attrib.premax_h = frame.height;
1563 Rect space = screen->availableArea();
1564 unsigned int dw = space.w(),
1566 dw -= frame.border_w * 2;
1567 dw -= frame.mwm_border_w * 2;
1568 dw -= client.base_width;
1570 dh -= frame.border_w * 2;
1571 dh -= frame.mwm_border_w * 2;
1572 dh -= ((frame.handle_h + frame.border_w) * decorations.handle);
1573 dh -= client.base_height;
1574 dh -= frame.y_border;
1576 if (dw < client.min_width) dw = client.min_width;
1577 if (dh < client.min_height) dh = client.min_height;
1578 if (dw > client.max_width) dw = client.max_width;
1579 if (dh > client.max_height) dh = client.max_height;
1581 dw -= (dw % client.width_inc);
1582 dw += client.base_width;
1583 dw += frame.mwm_border_w * 2;
1585 dh -= (dh % client.height_inc);
1586 dh += client.base_height;
1587 dh += frame.y_border;
1588 dh += ((frame.handle_h + frame.border_w) * decorations.handle);
1589 dh += frame.mwm_border_w * 2;
1591 int dx = space.x() + ((space.w() - dw) / 2) - frame.border_w,
1592 dy = space.y() + ((space.h() - dh) / 2) - frame.border_w;
1596 openbox_attrib.flags |= AttribMaxHoriz | AttribMaxVert;
1597 openbox_attrib.attrib |= AttribMaxHoriz | AttribMaxVert;
1601 openbox_attrib.flags |= AttribMaxVert;
1602 openbox_attrib.attrib |= AttribMaxVert;
1609 openbox_attrib.flags |= AttribMaxHoriz;
1610 openbox_attrib.attrib |= AttribMaxHoriz;
1618 openbox_attrib.flags ^= AttribShaded;
1619 openbox_attrib.attrib ^= AttribShaded;
1620 flags.shaded = False;
1623 flags.maximized = button;
1625 configure(dx, dy, dw, dh);
1626 screen->getWorkspace(workspace_number)->raiseWindow(this);
1627 redrawMaximizeButton(flags.maximized);
1628 setState(current_state);
1632 void OpenboxWindow::setWorkspace(int n) {
1633 ASSERT(n < screen->getWorkspaceCount());
1634 workspace_number = n;
1636 openbox_attrib.flags |= AttribWorkspace;
1637 openbox_attrib.workspace = workspace_number;
1641 void OpenboxWindow::shade(void) {
1642 if (!decorations.titlebar)
1646 XResizeWindow(display, frame.window, frame.width, frame.height);
1647 flags.shaded = False;
1648 openbox_attrib.flags ^= AttribShaded;
1649 openbox_attrib.attrib ^= AttribShaded;
1651 setState(NormalState);
1653 XResizeWindow(display, frame.window, frame.width, frame.title_h);
1654 flags.shaded = True;
1655 openbox_attrib.flags |= AttribShaded;
1656 openbox_attrib.attrib |= AttribShaded;
1658 setState(IconicState);
1663 void OpenboxWindow::stick(void) {
1665 openbox_attrib.flags ^= AttribOmnipresent;
1666 openbox_attrib.attrib ^= AttribOmnipresent;
1668 flags.stuck = False;
1671 screen->reassociateWindow(this, -1, True);
1673 setState(current_state);
1677 openbox_attrib.flags |= AttribOmnipresent;
1678 openbox_attrib.attrib |= AttribOmnipresent;
1680 setState(current_state);
1685 void OpenboxWindow::setFocusFlag(Bool focus) {
1686 flags.focused = focus;
1688 if (decorations.titlebar) {
1689 if (flags.focused) {
1691 XSetWindowBackgroundPixmap(display, frame.title, frame.ftitle);
1693 XSetWindowBackground(display, frame.title, frame.ftitle_pixel);
1696 XSetWindowBackgroundPixmap(display, frame.title, frame.utitle);
1698 XSetWindowBackground(display, frame.title, frame.utitle_pixel);
1700 XClearWindow(display, frame.title);
1706 if (decorations.handle) {
1707 if (flags.focused) {
1709 XSetWindowBackgroundPixmap(display, frame.handle, frame.fhandle);
1711 XSetWindowBackground(display, frame.handle, frame.fhandle_pixel);
1714 XSetWindowBackgroundPixmap(display, frame.right_grip, frame.fgrip);
1715 XSetWindowBackgroundPixmap(display, frame.left_grip, frame.fgrip);
1717 XSetWindowBackground(display, frame.right_grip, frame.fgrip_pixel);
1718 XSetWindowBackground(display, frame.left_grip, frame.fgrip_pixel);
1722 XSetWindowBackgroundPixmap(display, frame.handle, frame.uhandle);
1724 XSetWindowBackground(display, frame.handle, frame.uhandle_pixel);
1727 XSetWindowBackgroundPixmap(display, frame.right_grip, frame.ugrip);
1728 XSetWindowBackgroundPixmap(display, frame.left_grip, frame.ugrip);
1730 XSetWindowBackground(display, frame.right_grip, frame.ugrip_pixel);
1731 XSetWindowBackground(display, frame.left_grip, frame.ugrip_pixel);
1734 XClearWindow(display, frame.handle);
1735 XClearWindow(display, frame.right_grip);
1736 XClearWindow(display, frame.left_grip);
1739 if (decorations.border) {
1741 XSetWindowBorder(display, frame.plate, frame.fborder_pixel);
1743 XSetWindowBorder(display, frame.plate, frame.uborder_pixel);
1746 if (screen->sloppyFocus() && screen->autoRaise() && timer->isTiming())
1752 void OpenboxWindow::installColormap(Bool install) {
1754 if (! validateClient()) return;
1756 int i = 0, ncmap = 0;
1757 Colormap *cmaps = XListInstalledColormaps(display, client.window, &ncmap);
1758 XWindowAttributes wattrib;
1760 if (XGetWindowAttributes(display, client.window, &wattrib)) {
1762 // install the window's colormap
1763 for (i = 0; i < ncmap; i++) {
1764 if (*(cmaps + i) == wattrib.colormap)
1765 // this window is using an installed color map... do not install
1768 // otherwise, install the window's colormap
1770 XInstallColormap(display, wattrib.colormap);
1772 // uninstall the window's colormap
1773 for (i = 0; i < ncmap; i++) {
1774 if (*(cmaps + i) == wattrib.colormap)
1775 // we found the colormap to uninstall
1776 XUninstallColormap(display, wattrib.colormap);
1788 void OpenboxWindow::setState(unsigned long new_state) {
1789 if (! mapped) return;
1791 current_state = new_state;
1793 unsigned long state[2];
1794 state[0] = (unsigned long) current_state;
1795 state[1] = (unsigned long) None;
1796 XChangeProperty(display, client.window, openbox.getWMStateAtom(),
1797 openbox.getWMStateAtom(), 32, PropModeReplace,
1798 (unsigned char *) state, 2);
1800 XChangeProperty(display, client.window,
1801 openbox.getOpenboxAttributesAtom(),
1802 openbox.getOpenboxAttributesAtom(), 32, PropModeReplace,
1803 (unsigned char *) &openbox_attrib,
1804 PropOpenboxAttributesElements);
1808 Bool OpenboxWindow::getState(void) {
1814 unsigned long *state, ulfoo, nitems;
1816 if ((XGetWindowProperty(display, client.window, openbox.getWMStateAtom(),
1817 0l, 2l, False, openbox.getWMStateAtom(),
1818 &atom_return, &foo, &nitems, &ulfoo,
1819 (unsigned char **) &state) != Success) ||
1826 current_state = (unsigned long) state[0];
1831 XFree((void *) state);
1837 void OpenboxWindow::setGravityOffsets(void) {
1838 // x coordinates for each gravity type
1839 const int x_west = client.x;
1840 const int x_east = client.x + client.width - frame.width;
1841 const int x_center = client.x + client.width - frame.width/2;
1842 // y coordinates for each gravity type
1843 const int y_north = client.y;
1844 const int y_south = client.y + client.height - frame.height;
1845 const int y_center = client.y + client.height - frame.height/2;
1847 switch (client.win_gravity) {
1848 case NorthWestGravity:
1857 case NorthEastGravity:
1861 case SouthWestGravity:
1869 case SouthEastGravity:
1887 frame.x = client.x - frame.mwm_border_w + frame.border_w;
1888 frame.y = client.y - frame.y_border - frame.mwm_border_w - frame.border_w;
1894 void OpenboxWindow::restoreAttributes(void) {
1895 if (! getState()) current_state = NormalState;
1899 unsigned long ulfoo, nitems;
1901 OpenboxAttributes *net;
1902 int ret = XGetWindowProperty(display, client.window,
1903 openbox.getOpenboxAttributesAtom(), 0l,
1904 PropOpenboxAttributesElements, False,
1905 openbox.getOpenboxAttributesAtom(),
1906 &atom_return, &foo, &nitems, &ulfoo,
1907 (unsigned char **) &net);
1908 if (ret != Success || !net || nitems != PropOpenboxAttributesElements)
1911 openbox_attrib.flags = net->flags;
1912 openbox_attrib.attrib = net->attrib;
1913 openbox_attrib.decoration = net->decoration;
1914 openbox_attrib.workspace = net->workspace;
1915 openbox_attrib.stack = net->stack;
1916 openbox_attrib.premax_x = net->premax_x;
1917 openbox_attrib.premax_y = net->premax_y;
1918 openbox_attrib.premax_w = net->premax_w;
1919 openbox_attrib.premax_h = net->premax_h;
1921 XFree((void *) net);
1923 if (openbox_attrib.flags & AttribShaded &&
1924 openbox_attrib.attrib & AttribShaded) {
1926 ((current_state == IconicState) ? NormalState : current_state);
1928 flags.shaded = False;
1931 current_state = save_state;
1934 if (((int) openbox_attrib.workspace != screen->getCurrentWorkspaceID()) &&
1935 ((int) openbox_attrib.workspace < screen->getWorkspaceCount())) {
1936 screen->reassociateWindow(this, openbox_attrib.workspace, True);
1938 if (current_state == NormalState) current_state = WithdrawnState;
1939 } else if (current_state == WithdrawnState) {
1940 current_state = NormalState;
1943 if (openbox_attrib.flags & AttribOmnipresent &&
1944 openbox_attrib.attrib & AttribOmnipresent) {
1945 flags.stuck = False;
1948 current_state = NormalState;
1951 if ((openbox_attrib.flags & AttribMaxHoriz) ||
1952 (openbox_attrib.flags & AttribMaxVert)) {
1953 int x = openbox_attrib.premax_x, y = openbox_attrib.premax_y;
1954 unsigned int w = openbox_attrib.premax_w, h = openbox_attrib.premax_h;
1955 flags.maximized = 0;
1957 unsigned int m = False;
1958 if ((openbox_attrib.flags & AttribMaxHoriz) &&
1959 (openbox_attrib.flags & AttribMaxVert))
1960 m = (openbox_attrib.attrib & (AttribMaxHoriz | AttribMaxVert)) ? 1 : 0;
1961 else if (openbox_attrib.flags & AttribMaxVert)
1962 m = (openbox_attrib.attrib & AttribMaxVert) ? 2 : 0;
1963 else if (openbox_attrib.flags & AttribMaxHoriz)
1964 m = (openbox_attrib.attrib & AttribMaxHoriz) ? 3 : 0;
1968 openbox_attrib.premax_x = x;
1969 openbox_attrib.premax_y = y;
1970 openbox_attrib.premax_w = w;
1971 openbox_attrib.premax_h = h;
1974 setState(current_state);
1979 * The reverse of the setGravityOffsets function. Uses the frame window's
1980 * position to find the window's reference point.
1982 void OpenboxWindow::restoreGravity(void) {
1983 // x coordinates for each gravity type
1984 const int x_west = frame.x;
1985 const int x_east = frame.x + frame.width - client.width;
1986 const int x_center = frame.x + (frame.width/2) - client.width;
1987 // y coordinates for each gravity type
1988 const int y_north = frame.y;
1989 const int y_south = frame.y + frame.height - client.height;
1990 const int y_center = frame.y + (frame.height/2) - client.height;
1992 switch(client.win_gravity) {
1994 case NorthWestGravity:
1999 client.x = x_center;
2002 case NorthEastGravity:
2006 case SouthWestGravity:
2011 client.x = x_center;
2014 case SouthEastGravity:
2020 client.y = y_center;
2024 client.y = y_center;
2027 client.x = x_center;
2028 client.y = y_center;
2032 client.x = frame.x + frame.mwm_border_w + frame.border_w;
2033 client.y = frame.y + frame.y_border + frame.mwm_border_w +
2040 void OpenboxWindow::redrawLabel(void) {
2041 int dx = frame.bevel_w * 2, dlen = client.title_len;
2042 unsigned int l = client.title_text_w;
2044 if (flags.focused) {
2046 XSetWindowBackgroundPixmap(display, frame.label, frame.flabel);
2048 XSetWindowBackground(display, frame.label, frame.flabel_pixel);
2051 XSetWindowBackgroundPixmap(display, frame.label, frame.ulabel);
2053 XSetWindowBackground(display, frame.label, frame.ulabel_pixel);
2055 XClearWindow(display, frame.label);
2057 if (client.title_text_w > frame.label_w) {
2058 for (; dlen >= 0; dlen--) {
2059 if (i18n->multibyte()) {
2060 XRectangle ink, logical;
2061 XmbTextExtents(screen->getWindowStyle()->fontset, client.title, dlen,
2065 l = XTextWidth(screen->getWindowStyle()->font, client.title, dlen);
2067 l += (frame.bevel_w * 4);
2069 if (l < frame.label_w)
2074 switch (screen->getWindowStyle()->justify) {
2075 case BScreen::RightJustify:
2076 dx += frame.label_w - l;
2079 case BScreen::CenterJustify:
2080 dx += (frame.label_w - l) / 2;
2084 WindowStyle *style = screen->getWindowStyle();
2085 GC text_gc = (flags.focused) ? style->l_text_focus_gc :
2086 style->l_text_unfocus_gc;
2087 if (i18n->multibyte())
2088 XmbDrawString(display, frame.label, style->fontset, text_gc, dx,
2089 (1 - style->fontset_extents->max_ink_extent.y),
2090 client.title, dlen);
2092 XDrawString(display, frame.label, text_gc, dx,
2093 (style->font->ascent + 1), client.title, dlen);
2097 void OpenboxWindow::redrawAllButtons(void) {
2098 if (frame.iconify_button) redrawIconifyButton(False);
2099 if (frame.maximize_button) redrawMaximizeButton(flags.maximized);
2100 if (frame.close_button) redrawCloseButton(False);
2104 void OpenboxWindow::redrawIconifyButton(Bool pressed) {
2106 if (flags.focused) {
2108 XSetWindowBackgroundPixmap(display, frame.iconify_button,
2111 XSetWindowBackground(display, frame.iconify_button,
2112 frame.fbutton_pixel);
2115 XSetWindowBackgroundPixmap(display, frame.iconify_button,
2118 XSetWindowBackground(display, frame.iconify_button,
2119 frame.ubutton_pixel);
2123 XSetWindowBackgroundPixmap(display, frame.iconify_button, frame.pbutton);
2125 XSetWindowBackground(display, frame.iconify_button, frame.pbutton_pixel);
2127 XClearWindow(display, frame.iconify_button);
2129 XDrawRectangle(display, frame.iconify_button,
2130 ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc :
2131 screen->getWindowStyle()->b_pic_unfocus_gc),
2132 2, (frame.button_h - 5), (frame.button_w - 5), 2);
2136 void OpenboxWindow::redrawMaximizeButton(Bool pressed) {
2138 if (flags.focused) {
2140 XSetWindowBackgroundPixmap(display, frame.maximize_button,
2143 XSetWindowBackground(display, frame.maximize_button,
2144 frame.fbutton_pixel);
2147 XSetWindowBackgroundPixmap(display, frame.maximize_button,
2150 XSetWindowBackground(display, frame.maximize_button,
2151 frame.ubutton_pixel);
2155 XSetWindowBackgroundPixmap(display, frame.maximize_button,
2158 XSetWindowBackground(display, frame.maximize_button,
2159 frame.pbutton_pixel);
2161 XClearWindow(display, frame.maximize_button);
2163 XDrawRectangle(display, frame.maximize_button,
2164 ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc :
2165 screen->getWindowStyle()->b_pic_unfocus_gc),
2166 2, 2, (frame.button_w - 5), (frame.button_h - 5));
2167 XDrawLine(display, frame.maximize_button,
2168 ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc :
2169 screen->getWindowStyle()->b_pic_unfocus_gc),
2170 2, 3, (frame.button_w - 3), 3);
2174 void OpenboxWindow::redrawCloseButton(Bool pressed) {
2176 if (flags.focused) {
2178 XSetWindowBackgroundPixmap(display, frame.close_button,
2181 XSetWindowBackground(display, frame.close_button,
2182 frame.fbutton_pixel);
2185 XSetWindowBackgroundPixmap(display, frame.close_button,
2188 XSetWindowBackground(display, frame.close_button,
2189 frame.ubutton_pixel);
2193 XSetWindowBackgroundPixmap(display, frame.close_button, frame.pbutton);
2195 XSetWindowBackground(display, frame.close_button, frame.pbutton_pixel);
2197 XClearWindow(display, frame.close_button);
2199 XDrawLine(display, frame.close_button,
2200 ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc :
2201 screen->getWindowStyle()->b_pic_unfocus_gc), 2, 2,
2202 (frame.button_w - 3), (frame.button_h - 3));
2203 XDrawLine(display, frame.close_button,
2204 ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc :
2205 screen->getWindowStyle()->b_pic_unfocus_gc), 2,
2206 (frame.button_h - 3),
2207 (frame.button_w - 3), 2);
2211 void OpenboxWindow::mapRequestEvent(XMapRequestEvent *re) {
2212 if (re->window == client.window) {
2214 fprintf(stderr, i18n->getMessage(WindowSet, WindowMapRequest,
2215 "OpenboxWindow::mapRequestEvent() for 0x%lx\n"),
2220 if (! validateClient()) return;
2222 Bool get_state_ret = getState();
2223 if (! (get_state_ret && openbox.isStartup())) {
2224 if ((client.wm_hint_flags & StateHint) &&
2225 (! (current_state == NormalState || current_state == IconicState)))
2226 current_state = client.initial_state;
2228 current_state = NormalState;
2229 } else if (flags.iconic) {
2230 current_state = NormalState;
2235 switch (current_state) {
2240 case WithdrawnState:
2248 deiconify(False, True, True); // specify that we're initializing the
2258 void OpenboxWindow::mapNotifyEvent(XMapEvent *ne) {
2259 if ((ne->window == client.window) && (! ne->override_redirect)
2260 && (flags.visible)) {
2262 if (! validateClient()) return;
2264 setState(NormalState);
2266 if (flags.transient || screen->focusNew())
2269 setFocusFlag(False);
2271 flags.visible = True;
2272 flags.iconic = False;
2279 void OpenboxWindow::unmapNotifyEvent(XUnmapEvent *ue) {
2280 if (ue->window == client.window) {
2282 fprintf(stderr, i18n->getMessage(WindowSet, WindowUnmapNotify,
2283 "OpenboxWindow::unmapNotifyEvent() for 0x%lx\n"),
2288 if (! validateClient()) return;
2293 XChangeSaveSet(display, client.window, SetModeDelete);
2294 XSelectInput(display, client.window, NoEventMask);
2296 XDeleteProperty(display, client.window, openbox.getWMStateAtom());
2297 XDeleteProperty(display, client.window,
2298 openbox.getOpenboxAttributesAtom());
2300 XUnmapWindow(display, frame.window);
2301 XUnmapWindow(display, client.window);
2304 if (! XCheckTypedWindowEvent(display, client.window, ReparentNotify,
2307 fprintf(stderr, i18n->getMessage(WindowSet, WindowUnmapNotifyReparent,
2308 "OpenboxWindow::unmapNotifyEvent(): reparent 0x%lx to "
2309 "root.\n"), client.window);
2313 XReparentWindow(display, client.window, screen->getRootWindow(),
2314 client.x, client.y);
2326 void OpenboxWindow::destroyNotifyEvent(XDestroyWindowEvent *de) {
2327 if (de->window == client.window) {
2330 XUnmapWindow(display, frame.window);
2337 void OpenboxWindow::propertyNotifyEvent(Atom atom) {
2339 if (! validateClient()) return;
2343 case XA_WM_CLIENT_MACHINE:
2347 case XA_WM_TRANSIENT_FOR:
2348 // determine if this is a transient window
2350 if (XGetTransientForHint(display, client.window, &win)) {
2351 if (win && (win != client.window)) {
2352 if ((client.transient_for = openbox.searchWindow(win))) {
2353 client.transient_for->client.transient = this;
2354 flags.stuck = client.transient_for->flags.stuck;
2355 flags.transient = True;
2356 } else if (win == client.window_group) {
2357 //jr This doesn't look quite right...
2358 if ((client.transient_for = openbox.searchGroup(win, this))) {
2359 client.transient_for->client.transient = this;
2360 flags.stuck = client.transient_for->flags.stuck;
2361 flags.transient = True;
2366 if (win == screen->getRootWindow()) flags.modal = True;
2369 // adjust the window decorations based on transience
2370 if (flags.transient)
2371 decorations.maximize = decorations.handle = functions.maximize = False;
2381 case XA_WM_ICON_NAME:
2383 if (flags.iconic) screen->iconUpdate();
2389 if (decorations.titlebar)
2393 screen->getWorkspace(workspace_number)->update();
2397 case XA_WM_NORMAL_HINTS: {
2400 if ((client.normal_hint_flags & PMinSize) &&
2401 (client.normal_hint_flags & PMaxSize)) {
2402 if (client.max_width <= client.min_width &&
2403 client.max_height <= client.min_height)
2404 decorations.maximize = decorations.handle =
2405 functions.resize = functions.maximize = False;
2407 decorations.maximize = decorations.handle =
2408 functions.resize = functions.maximize = True;
2411 int x = frame.x, y = frame.y;
2412 unsigned int w = frame.width, h = frame.height;
2416 if ((x != frame.x) || (y != frame.y) ||
2417 (w != frame.width) || (h != frame.height))
2424 if (atom == openbox.getWMProtocolsAtom()) {
2427 if (decorations.close && (! frame.close_button)) {
2428 createCloseButton();
2429 if (decorations.titlebar) {
2433 if (windowmenu) windowmenu->reconfigure();
2444 void OpenboxWindow::exposeEvent(XExposeEvent *ee) {
2445 if (frame.label == ee->window && decorations.titlebar)
2447 else if (frame.close_button == ee->window)
2448 redrawCloseButton(False);
2449 else if (frame.maximize_button == ee->window)
2450 redrawMaximizeButton(flags.maximized);
2451 else if (frame.iconify_button == ee->window)
2452 redrawIconifyButton(False);
2456 void OpenboxWindow::configureRequestEvent(XConfigureRequestEvent *cr) {
2457 if (cr->window == client.window) {
2459 if (! validateClient()) return;
2461 int cx = frame.x, cy = frame.y;
2462 unsigned int cw = frame.width, ch = frame.height;
2464 if (cr->value_mask & CWBorderWidth)
2465 client.old_bw = cr->border_width;
2467 if (cr->value_mask & CWX)
2468 cx = cr->x - frame.mwm_border_w - frame.border_w;
2470 if (cr->value_mask & CWY)
2471 cy = cr->y - frame.y_border - frame.mwm_border_w -
2474 if (cr->value_mask & CWWidth)
2475 cw = cr->width + (frame.mwm_border_w * 2);
2477 if (cr->value_mask & CWHeight)
2478 ch = cr->height + frame.y_border + (frame.mwm_border_w * 2) +
2479 (frame.border_w * decorations.handle) + frame.handle_h;
2481 if (frame.x != cx || frame.y != cy ||
2482 frame.width != cw || frame.height != ch)
2483 configure(cx, cy, cw, ch);
2485 if (cr->value_mask & CWStackMode) {
2486 switch (cr->detail) {
2490 if (flags.iconic) deiconify();
2491 screen->getWorkspace(workspace_number)->raiseWindow(this);
2496 if (flags.iconic) deiconify();
2497 screen->getWorkspace(workspace_number)->lowerWindow(this);
2507 void OpenboxWindow::buttonPressEvent(XButtonEvent *be) {
2509 if (! validateClient())
2512 int stack_change = 1; // < 0 means to lower the window
2513 // > 0 means to raise the window
2514 // 0 means to leave it where it is
2516 // alt + left/right click begins interactively moving/resizing the window
2517 // when the mouse is moved
2518 if (be->state == Mod1Mask && (be->button == 1 || be->button == 3)) {
2519 if (be->button == 3) {
2520 if (screen->getWindowZones() == 4 &&
2521 be->y < (signed) frame.height / 2) {
2522 resize_zone = ZoneTop;
2524 resize_zone = ZoneBottom;
2526 if (screen->getWindowZones() >= 2 &&
2527 be->x < (signed) frame.width / 2) {
2528 resize_zone |= ZoneLeft;
2530 resize_zone |= ZoneRight;
2533 // control + left click on the titlebar shades the window
2534 } else if (be->state == ControlMask && be->button == 1) {
2535 if (be->window == frame.title ||
2536 be->window == frame.label)
2539 } else if (be->state == 0 && be->button == 1) {
2540 if (windowmenu && windowmenu->isVisible())
2543 if (be->window == frame.maximize_button) {
2544 redrawMaximizeButton(True);
2545 } else if (be->window == frame.iconify_button) {
2546 redrawIconifyButton(True);
2547 } else if (be->window == frame.close_button) {
2548 redrawCloseButton(True);
2549 } else if (be->window == frame.plate) {
2550 XAllowEvents(display, ReplayPointer, be->time);
2551 } else if (be->window == frame.title ||
2552 be->window == frame.label) {
2553 // shade the window when the titlebar is double clicked
2554 if ( (be->time - lastButtonPressTime) <=
2555 openbox.getDoubleClickInterval()) {
2556 lastButtonPressTime = 0;
2559 lastButtonPressTime = be->time;
2561 // clicking and dragging on the titlebar moves the window, so on a click
2562 // we need to save the coords of the click in case the user drags
2563 frame.grab_x = be->x_root - frame.x - frame.border_w;
2564 frame.grab_y = be->y_root - frame.y - frame.border_w;
2565 } else if (be->window == frame.handle ||
2566 be->window == frame.left_grip ||
2567 be->window == frame.right_grip ||
2568 be->window == frame.window) {
2569 // clicking and dragging on the window's frame moves the window, so on a
2570 // click we need to save the coords of the click in case the user drags
2571 frame.grab_x = be->x_root - frame.x - frame.border_w;
2572 frame.grab_y = be->y_root - frame.y - frame.border_w;
2573 if (be->window == frame.left_grip)
2574 resize_zone = ZoneBottom | ZoneLeft;
2575 else if (be->window == frame.right_grip)
2576 resize_zone = ZoneBottom | ZoneRight;
2579 } else if (be->state == 0 && be->button == 2) {
2580 if (be->window == frame.maximize_button) {
2581 redrawMaximizeButton(True);
2582 // a middle click anywhere on the window's frame except for on the buttons
2583 // will lower the window
2584 } else if (! (be->window == frame.iconify_button ||
2585 be->window == frame.close_button) ) {
2589 } else if (be->state == 0 && be->button == 3) {
2590 if (be->window == frame.maximize_button) {
2591 redrawMaximizeButton(True);
2592 // a right click on the window's frame will show or hide the window's
2594 } else if (be->window == frame.title ||
2595 be->window == frame.label ||
2596 be->window == frame.handle ||
2597 be->window == frame.window) {
2600 if (windowmenu->isVisible()) {
2603 // get the coords for the menu
2604 mx = be->x_root - windowmenu->getWidth() / 2;
2605 if (be->window == frame.title || be->window == frame.label) {
2606 my = frame.y + frame.title_h;
2607 } else if (be->window == frame.handle) {
2608 my = frame.y + frame.y_handle - windowmenu->getHeight();
2609 } else { // (be->window == frame.window)
2610 if (be->y <= (signed) frame.bevel_w) {
2611 my = frame.y + frame.y_border;
2613 my = be->y_root - (windowmenu->getHeight() / 2);
2617 if (mx > (signed) (frame.x + frame.width -
2618 windowmenu->getWidth())) {
2619 mx = frame.x + frame.width - windowmenu->getWidth();
2620 } else if (mx < frame.x) {
2624 if (my > (signed) (frame.y + frame.y_handle -
2625 windowmenu->getHeight())) {
2626 my = frame.y + frame.y_handle - windowmenu->getHeight();
2627 } else if (my < (signed) (frame.y +
2628 ((decorations.titlebar) ? frame.title_h : frame.y_border))) {
2630 ((decorations.titlebar) ? frame.title_h : frame.y_border);
2633 windowmenu->move(mx, my);
2635 XRaiseWindow(display, windowmenu->getWindowID());
2636 XRaiseWindow(display, windowmenu->getSendToMenu()->getWindowID());
2637 stack_change = 0; // dont raise the window overtop of the menu
2642 } else if (be->state == 0 && be->button == 4) {
2643 if ((be->window == frame.label ||
2644 be->window == frame.title) &&
2648 } else if (be->state == 0 && be->button == 5) {
2649 if ((be->window == frame.label ||
2650 be->window == frame.title) &&
2655 if (! (flags.focused || screen->sloppyFocus()) ) {
2656 setInputFocus(); // any click focus' the window in 'click to focus'
2658 if (stack_change < 0) {
2659 screen->getWorkspace(workspace_number)->lowerWindow(this);
2660 } else if (stack_change > 0) {
2661 screen->getWorkspace(workspace_number)->raiseWindow(this);
2668 void OpenboxWindow::buttonReleaseEvent(XButtonEvent *re) {
2670 if (! validateClient())
2673 // alt + middle button released
2674 if (re->state == (Mod1Mask & Button2Mask) && re->button == 2) {
2675 if (re->window == frame.window) {
2676 XUngrabPointer(display, CurrentTime); // why? i dont know
2678 // left button released
2679 } else if (re->button == 1) {
2680 if (re->window == frame.maximize_button) {
2681 if (re->state == Button1Mask && // only the left button was depressed
2682 (re->x >= 0) && ((unsigned) re->x <= frame.button_w) &&
2683 (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) {
2684 maximize(re->button);
2686 redrawMaximizeButton(False);
2688 } else if (re->window == frame.iconify_button) {
2689 if (re->state == Button1Mask && // only the left button was depressed
2690 (re->x >= 0) && ((unsigned) re->x <= frame.button_w) &&
2691 (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) {
2694 redrawIconifyButton(False);
2696 } else if (re->window == frame.close_button) {
2697 if (re->state == Button1Mask && // only the left button was depressed
2698 (re->x >= 0) && ((unsigned) re->x <= frame.button_w) &&
2699 (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) {
2702 //we should always redraw the close button. some applications
2703 //eg. acroread don't honour the close.
2704 redrawCloseButton(False);
2706 // middle button released
2707 } else if (re->button == 2) {
2708 if (re->window == frame.maximize_button) {
2709 if (re->state == Button2Mask && // only the middle button was depressed
2710 (re->x >= 0) && ((unsigned) re->x <= frame.button_w) &&
2711 (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) {
2712 maximize(re->button);
2714 redrawMaximizeButton(False);
2717 // right button released
2718 } else if (re->button == 3) {
2719 if (re->window == frame.maximize_button) {
2720 if (re->state == Button3Mask && // only the right button was depressed
2721 (re->x >= 0) && ((unsigned) re->x <= frame.button_w) &&
2722 (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) {
2723 maximize(re->button);
2725 redrawMaximizeButton(False);
2730 // when the window is being interactively moved, a button release stops the
2734 // when the window is being interactively resized, a button release stops the
2736 } else if (flags.resizing) {
2737 flags.resizing = False;
2738 XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
2739 frame.resize_x, frame.resize_y,
2740 frame.resize_w - 1, frame.resize_h - 1);
2741 screen->hideGeometry();
2742 // unset maximized state when resized after fully maximized
2743 if (flags.maximized == 1) {
2746 configure(frame.resize_x, frame.resize_y,
2747 frame.resize_w - (frame.border_w * 2),
2748 frame.resize_h - (frame.border_w * 2));
2750 XUngrabPointer(display, CurrentTime);
2758 void OpenboxWindow::startMove(int x, int y) {
2759 ASSERT(!flags.moving);
2761 // make sure only one window is moving at a time
2762 OpenboxWindow *w = openbox.getMaskedWindow();
2763 if (w != (OpenboxWindow *) 0 && w->flags.moving)
2766 XGrabPointer(display, frame.window, False, PointerMotionMask |
2767 ButtonReleaseMask, GrabModeAsync, GrabModeAsync,
2768 None, openbox.getMoveCursor(), CurrentTime);
2770 if (windowmenu && windowmenu->isVisible())
2773 flags.moving = True;
2775 openbox.maskWindowEvents(client.window, this);
2777 if (! screen->opaqueMove()) {
2780 frame.move_x = frame.x;
2781 frame.move_y = frame.y;
2782 frame.resize_w = frame.width + (frame.border_w * 2);
2783 frame.resize_h = ((flags.shaded) ? frame.title_h : frame.height) +
2784 (frame.border_w * 2);
2786 screen->showPosition(frame.x, frame.y);
2788 XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
2789 frame.move_x, frame.move_y,
2790 frame.resize_w - 1, frame.resize_h - 1);
2792 frame.grab_x = x - frame.x - frame.border_w;
2793 frame.grab_y = y - frame.y - frame.border_w;
2797 void OpenboxWindow::doMove(int x, int y) {
2798 ASSERT(flags.moving);
2800 int dx = x - frame.grab_x, dy = y - frame.grab_y;
2802 dx -= frame.border_w;
2803 dy -= frame.border_w;
2805 const int snap_distance = screen->edgeSnapThreshold();
2807 if (snap_distance) {
2809 const int wleft = dx,
2810 wright = dx + area().w() + (frame.border_w * 2) - 1,
2812 wbottom = dy + area().h() + (frame.border_w * 2) - 1;
2814 Workspace *w = screen->getWorkspace(getWorkspaceNumber());
2817 if (screen->windowToWindowSnap()) {
2818 // try snap to another window
2819 for (unsigned int i = 0, c = w->getCount(); i < c; ++i) {
2820 OpenboxWindow *snapwin = w->getWindow(i);
2821 if (snapwin == this)
2822 continue; // don't snap to self
2824 const Rect &winrect = snapwin->area();
2825 int dleft = std::abs(wright - winrect.left()),
2826 dright = std::abs(wleft - winrect.right()),
2827 dtop = std::abs(wbottom - winrect.top()),
2828 dbottom = std::abs(wtop - winrect.bottom());
2830 if (wtop >= (signed)(winrect.y() - area().h() - frame.border_w * 3) &&
2831 wtop < (signed)(winrect.y() + winrect.h() + frame.border_w * 3)) {
2833 // snap left of other window?
2834 if (dleft < snap_distance && dleft <= dright) {
2835 dx = winrect.left() - area().w() - (frame.border_w * 2);
2837 if (screen->windowCornerSnap()) {
2838 // try corner-snap to its other sides
2839 dtop = std::abs(wtop - winrect.top());
2840 dbottom = std::abs(wbottom - winrect.bottom());
2841 if (dtop < snap_distance && dtop <= dbottom)
2843 else if (dbottom < snap_distance)
2844 dy = winrect.bottom() - area().h() + frame.border_w;
2849 // snap right of other window?
2850 else if (dright < snap_distance) {
2851 dx = winrect.right() + (frame.border_w * 2) + 1;
2853 if (screen->windowCornerSnap()) {
2854 // try corner-snap to its other sides
2855 dtop = std::abs(wtop - winrect.top());
2856 dbottom = std::abs(wbottom - winrect.bottom());
2857 if (dtop < snap_distance && dtop <= dbottom)
2859 else if (dbottom < snap_distance)
2860 dy = winrect.bottom() - area().h() + frame.border_w;
2867 if (wleft >= (signed)(winrect.x() - area().w() - frame.border_w * 3) &&
2868 wleft < (signed)(winrect.x() + winrect.w() + frame.border_w * 3)) {
2870 // snap top of other window?
2871 if (dtop < snap_distance && dtop <= dbottom) {
2872 dy = winrect.top() - area().h() - (frame.border_w * 2);
2874 if (screen->windowCornerSnap()) {
2875 // try corner-snap to its other sides
2876 dleft = std::abs(wleft - winrect.left());
2877 dright = std::abs(wright - winrect.right());
2878 if (dleft < snap_distance && dleft <= dright)
2879 dx = winrect.left();
2880 else if (dright < snap_distance)
2881 dx = winrect.right() - area().w() + frame.border_w;
2886 // snap bottom of other window?
2887 else if (dbottom < snap_distance) {
2888 dy = winrect.bottom() + (frame.border_w * 2) + 1;
2890 if (screen->windowCornerSnap()) {
2891 // try corner-snap to its other sides
2892 dleft = std::abs(wleft - winrect.left());
2893 dright = std::abs(wright - winrect.right());
2894 if (dleft < snap_distance && dleft <= dright)
2895 dx = winrect.left();
2896 else if (dright < snap_distance)
2897 dx = winrect.right() - area().w() + frame.border_w;
2906 // try snap to the screen's available area
2907 Rect srect = screen->availableArea();
2909 int dleft = std::abs(wleft - srect.left()),
2910 dright = std::abs(wright - srect.right()),
2911 dtop = std::abs(wtop - srect.top()),
2912 dbottom = std::abs(wbottom - srect.bottom());
2915 if (dleft < snap_distance && dleft <= dright)
2918 else if (dright < snap_distance)
2919 dx = srect.right() - area().w() - (frame.border_w * 2) + 1;
2922 if (dtop < snap_distance && dtop <= dbottom)
2925 else if (dbottom < snap_distance)
2926 dy = srect.bottom() - area().h() - (frame.border_w * 2) + 1;
2928 if (! screen->fullMax()) {
2929 srect = Rect(Point(0,0), screen->size()); // now get the full screen
2931 dleft = std::abs(wleft - srect.left());
2932 dright = std::abs(wright - srect.right());
2933 dtop = std::abs(wtop - srect.top());
2934 dbottom = std::abs(wbottom - srect.bottom());
2937 if (dleft < snap_distance && dleft <= dright)
2940 else if (dright < snap_distance)
2941 dx = srect.right() - area().w() - (frame.border_w * 2) + 1;
2944 if (dtop < snap_distance && dtop <= dbottom)
2947 else if (dbottom < snap_distance)
2948 dy = srect.bottom() - area().h() - (frame.border_w * 2) + 1;
2954 if (screen->opaqueMove()) {
2955 configure(dx, dy, frame.width, frame.height);
2957 XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
2958 frame.move_x, frame.move_y, frame.resize_w - 1,
2959 frame.resize_h - 1);
2964 XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
2965 frame.move_x, frame.move_y, frame.resize_w - 1,
2966 frame.resize_h - 1);
2969 screen->showPosition(dx, dy);
2973 void OpenboxWindow::endMove() {
2974 ASSERT(flags.moving);
2976 flags.moving = False;
2978 openbox.maskWindowEvents(0, (OpenboxWindow *) 0);
2979 if (!screen->opaqueMove()) {
2980 XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
2981 frame.move_x, frame.move_y, frame.resize_w - 1,
2982 frame.resize_h - 1);
2984 configure(frame.move_x, frame.move_y, frame.width, frame.height);
2987 configure(frame.x, frame.y, frame.width, frame.height);
2989 screen->hideGeometry();
2990 XUngrabPointer(display, CurrentTime);
2991 // if there are any left over motions from the move, drop them now cuz they
2994 while (XCheckTypedWindowEvent(display, frame.window, MotionNotify, &e));
2998 void OpenboxWindow::motionNotifyEvent(XMotionEvent *me) {
3000 doMove(me->x_root, me->y_root);
3001 else if (!flags.resizing && (me->state & Button1Mask) && functions.move &&
3002 (frame.title == me->window || frame.label == me->window ||
3003 frame.handle == me->window || frame.window == me->window))
3004 startMove(me->x_root, me->y_root);
3005 else if (functions.resize &&
3006 (((me->state & Button1Mask) && (me->window == frame.right_grip ||
3007 me->window == frame.left_grip)) ||
3008 (me->state == (Mod1Mask | Button3Mask) &&
3009 me->window == frame.window))) {
3010 Bool left = resize_zone & ZoneLeft;
3012 if (! flags.resizing) {
3014 if (resize_zone & ZoneTop)
3015 cursor = (resize_zone & ZoneLeft) ?
3016 openbox.getUpperLeftAngleCursor() :
3017 openbox.getUpperRightAngleCursor();
3019 cursor = (resize_zone & ZoneLeft) ?
3020 openbox.getLowerLeftAngleCursor() :
3021 openbox.getLowerRightAngleCursor();
3022 XGrabPointer(display, me->window, False, ButtonMotionMask |
3023 ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None,
3024 cursor, CurrentTime);
3026 flags.resizing = True;
3031 if (resize_zone & ZoneRight)
3032 frame.grab_x = me->x - frame.border_w;
3034 frame.grab_x = me->x + frame.border_w;
3035 if (resize_zone & ZoneTop)
3036 frame.grab_y = me->y + (frame.border_w * 2);
3038 frame.grab_y = me->y - (frame.border_w * 2);
3039 frame.resize_x = frame.x;
3040 frame.resize_y = frame.y;
3041 frame.resize_w = frame.width + (frame.border_w * 2);
3042 frame.resize_h = frame.height + (frame.border_w * 2);
3045 left_fixsize(&gx, &gy);
3047 right_fixsize(&gx, &gy);
3049 screen->showGeometry(gx, gy);
3051 XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
3052 frame.resize_x, frame.resize_y,
3053 frame.resize_w - 1, frame.resize_h - 1);
3055 XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
3056 frame.resize_x, frame.resize_y,
3057 frame.resize_w - 1, frame.resize_h - 1);
3061 frame.resize_w = frame.width + (frame.border_w * 2);
3062 frame.resize_h = frame.height + (frame.border_w * 2);
3064 if (resize_zone & ZoneTop)
3065 frame.resize_h -= me->y - frame.grab_y;
3067 frame.resize_h += me->y - frame.grab_y;
3068 if (frame.resize_h < 1) frame.resize_h = 1;
3071 frame.resize_w += frame.grab_x - me->x;
3072 if (frame.resize_w < 1) frame.resize_w = 1;
3073 left_fixsize(&gx, &gy);
3075 frame.resize_w += me->x - frame.grab_x;
3076 if (frame.resize_w < 1) frame.resize_w = 1;
3077 right_fixsize(&gx, &gy);
3080 XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
3081 frame.resize_x, frame.resize_y,
3082 frame.resize_w - 1, frame.resize_h - 1);
3084 screen->showGeometry(gx, gy);
3091 void OpenboxWindow::shapeEvent(XShapeEvent *) {
3092 if (openbox.hasShapeExtensions()) {
3095 if (! validateClient()) return;
3096 XShapeCombineShape(display, frame.window, ShapeBounding,
3097 frame.mwm_border_w, frame.y_border +
3098 frame.mwm_border_w, client.window,
3099 ShapeBounding, ShapeSet);
3102 XRectangle xrect[2];
3103 xrect[0].x = xrect[0].y = 0;
3104 xrect[0].width = frame.width;
3105 xrect[0].height = frame.y_border;
3107 if (decorations.handle) {
3109 xrect[1].y = frame.y_handle;
3110 xrect[1].width = frame.width;
3111 xrect[1].height = frame.handle_h + frame.border_w;
3115 XShapeCombineRectangles(display, frame.window, ShapeBounding, 0, 0,
3116 xrect, num, ShapeUnion, Unsorted);
3124 bool OpenboxWindow::validateClient(void) {
3125 XSync(display, False);
3128 if (XCheckTypedWindowEvent(display, client.window, DestroyNotify, &e) ||
3129 XCheckTypedWindowEvent(display, client.window, UnmapNotify, &e)) {
3130 XPutBackEvent(display, &e);
3140 void OpenboxWindow::restore(void) {
3141 XChangeSaveSet(display, client.window, SetModeDelete);
3142 XSelectInput(display, client.window, NoEventMask);
3146 XUnmapWindow(display, frame.window);
3147 XUnmapWindow(display, client.window);
3149 XSetWindowBorderWidth(display, client.window, client.old_bw);
3150 XReparentWindow(display, client.window, screen->getRootWindow(),
3151 client.x, client.y);
3152 XMapWindow(display, client.window);
3160 void OpenboxWindow::timeout(void) {
3161 screen->getWorkspace(workspace_number)->raiseWindow(this);
3165 void OpenboxWindow::changeOpenboxHints(OpenboxHints *net) {
3166 if ((net->flags & AttribShaded) &&
3167 ((openbox_attrib.attrib & AttribShaded) !=
3168 (net->attrib & AttribShaded)))
3171 if (flags.visible && // watch out for requests when we can not be seen
3172 (net->flags & (AttribMaxVert | AttribMaxHoriz)) &&
3173 ((openbox_attrib.attrib & (AttribMaxVert | AttribMaxHoriz)) !=
3174 (net->attrib & (AttribMaxVert | AttribMaxHoriz)))) {
3175 if (flags.maximized) {
3180 if ((net->flags & AttribMaxHoriz) && (net->flags & AttribMaxVert))
3181 button = ((net->attrib & (AttribMaxHoriz | AttribMaxVert)) ? 1 : 0);
3182 else if (net->flags & AttribMaxVert)
3183 button = ((net->attrib & AttribMaxVert) ? 2 : 0);
3184 else if (net->flags & AttribMaxHoriz)
3185 button = ((net->attrib & AttribMaxHoriz) ? 3 : 0);
3191 if ((net->flags & AttribOmnipresent) &&
3192 ((openbox_attrib.attrib & AttribOmnipresent) !=
3193 (net->attrib & AttribOmnipresent)))
3196 if ((net->flags & AttribWorkspace) &&
3197 (workspace_number != (signed) net->workspace)) {
3198 screen->reassociateWindow(this, net->workspace, True);
3200 if (screen->getCurrentWorkspaceID() != (signed) net->workspace) withdraw();
3204 if (net->flags & AttribDecoration) {
3205 switch (net->decoration) {
3207 decorations.titlebar = decorations.border = decorations.handle =
3208 decorations.iconify = decorations.maximize = decorations.menu = False;
3214 decorations.titlebar = decorations.iconify = decorations.menu =
3215 decorations.border = True;
3216 decorations.handle = (functions.resize && !flags.transient);
3217 decorations.maximize = functions.maximize;
3222 decorations.titlebar = decorations.iconify = decorations.menu = True;
3223 decorations.border = decorations.border = decorations.handle = False;
3224 decorations.maximize = functions.maximize;
3229 decorations.titlebar = decorations.menu = True;
3230 decorations.iconify = decorations.border = False;
3231 decorations.handle = (functions.resize && !flags.transient);
3232 decorations.maximize = functions.maximize;
3237 XMapSubwindows(display, frame.window);
3238 XMapWindow(display, frame.window);
3242 setState(current_state);
3248 * Set the sizes of all components of the window frame
3249 * (the window decorations).
3250 * These values are based upon the current style settings and the client
3251 * window's dimentions.
3253 void OpenboxWindow::upsize(void) {
3254 frame.bevel_w = screen->getBevelWidth();
3256 if (decorations.border) {
3257 frame.border_w = screen->getBorderWidth();
3258 if (!flags.transient)
3259 frame.mwm_border_w = screen->getFrameWidth();
3261 frame.mwm_border_w = 0;
3263 frame.mwm_border_w = frame.border_w = 0;
3266 if (decorations.titlebar) {
3267 // the height of the titlebar is based upon the height of the font being
3268 // used to display the window's title
3269 WindowStyle *style = screen->getWindowStyle();
3270 if (i18n->multibyte())
3271 frame.title_h = (style->fontset_extents->max_ink_extent.height +
3272 (frame.bevel_w * 2) + 2);
3274 frame.title_h = (style->font->ascent + style->font->descent +
3275 (frame.bevel_w * 2) + 2);
3277 frame.label_h = frame.title_h - (frame.bevel_w * 2);
3278 frame.button_w = frame.button_h = (frame.label_h - 2);
3279 frame.y_border = frame.title_h + frame.border_w;
3283 frame.button_w = frame.button_h = 0;
3287 frame.border_h = client.height + frame.mwm_border_w * 2;
3289 if (decorations.handle) {
3290 frame.y_handle = frame.y_border + frame.border_h + frame.border_w;
3291 frame.grip_w = frame.button_w * 2;
3292 frame.grip_h = frame.handle_h = screen->getHandleWidth();
3294 frame.y_handle = frame.y_border + frame.border_h;
3296 frame.grip_w = frame.grip_h = 0;
3299 frame.width = client.width + (frame.mwm_border_w * 2);
3300 frame.height = frame.y_handle + frame.handle_h;
3305 * Set the size and position of the client window.
3306 * These values are based upon the current style settings and the frame
3307 * window's dimensions.
3309 void OpenboxWindow::downsize(void) {
3310 frame.y_handle = frame.height - frame.handle_h;
3311 frame.border_h = frame.y_handle - frame.y_border -
3312 (decorations.handle ? frame.border_w : 0);
3314 client.x = frame.x + frame.mwm_border_w + frame.border_w;
3315 client.y = frame.y + frame.y_border + frame.mwm_border_w + frame.border_w;
3317 client.width = frame.width - (frame.mwm_border_w * 2);
3318 client.height = frame.height - frame.y_border - (frame.mwm_border_w * 2)
3319 - frame.handle_h - (decorations.handle ? frame.border_w : 0);
3321 frame.y_handle = frame.border_h + frame.y_border + frame.border_w;
3325 void OpenboxWindow::right_fixsize(int *gx, int *gy) {
3326 // calculate the size of the client window and conform it to the
3327 // size specified by the size hints of the client window...
3328 int dx = frame.resize_w;
3329 int dy = frame.resize_h;
3331 // subtract the borders
3332 dx -= (frame.mwm_border_w * 2) + (frame.border_w * 2);
3333 dy -= frame.y_border + frame.handle_h + (frame.border_w * 3) +
3334 (frame.mwm_border_w * 2);
3336 dx += client.width_inc / 2;
3337 dy += client.height_inc / 2;
3339 if (dx < (signed) client.min_width) dx = client.min_width;
3340 if (dy < (signed) client.min_height) dy = client.min_height;
3341 if (dx > (signed) client.max_width) dx = client.max_width;
3342 if (dy > (signed) client.max_height) dy = client.max_height;
3344 dx -= client.base_width;
3345 dx /= client.width_inc;
3346 dy -= client.base_height;
3347 dy /= client.height_inc;
3352 dx *= client.width_inc;
3353 dx += client.base_width;
3354 dy *= client.height_inc;
3355 dy += client.base_height;
3358 dx += (frame.mwm_border_w * 2) + (frame.border_w * 2);
3359 dy += frame.y_border + frame.handle_h + (frame.border_w * 3) +
3360 (frame.mwm_border_w * 2);
3362 frame.resize_w = dx;
3363 frame.resize_h = dy;
3365 if (resize_zone & ZoneTop)
3366 frame.resize_y = frame.y + frame.height - frame.resize_h +
3367 screen->getBorderWidth() * 2;
3371 void OpenboxWindow::left_fixsize(int *gx, int *gy) {
3372 right_fixsize(gx, gy);
3374 frame.resize_x = frame.x + (frame.width + (frame.border_w * 2) -