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(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(WindowSet
, WindowXGetWindowAttributesFail
,
83 "OpenboxWindow::OpenboxWindow(): XGetWindowAttributes "
94 screen
= openbox
.searchScreen(RootWindowOfScreen(wattrib
.screen
));
97 fprintf(stderr
, i18n(WindowSet
, WindowCannotFindScreen
,
98 "OpenboxWindow::OpenboxWindow(): can't find screen\n"
99 "\tfor root window 0x%lx\n"),
100 RootWindowOfScreen(wattrib
.screen
));
108 flags
.moving
= flags
.resizing
= flags
.shaded
= flags
.visible
=
109 flags
.iconic
= flags
.transient
= flags
.focused
=
110 flags
.stuck
= flags
.modal
= flags
.send_focus_message
=
111 flags
.shaped
= flags
.managed
= False
;
114 openbox_attrib
.workspace
= workspace_number
= window_number
= -1;
116 openbox_attrib
.flags
= openbox_attrib
.attrib
= openbox_attrib
.stack
117 = openbox_attrib
.decoration
= 0l;
118 openbox_attrib
.premax_x
= openbox_attrib
.premax_y
= 0;
119 openbox_attrib
.premax_w
= openbox_attrib
.premax_h
= 0;
121 frame
.window
= frame
.plate
= frame
.title
= frame
.handle
= None
;
122 frame
.close_button
= frame
.iconify_button
= frame
.maximize_button
= None
;
123 frame
.right_grip
= frame
.left_grip
= None
;
125 frame
.utitle
= frame
.ftitle
= frame
.uhandle
= frame
.fhandle
= None
;
126 frame
.ulabel
= frame
.flabel
= frame
.ubutton
= frame
.fbutton
= None
;
127 frame
.pbutton
= frame
.ugrip
= frame
.fgrip
= None
;
129 decorations
.titlebar
= decorations
.border
= decorations
.handle
= True
;
130 decorations
.iconify
= decorations
.maximize
= decorations
.menu
= True
;
131 functions
.resize
= functions
.move
= functions
.iconify
=
132 functions
.maximize
= True
;
133 functions
.close
= decorations
.close
= False
;
135 client
.wm_hint_flags
= client
.normal_hint_flags
= 0;
136 client
.transient_for
= client
.transient
= 0;
138 client
.title_len
= 0;
139 client
.icon_title
= 0;
140 client
.mwm_hint
= (MwmHints
*) 0;
141 client
.openbox_hint
= (OpenboxHints
*) 0;
143 // get the initial size and location of client window (relative to the
144 // _root window_). This position is the reference point used with the
145 // window's gravity to find the window's initial position.
146 client
.x
= wattrib
.x
;
147 client
.y
= wattrib
.y
;
148 client
.width
= wattrib
.width
;
149 client
.height
= wattrib
.height
;
150 client
.old_bw
= wattrib
.border_width
;
153 lastButtonPressTime
= 0;
154 image_ctrl
= screen
->getImageControl();
156 timer
= new BTimer(openbox
, *this);
157 timer
->setTimeout(openbox
.getAutoRaiseDelay());
158 timer
->fireOnce(True
);
161 if (! client
.openbox_hint
)
164 // get size, aspect, minimum/maximum size and other hints set by the
171 if (client
.initial_state
== WithdrawnState
) {
172 screen
->getSlit()->addClient(client
.window
);
179 flags
.managed
= True
;
180 openbox
.saveWindowSearch(client
.window
, this);
182 // determine if this is a transient window
184 if (XGetTransientForHint(display
, client
.window
, &win
)) {
185 if (win
&& (win
!= client
.window
)) {
187 if ((tr
= openbox
.searchWindow(win
))) {
188 while (tr
->client
.transient
) tr
= tr
->client
.transient
;
189 client
.transient_for
= tr
;
190 tr
->client
.transient
= this;
191 flags
.stuck
= client
.transient_for
->flags
.stuck
;
192 flags
.transient
= True
;
193 } else if (win
== client
.window_group
) {
194 if ((tr
= openbox
.searchGroup(win
, this))) {
195 while (tr
->client
.transient
) tr
= tr
->client
.transient
;
196 client
.transient_for
= tr
;
197 tr
->client
.transient
= this;
198 flags
.stuck
= client
.transient_for
->flags
.stuck
;
199 flags
.transient
= True
;
204 if (win
== screen
->getRootWindow()) flags
.modal
= True
;
207 // adjust the window decorations based on transience and window sizes
209 decorations
.maximize
= decorations
.handle
= functions
.maximize
= False
;
211 if ((client
.normal_hint_flags
& PMinSize
) &&
212 (client
.normal_hint_flags
& PMaxSize
) &&
213 client
.max_width
<= client
.min_width
&&
214 client
.max_height
<= client
.min_height
) {
215 decorations
.maximize
= decorations
.handle
=
216 functions
.resize
= functions
.maximize
= False
;
221 if (openbox
.isStartup() || flags
.transient
||
222 client
.normal_hint_flags
& (PPosition
|USPosition
)) {
225 if ((openbox
.isStartup()) ||
227 (signed) (frame
.y
+ frame
.y_border
) >= 0 &&
228 frame
.x
<= (signed) screen
->size().w() &&
229 frame
.y
<= (signed) screen
->size().h()))
230 place_window
= false;
233 frame
.window
= createToplevelWindow(frame
.x
, frame
.y
, frame
.width
,
236 openbox
.saveWindowSearch(frame
.window
, this);
238 frame
.plate
= createChildWindow(frame
.window
);
239 openbox
.saveWindowSearch(frame
.plate
, this);
241 if (decorations
.titlebar
) {
242 frame
.title
= createChildWindow(frame
.window
);
243 frame
.label
= createChildWindow(frame
.title
);
244 openbox
.saveWindowSearch(frame
.title
, this);
245 openbox
.saveWindowSearch(frame
.label
, this);
248 if (decorations
.handle
) {
249 frame
.handle
= createChildWindow(frame
.window
);
250 openbox
.saveWindowSearch(frame
.handle
, this);
253 createChildWindow(frame
.handle
, openbox
.getLowerLeftAngleCursor());
254 openbox
.saveWindowSearch(frame
.left_grip
, this);
257 createChildWindow(frame
.handle
, openbox
.getLowerRightAngleCursor());
258 openbox
.saveWindowSearch(frame
.right_grip
, this);
261 associateClientWindow();
263 if (! screen
->sloppyFocus())
264 openbox
.grabButton(Button1
, 0, frame
.plate
, True
, ButtonPressMask
,
265 GrabModeSync
, GrabModeSync
, frame
.plate
, None
);
267 openbox
.grabButton(Button1
, Mod1Mask
, frame
.window
, True
,
268 ButtonReleaseMask
| ButtonMotionMask
, GrabModeAsync
,
269 GrabModeAsync
, frame
.window
, openbox
.getMoveCursor());
270 openbox
.grabButton(Button2
, Mod1Mask
, frame
.window
, True
,
271 ButtonReleaseMask
, GrabModeAsync
, GrabModeAsync
, frame
.window
, None
);
272 openbox
.grabButton(Button3
, Mod1Mask
, frame
.window
, True
,
273 ButtonReleaseMask
| ButtonMotionMask
, GrabModeAsync
,
274 GrabModeAsync
, frame
.window
, None
);
277 XRaiseWindow(display
, frame
.plate
);
278 XMapSubwindows(display
, frame
.plate
);
279 if (decorations
.titlebar
) XMapSubwindows(display
, frame
.title
);
280 XMapSubwindows(display
, frame
.window
);
282 if (decorations
.menu
)
283 windowmenu
= new Windowmenu(*this);
287 if (workspace_number
< 0 || workspace_number
>= screen
->getWorkspaceCount())
288 screen
->getCurrentWorkspace()->addWindow(this, place_window
);
290 screen
->getWorkspace(workspace_number
)->addWindow(this, place_window
);
292 configure(frame
.x
, frame
.y
, frame
.width
, frame
.height
);
295 flags
.shaded
= False
;
299 if (flags
.maximized
&& functions
.maximize
) {
300 unsigned int button
= flags
.maximized
;
311 OpenboxWindow::~OpenboxWindow(void) {
312 if (flags
.moving
|| flags
.resizing
) {
313 screen
->hideGeometry();
314 XUngrabPointer(display
, CurrentTime
);
317 if (workspace_number
!= -1 && window_number
!= -1) {
319 // make sure no other workspaces think that we're focused
320 for (int i
=0; i
< screen
->getWorkspaceCount(); i
++)
321 screen
->getWorkspace(i
)->removeWindow(this);
323 screen
->getWorkspace(workspace_number
)->removeWindow(this);
324 } else if (flags
.iconic
)
325 screen
->removeIcon(this);
328 if (timer
->isTiming()) timer
->stop();
332 if (windowmenu
) delete windowmenu
;
335 delete [] client
.title
;
337 if (client
.icon_title
)
338 delete [] client
.icon_title
;
341 XFree(client
.mwm_hint
);
343 if (client
.openbox_hint
)
344 XFree(client
.openbox_hint
);
346 if (client
.window_group
)
347 openbox
.removeGroupSearch(client
.window_group
);
349 if (flags
.transient
&& client
.transient_for
)
350 client
.transient_for
->client
.transient
= client
.transient
;
351 if (client
.transient
)
352 client
.transient
->client
.transient_for
= client
.transient_for
;
354 if (frame
.close_button
) {
355 openbox
.removeWindowSearch(frame
.close_button
);
356 XDestroyWindow(display
, frame
.close_button
);
359 if (frame
.iconify_button
) {
360 openbox
.removeWindowSearch(frame
.iconify_button
);
361 XDestroyWindow(display
, frame
.iconify_button
);
364 if (frame
.maximize_button
) {
365 openbox
.removeWindowSearch(frame
.maximize_button
);
366 XDestroyWindow(display
, frame
.maximize_button
);
371 image_ctrl
->removeImage(frame
.ftitle
);
374 image_ctrl
->removeImage(frame
.utitle
);
377 image_ctrl
->removeImage(frame
.flabel
);
380 image_ctrl
->removeImage(frame
.ulabel
);
382 openbox
.removeWindowSearch(frame
.label
);
383 openbox
.removeWindowSearch(frame
.title
);
384 XDestroyWindow(display
, frame
.label
);
385 XDestroyWindow(display
, frame
.title
);
390 image_ctrl
->removeImage(frame
.fhandle
);
393 image_ctrl
->removeImage(frame
.uhandle
);
396 image_ctrl
->removeImage(frame
.fgrip
);
399 image_ctrl
->removeImage(frame
.ugrip
);
401 openbox
.removeWindowSearch(frame
.handle
);
402 openbox
.removeWindowSearch(frame
.right_grip
);
403 openbox
.removeWindowSearch(frame
.left_grip
);
404 XDestroyWindow(display
, frame
.right_grip
);
405 XDestroyWindow(display
, frame
.left_grip
);
406 XDestroyWindow(display
, frame
.handle
);
410 image_ctrl
->removeImage(frame
.fbutton
);
413 image_ctrl
->removeImage(frame
.ubutton
);
416 image_ctrl
->removeImage(frame
.pbutton
);
419 openbox
.removeWindowSearch(frame
.plate
);
420 XDestroyWindow(display
, frame
.plate
);
424 openbox
.removeWindowSearch(frame
.window
);
425 XDestroyWindow(display
, frame
.window
);
429 openbox
.removeWindowSearch(client
.window
);
430 screen
->removeNetizen(client
.window
);
436 * Creates a new top level window, with a given location, size, and border
438 * Returns: the newly created window
440 Window
OpenboxWindow::createToplevelWindow(int x
, int y
, unsigned int width
,
442 unsigned int borderwidth
)
444 XSetWindowAttributes attrib_create
;
445 unsigned long create_mask
= CWBackPixmap
| CWBorderPixel
| CWColormap
|
446 CWOverrideRedirect
| CWEventMask
;
448 attrib_create
.background_pixmap
= None
;
449 attrib_create
.colormap
= screen
->getColormap();
450 attrib_create
.override_redirect
= True
;
451 attrib_create
.event_mask
= ButtonPressMask
| ButtonReleaseMask
|
452 ButtonMotionMask
| EnterWindowMask
;
454 return XCreateWindow(display
, screen
->getRootWindow(), x
, y
, width
, height
,
455 borderwidth
, screen
->getDepth(), InputOutput
,
456 screen
->getVisual(), create_mask
,
462 * Creates a child window, and optionally associates a given cursor with
465 Window
OpenboxWindow::createChildWindow(Window parent
, Cursor cursor
) {
466 XSetWindowAttributes attrib_create
;
467 unsigned long create_mask
= CWBackPixmap
| CWBorderPixel
|
470 attrib_create
.background_pixmap
= None
;
471 attrib_create
.event_mask
= ButtonPressMask
| ButtonReleaseMask
|
472 ButtonMotionMask
| ExposureMask
|
473 EnterWindowMask
| LeaveWindowMask
;
476 create_mask
|= CWCursor
;
477 attrib_create
.cursor
= cursor
;
480 return XCreateWindow(display
, parent
, 0, 0, 1, 1, 0, screen
->getDepth(),
481 InputOutput
, screen
->getVisual(), create_mask
,
486 void OpenboxWindow::associateClientWindow(void) {
487 XSetWindowBorderWidth(display
, client
.window
, 0);
491 XChangeSaveSet(display
, client
.window
, SetModeInsert
);
492 XSetWindowAttributes attrib_set
;
494 XSelectInput(display
, frame
.plate
, NoEventMask
);
495 XReparentWindow(display
, client
.window
, frame
.plate
, 0, 0);
496 XSelectInput(display
, frame
.plate
, SubstructureRedirectMask
);
500 attrib_set
.event_mask
= PropertyChangeMask
| StructureNotifyMask
|
502 attrib_set
.do_not_propagate_mask
= ButtonPressMask
| ButtonReleaseMask
|
505 XChangeWindowAttributes(display
, client
.window
, CWEventMask
|CWDontPropagate
,
509 if (openbox
.hasShapeExtensions()) {
510 XShapeSelectInput(display
, client
.window
, ShapeNotifyMask
);
515 XShapeQueryExtents(display
, client
.window
, &flags
.shaped
, &foo
, &foo
,
516 &ufoo
, &ufoo
, &foo
, &foo
, &foo
, &ufoo
, &ufoo
);
519 XShapeCombineShape(display
, frame
.window
, ShapeBounding
,
520 frame
.mwm_border_w
, frame
.y_border
+
521 frame
.mwm_border_w
, client
.window
,
522 ShapeBounding
, ShapeSet
);
526 xrect
[0].x
= xrect
[0].y
= 0;
527 xrect
[0].width
= frame
.width
;
528 xrect
[0].height
= frame
.y_border
;
530 if (decorations
.handle
) {
532 xrect
[1].y
= frame
.y_handle
;
533 xrect
[1].width
= frame
.width
;
534 xrect
[1].height
= frame
.handle_h
+ frame
.border_w
;
538 XShapeCombineRectangles(display
, frame
.window
, ShapeBounding
, 0, 0,
539 xrect
, num
, ShapeUnion
, Unsorted
);
544 if (decorations
.iconify
) createIconifyButton();
545 if (decorations
.maximize
) createMaximizeButton();
546 if (decorations
.close
) createCloseButton();
550 void OpenboxWindow::decorate(void) {
551 Pixmap tmp
= frame
.fbutton
;
552 BTexture
*texture
= &(screen
->getWindowStyle()->b_focus
);
553 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
554 frame
.fbutton
= None
;
555 frame
.fbutton_pixel
= texture
->getColor()->getPixel();
558 image_ctrl
->renderImage(frame
.button_w
, frame
.button_h
, texture
);
560 if (tmp
) image_ctrl
->removeImage(tmp
);
563 texture
= &(screen
->getWindowStyle()->b_unfocus
);
564 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
565 frame
.ubutton
= None
;
566 frame
.ubutton_pixel
= texture
->getColor()->getPixel();
569 image_ctrl
->renderImage(frame
.button_w
, frame
.button_h
, texture
);
571 if (tmp
) image_ctrl
->removeImage(tmp
);
574 texture
= &(screen
->getWindowStyle()->b_pressed
);
575 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
576 frame
.pbutton
= None
;
577 frame
.pbutton_pixel
= texture
->getColor()->getPixel();
580 image_ctrl
->renderImage(frame
.button_w
, frame
.button_h
, texture
);
582 if (tmp
) image_ctrl
->removeImage(tmp
);
584 if (decorations
.titlebar
) {
586 texture
= &(screen
->getWindowStyle()->t_focus
);
587 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
589 frame
.ftitle_pixel
= texture
->getColor()->getPixel();
592 image_ctrl
->renderImage(frame
.width
, frame
.title_h
, texture
);
594 if (tmp
) image_ctrl
->removeImage(tmp
);
597 texture
= &(screen
->getWindowStyle()->t_unfocus
);
598 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
600 frame
.utitle_pixel
= texture
->getColor()->getPixel();
603 image_ctrl
->renderImage(frame
.width
, frame
.title_h
, texture
);
605 if (tmp
) image_ctrl
->removeImage(tmp
);
607 XSetWindowBorder(display
, frame
.title
,
608 screen
->getBorderColor()->getPixel());
613 if (decorations
.border
) {
614 frame
.fborder_pixel
= screen
->getWindowStyle()->f_focus
.getPixel();
615 frame
.uborder_pixel
= screen
->getWindowStyle()->f_unfocus
.getPixel();
616 openbox_attrib
.flags
|= AttribDecoration
;
617 openbox_attrib
.decoration
= DecorNormal
;
619 openbox_attrib
.flags
|= AttribDecoration
;
620 openbox_attrib
.decoration
= DecorNone
;
623 if (decorations
.handle
) {
625 texture
= &(screen
->getWindowStyle()->h_focus
);
626 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
627 frame
.fhandle
= None
;
628 frame
.fhandle_pixel
= texture
->getColor()->getPixel();
631 image_ctrl
->renderImage(frame
.width
, frame
.handle_h
, texture
);
633 if (tmp
) image_ctrl
->removeImage(tmp
);
636 texture
= &(screen
->getWindowStyle()->h_unfocus
);
637 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
638 frame
.uhandle
= None
;
639 frame
.uhandle_pixel
= texture
->getColor()->getPixel();
642 image_ctrl
->renderImage(frame
.width
, frame
.handle_h
, texture
);
644 if (tmp
) image_ctrl
->removeImage(tmp
);
647 texture
= &(screen
->getWindowStyle()->g_focus
);
648 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
650 frame
.fgrip_pixel
= texture
->getColor()->getPixel();
653 image_ctrl
->renderImage(frame
.grip_w
, frame
.grip_h
, texture
);
655 if (tmp
) image_ctrl
->removeImage(tmp
);
658 texture
= &(screen
->getWindowStyle()->g_unfocus
);
659 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
661 frame
.ugrip_pixel
= texture
->getColor()->getPixel();
664 image_ctrl
->renderImage(frame
.grip_w
, frame
.grip_h
, texture
);
666 if (tmp
) image_ctrl
->removeImage(tmp
);
668 XSetWindowBorder(display
, frame
.handle
,
669 screen
->getBorderColor()->getPixel());
670 XSetWindowBorder(display
, frame
.left_grip
,
671 screen
->getBorderColor()->getPixel());
672 XSetWindowBorder(display
, frame
.right_grip
,
673 screen
->getBorderColor()->getPixel());
676 XSetWindowBorder(display
, frame
.window
,
677 screen
->getBorderColor()->getPixel());
681 void OpenboxWindow::decorateLabel(void) {
682 Pixmap tmp
= frame
.flabel
;
683 BTexture
*texture
= &(screen
->getWindowStyle()->l_focus
);
684 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
686 frame
.flabel_pixel
= texture
->getColor()->getPixel();
689 image_ctrl
->renderImage(frame
.label_w
, frame
.label_h
, texture
);
691 if (tmp
) image_ctrl
->removeImage(tmp
);
694 texture
= &(screen
->getWindowStyle()->l_unfocus
);
695 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
697 frame
.ulabel_pixel
= texture
->getColor()->getPixel();
700 image_ctrl
->renderImage(frame
.label_w
, frame
.label_h
, texture
);
702 if (tmp
) image_ctrl
->removeImage(tmp
);
706 void OpenboxWindow::createCloseButton(void) {
707 if (decorations
.close
&& frame
.title
!= None
) {
708 frame
.close_button
= createChildWindow(frame
.title
);
709 openbox
.saveWindowSearch(frame
.close_button
, this);
714 void OpenboxWindow::createIconifyButton(void) {
715 if (decorations
.iconify
&& frame
.title
!= None
) {
716 frame
.iconify_button
= createChildWindow(frame
.title
);
717 openbox
.saveWindowSearch(frame
.iconify_button
, this);
722 void OpenboxWindow::createMaximizeButton(void) {
723 if (decorations
.maximize
&& frame
.title
!= None
) {
724 frame
.maximize_button
= createChildWindow(frame
.title
);
725 openbox
.saveWindowSearch(frame
.maximize_button
, this);
730 void OpenboxWindow::positionButtons() {
731 const char *format
= openbox
.getTitleBarLayout();
732 const unsigned int bw
= frame
.bevel_w
+ 1;
733 const unsigned int by
= frame
.bevel_w
+ 1;
734 unsigned int bx
= frame
.bevel_w
+ 1;
735 unsigned int bcount
= strlen(format
) - 1;
737 if (!decorations
.close
)
739 if (!decorations
.maximize
)
741 if (!decorations
.iconify
)
743 frame
.label_w
= frame
.width
- bx
* 2 - (frame
.button_w
+ bw
) * bcount
;
745 bool hasclose
, hasiconify
, hasmaximize
;
746 hasclose
= hasiconify
= hasmaximize
= false;
748 for (int i
= 0; format
[i
] != '\0' && i
< 4; i
++) {
751 if (decorations
.close
) {
752 if (frame
.close_button
== None
)
754 XMoveResizeWindow(display
, frame
.close_button
, bx
, by
,
755 frame
.button_w
, frame
.button_h
);
756 XMapWindow(display
, frame
.close_button
);
757 XClearWindow(display
, frame
.close_button
);
758 bx
+= frame
.button_w
+ bw
;
763 if (decorations
.iconify
) {
764 if (frame
.iconify_button
== None
)
765 createIconifyButton();
766 XMoveResizeWindow(display
, frame
.iconify_button
, bx
, by
,
767 frame
.button_w
, frame
.button_h
);
768 XMapWindow(display
, frame
.iconify_button
);
769 XClearWindow(display
, frame
.iconify_button
);
770 bx
+= frame
.button_w
+ bw
;
775 if (decorations
.maximize
) {
776 if (frame
.maximize_button
== None
)
777 createMaximizeButton();
778 XMoveResizeWindow(display
, frame
.maximize_button
, bx
, by
,
779 frame
.button_w
, frame
.button_h
);
780 XMapWindow(display
, frame
.maximize_button
);
781 XClearWindow(display
, frame
.maximize_button
);
782 bx
+= frame
.button_w
+ bw
;
787 XMoveResizeWindow(display
, frame
.label
, bx
, by
- 1,
788 frame
.label_w
, frame
.label_h
);
789 bx
+= frame
.label_w
+ bw
;
794 if (!hasclose
&& frame
.close_button
) {
795 openbox
.removeWindowSearch(frame
.close_button
);
796 XDestroyWindow(display
, frame
.close_button
);
797 frame
.close_button
= None
;
799 if (!hasiconify
&& frame
.iconify_button
) {
800 openbox
.removeWindowSearch(frame
.iconify_button
);
801 XDestroyWindow(display
, frame
.iconify_button
);
802 frame
.iconify_button
= None
;
804 if (!hasmaximize
&& frame
.iconify_button
) {
805 openbox
.removeWindowSearch(frame
.maximize_button
);
806 XDestroyWindow(display
, frame
.maximize_button
);
807 frame
.maximize_button
= None
;
815 void OpenboxWindow::reconfigure(void) {
818 client
.x
= frame
.x
+ frame
.mwm_border_w
+ frame
.border_w
;
819 client
.y
= frame
.y
+ frame
.y_border
+ frame
.mwm_border_w
+
823 if (i18n
.multibyte()) {
824 XRectangle ink
, logical
;
825 XmbTextExtents(screen
->getWindowStyle()->fontset
,
826 client
.title
, client
.title_len
, &ink
, &logical
);
827 client
.title_text_w
= logical
.width
;
829 client
.title_text_w
= XTextWidth(screen
->getWindowStyle()->font
,
830 client
.title
, client
.title_len
);
832 client
.title_text_w
+= (frame
.bevel_w
* 4);
838 XClearWindow(display
, frame
.window
);
839 setFocusFlag(flags
.focused
);
841 configure(frame
.x
, frame
.y
, frame
.width
, frame
.height
);
843 if (! screen
->sloppyFocus())
844 openbox
.grabButton(Button1
, 0, frame
.plate
, True
, ButtonPressMask
,
845 GrabModeSync
, GrabModeSync
, None
, None
);
847 openbox
.ungrabButton(Button1
, 0, frame
.plate
);
850 windowmenu
->move(windowmenu
->getX(), frame
.y
+ frame
.title_h
);
851 windowmenu
->reconfigure();
854 // re-get the timeout delay
855 timer
->setTimeout(openbox
.getAutoRaiseDelay());
859 void OpenboxWindow::positionWindows(void) {
860 XResizeWindow(display
, frame
.window
, frame
.width
,
861 ((flags
.shaded
) ? frame
.title_h
: frame
.height
));
862 XSetWindowBorderWidth(display
, frame
.window
, frame
.border_w
);
863 XSetWindowBorderWidth(display
, frame
.plate
, frame
.mwm_border_w
);
864 XMoveResizeWindow(display
, frame
.plate
, 0, frame
.y_border
,
865 client
.width
, client
.height
);
866 XMoveResizeWindow(display
, client
.window
, 0, 0, client
.width
, client
.height
);
868 if (decorations
.titlebar
) {
869 XSetWindowBorderWidth(display
, frame
.title
, frame
.border_w
);
870 XMoveResizeWindow(display
, frame
.title
, -frame
.border_w
,
871 -frame
.border_w
, frame
.width
, frame
.title_h
);
874 } else if (frame
.title
) {
875 XUnmapWindow(display
, frame
.title
);
877 if (decorations
.handle
) {
878 XSetWindowBorderWidth(display
, frame
.handle
, frame
.border_w
);
879 XSetWindowBorderWidth(display
, frame
.left_grip
, frame
.border_w
);
880 XSetWindowBorderWidth(display
, frame
.right_grip
, frame
.border_w
);
882 XMoveResizeWindow(display
, frame
.handle
, -frame
.border_w
,
883 frame
.y_handle
- frame
.border_w
,
884 frame
.width
, frame
.handle_h
);
885 XMoveResizeWindow(display
, frame
.left_grip
, -frame
.border_w
,
886 -frame
.border_w
, frame
.grip_w
, frame
.grip_h
);
887 XMoveResizeWindow(display
, frame
.right_grip
,
888 frame
.width
- frame
.grip_w
- frame
.border_w
,
889 -frame
.border_w
, frame
.grip_w
, frame
.grip_h
);
890 XMapSubwindows(display
, frame
.handle
);
891 } else if (frame
.handle
) {
892 XUnmapWindow(display
, frame
.handle
);
897 void OpenboxWindow::getWMName(void) {
899 delete [] client
.title
;
900 client
.title
= (char *) 0;
903 XTextProperty text_prop
;
907 if (XGetWMName(display
, client
.window
, &text_prop
)) {
908 if (text_prop
.value
&& text_prop
.nitems
> 0) {
909 if (text_prop
.encoding
!= XA_STRING
) {
910 text_prop
.nitems
= strlen((char *) text_prop
.value
);
912 if ((XmbTextPropertyToTextList(display
, &text_prop
,
913 &list
, &num
) == Success
) &&
914 (num
> 0) && *list
) {
915 client
.title
= bstrdup(*list
);
916 XFreeStringList(list
);
918 client
.title
= bstrdup((char *) text_prop
.value
);
921 client
.title
= bstrdup((char *) text_prop
.value
);
923 XFree((char *) text_prop
.value
);
925 client
.title
= bstrdup(i18n(WindowSet
, WindowUnnamed
,
929 client
.title
= bstrdup(i18n(WindowSet
, WindowUnnamed
,
932 client
.title_len
= strlen(client
.title
);
934 if (i18n
.multibyte()) {
935 XRectangle ink
, logical
;
936 XmbTextExtents(screen
->getWindowStyle()->fontset
,
937 client
.title
, client
.title_len
, &ink
, &logical
);
938 client
.title_text_w
= logical
.width
;
940 client
.title_len
= strlen(client
.title
);
941 client
.title_text_w
= XTextWidth(screen
->getWindowStyle()->font
,
942 client
.title
, client
.title_len
);
945 client
.title_text_w
+= (frame
.bevel_w
* 4);
949 void OpenboxWindow::getWMIconName(void) {
950 if (client
.icon_title
) {
951 delete [] client
.icon_title
;
952 client
.icon_title
= (char *) 0;
955 XTextProperty text_prop
;
959 if (XGetWMIconName(display
, client
.window
, &text_prop
)) {
960 if (text_prop
.value
&& text_prop
.nitems
> 0) {
961 if (text_prop
.encoding
!= XA_STRING
) {
962 text_prop
.nitems
= strlen((char *) text_prop
.value
);
964 if ((XmbTextPropertyToTextList(display
, &text_prop
,
965 &list
, &num
) == Success
) &&
966 (num
> 0) && *list
) {
967 client
.icon_title
= bstrdup(*list
);
968 XFreeStringList(list
);
970 client
.icon_title
= bstrdup((char *) text_prop
.value
);
973 client
.icon_title
= bstrdup((char *) text_prop
.value
);
975 XFree((char *) text_prop
.value
);
977 client
.icon_title
= bstrdup(client
.title
);
980 client
.icon_title
= bstrdup(client
.title
);
986 * Retrieve which WM Protocols are supported by the client window.
987 * If the WM_DELETE_WINDOW protocol is supported, add the close button to the
988 * window's decorations and allow the close behavior.
989 * If the WM_TAKE_FOCUS protocol is supported, save a value that indicates
992 void OpenboxWindow::getWMProtocols(void) {
996 if (XGetWMProtocols(display
, client
.window
, &proto
, &num_return
)) {
997 for (int i
= 0; i
< num_return
; ++i
) {
998 if (proto
[i
] == openbox
.getWMDeleteAtom())
999 functions
.close
= decorations
.close
= True
;
1000 else if (proto
[i
] == openbox
.getWMTakeFocusAtom())
1001 flags
.send_focus_message
= True
;
1002 else if (proto
[i
] == openbox
.getOpenboxStructureMessagesAtom())
1003 screen
->addNetizen(new Netizen(*screen
, client
.window
));
1012 * Gets the value of the WM_HINTS property.
1013 * If the property is not set, then use a set of default values.
1015 void OpenboxWindow::getWMHints(void) {
1016 XWMHints
*wmhint
= XGetWMHints(display
, client
.window
);
1018 flags
.visible
= True
;
1019 flags
.iconic
= False
;
1020 focus_mode
= F_Passive
;
1021 client
.window_group
= None
;
1022 client
.initial_state
= NormalState
;
1025 client
.wm_hint_flags
= wmhint
->flags
;
1026 if (wmhint
->flags
& InputHint
) {
1027 if (wmhint
->input
== True
) {
1028 if (flags
.send_focus_message
)
1029 focus_mode
= F_LocallyActive
;
1031 focus_mode
= F_Passive
;
1033 if (flags
.send_focus_message
)
1034 focus_mode
= F_GloballyActive
;
1036 focus_mode
= F_NoInput
;
1039 focus_mode
= F_Passive
;
1042 if (wmhint
->flags
& StateHint
)
1043 client
.initial_state
= wmhint
->initial_state
;
1045 client
.initial_state
= NormalState
;
1047 if (wmhint
->flags
& WindowGroupHint
) {
1048 if (! client
.window_group
) {
1049 client
.window_group
= wmhint
->window_group
;
1050 openbox
.saveGroupSearch(client
.window_group
, this);
1053 client
.window_group
= None
;
1060 * Gets the value of the WM_NORMAL_HINTS property.
1061 * If the property is not set, then use a set of default values.
1063 void OpenboxWindow::getWMNormalHints(void) {
1065 XSizeHints sizehint
;
1067 client
.min_width
= client
.min_height
=
1068 client
.base_width
= client
.base_height
=
1069 client
.width_inc
= client
.height_inc
= 1;
1070 client
.max_width
= screen
->size().w();
1071 client
.max_height
= screen
->size().h();
1072 client
.min_aspect_x
= client
.min_aspect_y
=
1073 client
.max_aspect_x
= client
.max_aspect_y
= 1;
1074 client
.win_gravity
= NorthWestGravity
;
1076 if (! XGetWMNormalHints(display
, client
.window
, &sizehint
, &icccm_mask
))
1079 client
.normal_hint_flags
= sizehint
.flags
;
1081 if (sizehint
.flags
& PMinSize
) {
1082 client
.min_width
= sizehint
.min_width
;
1083 client
.min_height
= sizehint
.min_height
;
1086 if (sizehint
.flags
& PMaxSize
) {
1087 client
.max_width
= sizehint
.max_width
;
1088 client
.max_height
= sizehint
.max_height
;
1091 if (sizehint
.flags
& PResizeInc
) {
1092 client
.width_inc
= sizehint
.width_inc
;
1093 client
.height_inc
= sizehint
.height_inc
;
1096 if (sizehint
.flags
& PAspect
) {
1097 client
.min_aspect_x
= sizehint
.min_aspect
.x
;
1098 client
.min_aspect_y
= sizehint
.min_aspect
.y
;
1099 client
.max_aspect_x
= sizehint
.max_aspect
.x
;
1100 client
.max_aspect_y
= sizehint
.max_aspect
.y
;
1103 if (sizehint
.flags
& PBaseSize
) {
1104 client
.base_width
= sizehint
.base_width
;
1105 client
.base_height
= sizehint
.base_height
;
1108 if (sizehint
.flags
& PWinGravity
)
1109 client
.win_gravity
= sizehint
.win_gravity
;
1114 * Gets the MWM hints for the class' contained window.
1115 * This is used while initializing the window to its first state, and not
1117 * Returns: true if the MWM hints are successfully retreived and applied; false
1120 void OpenboxWindow::getMWMHints(void) {
1123 unsigned long num
, len
;
1125 int ret
= XGetWindowProperty(display
, client
.window
,
1126 openbox
.getMotifWMHintsAtom(), 0,
1127 PropMwmHintsElements
, False
,
1128 openbox
.getMotifWMHintsAtom(), &atom_return
,
1129 &format
, &num
, &len
,
1130 (unsigned char **) &client
.mwm_hint
);
1132 if (ret
!= Success
|| !client
.mwm_hint
|| num
!= PropMwmHintsElements
)
1135 if (client
.mwm_hint
->flags
& MwmHintsDecorations
) {
1136 if (client
.mwm_hint
->decorations
& MwmDecorAll
) {
1137 decorations
.titlebar
= decorations
.handle
= decorations
.border
=
1138 decorations
.iconify
= decorations
.maximize
=
1139 decorations
.close
= decorations
.menu
= True
;
1141 decorations
.titlebar
= decorations
.handle
= decorations
.border
=
1142 decorations
.iconify
= decorations
.maximize
=
1143 decorations
.close
= decorations
.menu
= False
;
1145 if (client
.mwm_hint
->decorations
& MwmDecorBorder
)
1146 decorations
.border
= True
;
1147 if (client
.mwm_hint
->decorations
& MwmDecorHandle
)
1148 decorations
.handle
= True
;
1149 if (client
.mwm_hint
->decorations
& MwmDecorTitle
)
1150 decorations
.titlebar
= True
;
1151 if (client
.mwm_hint
->decorations
& MwmDecorMenu
)
1152 decorations
.menu
= True
;
1153 if (client
.mwm_hint
->decorations
& MwmDecorIconify
)
1154 decorations
.iconify
= True
;
1155 if (client
.mwm_hint
->decorations
& MwmDecorMaximize
)
1156 decorations
.maximize
= True
;
1160 if (client
.mwm_hint
->flags
& MwmHintsFunctions
) {
1161 if (client
.mwm_hint
->functions
& MwmFuncAll
) {
1162 functions
.resize
= functions
.move
= functions
.iconify
=
1163 functions
.maximize
= functions
.close
= True
;
1165 functions
.resize
= functions
.move
= functions
.iconify
=
1166 functions
.maximize
= functions
.close
= False
;
1168 if (client
.mwm_hint
->functions
& MwmFuncResize
)
1169 functions
.resize
= True
;
1170 if (client
.mwm_hint
->functions
& MwmFuncMove
)
1171 functions
.move
= True
;
1172 if (client
.mwm_hint
->functions
& MwmFuncIconify
)
1173 functions
.iconify
= True
;
1174 if (client
.mwm_hint
->functions
& MwmFuncMaximize
)
1175 functions
.maximize
= True
;
1176 if (client
.mwm_hint
->functions
& MwmFuncClose
)
1177 functions
.close
= True
;
1184 * Gets the openbox hints from the class' contained window.
1185 * This is used while initializing the window to its first state, and not
1187 * Returns: true if the hints are successfully retreived and applied; false if
1190 void OpenboxWindow::getOpenboxHints(void) {
1193 unsigned long num
, len
;
1195 int ret
= XGetWindowProperty(display
, client
.window
,
1196 openbox
.getOpenboxHintsAtom(), 0,
1197 PropOpenboxHintsElements
, False
,
1198 openbox
.getOpenboxHintsAtom(), &atom_return
,
1199 &format
, &num
, &len
,
1200 (unsigned char **) &client
.openbox_hint
);
1201 if (ret
!= Success
|| !client
.openbox_hint
||
1202 num
!= PropOpenboxHintsElements
)
1205 if (client
.openbox_hint
->flags
& AttribShaded
)
1206 flags
.shaded
= (client
.openbox_hint
->attrib
& AttribShaded
);
1208 if ((client
.openbox_hint
->flags
& AttribMaxHoriz
) &&
1209 (client
.openbox_hint
->flags
& AttribMaxVert
))
1210 flags
.maximized
= (client
.openbox_hint
->attrib
&
1211 (AttribMaxHoriz
| AttribMaxVert
)) ? 1 : 0;
1212 else if (client
.openbox_hint
->flags
& AttribMaxVert
)
1213 flags
.maximized
= (client
.openbox_hint
->attrib
& AttribMaxVert
) ? 2 : 0;
1214 else if (client
.openbox_hint
->flags
& AttribMaxHoriz
)
1215 flags
.maximized
= (client
.openbox_hint
->attrib
& AttribMaxHoriz
) ? 3 : 0;
1217 if (client
.openbox_hint
->flags
& AttribOmnipresent
)
1218 flags
.stuck
= (client
.openbox_hint
->attrib
& AttribOmnipresent
);
1220 if (client
.openbox_hint
->flags
& AttribWorkspace
)
1221 workspace_number
= client
.openbox_hint
->workspace
;
1223 // if (client.openbox_hint->flags & AttribStack)
1224 // don't yet have always on top/bottom for openbox yet... working
1227 if (client
.openbox_hint
->flags
& AttribDecoration
) {
1228 switch (client
.openbox_hint
->decoration
) {
1230 decorations
.titlebar
= decorations
.border
= decorations
.handle
=
1231 decorations
.iconify
= decorations
.maximize
=
1232 decorations
.menu
= False
;
1233 functions
.resize
= functions
.move
= functions
.iconify
=
1234 functions
.maximize
= False
;
1239 decorations
.titlebar
= decorations
.iconify
= decorations
.menu
=
1240 functions
.move
= functions
.iconify
= True
;
1241 decorations
.border
= decorations
.handle
= decorations
.maximize
=
1242 functions
.resize
= functions
.maximize
= False
;
1247 decorations
.titlebar
= decorations
.menu
= functions
.move
= True
;
1248 decorations
.iconify
= decorations
.border
= decorations
.handle
=
1249 decorations
.maximize
= functions
.resize
= functions
.maximize
=
1250 functions
.iconify
= False
;
1256 decorations
.titlebar
= decorations
.border
= decorations
.handle
=
1257 decorations
.iconify
= decorations
.maximize
=
1258 decorations
.menu
= True
;
1259 functions
.resize
= functions
.move
= functions
.iconify
=
1260 functions
.maximize
= True
;
1270 void OpenboxWindow::configure(int dx
, int dy
,
1271 unsigned int dw
, unsigned int dh
) {
1272 Bool send_event
= (frame
.x
!= dx
|| frame
.y
!= dy
);
1274 if ((dw
!= frame
.width
) || (dh
!= frame
.height
)) {
1275 if ((((signed) frame
.width
) + dx
) < 0) dx
= 0;
1276 if ((((signed) frame
.height
) + dy
) < 0) dy
= 0;
1286 if (openbox
.hasShapeExtensions() && flags
.shaped
) {
1287 XShapeCombineShape(display
, frame
.window
, ShapeBounding
,
1288 frame
.mwm_border_w
, frame
.y_border
+
1289 frame
.mwm_border_w
, client
.window
,
1290 ShapeBounding
, ShapeSet
);
1293 XRectangle xrect
[2];
1294 xrect
[0].x
= xrect
[0].y
= 0;
1295 xrect
[0].width
= frame
.width
;
1296 xrect
[0].height
= frame
.y_border
;
1298 if (decorations
.handle
) {
1300 xrect
[1].y
= frame
.y_handle
;
1301 xrect
[1].width
= frame
.width
;
1302 xrect
[1].height
= frame
.handle_h
+ frame
.border_w
;
1306 XShapeCombineRectangles(display
, frame
.window
, ShapeBounding
, 0, 0,
1307 xrect
, num
, ShapeUnion
, Unsorted
);
1311 XMoveWindow(display
, frame
.window
, frame
.x
, frame
.y
);
1313 setFocusFlag(flags
.focused
);
1320 XMoveWindow(display
, frame
.window
, frame
.x
, frame
.y
);
1322 if (! flags
.moving
) send_event
= True
;
1325 if (send_event
&& ! flags
.moving
) {
1326 client
.x
= dx
+ frame
.mwm_border_w
+ frame
.border_w
;
1327 client
.y
= dy
+ frame
.y_border
+ frame
.mwm_border_w
+
1331 event
.type
= ConfigureNotify
;
1333 event
.xconfigure
.display
= display
;
1334 event
.xconfigure
.event
= client
.window
;
1335 event
.xconfigure
.window
= client
.window
;
1336 event
.xconfigure
.x
= client
.x
;
1337 event
.xconfigure
.y
= client
.y
;
1338 event
.xconfigure
.width
= client
.width
;
1339 event
.xconfigure
.height
= client
.height
;
1340 event
.xconfigure
.border_width
= client
.old_bw
;
1341 event
.xconfigure
.above
= frame
.window
;
1342 event
.xconfigure
.override_redirect
= False
;
1344 XSendEvent(display
, client
.window
, True
, NoEventMask
, &event
);
1346 screen
->updateNetizenConfigNotify(&event
);
1351 bool OpenboxWindow::setInputFocus(void) {
1352 if (((signed) (frame
.x
+ frame
.width
)) < 0) {
1353 if (((signed) (frame
.y
+ frame
.y_border
)) < 0)
1354 configure(frame
.border_w
, frame
.border_w
, frame
.width
, frame
.height
);
1355 else if (frame
.y
> (signed) screen
->size().h())
1356 configure(frame
.border_w
, screen
->size().h() - frame
.height
,
1357 frame
.width
, frame
.height
);
1359 configure(frame
.border_w
, frame
.y
+ frame
.border_w
,
1360 frame
.width
, frame
.height
);
1361 } else if (frame
.x
> (signed) screen
->size().w()) {
1362 if (((signed) (frame
.y
+ frame
.y_border
)) < 0)
1363 configure(screen
->size().w() - frame
.width
, frame
.border_w
,
1364 frame
.width
, frame
.height
);
1365 else if (frame
.y
> (signed) screen
->size().h())
1366 configure(screen
->size().w() - frame
.width
,
1367 screen
->size().h() - frame
.height
, frame
.width
, frame
.height
);
1369 configure(screen
->size().w() - frame
.width
,
1370 frame
.y
+ frame
.border_w
, frame
.width
, frame
.height
);
1374 if (! validateClient()) return False
;
1378 if (client
.transient
&& flags
.modal
) {
1379 ret
= client
.transient
->setInputFocus();
1380 } else if (! flags
.focused
) {
1381 if (focus_mode
== F_LocallyActive
|| focus_mode
== F_Passive
) {
1382 XSetInputFocus(display
, client
.window
,
1383 RevertToPointerRoot
, CurrentTime
);
1384 openbox
.focusWindow(this);
1386 if (flags
.send_focus_message
) {
1388 ce
.xclient
.type
= ClientMessage
;
1389 ce
.xclient
.message_type
= openbox
.getWMProtocolsAtom();
1390 ce
.xclient
.display
= display
;
1391 ce
.xclient
.window
= client
.window
;
1392 ce
.xclient
.format
= 32;
1393 ce
.xclient
.data
.l
[0] = openbox
.getWMTakeFocusAtom();
1394 ce
.xclient
.data
.l
[1] = openbox
.getLastTime();
1395 ce
.xclient
.data
.l
[2] = 0l;
1396 ce
.xclient
.data
.l
[3] = 0l;
1397 ce
.xclient
.data
.l
[4] = 0l;
1398 XSendEvent(display
, client
.window
, False
, NoEventMask
, &ce
);
1401 if (screen
->sloppyFocus() && screen
->autoRaise())
1414 void OpenboxWindow::iconify(void) {
1415 if (flags
.iconic
) return;
1420 if (windowmenu
) windowmenu
->hide();
1422 setState(IconicState
);
1424 XSelectInput(display
, client
.window
, NoEventMask
);
1425 XUnmapWindow(display
, client
.window
);
1426 XSelectInput(display
, client
.window
,
1427 PropertyChangeMask
| StructureNotifyMask
| FocusChangeMask
);
1429 XUnmapWindow(display
, frame
.window
);
1430 flags
.visible
= False
;
1431 flags
.iconic
= True
;
1433 screen
->getWorkspace(workspace_number
)->removeWindow(this);
1435 if (flags
.transient
&& client
.transient_for
&&
1436 !client
.transient_for
->flags
.iconic
) {
1437 client
.transient_for
->iconify();
1439 screen
->addIcon(this);
1441 if (client
.transient
&& !client
.transient
->flags
.iconic
) {
1442 client
.transient
->iconify();
1447 void OpenboxWindow::deiconify(bool reassoc
, bool raise
, bool initial
) {
1448 if (flags
.iconic
|| reassoc
)
1449 screen
->reassociateWindow(this, -1, False
);
1450 else if (workspace_number
!= screen
->getCurrentWorkspace()->getWorkspaceID())
1453 setState(NormalState
);
1455 XSelectInput(display
, client
.window
, NoEventMask
);
1456 XMapWindow(display
, client
.window
);
1457 XSelectInput(display
, client
.window
,
1458 PropertyChangeMask
| StructureNotifyMask
| FocusChangeMask
);
1460 XMapSubwindows(display
, frame
.window
);
1461 XMapWindow(display
, frame
.window
);
1463 // if we're using the click to place placement type, then immediately
1464 // after the window is mapped, we need to start interactively moving it
1465 if (initial
&& place_window
&&
1466 screen
->placementPolicy() == BScreen::ClickMousePlacement
) {
1470 XQueryPointer(openbox
.getXDisplay(), screen
->getRootWindow(),
1471 &r
, &c
, &rx
, &ry
, &x
, &y
, &m
);
1475 if (flags
.iconic
&& screen
->focusNew()) setInputFocus();
1477 flags
.visible
= True
;
1478 flags
.iconic
= False
;
1480 if (reassoc
&& client
.transient
) client
.transient
->deiconify(True
, False
);
1483 screen
->getWorkspace(workspace_number
)->raiseWindow(this);
1487 void OpenboxWindow::close(void) {
1489 ce
.xclient
.type
= ClientMessage
;
1490 ce
.xclient
.message_type
= openbox
.getWMProtocolsAtom();
1491 ce
.xclient
.display
= display
;
1492 ce
.xclient
.window
= client
.window
;
1493 ce
.xclient
.format
= 32;
1494 ce
.xclient
.data
.l
[0] = openbox
.getWMDeleteAtom();
1495 ce
.xclient
.data
.l
[1] = CurrentTime
;
1496 ce
.xclient
.data
.l
[2] = 0l;
1497 ce
.xclient
.data
.l
[3] = 0l;
1498 ce
.xclient
.data
.l
[4] = 0l;
1499 XSendEvent(display
, client
.window
, False
, NoEventMask
, &ce
);
1503 void OpenboxWindow::withdraw(void) {
1507 flags
.visible
= False
;
1508 flags
.iconic
= False
;
1510 XUnmapWindow(display
, frame
.window
);
1512 XSelectInput(display
, client
.window
, NoEventMask
);
1513 XUnmapWindow(display
, client
.window
);
1514 XSelectInput(display
, client
.window
,
1515 PropertyChangeMask
| StructureNotifyMask
| FocusChangeMask
);
1517 if (windowmenu
) windowmenu
->hide();
1521 void OpenboxWindow::maximize(unsigned int button
) {
1525 // handle case where menu is open then the max button is used instead
1526 if (windowmenu
&& windowmenu
->isVisible()) windowmenu
->hide();
1528 if (flags
.maximized
) {
1529 flags
.maximized
= 0;
1531 openbox_attrib
.flags
&= ! (AttribMaxHoriz
| AttribMaxVert
);
1532 openbox_attrib
.attrib
&= ! (AttribMaxHoriz
| AttribMaxVert
);
1534 // when a resize is begun, maximize(0) is called to clear any maximization
1535 // flags currently set. Otherwise it still thinks it is maximized.
1536 // so we do not need to call configure() because resizing will handle it
1537 if (!flags
.resizing
)
1538 configure(openbox_attrib
.premax_x
, openbox_attrib
.premax_y
,
1539 openbox_attrib
.premax_w
, openbox_attrib
.premax_h
);
1541 openbox_attrib
.premax_x
= openbox_attrib
.premax_y
= 0;
1542 openbox_attrib
.premax_w
= openbox_attrib
.premax_h
= 0;
1544 redrawMaximizeButton(flags
.maximized
);
1545 setState(current_state
);
1549 openbox_attrib
.premax_x
= frame
.x
;
1550 openbox_attrib
.premax_y
= frame
.y
;
1551 openbox_attrib
.premax_w
= frame
.width
;
1552 openbox_attrib
.premax_h
= frame
.height
;
1554 Rect space
= screen
->availableArea();
1555 unsigned int dw
= space
.w(),
1557 dw
-= frame
.border_w
* 2;
1558 dw
-= frame
.mwm_border_w
* 2;
1559 dw
-= client
.base_width
;
1561 dh
-= frame
.border_w
* 2;
1562 dh
-= frame
.mwm_border_w
* 2;
1563 dh
-= ((frame
.handle_h
+ frame
.border_w
) * decorations
.handle
);
1564 dh
-= client
.base_height
;
1565 dh
-= frame
.y_border
;
1567 if (dw
< client
.min_width
) dw
= client
.min_width
;
1568 if (dh
< client
.min_height
) dh
= client
.min_height
;
1569 if (dw
> client
.max_width
) dw
= client
.max_width
;
1570 if (dh
> client
.max_height
) dh
= client
.max_height
;
1572 dw
-= (dw
% client
.width_inc
);
1573 dw
+= client
.base_width
;
1574 dw
+= frame
.mwm_border_w
* 2;
1576 dh
-= (dh
% client
.height_inc
);
1577 dh
+= client
.base_height
;
1578 dh
+= frame
.y_border
;
1579 dh
+= ((frame
.handle_h
+ frame
.border_w
) * decorations
.handle
);
1580 dh
+= frame
.mwm_border_w
* 2;
1582 int dx
= space
.x() + ((space
.w() - dw
) / 2) - frame
.border_w
,
1583 dy
= space
.y() + ((space
.h() - dh
) / 2) - frame
.border_w
;
1587 openbox_attrib
.flags
|= AttribMaxHoriz
| AttribMaxVert
;
1588 openbox_attrib
.attrib
|= AttribMaxHoriz
| AttribMaxVert
;
1592 openbox_attrib
.flags
|= AttribMaxVert
;
1593 openbox_attrib
.attrib
|= AttribMaxVert
;
1600 openbox_attrib
.flags
|= AttribMaxHoriz
;
1601 openbox_attrib
.attrib
|= AttribMaxHoriz
;
1609 openbox_attrib
.flags
^= AttribShaded
;
1610 openbox_attrib
.attrib
^= AttribShaded
;
1611 flags
.shaded
= False
;
1614 flags
.maximized
= button
;
1616 configure(dx
, dy
, dw
, dh
);
1617 screen
->getWorkspace(workspace_number
)->raiseWindow(this);
1618 redrawMaximizeButton(flags
.maximized
);
1619 setState(current_state
);
1623 void OpenboxWindow::setWorkspace(int n
) {
1624 ASSERT(n
< screen
->getWorkspaceCount());
1625 workspace_number
= n
;
1627 openbox_attrib
.flags
|= AttribWorkspace
;
1628 openbox_attrib
.workspace
= workspace_number
;
1632 void OpenboxWindow::shade(void) {
1633 if (!decorations
.titlebar
)
1637 XResizeWindow(display
, frame
.window
, frame
.width
, frame
.height
);
1638 flags
.shaded
= False
;
1639 openbox_attrib
.flags
^= AttribShaded
;
1640 openbox_attrib
.attrib
^= AttribShaded
;
1642 setState(NormalState
);
1644 XResizeWindow(display
, frame
.window
, frame
.width
, frame
.title_h
);
1645 flags
.shaded
= True
;
1646 openbox_attrib
.flags
|= AttribShaded
;
1647 openbox_attrib
.attrib
|= AttribShaded
;
1649 setState(IconicState
);
1654 void OpenboxWindow::stick(void) {
1656 openbox_attrib
.flags
^= AttribOmnipresent
;
1657 openbox_attrib
.attrib
^= AttribOmnipresent
;
1659 flags
.stuck
= False
;
1662 screen
->reassociateWindow(this, -1, True
);
1664 setState(current_state
);
1668 openbox_attrib
.flags
|= AttribOmnipresent
;
1669 openbox_attrib
.attrib
|= AttribOmnipresent
;
1671 setState(current_state
);
1676 void OpenboxWindow::setFocusFlag(Bool focus
) {
1677 flags
.focused
= focus
;
1679 if (decorations
.titlebar
) {
1680 if (flags
.focused
) {
1682 XSetWindowBackgroundPixmap(display
, frame
.title
, frame
.ftitle
);
1684 XSetWindowBackground(display
, frame
.title
, frame
.ftitle_pixel
);
1687 XSetWindowBackgroundPixmap(display
, frame
.title
, frame
.utitle
);
1689 XSetWindowBackground(display
, frame
.title
, frame
.utitle_pixel
);
1691 XClearWindow(display
, frame
.title
);
1697 if (decorations
.handle
) {
1698 if (flags
.focused
) {
1700 XSetWindowBackgroundPixmap(display
, frame
.handle
, frame
.fhandle
);
1702 XSetWindowBackground(display
, frame
.handle
, frame
.fhandle_pixel
);
1705 XSetWindowBackgroundPixmap(display
, frame
.right_grip
, frame
.fgrip
);
1706 XSetWindowBackgroundPixmap(display
, frame
.left_grip
, frame
.fgrip
);
1708 XSetWindowBackground(display
, frame
.right_grip
, frame
.fgrip_pixel
);
1709 XSetWindowBackground(display
, frame
.left_grip
, frame
.fgrip_pixel
);
1713 XSetWindowBackgroundPixmap(display
, frame
.handle
, frame
.uhandle
);
1715 XSetWindowBackground(display
, frame
.handle
, frame
.uhandle_pixel
);
1718 XSetWindowBackgroundPixmap(display
, frame
.right_grip
, frame
.ugrip
);
1719 XSetWindowBackgroundPixmap(display
, frame
.left_grip
, frame
.ugrip
);
1721 XSetWindowBackground(display
, frame
.right_grip
, frame
.ugrip_pixel
);
1722 XSetWindowBackground(display
, frame
.left_grip
, frame
.ugrip_pixel
);
1725 XClearWindow(display
, frame
.handle
);
1726 XClearWindow(display
, frame
.right_grip
);
1727 XClearWindow(display
, frame
.left_grip
);
1730 if (decorations
.border
) {
1732 XSetWindowBorder(display
, frame
.plate
, frame
.fborder_pixel
);
1734 XSetWindowBorder(display
, frame
.plate
, frame
.uborder_pixel
);
1737 if (screen
->sloppyFocus() && screen
->autoRaise() && timer
->isTiming())
1743 void OpenboxWindow::installColormap(Bool install
) {
1745 if (! validateClient()) return;
1747 int i
= 0, ncmap
= 0;
1748 Colormap
*cmaps
= XListInstalledColormaps(display
, client
.window
, &ncmap
);
1749 XWindowAttributes wattrib
;
1751 if (XGetWindowAttributes(display
, client
.window
, &wattrib
)) {
1753 // install the window's colormap
1754 for (i
= 0; i
< ncmap
; i
++) {
1755 if (*(cmaps
+ i
) == wattrib
.colormap
)
1756 // this window is using an installed color map... do not install
1759 // otherwise, install the window's colormap
1761 XInstallColormap(display
, wattrib
.colormap
);
1763 // uninstall the window's colormap
1764 for (i
= 0; i
< ncmap
; i
++) {
1765 if (*(cmaps
+ i
) == wattrib
.colormap
)
1766 // we found the colormap to uninstall
1767 XUninstallColormap(display
, wattrib
.colormap
);
1779 void OpenboxWindow::setState(unsigned long new_state
) {
1780 current_state
= new_state
;
1782 unsigned long state
[2];
1783 state
[0] = (unsigned long) current_state
;
1784 state
[1] = (unsigned long) None
;
1785 XChangeProperty(display
, client
.window
, openbox
.getWMStateAtom(),
1786 openbox
.getWMStateAtom(), 32, PropModeReplace
,
1787 (unsigned char *) state
, 2);
1789 XChangeProperty(display
, client
.window
,
1790 openbox
.getOpenboxAttributesAtom(),
1791 openbox
.getOpenboxAttributesAtom(), 32, PropModeReplace
,
1792 (unsigned char *) &openbox_attrib
,
1793 PropOpenboxAttributesElements
);
1797 Bool
OpenboxWindow::getState(void) {
1803 unsigned long *state
, ulfoo
, nitems
;
1805 if ((XGetWindowProperty(display
, client
.window
, openbox
.getWMStateAtom(),
1806 0l, 2l, False
, openbox
.getWMStateAtom(),
1807 &atom_return
, &foo
, &nitems
, &ulfoo
,
1808 (unsigned char **) &state
) != Success
) ||
1815 current_state
= (unsigned long) state
[0];
1820 XFree((void *) state
);
1826 void OpenboxWindow::setGravityOffsets(void) {
1827 // x coordinates for each gravity type
1828 const int x_west
= client
.x
;
1829 const int x_east
= client
.x
+ client
.width
- frame
.width
;
1830 const int x_center
= client
.x
+ client
.width
- frame
.width
/2;
1831 // y coordinates for each gravity type
1832 const int y_north
= client
.y
;
1833 const int y_south
= client
.y
+ client
.height
- frame
.height
;
1834 const int y_center
= client
.y
+ client
.height
- frame
.height
/2;
1836 switch (client
.win_gravity
) {
1837 case NorthWestGravity
:
1846 case NorthEastGravity
:
1850 case SouthWestGravity
:
1858 case SouthEastGravity
:
1876 frame
.x
= client
.x
- frame
.mwm_border_w
+ frame
.border_w
;
1877 frame
.y
= client
.y
- frame
.y_border
- frame
.mwm_border_w
- frame
.border_w
;
1883 void OpenboxWindow::restoreAttributes(void) {
1884 if (! getState()) current_state
= NormalState
;
1888 unsigned long ulfoo
, nitems
;
1890 OpenboxAttributes
*net
;
1891 int ret
= XGetWindowProperty(display
, client
.window
,
1892 openbox
.getOpenboxAttributesAtom(), 0l,
1893 PropOpenboxAttributesElements
, False
,
1894 openbox
.getOpenboxAttributesAtom(),
1895 &atom_return
, &foo
, &nitems
, &ulfoo
,
1896 (unsigned char **) &net
);
1897 if (ret
!= Success
|| !net
|| nitems
!= PropOpenboxAttributesElements
)
1900 openbox_attrib
.flags
= net
->flags
;
1901 openbox_attrib
.attrib
= net
->attrib
;
1902 openbox_attrib
.decoration
= net
->decoration
;
1903 openbox_attrib
.workspace
= net
->workspace
;
1904 openbox_attrib
.stack
= net
->stack
;
1905 openbox_attrib
.premax_x
= net
->premax_x
;
1906 openbox_attrib
.premax_y
= net
->premax_y
;
1907 openbox_attrib
.premax_w
= net
->premax_w
;
1908 openbox_attrib
.premax_h
= net
->premax_h
;
1910 XFree((void *) net
);
1912 if (openbox_attrib
.flags
& AttribShaded
&&
1913 openbox_attrib
.attrib
& AttribShaded
) {
1915 ((current_state
== IconicState
) ? NormalState
: current_state
);
1917 flags
.shaded
= False
;
1920 current_state
= save_state
;
1923 if (((int) openbox_attrib
.workspace
!= screen
->getCurrentWorkspaceID()) &&
1924 ((int) openbox_attrib
.workspace
< screen
->getWorkspaceCount())) {
1925 screen
->reassociateWindow(this, openbox_attrib
.workspace
, True
);
1927 if (current_state
== NormalState
) current_state
= WithdrawnState
;
1928 } else if (current_state
== WithdrawnState
) {
1929 current_state
= NormalState
;
1932 if (openbox_attrib
.flags
& AttribOmnipresent
&&
1933 openbox_attrib
.attrib
& AttribOmnipresent
) {
1934 flags
.stuck
= False
;
1937 current_state
= NormalState
;
1940 if ((openbox_attrib
.flags
& AttribMaxHoriz
) ||
1941 (openbox_attrib
.flags
& AttribMaxVert
)) {
1942 int x
= openbox_attrib
.premax_x
, y
= openbox_attrib
.premax_y
;
1943 unsigned int w
= openbox_attrib
.premax_w
, h
= openbox_attrib
.premax_h
;
1944 flags
.maximized
= 0;
1946 unsigned int m
= False
;
1947 if ((openbox_attrib
.flags
& AttribMaxHoriz
) &&
1948 (openbox_attrib
.flags
& AttribMaxVert
))
1949 m
= (openbox_attrib
.attrib
& (AttribMaxHoriz
| AttribMaxVert
)) ? 1 : 0;
1950 else if (openbox_attrib
.flags
& AttribMaxVert
)
1951 m
= (openbox_attrib
.attrib
& AttribMaxVert
) ? 2 : 0;
1952 else if (openbox_attrib
.flags
& AttribMaxHoriz
)
1953 m
= (openbox_attrib
.attrib
& AttribMaxHoriz
) ? 3 : 0;
1957 openbox_attrib
.premax_x
= x
;
1958 openbox_attrib
.premax_y
= y
;
1959 openbox_attrib
.premax_w
= w
;
1960 openbox_attrib
.premax_h
= h
;
1963 setState(current_state
);
1968 * The reverse of the setGravityOffsets function. Uses the frame window's
1969 * position to find the window's reference point.
1971 void OpenboxWindow::restoreGravity(void) {
1972 // x coordinates for each gravity type
1973 const int x_west
= frame
.x
;
1974 const int x_east
= frame
.x
+ frame
.width
- client
.width
;
1975 const int x_center
= frame
.x
+ (frame
.width
/2) - client
.width
;
1976 // y coordinates for each gravity type
1977 const int y_north
= frame
.y
;
1978 const int y_south
= frame
.y
+ frame
.height
- client
.height
;
1979 const int y_center
= frame
.y
+ (frame
.height
/2) - client
.height
;
1981 switch(client
.win_gravity
) {
1983 case NorthWestGravity
:
1988 client
.x
= x_center
;
1991 case NorthEastGravity
:
1995 case SouthWestGravity
:
2000 client
.x
= x_center
;
2003 case SouthEastGravity
:
2009 client
.y
= y_center
;
2013 client
.y
= y_center
;
2016 client
.x
= x_center
;
2017 client
.y
= y_center
;
2021 client
.x
= frame
.x
+ frame
.mwm_border_w
+ frame
.border_w
;
2022 client
.y
= frame
.y
+ frame
.y_border
+ frame
.mwm_border_w
+
2029 void OpenboxWindow::redrawLabel(void) {
2030 int dx
= frame
.bevel_w
* 2, dlen
= client
.title_len
;
2031 unsigned int l
= client
.title_text_w
;
2033 if (flags
.focused
) {
2035 XSetWindowBackgroundPixmap(display
, frame
.label
, frame
.flabel
);
2037 XSetWindowBackground(display
, frame
.label
, frame
.flabel_pixel
);
2040 XSetWindowBackgroundPixmap(display
, frame
.label
, frame
.ulabel
);
2042 XSetWindowBackground(display
, frame
.label
, frame
.ulabel_pixel
);
2044 XClearWindow(display
, frame
.label
);
2046 if (client
.title_text_w
> frame
.label_w
) {
2047 for (; dlen
>= 0; dlen
--) {
2048 if (i18n
.multibyte()) {
2049 XRectangle ink
, logical
;
2050 XmbTextExtents(screen
->getWindowStyle()->fontset
, client
.title
, dlen
,
2054 l
= XTextWidth(screen
->getWindowStyle()->font
, client
.title
, dlen
);
2056 l
+= (frame
.bevel_w
* 4);
2058 if (l
< frame
.label_w
)
2063 switch (screen
->getWindowStyle()->justify
) {
2064 case BScreen::RightJustify
:
2065 dx
+= frame
.label_w
- l
;
2068 case BScreen::CenterJustify
:
2069 dx
+= (frame
.label_w
- l
) / 2;
2073 WindowStyle
*style
= screen
->getWindowStyle();
2074 GC text_gc
= (flags
.focused
) ? style
->l_text_focus_gc
:
2075 style
->l_text_unfocus_gc
;
2076 if (i18n
.multibyte())
2077 XmbDrawString(display
, frame
.label
, style
->fontset
, text_gc
, dx
,
2078 (1 - style
->fontset_extents
->max_ink_extent
.y
),
2079 client
.title
, dlen
);
2081 XDrawString(display
, frame
.label
, text_gc
, dx
,
2082 (style
->font
->ascent
+ 1), client
.title
, dlen
);
2086 void OpenboxWindow::redrawAllButtons(void) {
2087 if (frame
.iconify_button
) redrawIconifyButton(False
);
2088 if (frame
.maximize_button
) redrawMaximizeButton(flags
.maximized
);
2089 if (frame
.close_button
) redrawCloseButton(False
);
2093 void OpenboxWindow::redrawIconifyButton(Bool pressed
) {
2095 if (flags
.focused
) {
2097 XSetWindowBackgroundPixmap(display
, frame
.iconify_button
,
2100 XSetWindowBackground(display
, frame
.iconify_button
,
2101 frame
.fbutton_pixel
);
2104 XSetWindowBackgroundPixmap(display
, frame
.iconify_button
,
2107 XSetWindowBackground(display
, frame
.iconify_button
,
2108 frame
.ubutton_pixel
);
2112 XSetWindowBackgroundPixmap(display
, frame
.iconify_button
, frame
.pbutton
);
2114 XSetWindowBackground(display
, frame
.iconify_button
, frame
.pbutton_pixel
);
2116 XClearWindow(display
, frame
.iconify_button
);
2118 XDrawRectangle(display
, frame
.iconify_button
,
2119 ((flags
.focused
) ? screen
->getWindowStyle()->b_pic_focus_gc
:
2120 screen
->getWindowStyle()->b_pic_unfocus_gc
),
2121 2, (frame
.button_h
- 5), (frame
.button_w
- 5), 2);
2125 void OpenboxWindow::redrawMaximizeButton(Bool pressed
) {
2127 if (flags
.focused
) {
2129 XSetWindowBackgroundPixmap(display
, frame
.maximize_button
,
2132 XSetWindowBackground(display
, frame
.maximize_button
,
2133 frame
.fbutton_pixel
);
2136 XSetWindowBackgroundPixmap(display
, frame
.maximize_button
,
2139 XSetWindowBackground(display
, frame
.maximize_button
,
2140 frame
.ubutton_pixel
);
2144 XSetWindowBackgroundPixmap(display
, frame
.maximize_button
,
2147 XSetWindowBackground(display
, frame
.maximize_button
,
2148 frame
.pbutton_pixel
);
2150 XClearWindow(display
, frame
.maximize_button
);
2152 XDrawRectangle(display
, frame
.maximize_button
,
2153 ((flags
.focused
) ? screen
->getWindowStyle()->b_pic_focus_gc
:
2154 screen
->getWindowStyle()->b_pic_unfocus_gc
),
2155 2, 2, (frame
.button_w
- 5), (frame
.button_h
- 5));
2156 XDrawLine(display
, frame
.maximize_button
,
2157 ((flags
.focused
) ? screen
->getWindowStyle()->b_pic_focus_gc
:
2158 screen
->getWindowStyle()->b_pic_unfocus_gc
),
2159 2, 3, (frame
.button_w
- 3), 3);
2163 void OpenboxWindow::redrawCloseButton(Bool pressed
) {
2165 if (flags
.focused
) {
2167 XSetWindowBackgroundPixmap(display
, frame
.close_button
,
2170 XSetWindowBackground(display
, frame
.close_button
,
2171 frame
.fbutton_pixel
);
2174 XSetWindowBackgroundPixmap(display
, frame
.close_button
,
2177 XSetWindowBackground(display
, frame
.close_button
,
2178 frame
.ubutton_pixel
);
2182 XSetWindowBackgroundPixmap(display
, frame
.close_button
, frame
.pbutton
);
2184 XSetWindowBackground(display
, frame
.close_button
, frame
.pbutton_pixel
);
2186 XClearWindow(display
, frame
.close_button
);
2188 XDrawLine(display
, frame
.close_button
,
2189 ((flags
.focused
) ? screen
->getWindowStyle()->b_pic_focus_gc
:
2190 screen
->getWindowStyle()->b_pic_unfocus_gc
), 2, 2,
2191 (frame
.button_w
- 3), (frame
.button_h
- 3));
2192 XDrawLine(display
, frame
.close_button
,
2193 ((flags
.focused
) ? screen
->getWindowStyle()->b_pic_focus_gc
:
2194 screen
->getWindowStyle()->b_pic_unfocus_gc
), 2,
2195 (frame
.button_h
- 3),
2196 (frame
.button_w
- 3), 2);
2200 void OpenboxWindow::mapRequestEvent(XMapRequestEvent
*re
) {
2201 if (re
->window
== client
.window
) {
2203 fprintf(stderr
, i18n(WindowSet
, WindowMapRequest
,
2204 "OpenboxWindow::mapRequestEvent() for 0x%lx\n"),
2209 if (! validateClient()) return;
2211 Bool get_state_ret
= getState();
2212 if (! (get_state_ret
&& openbox
.isStartup())) {
2213 if ((client
.wm_hint_flags
& StateHint
) &&
2214 (! (current_state
== NormalState
|| current_state
== IconicState
)))
2215 current_state
= client
.initial_state
;
2217 current_state
= NormalState
;
2218 } else if (flags
.iconic
) {
2219 current_state
= NormalState
;
2222 switch (current_state
) {
2227 case WithdrawnState
:
2235 deiconify(False
, True
, True
); // specify that we're initializing the
2245 void OpenboxWindow::mapNotifyEvent(XMapEvent
*ne
) {
2246 if ((ne
->window
== client
.window
) && (! ne
->override_redirect
)
2247 && (flags
.visible
)) {
2249 if (! validateClient()) return;
2251 setState(NormalState
);
2253 if (flags
.transient
|| screen
->focusNew())
2256 setFocusFlag(False
);
2258 flags
.visible
= True
;
2259 flags
.iconic
= False
;
2266 void OpenboxWindow::unmapNotifyEvent(XUnmapEvent
*ue
) {
2267 if (ue
->window
== client
.window
) {
2269 fprintf(stderr
, i18n(WindowSet
, WindowUnmapNotify
,
2270 "OpenboxWindow::unmapNotifyEvent() for 0x%lx\n"),
2275 if (! validateClient()) return;
2280 XChangeSaveSet(display
, client
.window
, SetModeDelete
);
2281 XSelectInput(display
, client
.window
, NoEventMask
);
2283 XDeleteProperty(display
, client
.window
, openbox
.getWMStateAtom());
2284 XDeleteProperty(display
, client
.window
,
2285 openbox
.getOpenboxAttributesAtom());
2287 XUnmapWindow(display
, frame
.window
);
2288 XUnmapWindow(display
, client
.window
);
2291 if (! XCheckTypedWindowEvent(display
, client
.window
, ReparentNotify
,
2294 fprintf(stderr
, i18n(WindowSet
, WindowUnmapNotifyReparent
,
2295 "OpenboxWindow::unmapNotifyEvent(): reparent 0x%lx to "
2296 "root.\n"), client
.window
);
2300 XReparentWindow(display
, client
.window
, screen
->getRootWindow(),
2301 client
.x
, client
.y
);
2313 void OpenboxWindow::destroyNotifyEvent(XDestroyWindowEvent
*de
) {
2314 if (de
->window
== client
.window
) {
2317 XUnmapWindow(display
, frame
.window
);
2324 void OpenboxWindow::propertyNotifyEvent(Atom atom
) {
2326 if (! validateClient()) return;
2330 case XA_WM_CLIENT_MACHINE
:
2334 case XA_WM_TRANSIENT_FOR
:
2335 // determine if this is a transient window
2337 if (XGetTransientForHint(display
, client
.window
, &win
)) {
2338 if (win
&& (win
!= client
.window
)) {
2339 if ((client
.transient_for
= openbox
.searchWindow(win
))) {
2340 client
.transient_for
->client
.transient
= this;
2341 flags
.stuck
= client
.transient_for
->flags
.stuck
;
2342 flags
.transient
= True
;
2343 } else if (win
== client
.window_group
) {
2344 //jr This doesn't look quite right...
2345 if ((client
.transient_for
= openbox
.searchGroup(win
, this))) {
2346 client
.transient_for
->client
.transient
= this;
2347 flags
.stuck
= client
.transient_for
->flags
.stuck
;
2348 flags
.transient
= True
;
2353 if (win
== screen
->getRootWindow()) flags
.modal
= True
;
2356 // adjust the window decorations based on transience
2357 if (flags
.transient
)
2358 decorations
.maximize
= decorations
.handle
= functions
.maximize
= False
;
2368 case XA_WM_ICON_NAME
:
2370 if (flags
.iconic
) screen
->iconUpdate();
2376 if (decorations
.titlebar
)
2380 screen
->getWorkspace(workspace_number
)->update();
2384 case XA_WM_NORMAL_HINTS
: {
2387 if ((client
.normal_hint_flags
& PMinSize
) &&
2388 (client
.normal_hint_flags
& PMaxSize
)) {
2389 if (client
.max_width
<= client
.min_width
&&
2390 client
.max_height
<= client
.min_height
)
2391 decorations
.maximize
= decorations
.handle
=
2392 functions
.resize
= functions
.maximize
= False
;
2394 decorations
.maximize
= decorations
.handle
=
2395 functions
.resize
= functions
.maximize
= True
;
2398 int x
= frame
.x
, y
= frame
.y
;
2399 unsigned int w
= frame
.width
, h
= frame
.height
;
2403 if ((x
!= frame
.x
) || (y
!= frame
.y
) ||
2404 (w
!= frame
.width
) || (h
!= frame
.height
))
2411 if (atom
== openbox
.getWMProtocolsAtom()) {
2414 if (decorations
.close
&& (! frame
.close_button
)) {
2415 createCloseButton();
2416 if (decorations
.titlebar
) {
2420 if (windowmenu
) windowmenu
->reconfigure();
2431 void OpenboxWindow::exposeEvent(XExposeEvent
*ee
) {
2432 if (frame
.label
== ee
->window
&& decorations
.titlebar
)
2434 else if (frame
.close_button
== ee
->window
)
2435 redrawCloseButton(False
);
2436 else if (frame
.maximize_button
== ee
->window
)
2437 redrawMaximizeButton(flags
.maximized
);
2438 else if (frame
.iconify_button
== ee
->window
)
2439 redrawIconifyButton(False
);
2443 void OpenboxWindow::configureRequestEvent(XConfigureRequestEvent
*cr
) {
2444 if (cr
->window
== client
.window
) {
2446 if (! validateClient()) return;
2448 int cx
= frame
.x
, cy
= frame
.y
;
2449 unsigned int cw
= frame
.width
, ch
= frame
.height
;
2451 if (cr
->value_mask
& CWBorderWidth
)
2452 client
.old_bw
= cr
->border_width
;
2454 if (cr
->value_mask
& CWX
)
2455 cx
= cr
->x
- frame
.mwm_border_w
- frame
.border_w
;
2457 if (cr
->value_mask
& CWY
)
2458 cy
= cr
->y
- frame
.y_border
- frame
.mwm_border_w
-
2461 if (cr
->value_mask
& CWWidth
)
2462 cw
= cr
->width
+ (frame
.mwm_border_w
* 2);
2464 if (cr
->value_mask
& CWHeight
)
2465 ch
= cr
->height
+ frame
.y_border
+ (frame
.mwm_border_w
* 2) +
2466 (frame
.border_w
* decorations
.handle
) + frame
.handle_h
;
2468 if (frame
.x
!= cx
|| frame
.y
!= cy
||
2469 frame
.width
!= cw
|| frame
.height
!= ch
)
2470 configure(cx
, cy
, cw
, ch
);
2472 if (cr
->value_mask
& CWStackMode
) {
2473 switch (cr
->detail
) {
2477 if (flags
.iconic
) deiconify();
2478 screen
->getWorkspace(workspace_number
)->raiseWindow(this);
2483 if (flags
.iconic
) deiconify();
2484 screen
->getWorkspace(workspace_number
)->lowerWindow(this);
2494 void OpenboxWindow::buttonPressEvent(XButtonEvent
*be
) {
2496 if (! validateClient())
2499 int stack_change
= 1; // < 0 means to lower the window
2500 // > 0 means to raise the window
2501 // 0 means to leave it where it is
2503 // alt + left/right click begins interactively moving/resizing the window
2504 // when the mouse is moved
2505 if (be
->state
== Mod1Mask
&& (be
->button
== 1 || be
->button
== 3)) {
2506 if (be
->button
== 3) {
2507 if (screen
->getWindowZones() == 4 &&
2508 be
->y
< (signed) frame
.height
/ 2) {
2509 resize_zone
= ZoneTop
;
2511 resize_zone
= ZoneBottom
;
2513 if (screen
->getWindowZones() >= 2 &&
2514 be
->x
< (signed) frame
.width
/ 2) {
2515 resize_zone
|= ZoneLeft
;
2517 resize_zone
|= ZoneRight
;
2520 // control + left click on the titlebar shades the window
2521 } else if (be
->state
== ControlMask
&& be
->button
== 1) {
2522 if (be
->window
== frame
.title
||
2523 be
->window
== frame
.label
)
2526 } else if (be
->state
== 0 && be
->button
== 1) {
2527 if (windowmenu
&& windowmenu
->isVisible())
2530 if (be
->window
== frame
.maximize_button
) {
2531 redrawMaximizeButton(True
);
2532 } else if (be
->window
== frame
.iconify_button
) {
2533 redrawIconifyButton(True
);
2534 } else if (be
->window
== frame
.close_button
) {
2535 redrawCloseButton(True
);
2536 } else if (be
->window
== frame
.plate
) {
2537 XAllowEvents(display
, ReplayPointer
, be
->time
);
2538 } else if (be
->window
== frame
.title
||
2539 be
->window
== frame
.label
) {
2540 // shade the window when the titlebar is double clicked
2541 if ( (be
->time
- lastButtonPressTime
) <=
2542 openbox
.getDoubleClickInterval()) {
2543 lastButtonPressTime
= 0;
2546 lastButtonPressTime
= be
->time
;
2548 // clicking and dragging on the titlebar moves the window, so on a click
2549 // we need to save the coords of the click in case the user drags
2550 frame
.grab_x
= be
->x_root
- frame
.x
- frame
.border_w
;
2551 frame
.grab_y
= be
->y_root
- frame
.y
- frame
.border_w
;
2552 } else if (be
->window
== frame
.handle
||
2553 be
->window
== frame
.left_grip
||
2554 be
->window
== frame
.right_grip
||
2555 be
->window
== frame
.window
) {
2556 // clicking and dragging on the window's frame moves the window, so on a
2557 // click we need to save the coords of the click in case the user drags
2558 frame
.grab_x
= be
->x_root
- frame
.x
- frame
.border_w
;
2559 frame
.grab_y
= be
->y_root
- frame
.y
- frame
.border_w
;
2560 if (be
->window
== frame
.left_grip
)
2561 resize_zone
= ZoneBottom
| ZoneLeft
;
2562 else if (be
->window
== frame
.right_grip
)
2563 resize_zone
= ZoneBottom
| ZoneRight
;
2566 } else if (be
->state
== 0 && be
->button
== 2) {
2567 if (be
->window
== frame
.maximize_button
) {
2568 redrawMaximizeButton(True
);
2569 // a middle click anywhere on the window's frame except for on the buttons
2570 // will lower the window
2571 } else if (! (be
->window
== frame
.iconify_button
||
2572 be
->window
== frame
.close_button
) ) {
2576 } else if (be
->state
== 0 && be
->button
== 3) {
2577 if (be
->window
== frame
.maximize_button
) {
2578 redrawMaximizeButton(True
);
2579 // a right click on the window's frame will show or hide the window's
2581 } else if (be
->window
== frame
.title
||
2582 be
->window
== frame
.label
||
2583 be
->window
== frame
.handle
||
2584 be
->window
== frame
.window
) {
2587 if (windowmenu
->isVisible()) {
2590 // get the coords for the menu
2591 mx
= be
->x_root
- windowmenu
->getWidth() / 2;
2592 if (be
->window
== frame
.title
|| be
->window
== frame
.label
) {
2593 my
= frame
.y
+ frame
.title_h
;
2594 } else if (be
->window
== frame
.handle
) {
2595 my
= frame
.y
+ frame
.y_handle
- windowmenu
->getHeight();
2596 } else { // (be->window == frame.window)
2597 if (be
->y
<= (signed) frame
.bevel_w
) {
2598 my
= frame
.y
+ frame
.y_border
;
2600 my
= be
->y_root
- (windowmenu
->getHeight() / 2);
2604 if (mx
> (signed) (frame
.x
+ frame
.width
-
2605 windowmenu
->getWidth())) {
2606 mx
= frame
.x
+ frame
.width
- windowmenu
->getWidth();
2607 } else if (mx
< frame
.x
) {
2611 if (my
> (signed) (frame
.y
+ frame
.y_handle
-
2612 windowmenu
->getHeight())) {
2613 my
= frame
.y
+ frame
.y_handle
- windowmenu
->getHeight();
2614 } else if (my
< (signed) (frame
.y
+
2615 ((decorations
.titlebar
) ? frame
.title_h
: frame
.y_border
))) {
2617 ((decorations
.titlebar
) ? frame
.title_h
: frame
.y_border
);
2620 windowmenu
->move(mx
, my
);
2622 XRaiseWindow(display
, windowmenu
->getWindowID());
2623 XRaiseWindow(display
, windowmenu
->getSendToMenu()->getWindowID());
2624 stack_change
= 0; // dont raise the window overtop of the menu
2629 } else if (be
->state
== 0 && be
->button
== 4) {
2630 if ((be
->window
== frame
.label
||
2631 be
->window
== frame
.title
) &&
2635 } else if (be
->state
== 0 && be
->button
== 5) {
2636 if ((be
->window
== frame
.label
||
2637 be
->window
== frame
.title
) &&
2642 if (! (flags
.focused
|| screen
->sloppyFocus()) ) {
2643 setInputFocus(); // any click focus' the window in 'click to focus'
2645 if (stack_change
< 0) {
2646 screen
->getWorkspace(workspace_number
)->lowerWindow(this);
2647 } else if (stack_change
> 0) {
2648 screen
->getWorkspace(workspace_number
)->raiseWindow(this);
2655 void OpenboxWindow::buttonReleaseEvent(XButtonEvent
*re
) {
2657 if (! validateClient())
2660 // alt + middle button released
2661 if (re
->state
== (Mod1Mask
& Button2Mask
) && re
->button
== 2) {
2662 if (re
->window
== frame
.window
) {
2663 XUngrabPointer(display
, CurrentTime
); // why? i dont know
2665 // left button released
2666 } else if (re
->button
== 1) {
2667 if (re
->window
== frame
.maximize_button
) {
2668 if (re
->state
== Button1Mask
&& // only the left button was depressed
2669 (re
->x
>= 0) && ((unsigned) re
->x
<= frame
.button_w
) &&
2670 (re
->y
>= 0) && ((unsigned) re
->y
<= frame
.button_h
)) {
2671 maximize(re
->button
);
2673 redrawMaximizeButton(False
);
2675 } else if (re
->window
== frame
.iconify_button
) {
2676 if (re
->state
== Button1Mask
&& // only the left button was depressed
2677 (re
->x
>= 0) && ((unsigned) re
->x
<= frame
.button_w
) &&
2678 (re
->y
>= 0) && ((unsigned) re
->y
<= frame
.button_h
)) {
2681 redrawIconifyButton(False
);
2683 } else if (re
->window
== frame
.close_button
) {
2684 if (re
->state
== Button1Mask
&& // only the left button was depressed
2685 (re
->x
>= 0) && ((unsigned) re
->x
<= frame
.button_w
) &&
2686 (re
->y
>= 0) && ((unsigned) re
->y
<= frame
.button_h
)) {
2689 //we should always redraw the close button. some applications
2690 //eg. acroread don't honour the close.
2691 redrawCloseButton(False
);
2693 // middle button released
2694 } else if (re
->button
== 2) {
2695 if (re
->window
== frame
.maximize_button
) {
2696 if (re
->state
== Button2Mask
&& // only the middle button was depressed
2697 (re
->x
>= 0) && ((unsigned) re
->x
<= frame
.button_w
) &&
2698 (re
->y
>= 0) && ((unsigned) re
->y
<= frame
.button_h
)) {
2699 maximize(re
->button
);
2701 redrawMaximizeButton(False
);
2704 // right button released
2705 } else if (re
->button
== 3) {
2706 if (re
->window
== frame
.maximize_button
) {
2707 if (re
->state
== Button3Mask
&& // only the right button was depressed
2708 (re
->x
>= 0) && ((unsigned) re
->x
<= frame
.button_w
) &&
2709 (re
->y
>= 0) && ((unsigned) re
->y
<= frame
.button_h
)) {
2710 maximize(re
->button
);
2712 redrawMaximizeButton(False
);
2717 // when the window is being interactively moved, a button release stops the
2721 // when the window is being interactively resized, a button release stops the
2723 } else if (flags
.resizing
) {
2724 flags
.resizing
= False
;
2725 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2726 frame
.resize_x
, frame
.resize_y
,
2727 frame
.resize_w
- 1, frame
.resize_h
- 1);
2728 screen
->hideGeometry();
2729 if (resize_zone
& ZoneLeft
) {
2731 } else { // when resizing with "Alt+Button3", the resize is the same as if
2732 // done with the right grip (the right side of the window is what
2736 // unset maximized state when resized after fully maximized
2737 if (flags
.maximized
== 1) {
2740 configure(frame
.resize_x
, frame
.resize_y
,
2741 frame
.resize_w
- (frame
.border_w
* 2),
2742 frame
.resize_h
- (frame
.border_w
* 2));
2744 XUngrabPointer(display
, CurrentTime
);
2752 void OpenboxWindow::startMove(int x
, int y
) {
2753 ASSERT(!flags
.moving
);
2755 // make sure only one window is moving at a time
2756 OpenboxWindow
*w
= openbox
.getMaskedWindow();
2757 if (w
!= (OpenboxWindow
*) 0 && w
->flags
.moving
)
2760 XGrabPointer(display
, frame
.window
, False
, PointerMotionMask
|
2761 ButtonReleaseMask
, GrabModeAsync
, GrabModeAsync
,
2762 None
, openbox
.getMoveCursor(), CurrentTime
);
2764 if (windowmenu
&& windowmenu
->isVisible())
2767 flags
.moving
= True
;
2769 openbox
.maskWindowEvents(client
.window
, this);
2771 if (! screen
->opaqueMove()) {
2774 frame
.move_x
= frame
.x
;
2775 frame
.move_y
= frame
.y
;
2776 frame
.resize_w
= frame
.width
+ (frame
.border_w
* 2);
2777 frame
.resize_h
= ((flags
.shaded
) ? frame
.title_h
: frame
.height
) +
2778 (frame
.border_w
* 2);
2780 screen
->showPosition(frame
.x
, frame
.y
);
2782 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2783 frame
.move_x
, frame
.move_y
,
2784 frame
.resize_w
- 1, frame
.resize_h
- 1);
2786 frame
.grab_x
= x
- frame
.x
- frame
.border_w
;
2787 frame
.grab_y
= y
- frame
.y
- frame
.border_w
;
2791 void OpenboxWindow::doMove(int x
, int y
) {
2792 ASSERT(flags
.moving
);
2794 int dx
= x
- frame
.grab_x
, dy
= y
- frame
.grab_y
;
2796 dx
-= frame
.border_w
;
2797 dy
-= frame
.border_w
;
2799 int snap_distance
= screen
->edgeSnapThreshold();
2800 // width/height of the snapping window
2801 unsigned int snap_w
= frame
.width
+ (frame
.border_w
* 2);
2802 unsigned int snap_h
= area().h() + (frame
.border_w
* 2);
2803 if (snap_distance
) {
2804 int drx
= screen
->size().w() - (dx
+ snap_w
);
2806 if (dx
< drx
&& (dx
> 0 && dx
< snap_distance
) ||
2807 (dx
< 0 && dx
> -snap_distance
) )
2809 else if ( (drx
> 0 && drx
< snap_distance
) ||
2810 (drx
< 0 && drx
> -snap_distance
) )
2811 dx
= screen
->size().w() - snap_w
;
2813 int dtty
, dbby
, dty
, dby
;
2814 switch (screen
->getToolbar()->placement()) {
2815 case Toolbar::TopLeft
:
2816 case Toolbar::TopCenter
:
2817 case Toolbar::TopRight
:
2818 dtty
= screen
->getToolbar()->getExposedHeight() +
2820 dbby
= screen
->size().h();
2825 dbby
= screen
->getToolbar()->area().y();
2830 dby
= dbby
- (dy
+ snap_h
);
2832 if ( (dy
> 0 && dty
< snap_distance
) ||
2833 (dy
< 0 && dty
> -snap_distance
) )
2835 else if ( (dby
> 0 && dby
< snap_distance
) ||
2836 (dby
< 0 && dby
> -snap_distance
) )
2840 if (screen
->opaqueMove()) {
2841 configure(dx
, dy
, frame
.width
, frame
.height
);
2843 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2844 frame
.move_x
, frame
.move_y
, frame
.resize_w
- 1,
2845 frame
.resize_h
- 1);
2850 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2851 frame
.move_x
, frame
.move_y
, frame
.resize_w
- 1,
2852 frame
.resize_h
- 1);
2855 screen
->showPosition(dx
, dy
);
2859 void OpenboxWindow::endMove() {
2860 ASSERT(flags
.moving
);
2862 flags
.moving
= False
;
2864 openbox
.maskWindowEvents(0, (OpenboxWindow
*) 0);
2865 if (!screen
->opaqueMove()) {
2866 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2867 frame
.move_x
, frame
.move_y
, frame
.resize_w
- 1,
2868 frame
.resize_h
- 1);
2870 configure(frame
.move_x
, frame
.move_y
, frame
.width
, frame
.height
);
2873 configure(frame
.x
, frame
.y
, frame
.width
, frame
.height
);
2875 screen
->hideGeometry();
2876 XUngrabPointer(display
, CurrentTime
);
2877 // if there are any left over motions from the move, drop them now cuz they
2880 while (XCheckTypedWindowEvent(display
, frame
.window
, MotionNotify
, &e
));
2884 void OpenboxWindow::motionNotifyEvent(XMotionEvent
*me
) {
2886 doMove(me
->x_root
, me
->y_root
);
2887 else if (!flags
.resizing
&& (me
->state
& Button1Mask
) && functions
.move
&&
2888 (frame
.title
== me
->window
|| frame
.label
== me
->window
||
2889 frame
.handle
== me
->window
|| frame
.window
== me
->window
))
2890 startMove(me
->x_root
, me
->y_root
);
2891 else if (functions
.resize
&&
2892 (((me
->state
& Button1Mask
) && (me
->window
== frame
.right_grip
||
2893 me
->window
== frame
.left_grip
)) ||
2894 (me
->state
== (Mod1Mask
| Button3Mask
) &&
2895 me
->window
== frame
.window
))) {
2896 Bool left
= resize_zone
& ZoneLeft
;
2898 if (! flags
.resizing
) {
2900 if (resize_zone
& ZoneTop
)
2901 cursor
= (resize_zone
& ZoneLeft
) ?
2902 openbox
.getUpperLeftAngleCursor() :
2903 openbox
.getUpperRightAngleCursor();
2905 cursor
= (resize_zone
& ZoneLeft
) ?
2906 openbox
.getLowerLeftAngleCursor() :
2907 openbox
.getLowerRightAngleCursor();
2908 XGrabPointer(display
, me
->window
, False
, ButtonMotionMask
|
2909 ButtonReleaseMask
, GrabModeAsync
, GrabModeAsync
, None
,
2910 cursor
, CurrentTime
);
2912 flags
.resizing
= True
;
2917 if (resize_zone
& ZoneRight
)
2918 frame
.grab_x
= me
->x
- screen
->getBorderWidth();
2920 frame
.grab_x
= me
->x
+ screen
->getBorderWidth();
2921 if (resize_zone
& ZoneTop
)
2922 frame
.grab_y
= me
->y
+ screen
->getBorderWidth() * 2;
2924 frame
.grab_y
= me
->y
- screen
->getBorderWidth() * 2;
2925 frame
.resize_x
= frame
.x
;
2926 frame
.resize_y
= frame
.y
;
2927 frame
.resize_w
= frame
.width
+ (frame
.border_w
* 2);
2928 frame
.resize_h
= frame
.height
+ (frame
.border_w
* 2);
2931 left_fixsize(&gx
, &gy
);
2933 right_fixsize(&gx
, &gy
);
2935 screen
->showGeometry(gx
, gy
);
2937 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2938 frame
.resize_x
, frame
.resize_y
,
2939 frame
.resize_w
- 1, frame
.resize_h
- 1);
2941 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2942 frame
.resize_x
, frame
.resize_y
,
2943 frame
.resize_w
- 1, frame
.resize_h
- 1);
2947 if (resize_zone
& ZoneTop
)
2948 frame
.resize_h
= frame
.height
- (me
->y
- frame
.grab_y
);
2950 frame
.resize_h
= frame
.height
+ (me
->y
- frame
.grab_y
);
2951 if (frame
.resize_h
< 1) frame
.resize_h
= 1;
2954 frame
.resize_x
= me
->x_root
- frame
.grab_x
;
2955 if (frame
.resize_x
> (signed) (frame
.x
+ frame
.width
))
2956 frame
.resize_x
= frame
.resize_x
+ frame
.width
- 1;
2958 left_fixsize(&gx
, &gy
);
2960 frame
.resize_w
= frame
.width
+ (me
->x
- frame
.grab_x
);
2961 if (frame
.resize_w
< 1) frame
.resize_w
= 1;
2963 right_fixsize(&gx
, &gy
);
2966 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2967 frame
.resize_x
, frame
.resize_y
,
2968 frame
.resize_w
- 1, frame
.resize_h
- 1);
2970 screen
->showGeometry(gx
, gy
);
2977 void OpenboxWindow::shapeEvent(XShapeEvent
*) {
2978 if (openbox
.hasShapeExtensions()) {
2981 if (! validateClient()) return;
2982 XShapeCombineShape(display
, frame
.window
, ShapeBounding
,
2983 frame
.mwm_border_w
, frame
.y_border
+
2984 frame
.mwm_border_w
, client
.window
,
2985 ShapeBounding
, ShapeSet
);
2988 XRectangle xrect
[2];
2989 xrect
[0].x
= xrect
[0].y
= 0;
2990 xrect
[0].width
= frame
.width
;
2991 xrect
[0].height
= frame
.y_border
;
2993 if (decorations
.handle
) {
2995 xrect
[1].y
= frame
.y_handle
;
2996 xrect
[1].width
= frame
.width
;
2997 xrect
[1].height
= frame
.handle_h
+ frame
.border_w
;
3001 XShapeCombineRectangles(display
, frame
.window
, ShapeBounding
, 0, 0,
3002 xrect
, num
, ShapeUnion
, Unsorted
);
3010 bool OpenboxWindow::validateClient(void) {
3011 XSync(display
, False
);
3014 if (XCheckTypedWindowEvent(display
, client
.window
, DestroyNotify
, &e
) ||
3015 XCheckTypedWindowEvent(display
, client
.window
, UnmapNotify
, &e
)) {
3016 XPutBackEvent(display
, &e
);
3026 void OpenboxWindow::restore(void) {
3027 XChangeSaveSet(display
, client
.window
, SetModeDelete
);
3028 XSelectInput(display
, client
.window
, NoEventMask
);
3032 XUnmapWindow(display
, frame
.window
);
3033 XUnmapWindow(display
, client
.window
);
3035 XSetWindowBorderWidth(display
, client
.window
, client
.old_bw
);
3036 XReparentWindow(display
, client
.window
, screen
->getRootWindow(),
3037 client
.x
, client
.y
);
3038 XMapWindow(display
, client
.window
);
3046 void OpenboxWindow::timeout(void) {
3047 screen
->getWorkspace(workspace_number
)->raiseWindow(this);
3051 void OpenboxWindow::changeOpenboxHints(OpenboxHints
*net
) {
3052 if ((net
->flags
& AttribShaded
) &&
3053 ((openbox_attrib
.attrib
& AttribShaded
) !=
3054 (net
->attrib
& AttribShaded
)))
3057 if (flags
.visible
&& // watch out for requests when we can not be seen
3058 (net
->flags
& (AttribMaxVert
| AttribMaxHoriz
)) &&
3059 ((openbox_attrib
.attrib
& (AttribMaxVert
| AttribMaxHoriz
)) !=
3060 (net
->attrib
& (AttribMaxVert
| AttribMaxHoriz
)))) {
3061 if (flags
.maximized
) {
3066 if ((net
->flags
& AttribMaxHoriz
) && (net
->flags
& AttribMaxVert
))
3067 button
= ((net
->attrib
& (AttribMaxHoriz
| AttribMaxVert
)) ? 1 : 0);
3068 else if (net
->flags
& AttribMaxVert
)
3069 button
= ((net
->attrib
& AttribMaxVert
) ? 2 : 0);
3070 else if (net
->flags
& AttribMaxHoriz
)
3071 button
= ((net
->attrib
& AttribMaxHoriz
) ? 3 : 0);
3077 if ((net
->flags
& AttribOmnipresent
) &&
3078 ((openbox_attrib
.attrib
& AttribOmnipresent
) !=
3079 (net
->attrib
& AttribOmnipresent
)))
3082 if ((net
->flags
& AttribWorkspace
) &&
3083 (workspace_number
!= (signed) net
->workspace
)) {
3084 screen
->reassociateWindow(this, net
->workspace
, True
);
3086 if (screen
->getCurrentWorkspaceID() != (signed) net
->workspace
) withdraw();
3090 if (net
->flags
& AttribDecoration
) {
3091 switch (net
->decoration
) {
3093 decorations
.titlebar
= decorations
.border
= decorations
.handle
=
3094 decorations
.iconify
= decorations
.maximize
= decorations
.menu
= False
;
3100 decorations
.titlebar
= decorations
.iconify
= decorations
.menu
=
3101 decorations
.border
= True
;
3102 decorations
.handle
= (functions
.resize
&& !flags
.transient
);
3103 decorations
.maximize
= functions
.maximize
;
3108 decorations
.titlebar
= decorations
.iconify
= decorations
.menu
= True
;
3109 decorations
.border
= decorations
.border
= decorations
.handle
= False
;
3110 decorations
.maximize
= functions
.maximize
;
3115 decorations
.titlebar
= decorations
.menu
= True
;
3116 decorations
.iconify
= decorations
.border
= False
;
3117 decorations
.handle
= (functions
.resize
&& !flags
.transient
);
3118 decorations
.maximize
= functions
.maximize
;
3123 XMapSubwindows(display
, frame
.window
);
3124 XMapWindow(display
, frame
.window
);
3128 setState(current_state
);
3134 * Set the sizes of all components of the window frame
3135 * (the window decorations).
3136 * These values are based upon the current style settings and the client
3137 * window's dimentions.
3139 void OpenboxWindow::upsize(void) {
3140 frame
.bevel_w
= screen
->getBevelWidth();
3142 if (decorations
.border
) {
3143 frame
.border_w
= screen
->getBorderWidth();
3144 if (!flags
.transient
)
3145 frame
.mwm_border_w
= screen
->getFrameWidth();
3147 frame
.mwm_border_w
= 0;
3149 frame
.mwm_border_w
= frame
.border_w
= 0;
3152 if (decorations
.titlebar
) {
3153 // the height of the titlebar is based upon the height of the font being
3154 // used to display the window's title
3155 WindowStyle
*style
= screen
->getWindowStyle();
3156 if (i18n
.multibyte())
3157 frame
.title_h
= (style
->fontset_extents
->max_ink_extent
.height
+
3158 (frame
.bevel_w
* 2) + 2);
3160 frame
.title_h
= (style
->font
->ascent
+ style
->font
->descent
+
3161 (frame
.bevel_w
* 2) + 2);
3163 frame
.label_h
= frame
.title_h
- (frame
.bevel_w
* 2);
3164 frame
.button_w
= frame
.button_h
= (frame
.label_h
- 2);
3165 frame
.y_border
= frame
.title_h
+ frame
.border_w
;
3169 frame
.button_w
= frame
.button_h
= 0;
3173 frame
.border_h
= client
.height
+ frame
.mwm_border_w
* 2;
3175 if (decorations
.handle
) {
3176 frame
.y_handle
= frame
.y_border
+ frame
.border_h
+ frame
.border_w
;
3177 frame
.grip_w
= frame
.button_w
* 2;
3178 frame
.grip_h
= frame
.handle_h
= screen
->getHandleWidth();
3180 frame
.y_handle
= frame
.y_border
+ frame
.border_h
;
3182 frame
.grip_w
= frame
.grip_h
= 0;
3185 frame
.width
= client
.width
+ (frame
.mwm_border_w
* 2);
3186 frame
.height
= frame
.y_handle
+ frame
.handle_h
;
3191 * Set the size and position of the client window.
3192 * These values are based upon the current style settings and the frame
3193 * window's dimensions.
3195 void OpenboxWindow::downsize(void) {
3196 frame
.y_handle
= frame
.height
- frame
.handle_h
;
3197 frame
.border_h
= frame
.y_handle
- frame
.y_border
-
3198 (decorations
.handle
? frame
.border_w
: 0);
3200 client
.x
= frame
.x
+ frame
.mwm_border_w
+ frame
.border_w
;
3201 client
.y
= frame
.y
+ frame
.y_border
+ frame
.mwm_border_w
+ frame
.border_w
;
3203 client
.width
= frame
.width
- (frame
.mwm_border_w
* 2);
3204 client
.height
= frame
.height
- frame
.y_border
- (frame
.mwm_border_w
* 2)
3205 - frame
.handle_h
- (decorations
.handle
? frame
.border_w
: 0);
3207 frame
.y_handle
= frame
.border_h
+ frame
.y_border
+ frame
.border_w
;
3211 void OpenboxWindow::right_fixsize(int *gx
, int *gy
) {
3212 // calculate the size of the client window and conform it to the
3213 // size specified by the size hints of the client window...
3214 int dx
= 1 + frame
.resize_w
- client
.base_width
- (frame
.mwm_border_w
* 2) -
3215 (frame
.border_w
* 2) + (client
.width_inc
/ 2);
3216 int dy
= 1 + frame
.resize_h
- frame
.y_border
- client
.base_height
-
3217 frame
.handle_h
- (frame
.border_w
* 3) - (frame
.mwm_border_w
* 2)
3218 + (client
.height_inc
/ 2);
3220 if (dx
< (signed) client
.min_width
) dx
= client
.min_width
;
3221 if (dy
< (signed) client
.min_height
) dy
= client
.min_height
;
3222 if ((unsigned) dx
> client
.max_width
) dx
= client
.max_width
;
3223 if ((unsigned) dy
> client
.max_height
) dy
= client
.max_height
;
3225 dx
/= client
.width_inc
;
3226 dy
/= client
.height_inc
;
3231 dx
= (dx
* client
.width_inc
) + client
.base_width
;
3232 dy
= (dy
* client
.height_inc
) + client
.base_height
;
3234 frame
.resize_w
= dx
+ (frame
.mwm_border_w
* 2) + (frame
.border_w
* 2) - 1;
3235 frame
.resize_h
= dy
+ frame
.y_border
+ frame
.handle_h
+
3236 (frame
.mwm_border_w
* 2) + (frame
.border_w
* 3) - 1;
3237 if (resize_zone
& ZoneTop
)
3238 frame
.resize_y
= frame
.y
+ frame
.height
- frame
.resize_h
+
3239 screen
->getBorderWidth() * 2;
3243 void OpenboxWindow::left_fixsize(int *gx
, int *gy
) {
3244 // calculate the size of the client window and conform it to the
3245 // size specified by the size hints of the client window...
3246 int dx
= 1 + frame
.x
+ frame
.width
- frame
.resize_x
- client
.base_width
-
3247 (frame
.mwm_border_w
* 2) + (client
.width_inc
/ 2);
3248 int dy
= 1 + frame
.resize_h
- frame
.y_border
- client
.base_height
-
3249 frame
.handle_h
- (frame
.border_w
* 3) - (frame
.mwm_border_w
* 2)
3250 + (client
.height_inc
/ 2);
3252 if (dx
< (signed) client
.min_width
) dx
= client
.min_width
;
3253 if (dy
< (signed) client
.min_height
) dy
= client
.min_height
;
3254 if ((unsigned) dx
> client
.max_width
) dx
= client
.max_width
;
3255 if ((unsigned) dy
> client
.max_height
) dy
= client
.max_height
;
3257 dx
/= client
.width_inc
;
3258 dy
/= client
.height_inc
;
3263 dx
= (dx
* client
.width_inc
) + client
.base_width
;
3264 dy
= (dy
* client
.height_inc
) + client
.base_height
;
3266 frame
.resize_w
= dx
+ (frame
.mwm_border_w
* 2) + (frame
.border_w
* 2) - 1;
3267 frame
.resize_x
= frame
.x
+ frame
.width
- frame
.resize_w
+
3268 (frame
.border_w
* 2);
3269 frame
.resize_h
= dy
+ frame
.y_border
+ frame
.handle_h
+
3270 (frame
.mwm_border_w
* 2) + (frame
.border_w
* 3) - 1;
3271 if (resize_zone
& ZoneTop
)
3272 frame
.resize_y
= frame
.y
+ frame
.height
- frame
.resize_h
+
3273 screen
->getBorderWidth() * 2;