1 // Window.cc for Openbox
2 // Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
3 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
5 // Permission is hereby granted, free of charge, to any person obtaining a
6 // copy of this software and associated documentation files (the "Software"),
7 // to deal in the Software without restriction, including without limitation
8 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 // and/or sell copies of the Software, and to permit persons to whom the
10 // Software is furnished to do so, subject to the following conditions:
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 // DEALINGS IN THE SOFTWARE.
23 // stupid macros needed to access some functions in version 2 of the GNU C
30 # include "../config.h"
31 #endif // HAVE_CONFIG_H
33 #include <X11/Xatom.h>
34 #include <X11/keysym.h>
38 #endif // HAVE_STRING_H
43 # endif // HAVE_STDIO_H
52 #include "Windowmenu.h"
53 #include "Workspace.h"
63 * Initializes the class with default values/the window's set initial values.
65 OpenboxWindow::OpenboxWindow(Openbox
&o
, Window w
, BScreen
*s
) : openbox(o
) {
67 fprintf(stderr
, i18n
->getMessage(WindowSet
, WindowCreating
,
68 "OpenboxWindow::OpenboxWindow(): creating 0x%lx\n"),
73 display
= openbox
.getXDisplay();
76 if (! validateClient()) return;
78 // fetch client size and placement
79 XWindowAttributes wattrib
;
80 if ((! XGetWindowAttributes(display
, client
.window
, &wattrib
)) ||
81 (! wattrib
.screen
) || wattrib
.override_redirect
) {
84 i18n
->getMessage(WindowSet
, WindowXGetWindowAttributesFail
,
85 "OpenboxWindow::OpenboxWindow(): XGetWindowAttributes "
96 screen
= openbox
.searchScreen(RootWindowOfScreen(wattrib
.screen
));
99 fprintf(stderr
, i18n
->getMessage(WindowSet
, WindowCannotFindScreen
,
100 "OpenboxWindow::OpenboxWindow(): can't find screen\n"
101 "\tfor root window 0x%lx\n"),
102 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 timer
= new BTimer(openbox
, *this);
159 timer
->setTimeout(openbox
.getAutoRaiseDelay());
160 timer
->fireOnce(True
);
163 if (! client
.openbox_hint
)
166 // get size, aspect, minimum/maximum size and other hints set by the
173 if (client
.initial_state
== WithdrawnState
) {
174 screen
->getSlit()->addClient(client
.window
);
181 flags
.managed
= True
;
182 openbox
.saveWindowSearch(client
.window
, this);
184 // determine if this is a transient window
186 if (XGetTransientForHint(display
, client
.window
, &win
)) {
187 if (win
&& (win
!= client
.window
)) {
189 if ((tr
= openbox
.searchWindow(win
))) {
190 while (tr
->client
.transient
) tr
= tr
->client
.transient
;
191 client
.transient_for
= tr
;
192 tr
->client
.transient
= this;
193 flags
.stuck
= client
.transient_for
->flags
.stuck
;
194 flags
.transient
= True
;
195 } else if (win
== client
.window_group
) {
196 if ((tr
= openbox
.searchGroup(win
, this))) {
197 while (tr
->client
.transient
) tr
= tr
->client
.transient
;
198 client
.transient_for
= tr
;
199 tr
->client
.transient
= this;
200 flags
.stuck
= client
.transient_for
->flags
.stuck
;
201 flags
.transient
= True
;
206 if (win
== screen
->getRootWindow()) flags
.modal
= True
;
209 // adjust the window decorations based on transience and window sizes
211 decorations
.maximize
= decorations
.handle
= functions
.maximize
= False
;
213 if ((client
.normal_hint_flags
& PMinSize
) &&
214 (client
.normal_hint_flags
& PMaxSize
) &&
215 client
.max_width
<= client
.min_width
&&
216 client
.max_height
<= client
.min_height
) {
217 decorations
.maximize
= decorations
.handle
=
218 functions
.resize
= functions
.maximize
= False
;
223 if (openbox
.isStartup() || flags
.transient
||
224 client
.normal_hint_flags
& (PPosition
|USPosition
)) {
227 if ((openbox
.isStartup()) ||
229 (signed) (frame
.y
+ frame
.y_border
) >= 0 &&
230 frame
.x
<= (signed) screen
->size().w() &&
231 frame
.y
<= (signed) screen
->size().h()))
232 place_window
= false;
235 frame
.window
= createToplevelWindow(frame
.x
, frame
.y
, frame
.width
,
238 openbox
.saveWindowSearch(frame
.window
, this);
240 frame
.plate
= createChildWindow(frame
.window
);
241 openbox
.saveWindowSearch(frame
.plate
, this);
243 if (decorations
.titlebar
) {
244 frame
.title
= createChildWindow(frame
.window
);
245 frame
.label
= createChildWindow(frame
.title
);
246 openbox
.saveWindowSearch(frame
.title
, this);
247 openbox
.saveWindowSearch(frame
.label
, this);
250 if (decorations
.handle
) {
251 frame
.handle
= createChildWindow(frame
.window
);
252 openbox
.saveWindowSearch(frame
.handle
, this);
255 createChildWindow(frame
.handle
, openbox
.getLowerLeftAngleCursor());
256 openbox
.saveWindowSearch(frame
.left_grip
, this);
259 createChildWindow(frame
.handle
, openbox
.getLowerRightAngleCursor());
260 openbox
.saveWindowSearch(frame
.right_grip
, this);
263 associateClientWindow();
265 if (! screen
->sloppyFocus())
266 openbox
.grabButton(Button1
, 0, frame
.plate
, True
, ButtonPressMask
,
267 GrabModeSync
, GrabModeSync
, None
, None
);
269 openbox
.grabButton(Button1
, Mod1Mask
, frame
.window
, True
,
270 ButtonReleaseMask
| ButtonMotionMask
, GrabModeAsync
,
271 GrabModeAsync
, None
, openbox
.getMoveCursor());
272 openbox
.grabButton(Button2
, Mod1Mask
, frame
.window
, True
,
273 ButtonReleaseMask
, GrabModeAsync
, GrabModeAsync
, None
, None
);
274 openbox
.grabButton(Button3
, Mod1Mask
, frame
.window
, True
,
275 ButtonReleaseMask
| ButtonMotionMask
, GrabModeAsync
,
276 GrabModeAsync
, None
, None
);
279 XRaiseWindow(display
, frame
.plate
);
280 XMapSubwindows(display
, frame
.plate
);
281 if (decorations
.titlebar
) XMapSubwindows(display
, frame
.title
);
282 XMapSubwindows(display
, frame
.window
);
284 if (decorations
.menu
)
285 windowmenu
= new Windowmenu(*this);
289 if (workspace_number
< 0 || workspace_number
>= screen
->getWorkspaceCount())
290 screen
->getCurrentWorkspace()->addWindow(this, place_window
);
292 screen
->getWorkspace(workspace_number
)->addWindow(this, place_window
);
294 configure(frame
.x
, frame
.y
, frame
.width
, frame
.height
);
297 flags
.shaded
= False
;
301 if (flags
.maximized
&& functions
.maximize
) {
302 unsigned int button
= flags
.maximized
;
313 OpenboxWindow::~OpenboxWindow(void) {
314 if (flags
.moving
|| flags
.resizing
) {
315 screen
->hideGeometry();
316 XUngrabPointer(display
, CurrentTime
);
319 if (workspace_number
!= -1 && window_number
!= -1)
320 screen
->getWorkspace(workspace_number
)->removeWindow(this);
321 else if (flags
.iconic
)
322 screen
->removeIcon(this);
325 if (timer
->isTiming()) timer
->stop();
329 if (windowmenu
) delete windowmenu
;
332 delete [] client
.title
;
334 if (client
.icon_title
)
335 delete [] client
.icon_title
;
338 XFree(client
.mwm_hint
);
340 if (client
.openbox_hint
)
341 XFree(client
.openbox_hint
);
343 if (client
.window_group
)
344 openbox
.removeGroupSearch(client
.window_group
);
346 if (flags
.transient
&& client
.transient_for
)
347 client
.transient_for
->client
.transient
= client
.transient
;
348 if (client
.transient
)
349 client
.transient
->client
.transient_for
= client
.transient_for
;
351 if (frame
.close_button
) {
352 openbox
.removeWindowSearch(frame
.close_button
);
353 XDestroyWindow(display
, frame
.close_button
);
356 if (frame
.iconify_button
) {
357 openbox
.removeWindowSearch(frame
.iconify_button
);
358 XDestroyWindow(display
, frame
.iconify_button
);
361 if (frame
.maximize_button
) {
362 openbox
.removeWindowSearch(frame
.maximize_button
);
363 XDestroyWindow(display
, frame
.maximize_button
);
368 image_ctrl
->removeImage(frame
.ftitle
);
371 image_ctrl
->removeImage(frame
.utitle
);
374 image_ctrl
->removeImage(frame
.flabel
);
377 image_ctrl
->removeImage(frame
.ulabel
);
379 openbox
.removeWindowSearch(frame
.label
);
380 openbox
.removeWindowSearch(frame
.title
);
381 XDestroyWindow(display
, frame
.label
);
382 XDestroyWindow(display
, frame
.title
);
387 image_ctrl
->removeImage(frame
.fhandle
);
390 image_ctrl
->removeImage(frame
.uhandle
);
393 image_ctrl
->removeImage(frame
.fgrip
);
396 image_ctrl
->removeImage(frame
.ugrip
);
398 openbox
.removeWindowSearch(frame
.handle
);
399 openbox
.removeWindowSearch(frame
.right_grip
);
400 openbox
.removeWindowSearch(frame
.left_grip
);
401 XDestroyWindow(display
, frame
.right_grip
);
402 XDestroyWindow(display
, frame
.left_grip
);
403 XDestroyWindow(display
, frame
.handle
);
407 image_ctrl
->removeImage(frame
.fbutton
);
410 image_ctrl
->removeImage(frame
.ubutton
);
413 image_ctrl
->removeImage(frame
.pbutton
);
416 openbox
.removeWindowSearch(frame
.plate
);
417 XDestroyWindow(display
, frame
.plate
);
421 openbox
.removeWindowSearch(frame
.window
);
422 XDestroyWindow(display
, frame
.window
);
426 openbox
.removeWindowSearch(client
.window
);
427 screen
->removeNetizen(client
.window
);
433 * Creates a new top level window, with a given location, size, and border
435 * Returns: the newly created window
437 Window
OpenboxWindow::createToplevelWindow(int x
, int y
, unsigned int width
,
439 unsigned int borderwidth
)
441 XSetWindowAttributes attrib_create
;
442 unsigned long create_mask
= CWBackPixmap
| CWBorderPixel
| CWColormap
|
443 CWOverrideRedirect
| CWEventMask
;
445 attrib_create
.background_pixmap
= None
;
446 attrib_create
.colormap
= screen
->getColormap();
447 attrib_create
.override_redirect
= True
;
448 attrib_create
.event_mask
= ButtonPressMask
| ButtonReleaseMask
|
449 ButtonMotionMask
| EnterWindowMask
;
451 return XCreateWindow(display
, screen
->getRootWindow(), x
, y
, width
, height
,
452 borderwidth
, screen
->getDepth(), InputOutput
,
453 screen
->getVisual(), create_mask
,
459 * Creates a child window, and optionally associates a given cursor with
462 Window
OpenboxWindow::createChildWindow(Window parent
, Cursor cursor
) {
463 XSetWindowAttributes attrib_create
;
464 unsigned long create_mask
= CWBackPixmap
| CWBorderPixel
|
467 attrib_create
.background_pixmap
= None
;
468 attrib_create
.event_mask
= ButtonPressMask
| ButtonReleaseMask
|
469 ButtonMotionMask
| ExposureMask
|
470 EnterWindowMask
| LeaveWindowMask
;
473 create_mask
|= CWCursor
;
474 attrib_create
.cursor
= cursor
;
477 return XCreateWindow(display
, parent
, 0, 0, 1, 1, 0, screen
->getDepth(),
478 InputOutput
, screen
->getVisual(), create_mask
,
483 void OpenboxWindow::associateClientWindow(void) {
484 XSetWindowBorderWidth(display
, client
.window
, 0);
488 XChangeSaveSet(display
, client
.window
, SetModeInsert
);
489 XSetWindowAttributes attrib_set
;
491 XSelectInput(display
, frame
.plate
, NoEventMask
);
492 XReparentWindow(display
, client
.window
, frame
.plate
, 0, 0);
493 XSelectInput(display
, frame
.plate
, SubstructureRedirectMask
);
497 attrib_set
.event_mask
= PropertyChangeMask
| StructureNotifyMask
|
499 attrib_set
.do_not_propagate_mask
= ButtonPressMask
| ButtonReleaseMask
|
502 XChangeWindowAttributes(display
, client
.window
, CWEventMask
|CWDontPropagate
,
506 if (openbox
.hasShapeExtensions()) {
507 XShapeSelectInput(display
, client
.window
, ShapeNotifyMask
);
512 XShapeQueryExtents(display
, client
.window
, &flags
.shaped
, &foo
, &foo
,
513 &ufoo
, &ufoo
, &foo
, &foo
, &foo
, &ufoo
, &ufoo
);
516 XShapeCombineShape(display
, frame
.window
, ShapeBounding
,
517 frame
.mwm_border_w
, frame
.y_border
+
518 frame
.mwm_border_w
, client
.window
,
519 ShapeBounding
, ShapeSet
);
523 xrect
[0].x
= xrect
[0].y
= 0;
524 xrect
[0].width
= frame
.width
;
525 xrect
[0].height
= frame
.y_border
;
527 if (decorations
.handle
) {
529 xrect
[1].y
= frame
.y_handle
;
530 xrect
[1].width
= frame
.width
;
531 xrect
[1].height
= frame
.handle_h
+ frame
.border_w
;
535 XShapeCombineRectangles(display
, frame
.window
, ShapeBounding
, 0, 0,
536 xrect
, num
, ShapeUnion
, Unsorted
);
541 if (decorations
.iconify
) createIconifyButton();
542 if (decorations
.maximize
) createMaximizeButton();
543 if (decorations
.close
) createCloseButton();
546 if (frame
.close_button
)
547 XSetWindowBackgroundPixmap(display
, frame
.close_button
, frame
.ubutton
);
548 if (frame
.maximize_button
)
549 XSetWindowBackgroundPixmap(display
, frame
.maximize_button
,
551 if (frame
.iconify_button
)
552 XSetWindowBackgroundPixmap(display
, frame
.iconify_button
, frame
.ubutton
);
554 if (frame
.close_button
)
555 XSetWindowBackground(display
, frame
.close_button
, frame
.ubutton_pixel
);
556 if (frame
.maximize_button
)
557 XSetWindowBackground(display
, frame
.maximize_button
,
558 frame
.ubutton_pixel
);
559 if (frame
.iconify_button
)
560 XSetWindowBackground(display
, frame
.iconify_button
, frame
.ubutton_pixel
);
565 void OpenboxWindow::decorate(void) {
566 Pixmap tmp
= frame
.fbutton
;
567 BTexture
*texture
= &(screen
->getWindowStyle()->b_focus
);
568 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
569 frame
.fbutton
= None
;
570 frame
.fbutton_pixel
= texture
->getColor()->getPixel();
573 image_ctrl
->renderImage(frame
.button_w
, frame
.button_h
, texture
);
575 if (tmp
) image_ctrl
->removeImage(tmp
);
578 texture
= &(screen
->getWindowStyle()->b_unfocus
);
579 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
580 frame
.ubutton
= None
;
581 frame
.ubutton_pixel
= texture
->getColor()->getPixel();
584 image_ctrl
->renderImage(frame
.button_w
, frame
.button_h
, texture
);
586 if (tmp
) image_ctrl
->removeImage(tmp
);
589 texture
= &(screen
->getWindowStyle()->b_pressed
);
590 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
591 frame
.pbutton
= None
;
592 frame
.pbutton_pixel
= texture
->getColor()->getPixel();
595 image_ctrl
->renderImage(frame
.button_w
, frame
.button_h
, texture
);
597 if (tmp
) image_ctrl
->removeImage(tmp
);
599 if (decorations
.titlebar
) {
601 texture
= &(screen
->getWindowStyle()->t_focus
);
602 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
604 frame
.ftitle_pixel
= texture
->getColor()->getPixel();
607 image_ctrl
->renderImage(frame
.width
, frame
.title_h
, texture
);
609 if (tmp
) image_ctrl
->removeImage(tmp
);
612 texture
= &(screen
->getWindowStyle()->t_unfocus
);
613 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
615 frame
.utitle_pixel
= texture
->getColor()->getPixel();
618 image_ctrl
->renderImage(frame
.width
, frame
.title_h
, texture
);
620 if (tmp
) image_ctrl
->removeImage(tmp
);
622 XSetWindowBorder(display
, frame
.title
,
623 screen
->getBorderColor()->getPixel());
628 if (decorations
.border
) {
629 frame
.fborder_pixel
= screen
->getWindowStyle()->f_focus
.getPixel();
630 frame
.uborder_pixel
= screen
->getWindowStyle()->f_unfocus
.getPixel();
631 openbox_attrib
.flags
|= AttribDecoration
;
632 openbox_attrib
.decoration
= DecorNormal
;
634 openbox_attrib
.flags
|= AttribDecoration
;
635 openbox_attrib
.decoration
= DecorNone
;
638 if (decorations
.handle
) {
640 texture
= &(screen
->getWindowStyle()->h_focus
);
641 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
642 frame
.fhandle
= None
;
643 frame
.fhandle_pixel
= texture
->getColor()->getPixel();
646 image_ctrl
->renderImage(frame
.width
, frame
.handle_h
, texture
);
648 if (tmp
) image_ctrl
->removeImage(tmp
);
651 texture
= &(screen
->getWindowStyle()->h_unfocus
);
652 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
653 frame
.uhandle
= None
;
654 frame
.uhandle_pixel
= texture
->getColor()->getPixel();
657 image_ctrl
->renderImage(frame
.width
, frame
.handle_h
, texture
);
659 if (tmp
) image_ctrl
->removeImage(tmp
);
662 texture
= &(screen
->getWindowStyle()->g_focus
);
663 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
665 frame
.fgrip_pixel
= texture
->getColor()->getPixel();
668 image_ctrl
->renderImage(frame
.grip_w
, frame
.grip_h
, texture
);
670 if (tmp
) image_ctrl
->removeImage(tmp
);
673 texture
= &(screen
->getWindowStyle()->g_unfocus
);
674 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
676 frame
.ugrip_pixel
= texture
->getColor()->getPixel();
679 image_ctrl
->renderImage(frame
.grip_w
, frame
.grip_h
, texture
);
681 if (tmp
) image_ctrl
->removeImage(tmp
);
683 XSetWindowBorder(display
, frame
.handle
,
684 screen
->getBorderColor()->getPixel());
685 XSetWindowBorder(display
, frame
.left_grip
,
686 screen
->getBorderColor()->getPixel());
687 XSetWindowBorder(display
, frame
.right_grip
,
688 screen
->getBorderColor()->getPixel());
691 XSetWindowBorder(display
, frame
.window
,
692 screen
->getBorderColor()->getPixel());
696 void OpenboxWindow::decorateLabel(void) {
697 Pixmap tmp
= frame
.flabel
;
698 BTexture
*texture
= &(screen
->getWindowStyle()->l_focus
);
699 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
701 frame
.flabel_pixel
= texture
->getColor()->getPixel();
704 image_ctrl
->renderImage(frame
.label_w
, frame
.label_h
, texture
);
706 if (tmp
) image_ctrl
->removeImage(tmp
);
709 texture
= &(screen
->getWindowStyle()->l_unfocus
);
710 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
712 frame
.ulabel_pixel
= texture
->getColor()->getPixel();
715 image_ctrl
->renderImage(frame
.label_w
, frame
.label_h
, texture
);
717 if (tmp
) image_ctrl
->removeImage(tmp
);
721 void OpenboxWindow::createCloseButton(void) {
722 if (decorations
.close
&& frame
.title
!= None
) {
723 frame
.close_button
= createChildWindow(frame
.title
);
724 openbox
.saveWindowSearch(frame
.close_button
, this);
729 void OpenboxWindow::createIconifyButton(void) {
730 if (decorations
.iconify
&& frame
.title
!= None
) {
731 frame
.iconify_button
= createChildWindow(frame
.title
);
732 openbox
.saveWindowSearch(frame
.iconify_button
, this);
737 void OpenboxWindow::createMaximizeButton(void) {
738 if (decorations
.maximize
&& frame
.title
!= None
) {
739 frame
.maximize_button
= createChildWindow(frame
.title
);
740 openbox
.saveWindowSearch(frame
.maximize_button
, this);
745 void OpenboxWindow::positionButtons(Bool redecorate_label
) {
746 const char *format
= openbox
.getTitleBarLayout();
747 const unsigned int bw
= frame
.bevel_w
+ 1;
748 const unsigned int by
= frame
.bevel_w
+ 1;
749 unsigned int bx
= frame
.bevel_w
+ 1;
750 unsigned int bcount
= strlen(format
) - 1;
752 if (!decorations
.close
)
754 if (!decorations
.maximize
)
756 if (!decorations
.iconify
)
758 frame
.label_w
= frame
.width
- bx
* 2 - (frame
.button_w
+ bw
) * bcount
;
760 bool hasclose
, hasiconify
, hasmaximize
;
761 hasclose
= hasiconify
= hasmaximize
= false;
763 for (int i
= 0; format
[i
] != '\0' && i
< 4; i
++) {
766 if (decorations
.close
&& frame
.close_button
!= None
) {
767 XMoveResizeWindow(display
, frame
.close_button
, bx
, by
,
768 frame
.button_w
, frame
.button_h
);
769 XMapWindow(display
, frame
.close_button
);
770 XClearWindow(display
, frame
.close_button
);
771 bx
+= frame
.button_w
+ bw
;
773 } else if (frame
.close_button
)
774 XUnmapWindow(display
, frame
.close_button
);
777 if (decorations
.iconify
&& frame
.iconify_button
!= None
) {
778 XMoveResizeWindow(display
, frame
.iconify_button
, bx
, by
,
779 frame
.button_w
, frame
.button_h
);
780 XMapWindow(display
, frame
.iconify_button
);
781 XClearWindow(display
, frame
.iconify_button
);
782 bx
+= frame
.button_w
+ bw
;
784 } else if (frame
.close_button
)
785 XUnmapWindow(display
, frame
.close_button
);
788 if (decorations
.maximize
&& frame
.maximize_button
!= None
) {
789 XMoveResizeWindow(display
, frame
.maximize_button
, bx
, by
,
790 frame
.button_w
, frame
.button_h
);
791 XMapWindow(display
, frame
.maximize_button
);
792 XClearWindow(display
, frame
.maximize_button
);
793 bx
+= frame
.button_w
+ bw
;
795 } else if (frame
.close_button
)
796 XUnmapWindow(display
, frame
.close_button
);
799 XMoveResizeWindow(display
, frame
.label
, bx
, by
- 1,
800 frame
.label_w
, frame
.label_h
);
801 bx
+= frame
.label_w
+ bw
;
807 openbox
.removeWindowSearch(frame
.close_button
);
808 XDestroyWindow(display
, frame
.close_button
);
811 openbox
.removeWindowSearch(frame
.iconify_button
);
812 XDestroyWindow(display
, frame
.iconify_button
);
815 openbox
.removeWindowSearch(frame
.maximize_button
);
816 XDestroyWindow(display
, frame
.maximize_button
);
818 if (redecorate_label
)
825 void OpenboxWindow::reconfigure(void) {
828 client
.x
= frame
.x
+ frame
.mwm_border_w
+ frame
.border_w
;
829 client
.y
= frame
.y
+ frame
.y_border
+ frame
.mwm_border_w
+
833 if (i18n
->multibyte()) {
834 XRectangle ink
, logical
;
835 XmbTextExtents(screen
->getWindowStyle()->fontset
,
836 client
.title
, client
.title_len
, &ink
, &logical
);
837 client
.title_text_w
= logical
.width
;
839 client
.title_text_w
= XTextWidth(screen
->getWindowStyle()->font
,
840 client
.title
, client
.title_len
);
842 client
.title_text_w
+= (frame
.bevel_w
* 4);
848 XClearWindow(display
, frame
.window
);
849 setFocusFlag(flags
.focused
);
851 configure(frame
.x
, frame
.y
, frame
.width
, frame
.height
);
853 if (! screen
->sloppyFocus())
854 openbox
.grabButton(Button1
, 0, frame
.plate
, True
, ButtonPressMask
,
855 GrabModeSync
, GrabModeSync
, None
, None
);
857 openbox
.ungrabButton(Button1
, 0, frame
.plate
);
860 windowmenu
->move(windowmenu
->getX(), frame
.y
+ frame
.title_h
);
861 windowmenu
->reconfigure();
866 void OpenboxWindow::positionWindows(void) {
867 XResizeWindow(display
, frame
.window
, frame
.width
,
868 ((flags
.shaded
) ? frame
.title_h
: frame
.height
));
869 XSetWindowBorderWidth(display
, frame
.window
, frame
.border_w
);
870 XSetWindowBorderWidth(display
, frame
.plate
, frame
.mwm_border_w
);
871 XMoveResizeWindow(display
, frame
.plate
, 0, frame
.y_border
,
872 client
.width
, client
.height
);
873 XMoveResizeWindow(display
, client
.window
, 0, 0, client
.width
, client
.height
);
875 if (decorations
.titlebar
) {
876 XSetWindowBorderWidth(display
, frame
.title
, frame
.border_w
);
877 XMoveResizeWindow(display
, frame
.title
, -frame
.border_w
,
878 -frame
.border_w
, frame
.width
, frame
.title_h
);
881 } else if (frame
.title
) {
882 XUnmapWindow(display
, frame
.title
);
884 if (decorations
.handle
) {
885 XSetWindowBorderWidth(display
, frame
.handle
, frame
.border_w
);
886 XSetWindowBorderWidth(display
, frame
.left_grip
, frame
.border_w
);
887 XSetWindowBorderWidth(display
, frame
.right_grip
, frame
.border_w
);
889 XMoveResizeWindow(display
, frame
.handle
, -frame
.border_w
,
890 frame
.y_handle
- frame
.border_w
,
891 frame
.width
, frame
.handle_h
);
892 XMoveResizeWindow(display
, frame
.left_grip
, -frame
.border_w
,
893 -frame
.border_w
, frame
.grip_w
, frame
.grip_h
);
894 XMoveResizeWindow(display
, frame
.right_grip
,
895 frame
.width
- frame
.grip_w
- frame
.border_w
,
896 -frame
.border_w
, frame
.grip_w
, frame
.grip_h
);
897 XMapSubwindows(display
, frame
.handle
);
898 } else if (frame
.handle
) {
899 XUnmapWindow(display
, frame
.handle
);
904 void OpenboxWindow::getWMName(void) {
906 delete [] client
.title
;
907 client
.title
= (char *) 0;
910 XTextProperty text_prop
;
914 if (XGetWMName(display
, client
.window
, &text_prop
)) {
915 if (text_prop
.value
&& text_prop
.nitems
> 0) {
916 if (text_prop
.encoding
!= XA_STRING
) {
917 text_prop
.nitems
= strlen((char *) text_prop
.value
);
919 if ((XmbTextPropertyToTextList(display
, &text_prop
,
920 &list
, &num
) == Success
) &&
921 (num
> 0) && *list
) {
922 client
.title
= bstrdup(*list
);
923 XFreeStringList(list
);
925 client
.title
= bstrdup((char *) text_prop
.value
);
928 client
.title
= bstrdup((char *) text_prop
.value
);
930 XFree((char *) text_prop
.value
);
932 client
.title
= bstrdup(i18n
->getMessage(WindowSet
, WindowUnnamed
,
936 client
.title
= bstrdup(i18n
->getMessage(WindowSet
, WindowUnnamed
,
939 client
.title_len
= strlen(client
.title
);
941 if (i18n
->multibyte()) {
942 XRectangle ink
, logical
;
943 XmbTextExtents(screen
->getWindowStyle()->fontset
,
944 client
.title
, client
.title_len
, &ink
, &logical
);
945 client
.title_text_w
= logical
.width
;
947 client
.title_len
= strlen(client
.title
);
948 client
.title_text_w
= XTextWidth(screen
->getWindowStyle()->font
,
949 client
.title
, client
.title_len
);
952 client
.title_text_w
+= (frame
.bevel_w
* 4);
956 void OpenboxWindow::getWMIconName(void) {
957 if (client
.icon_title
) {
958 delete [] client
.icon_title
;
959 client
.icon_title
= (char *) 0;
962 XTextProperty text_prop
;
966 if (XGetWMIconName(display
, client
.window
, &text_prop
)) {
967 if (text_prop
.value
&& text_prop
.nitems
> 0) {
968 if (text_prop
.encoding
!= XA_STRING
) {
969 text_prop
.nitems
= strlen((char *) text_prop
.value
);
971 if ((XmbTextPropertyToTextList(display
, &text_prop
,
972 &list
, &num
) == Success
) &&
973 (num
> 0) && *list
) {
974 client
.icon_title
= bstrdup(*list
);
975 XFreeStringList(list
);
977 client
.icon_title
= bstrdup((char *) text_prop
.value
);
980 client
.icon_title
= bstrdup((char *) text_prop
.value
);
982 XFree((char *) text_prop
.value
);
984 client
.icon_title
= bstrdup(client
.title
);
987 client
.icon_title
= bstrdup(client
.title
);
993 * Retrieve which WM Protocols are supported by the client window.
994 * If the WM_DELETE_WINDOW protocol is supported, add the close button to the
995 * window's decorations and allow the close behavior.
996 * If the WM_TAKE_FOCUS protocol is supported, save a value that indicates
999 void OpenboxWindow::getWMProtocols(void) {
1003 if (XGetWMProtocols(display
, client
.window
, &proto
, &num_return
)) {
1004 for (int i
= 0; i
< num_return
; ++i
) {
1005 if (proto
[i
] == openbox
.getWMDeleteAtom())
1006 functions
.close
= decorations
.close
= True
;
1007 else if (proto
[i
] == openbox
.getWMTakeFocusAtom())
1008 flags
.send_focus_message
= True
;
1009 else if (proto
[i
] == openbox
.getOpenboxStructureMessagesAtom())
1010 screen
->addNetizen(new Netizen(*screen
, client
.window
));
1019 * Gets the value of the WM_HINTS property.
1020 * If the property is not set, then use a set of default values.
1022 void OpenboxWindow::getWMHints(void) {
1023 XWMHints
*wmhint
= XGetWMHints(display
, client
.window
);
1025 flags
.visible
= True
;
1026 flags
.iconic
= False
;
1027 focus_mode
= F_Passive
;
1028 client
.window_group
= None
;
1029 client
.initial_state
= NormalState
;
1032 client
.wm_hint_flags
= wmhint
->flags
;
1033 if (wmhint
->flags
& InputHint
) {
1034 if (wmhint
->input
== True
) {
1035 if (flags
.send_focus_message
)
1036 focus_mode
= F_LocallyActive
;
1038 focus_mode
= F_Passive
;
1040 if (flags
.send_focus_message
)
1041 focus_mode
= F_GloballyActive
;
1043 focus_mode
= F_NoInput
;
1046 focus_mode
= F_Passive
;
1049 if (wmhint
->flags
& StateHint
)
1050 client
.initial_state
= wmhint
->initial_state
;
1052 client
.initial_state
= NormalState
;
1054 if (wmhint
->flags
& WindowGroupHint
) {
1055 if (! client
.window_group
) {
1056 client
.window_group
= wmhint
->window_group
;
1057 openbox
.saveGroupSearch(client
.window_group
, this);
1060 client
.window_group
= None
;
1067 * Gets the value of the WM_NORMAL_HINTS property.
1068 * If the property is not set, then use a set of default values.
1070 void OpenboxWindow::getWMNormalHints(void) {
1072 XSizeHints sizehint
;
1074 client
.min_width
= client
.min_height
=
1075 client
.base_width
= client
.base_height
=
1076 client
.width_inc
= client
.height_inc
= 1;
1077 client
.max_width
= screen
->size().w();
1078 client
.max_height
= screen
->size().h();
1079 client
.min_aspect_x
= client
.min_aspect_y
=
1080 client
.max_aspect_x
= client
.max_aspect_y
= 1;
1081 client
.win_gravity
= NorthWestGravity
;
1083 if (! XGetWMNormalHints(display
, client
.window
, &sizehint
, &icccm_mask
))
1086 client
.normal_hint_flags
= sizehint
.flags
;
1088 if (sizehint
.flags
& PMinSize
) {
1089 client
.min_width
= sizehint
.min_width
;
1090 client
.min_height
= sizehint
.min_height
;
1093 if (sizehint
.flags
& PMaxSize
) {
1094 client
.max_width
= sizehint
.max_width
;
1095 client
.max_height
= sizehint
.max_height
;
1098 if (sizehint
.flags
& PResizeInc
) {
1099 client
.width_inc
= sizehint
.width_inc
;
1100 client
.height_inc
= sizehint
.height_inc
;
1103 if (sizehint
.flags
& PAspect
) {
1104 client
.min_aspect_x
= sizehint
.min_aspect
.x
;
1105 client
.min_aspect_y
= sizehint
.min_aspect
.y
;
1106 client
.max_aspect_x
= sizehint
.max_aspect
.x
;
1107 client
.max_aspect_y
= sizehint
.max_aspect
.y
;
1110 if (sizehint
.flags
& PBaseSize
) {
1111 client
.base_width
= sizehint
.base_width
;
1112 client
.base_height
= sizehint
.base_height
;
1115 if (sizehint
.flags
& PWinGravity
)
1116 client
.win_gravity
= sizehint
.win_gravity
;
1121 * Gets the MWM hints for the class' contained window.
1122 * This is used while initializing the window to its first state, and not
1124 * Returns: true if the MWM hints are successfully retreived and applied; false
1127 void OpenboxWindow::getMWMHints(void) {
1130 unsigned long num
, len
;
1132 int ret
= XGetWindowProperty(display
, client
.window
,
1133 openbox
.getMotifWMHintsAtom(), 0,
1134 PropMwmHintsElements
, False
,
1135 openbox
.getMotifWMHintsAtom(), &atom_return
,
1136 &format
, &num
, &len
,
1137 (unsigned char **) &client
.mwm_hint
);
1139 if (ret
!= Success
|| !client
.mwm_hint
|| num
!= PropMwmHintsElements
)
1142 if (client
.mwm_hint
->flags
& MwmHintsDecorations
) {
1143 if (client
.mwm_hint
->decorations
& MwmDecorAll
) {
1144 decorations
.titlebar
= decorations
.handle
= decorations
.border
=
1145 decorations
.iconify
= decorations
.maximize
=
1146 decorations
.close
= decorations
.menu
= True
;
1148 decorations
.titlebar
= decorations
.handle
= decorations
.border
=
1149 decorations
.iconify
= decorations
.maximize
=
1150 decorations
.close
= decorations
.menu
= False
;
1152 if (client
.mwm_hint
->decorations
& MwmDecorBorder
)
1153 decorations
.border
= True
;
1154 if (client
.mwm_hint
->decorations
& MwmDecorHandle
)
1155 decorations
.handle
= True
;
1156 if (client
.mwm_hint
->decorations
& MwmDecorTitle
)
1157 decorations
.titlebar
= True
;
1158 if (client
.mwm_hint
->decorations
& MwmDecorMenu
)
1159 decorations
.menu
= True
;
1160 if (client
.mwm_hint
->decorations
& MwmDecorIconify
)
1161 decorations
.iconify
= True
;
1162 if (client
.mwm_hint
->decorations
& MwmDecorMaximize
)
1163 decorations
.maximize
= True
;
1167 if (client
.mwm_hint
->flags
& MwmHintsFunctions
) {
1168 if (client
.mwm_hint
->functions
& MwmFuncAll
) {
1169 functions
.resize
= functions
.move
= functions
.iconify
=
1170 functions
.maximize
= functions
.close
= True
;
1172 functions
.resize
= functions
.move
= functions
.iconify
=
1173 functions
.maximize
= functions
.close
= False
;
1175 if (client
.mwm_hint
->functions
& MwmFuncResize
)
1176 functions
.resize
= True
;
1177 if (client
.mwm_hint
->functions
& MwmFuncMove
)
1178 functions
.move
= True
;
1179 if (client
.mwm_hint
->functions
& MwmFuncIconify
)
1180 functions
.iconify
= True
;
1181 if (client
.mwm_hint
->functions
& MwmFuncMaximize
)
1182 functions
.maximize
= True
;
1183 if (client
.mwm_hint
->functions
& MwmFuncClose
)
1184 functions
.close
= True
;
1191 * Gets the openbox hints from the class' contained window.
1192 * This is used while initializing the window to its first state, and not
1194 * Returns: true if the hints are successfully retreived and applied; false if
1197 void OpenboxWindow::getOpenboxHints(void) {
1200 unsigned long num
, len
;
1202 int ret
= XGetWindowProperty(display
, client
.window
,
1203 openbox
.getOpenboxHintsAtom(), 0,
1204 PropOpenboxHintsElements
, False
,
1205 openbox
.getOpenboxHintsAtom(), &atom_return
,
1206 &format
, &num
, &len
,
1207 (unsigned char **) &client
.openbox_hint
);
1208 if (ret
!= Success
|| !client
.openbox_hint
||
1209 num
!= PropOpenboxHintsElements
)
1212 if (client
.openbox_hint
->flags
& AttribShaded
)
1213 flags
.shaded
= (client
.openbox_hint
->attrib
& AttribShaded
);
1215 if ((client
.openbox_hint
->flags
& AttribMaxHoriz
) &&
1216 (client
.openbox_hint
->flags
& AttribMaxVert
))
1217 flags
.maximized
= (client
.openbox_hint
->attrib
&
1218 (AttribMaxHoriz
| AttribMaxVert
)) ? 1 : 0;
1219 else if (client
.openbox_hint
->flags
& AttribMaxVert
)
1220 flags
.maximized
= (client
.openbox_hint
->attrib
& AttribMaxVert
) ? 2 : 0;
1221 else if (client
.openbox_hint
->flags
& AttribMaxHoriz
)
1222 flags
.maximized
= (client
.openbox_hint
->attrib
& AttribMaxHoriz
) ? 3 : 0;
1224 if (client
.openbox_hint
->flags
& AttribOmnipresent
)
1225 flags
.stuck
= (client
.openbox_hint
->attrib
& AttribOmnipresent
);
1227 if (client
.openbox_hint
->flags
& AttribWorkspace
)
1228 workspace_number
= client
.openbox_hint
->workspace
;
1230 // if (client.openbox_hint->flags & AttribStack)
1231 // don't yet have always on top/bottom for openbox yet... working
1234 if (client
.openbox_hint
->flags
& AttribDecoration
) {
1235 switch (client
.openbox_hint
->decoration
) {
1237 decorations
.titlebar
= decorations
.border
= decorations
.handle
=
1238 decorations
.iconify
= decorations
.maximize
=
1239 decorations
.menu
= False
;
1240 functions
.resize
= functions
.move
= functions
.iconify
=
1241 functions
.maximize
= False
;
1246 decorations
.titlebar
= decorations
.iconify
= decorations
.menu
=
1247 functions
.move
= functions
.iconify
= True
;
1248 decorations
.border
= decorations
.handle
= decorations
.maximize
=
1249 functions
.resize
= functions
.maximize
= False
;
1254 decorations
.titlebar
= decorations
.menu
= functions
.move
= True
;
1255 decorations
.iconify
= decorations
.border
= decorations
.handle
=
1256 decorations
.maximize
= functions
.resize
= functions
.maximize
=
1257 functions
.iconify
= False
;
1263 decorations
.titlebar
= decorations
.border
= decorations
.handle
=
1264 decorations
.iconify
= decorations
.maximize
=
1265 decorations
.menu
= True
;
1266 functions
.resize
= functions
.move
= functions
.iconify
=
1267 functions
.maximize
= True
;
1277 void OpenboxWindow::configure(int dx
, int dy
,
1278 unsigned int dw
, unsigned int dh
) {
1279 Bool send_event
= (frame
.x
!= dx
|| frame
.y
!= dy
);
1281 if ((dw
!= frame
.width
) || (dh
!= frame
.height
)) {
1282 if ((((signed) frame
.width
) + dx
) < 0) dx
= 0;
1283 if ((((signed) frame
.height
) + dy
) < 0) dy
= 0;
1293 if (openbox
.hasShapeExtensions() && flags
.shaped
) {
1294 XShapeCombineShape(display
, frame
.window
, ShapeBounding
,
1295 frame
.mwm_border_w
, frame
.y_border
+
1296 frame
.mwm_border_w
, client
.window
,
1297 ShapeBounding
, ShapeSet
);
1300 XRectangle xrect
[2];
1301 xrect
[0].x
= xrect
[0].y
= 0;
1302 xrect
[0].width
= frame
.width
;
1303 xrect
[0].height
= frame
.y_border
;
1305 if (decorations
.handle
) {
1307 xrect
[1].y
= frame
.y_handle
;
1308 xrect
[1].width
= frame
.width
;
1309 xrect
[1].height
= frame
.handle_h
+ frame
.border_w
;
1313 XShapeCombineRectangles(display
, frame
.window
, ShapeBounding
, 0, 0,
1314 xrect
, num
, ShapeUnion
, Unsorted
);
1318 XMoveWindow(display
, frame
.window
, frame
.x
, frame
.y
);
1322 setFocusFlag(flags
.focused
);
1328 XMoveWindow(display
, frame
.window
, frame
.x
, frame
.y
);
1330 if (! flags
.moving
) send_event
= True
;
1333 if (send_event
&& ! flags
.moving
) {
1334 client
.x
= dx
+ frame
.mwm_border_w
+ frame
.border_w
;
1335 client
.y
= dy
+ frame
.y_border
+ frame
.mwm_border_w
+
1339 event
.type
= ConfigureNotify
;
1341 event
.xconfigure
.display
= display
;
1342 event
.xconfigure
.event
= client
.window
;
1343 event
.xconfigure
.window
= client
.window
;
1344 event
.xconfigure
.x
= client
.x
;
1345 event
.xconfigure
.y
= client
.y
;
1346 event
.xconfigure
.width
= client
.width
;
1347 event
.xconfigure
.height
= client
.height
;
1348 event
.xconfigure
.border_width
= client
.old_bw
;
1349 event
.xconfigure
.above
= frame
.window
;
1350 event
.xconfigure
.override_redirect
= False
;
1352 XSendEvent(display
, client
.window
, True
, NoEventMask
, &event
);
1354 screen
->updateNetizenConfigNotify(&event
);
1359 Bool
OpenboxWindow::setInputFocus(void) {
1360 if (((signed) (frame
.x
+ frame
.width
)) < 0) {
1361 if (((signed) (frame
.y
+ frame
.y_border
)) < 0)
1362 configure(frame
.border_w
, frame
.border_w
, frame
.width
, frame
.height
);
1363 else if (frame
.y
> (signed) screen
->size().h())
1364 configure(frame
.border_w
, screen
->size().h() - frame
.height
,
1365 frame
.width
, frame
.height
);
1367 configure(frame
.border_w
, frame
.y
+ frame
.border_w
,
1368 frame
.width
, frame
.height
);
1369 } else if (frame
.x
> (signed) screen
->size().w()) {
1370 if (((signed) (frame
.y
+ frame
.y_border
)) < 0)
1371 configure(screen
->size().w() - frame
.width
, frame
.border_w
,
1372 frame
.width
, frame
.height
);
1373 else if (frame
.y
> (signed) screen
->size().h())
1374 configure(screen
->size().w() - frame
.width
,
1375 screen
->size().h() - frame
.height
, frame
.width
, frame
.height
);
1377 configure(screen
->size().w() - frame
.width
,
1378 frame
.y
+ frame
.border_w
, frame
.width
, frame
.height
);
1382 if (! validateClient()) return False
;
1386 if (client
.transient
&& flags
.modal
) {
1387 ret
= client
.transient
->setInputFocus();
1388 } else if (! flags
.focused
) {
1389 if (focus_mode
== F_LocallyActive
|| focus_mode
== F_Passive
)
1390 XSetInputFocus(display
, client
.window
,
1391 RevertToPointerRoot
, CurrentTime
);
1393 XSetInputFocus(display
, screen
->getRootWindow(),
1394 RevertToNone
, CurrentTime
);
1396 openbox
.focusWindow(this);
1398 if (flags
.send_focus_message
) {
1400 ce
.xclient
.type
= ClientMessage
;
1401 ce
.xclient
.message_type
= openbox
.getWMProtocolsAtom();
1402 ce
.xclient
.display
= display
;
1403 ce
.xclient
.window
= client
.window
;
1404 ce
.xclient
.format
= 32;
1405 ce
.xclient
.data
.l
[0] = openbox
.getWMTakeFocusAtom();
1406 ce
.xclient
.data
.l
[1] = openbox
.getLastTime();
1407 ce
.xclient
.data
.l
[2] = 0l;
1408 ce
.xclient
.data
.l
[3] = 0l;
1409 ce
.xclient
.data
.l
[4] = 0l;
1410 XSendEvent(display
, client
.window
, False
, NoEventMask
, &ce
);
1413 if (screen
->sloppyFocus() && screen
->autoRaise())
1425 void OpenboxWindow::iconify(void) {
1426 if (flags
.iconic
) return;
1431 if (windowmenu
) windowmenu
->hide();
1433 setState(IconicState
);
1435 XSelectInput(display
, client
.window
, NoEventMask
);
1436 XUnmapWindow(display
, client
.window
);
1437 XSelectInput(display
, client
.window
,
1438 PropertyChangeMask
| StructureNotifyMask
| FocusChangeMask
);
1440 XUnmapWindow(display
, frame
.window
);
1441 flags
.visible
= False
;
1442 flags
.iconic
= True
;
1444 screen
->getWorkspace(workspace_number
)->removeWindow(this);
1446 if (flags
.transient
&& client
.transient_for
&&
1447 !client
.transient_for
->flags
.iconic
) {
1448 client
.transient_for
->iconify();
1450 screen
->addIcon(this);
1452 if (client
.transient
&& !client
.transient
->flags
.iconic
) {
1453 client
.transient
->iconify();
1458 void OpenboxWindow::deiconify(bool reassoc
, bool raise
, bool initial
) {
1459 if (flags
.iconic
|| reassoc
)
1460 screen
->reassociateWindow(this, -1, False
);
1461 else if (workspace_number
!= screen
->getCurrentWorkspace()->getWorkspaceID())
1464 setState(NormalState
);
1466 XSelectInput(display
, client
.window
, NoEventMask
);
1467 XMapWindow(display
, client
.window
);
1468 XSelectInput(display
, client
.window
,
1469 PropertyChangeMask
| StructureNotifyMask
| FocusChangeMask
);
1471 XMapSubwindows(display
, frame
.window
);
1472 XMapWindow(display
, frame
.window
);
1474 // if we're using the click to place placement type, then immediately
1475 // after the window is mapped, we need to start interactively moving it
1476 if (initial
&& place_window
&&
1477 screen
->placementPolicy() == BScreen::ClickMousePlacement
) {
1481 XQueryPointer(openbox
.getXDisplay(), screen
->getRootWindow(),
1482 &r
, &c
, &rx
, &ry
, &x
, &y
, &m
);
1486 if (flags
.iconic
&& screen
->focusNew()) setInputFocus();
1488 flags
.visible
= True
;
1489 flags
.iconic
= False
;
1491 if (reassoc
&& client
.transient
) client
.transient
->deiconify(True
, False
);
1494 screen
->getWorkspace(workspace_number
)->raiseWindow(this);
1498 void OpenboxWindow::close(void) {
1500 ce
.xclient
.type
= ClientMessage
;
1501 ce
.xclient
.message_type
= openbox
.getWMProtocolsAtom();
1502 ce
.xclient
.display
= display
;
1503 ce
.xclient
.window
= client
.window
;
1504 ce
.xclient
.format
= 32;
1505 ce
.xclient
.data
.l
[0] = openbox
.getWMDeleteAtom();
1506 ce
.xclient
.data
.l
[1] = CurrentTime
;
1507 ce
.xclient
.data
.l
[2] = 0l;
1508 ce
.xclient
.data
.l
[3] = 0l;
1509 ce
.xclient
.data
.l
[4] = 0l;
1510 XSendEvent(display
, client
.window
, False
, NoEventMask
, &ce
);
1514 void OpenboxWindow::withdraw(void) {
1518 flags
.visible
= False
;
1519 flags
.iconic
= False
;
1521 XUnmapWindow(display
, frame
.window
);
1523 XSelectInput(display
, client
.window
, NoEventMask
);
1524 XUnmapWindow(display
, client
.window
);
1525 XSelectInput(display
, client
.window
,
1526 PropertyChangeMask
| StructureNotifyMask
| FocusChangeMask
);
1528 if (windowmenu
) windowmenu
->hide();
1532 void OpenboxWindow::maximize(unsigned int button
) {
1536 // handle case where menu is open then the max button is used instead
1537 if (windowmenu
&& windowmenu
->isVisible()) windowmenu
->hide();
1539 if (flags
.maximized
) {
1540 flags
.maximized
= 0;
1542 openbox_attrib
.flags
&= ! (AttribMaxHoriz
| AttribMaxVert
);
1543 openbox_attrib
.attrib
&= ! (AttribMaxHoriz
| AttribMaxVert
);
1545 // when a resize is begun, maximize(0) is called to clear any maximization
1546 // flags currently set. Otherwise it still thinks it is maximized.
1547 // so we do not need to call configure() because resizing will handle it
1548 if (!flags
.resizing
)
1549 configure(openbox_attrib
.premax_x
, openbox_attrib
.premax_y
,
1550 openbox_attrib
.premax_w
, openbox_attrib
.premax_h
);
1552 openbox_attrib
.premax_x
= openbox_attrib
.premax_y
= 0;
1553 openbox_attrib
.premax_w
= openbox_attrib
.premax_h
= 0;
1556 setState(current_state
);
1560 openbox_attrib
.premax_x
= frame
.x
;
1561 openbox_attrib
.premax_y
= frame
.y
;
1562 openbox_attrib
.premax_w
= frame
.width
;
1563 openbox_attrib
.premax_h
= frame
.height
;
1565 Rect space
= screen
->availableArea();
1566 unsigned int dw
= space
.w(),
1568 dw
-= frame
.border_w
* 2;
1569 dw
-= frame
.mwm_border_w
* 2;
1570 dw
-= client
.base_width
;
1572 dh
-= frame
.border_w
* 2;
1573 dh
-= frame
.mwm_border_w
* 2;
1574 dh
-= ((frame
.handle_h
+ frame
.border_w
) * decorations
.handle
);
1575 dh
-= client
.base_height
;
1576 dh
-= frame
.y_border
;
1578 if (dw
< client
.min_width
) dw
= client
.min_width
;
1579 if (dh
< client
.min_height
) dh
= client
.min_height
;
1580 if (dw
> client
.max_width
) dw
= client
.max_width
;
1581 if (dh
> client
.max_height
) dh
= client
.max_height
;
1583 dw
-= (dw
% client
.width_inc
);
1584 dw
+= client
.base_width
;
1585 dw
+= frame
.mwm_border_w
* 2;
1587 dh
-= (dh
% client
.height_inc
);
1588 dh
+= client
.base_height
;
1589 dh
+= frame
.y_border
;
1590 dh
+= ((frame
.handle_h
+ frame
.border_w
) * decorations
.handle
);
1591 dh
+= frame
.mwm_border_w
* 2;
1593 int dx
= space
.x() + ((space
.w() - dw
) / 2) - frame
.border_w
,
1594 dy
= space
.y() + ((space
.h() - dh
) / 2) - frame
.border_w
;
1598 openbox_attrib
.flags
|= AttribMaxHoriz
| AttribMaxVert
;
1599 openbox_attrib
.attrib
|= AttribMaxHoriz
| AttribMaxVert
;
1603 openbox_attrib
.flags
|= AttribMaxVert
;
1604 openbox_attrib
.attrib
|= AttribMaxVert
;
1611 openbox_attrib
.flags
|= AttribMaxHoriz
;
1612 openbox_attrib
.attrib
|= AttribMaxHoriz
;
1620 openbox_attrib
.flags
^= AttribShaded
;
1621 openbox_attrib
.attrib
^= AttribShaded
;
1622 flags
.shaded
= False
;
1625 flags
.maximized
= button
;
1627 configure(dx
, dy
, dw
, dh
);
1628 screen
->getWorkspace(workspace_number
)->raiseWindow(this);
1630 setState(current_state
);
1634 void OpenboxWindow::setWorkspace(int n
) {
1635 workspace_number
= n
;
1637 openbox_attrib
.flags
|= AttribWorkspace
;
1638 openbox_attrib
.workspace
= workspace_number
;
1642 void OpenboxWindow::shade(void) {
1643 if (!decorations
.titlebar
)
1647 XResizeWindow(display
, frame
.window
, frame
.width
, frame
.height
);
1648 flags
.shaded
= False
;
1649 openbox_attrib
.flags
^= AttribShaded
;
1650 openbox_attrib
.attrib
^= AttribShaded
;
1652 setState(NormalState
);
1654 XResizeWindow(display
, frame
.window
, frame
.width
, frame
.title_h
);
1655 flags
.shaded
= True
;
1656 openbox_attrib
.flags
|= AttribShaded
;
1657 openbox_attrib
.attrib
|= AttribShaded
;
1659 setState(IconicState
);
1664 void OpenboxWindow::stick(void) {
1666 openbox_attrib
.flags
^= AttribOmnipresent
;
1667 openbox_attrib
.attrib
^= AttribOmnipresent
;
1669 flags
.stuck
= False
;
1672 screen
->reassociateWindow(this, -1, True
);
1674 setState(current_state
);
1678 openbox_attrib
.flags
|= AttribOmnipresent
;
1679 openbox_attrib
.attrib
|= AttribOmnipresent
;
1681 setState(current_state
);
1686 void OpenboxWindow::setFocusFlag(Bool focus
) {
1687 flags
.focused
= focus
;
1689 if (decorations
.titlebar
) {
1690 if (flags
.focused
) {
1692 XSetWindowBackgroundPixmap(display
, frame
.title
, frame
.ftitle
);
1694 XSetWindowBackground(display
, frame
.title
, frame
.ftitle_pixel
);
1697 XSetWindowBackgroundPixmap(display
, frame
.title
, frame
.utitle
);
1699 XSetWindowBackground(display
, frame
.title
, frame
.utitle_pixel
);
1701 XClearWindow(display
, frame
.title
);
1707 if (decorations
.handle
) {
1708 if (flags
.focused
) {
1710 XSetWindowBackgroundPixmap(display
, frame
.handle
, frame
.fhandle
);
1712 XSetWindowBackground(display
, frame
.handle
, frame
.fhandle_pixel
);
1715 XSetWindowBackgroundPixmap(display
, frame
.right_grip
, frame
.fgrip
);
1716 XSetWindowBackgroundPixmap(display
, frame
.left_grip
, frame
.fgrip
);
1718 XSetWindowBackground(display
, frame
.right_grip
, frame
.fgrip_pixel
);
1719 XSetWindowBackground(display
, frame
.left_grip
, frame
.fgrip_pixel
);
1723 XSetWindowBackgroundPixmap(display
, frame
.handle
, frame
.uhandle
);
1725 XSetWindowBackground(display
, frame
.handle
, frame
.uhandle_pixel
);
1728 XSetWindowBackgroundPixmap(display
, frame
.right_grip
, frame
.ugrip
);
1729 XSetWindowBackgroundPixmap(display
, frame
.left_grip
, frame
.ugrip
);
1731 XSetWindowBackground(display
, frame
.right_grip
, frame
.ugrip_pixel
);
1732 XSetWindowBackground(display
, frame
.left_grip
, frame
.ugrip_pixel
);
1735 XClearWindow(display
, frame
.handle
);
1736 XClearWindow(display
, frame
.right_grip
);
1737 XClearWindow(display
, frame
.left_grip
);
1740 if (decorations
.border
) {
1742 XSetWindowBorder(display
, frame
.plate
, frame
.fborder_pixel
);
1744 XSetWindowBorder(display
, frame
.plate
, frame
.uborder_pixel
);
1747 if (screen
->sloppyFocus() && screen
->autoRaise() && timer
->isTiming())
1753 void OpenboxWindow::installColormap(Bool install
) {
1755 if (! validateClient()) return;
1757 int i
= 0, ncmap
= 0;
1758 Colormap
*cmaps
= XListInstalledColormaps(display
, client
.window
, &ncmap
);
1759 XWindowAttributes wattrib
;
1761 if (XGetWindowAttributes(display
, client
.window
, &wattrib
)) {
1763 // install the window's colormap
1764 for (i
= 0; i
< ncmap
; i
++) {
1765 if (*(cmaps
+ i
) == wattrib
.colormap
)
1766 // this window is using an installed color map... do not install
1769 // otherwise, install the window's colormap
1771 XInstallColormap(display
, wattrib
.colormap
);
1773 // uninstall the window's colormap
1774 for (i
= 0; i
< ncmap
; i
++) {
1775 if (*(cmaps
+ i
) == wattrib
.colormap
)
1776 // we found the colormap to uninstall
1777 XUninstallColormap(display
, wattrib
.colormap
);
1789 void OpenboxWindow::setState(unsigned long new_state
) {
1790 current_state
= new_state
;
1792 unsigned long state
[2];
1793 state
[0] = (unsigned long) current_state
;
1794 state
[1] = (unsigned long) None
;
1795 XChangeProperty(display
, client
.window
, openbox
.getWMStateAtom(),
1796 openbox
.getWMStateAtom(), 32, PropModeReplace
,
1797 (unsigned char *) state
, 2);
1799 XChangeProperty(display
, client
.window
,
1800 openbox
.getOpenboxAttributesAtom(),
1801 openbox
.getOpenboxAttributesAtom(), 32, PropModeReplace
,
1802 (unsigned char *) &openbox_attrib
,
1803 PropOpenboxAttributesElements
);
1807 Bool
OpenboxWindow::getState(void) {
1813 unsigned long *state
, ulfoo
, nitems
;
1815 if ((XGetWindowProperty(display
, client
.window
, openbox
.getWMStateAtom(),
1816 0l, 2l, False
, openbox
.getWMStateAtom(),
1817 &atom_return
, &foo
, &nitems
, &ulfoo
,
1818 (unsigned char **) &state
) != Success
) ||
1825 current_state
= (unsigned long) state
[0];
1830 XFree((void *) state
);
1836 void OpenboxWindow::setGravityOffsets(void) {
1837 // x coordinates for each gravity type
1838 const int x_west
= client
.x
;
1839 const int x_east
= client
.x
+ client
.width
- frame
.width
;
1840 const int x_center
= client
.x
+ client
.width
- frame
.width
/2;
1841 // y coordinates for each gravity type
1842 const int y_north
= client
.y
;
1843 const int y_south
= client
.y
+ client
.height
- frame
.height
;
1844 const int y_center
= client
.y
+ client
.height
- frame
.height
/2;
1846 switch (client
.win_gravity
) {
1847 case NorthWestGravity
:
1856 case NorthEastGravity
:
1860 case SouthWestGravity
:
1868 case SouthEastGravity
:
1886 frame
.x
= client
.x
- frame
.mwm_border_w
+ frame
.border_w
;
1887 frame
.y
= client
.y
- frame
.y_border
- frame
.mwm_border_w
- frame
.border_w
;
1893 void OpenboxWindow::restoreAttributes(void) {
1894 if (! getState()) current_state
= NormalState
;
1898 unsigned long ulfoo
, nitems
;
1900 OpenboxAttributes
*net
;
1901 int ret
= XGetWindowProperty(display
, client
.window
,
1902 openbox
.getOpenboxAttributesAtom(), 0l,
1903 PropOpenboxAttributesElements
, False
,
1904 openbox
.getOpenboxAttributesAtom(),
1905 &atom_return
, &foo
, &nitems
, &ulfoo
,
1906 (unsigned char **) &net
);
1907 if (ret
!= Success
|| !net
|| nitems
!= PropOpenboxAttributesElements
)
1910 openbox_attrib
.flags
= net
->flags
;
1911 openbox_attrib
.attrib
= net
->attrib
;
1912 openbox_attrib
.decoration
= net
->decoration
;
1913 openbox_attrib
.workspace
= net
->workspace
;
1914 openbox_attrib
.stack
= net
->stack
;
1915 openbox_attrib
.premax_x
= net
->premax_x
;
1916 openbox_attrib
.premax_y
= net
->premax_y
;
1917 openbox_attrib
.premax_w
= net
->premax_w
;
1918 openbox_attrib
.premax_h
= net
->premax_h
;
1920 XFree((void *) net
);
1922 if (openbox_attrib
.flags
& AttribShaded
&&
1923 openbox_attrib
.attrib
& AttribShaded
) {
1925 ((current_state
== IconicState
) ? NormalState
: current_state
);
1927 flags
.shaded
= False
;
1930 current_state
= save_state
;
1933 if (((int) openbox_attrib
.workspace
!= screen
->getCurrentWorkspaceID()) &&
1934 ((int) openbox_attrib
.workspace
< screen
->getWorkspaceCount())) {
1935 screen
->reassociateWindow(this, openbox_attrib
.workspace
, True
);
1937 if (current_state
== NormalState
) current_state
= WithdrawnState
;
1938 } else if (current_state
== WithdrawnState
) {
1939 current_state
= NormalState
;
1942 if (openbox_attrib
.flags
& AttribOmnipresent
&&
1943 openbox_attrib
.attrib
& AttribOmnipresent
) {
1944 flags
.stuck
= False
;
1947 current_state
= NormalState
;
1950 if ((openbox_attrib
.flags
& AttribMaxHoriz
) ||
1951 (openbox_attrib
.flags
& AttribMaxVert
)) {
1952 int x
= openbox_attrib
.premax_x
, y
= openbox_attrib
.premax_y
;
1953 unsigned int w
= openbox_attrib
.premax_w
, h
= openbox_attrib
.premax_h
;
1954 flags
.maximized
= 0;
1956 unsigned int m
= False
;
1957 if ((openbox_attrib
.flags
& AttribMaxHoriz
) &&
1958 (openbox_attrib
.flags
& AttribMaxVert
))
1959 m
= (openbox_attrib
.attrib
& (AttribMaxHoriz
| AttribMaxVert
)) ? 1 : 0;
1960 else if (openbox_attrib
.flags
& AttribMaxVert
)
1961 m
= (openbox_attrib
.attrib
& AttribMaxVert
) ? 2 : 0;
1962 else if (openbox_attrib
.flags
& AttribMaxHoriz
)
1963 m
= (openbox_attrib
.attrib
& AttribMaxHoriz
) ? 3 : 0;
1967 openbox_attrib
.premax_x
= x
;
1968 openbox_attrib
.premax_y
= y
;
1969 openbox_attrib
.premax_w
= w
;
1970 openbox_attrib
.premax_h
= h
;
1973 setState(current_state
);
1978 * The reverse of the setGravityOffsets function. Uses the frame window's
1979 * position to find the window's reference point.
1981 void OpenboxWindow::restoreGravity(void) {
1982 // x coordinates for each gravity type
1983 const int x_west
= frame
.x
;
1984 const int x_east
= frame
.x
+ frame
.width
- client
.width
;
1985 const int x_center
= frame
.x
+ (frame
.width
/2) - client
.width
;
1986 // y coordinates for each gravity type
1987 const int y_north
= frame
.y
;
1988 const int y_south
= frame
.y
+ frame
.height
- client
.height
;
1989 const int y_center
= frame
.y
+ (frame
.height
/2) - client
.height
;
1991 switch(client
.win_gravity
) {
1993 case NorthWestGravity
:
1998 client
.x
= x_center
;
2001 case NorthEastGravity
:
2005 case SouthWestGravity
:
2010 client
.x
= x_center
;
2013 case SouthEastGravity
:
2019 client
.y
= y_center
;
2023 client
.y
= y_center
;
2026 client
.x
= x_center
;
2027 client
.y
= y_center
;
2031 client
.x
= frame
.x
+ frame
.mwm_border_w
+ frame
.border_w
;
2032 client
.y
= frame
.y
+ frame
.y_border
+ frame
.mwm_border_w
+
2039 void OpenboxWindow::redrawLabel(void) {
2040 int dx
= frame
.bevel_w
* 2, dlen
= client
.title_len
;
2041 unsigned int l
= client
.title_text_w
;
2043 if (flags
.focused
) {
2045 XSetWindowBackgroundPixmap(display
, frame
.label
, frame
.flabel
);
2047 XSetWindowBackground(display
, frame
.label
, frame
.flabel_pixel
);
2050 XSetWindowBackgroundPixmap(display
, frame
.label
, frame
.ulabel
);
2052 XSetWindowBackground(display
, frame
.label
, frame
.ulabel_pixel
);
2054 XClearWindow(display
, frame
.label
);
2056 if (client
.title_text_w
> frame
.label_w
) {
2057 for (; dlen
>= 0; dlen
--) {
2058 if (i18n
->multibyte()) {
2059 XRectangle ink
, logical
;
2060 XmbTextExtents(screen
->getWindowStyle()->fontset
, client
.title
, dlen
,
2064 l
= XTextWidth(screen
->getWindowStyle()->font
, client
.title
, dlen
);
2066 l
+= (frame
.bevel_w
* 4);
2068 if (l
< frame
.label_w
)
2073 switch (screen
->getWindowStyle()->justify
) {
2074 case BScreen::RightJustify
:
2075 dx
+= frame
.label_w
- l
;
2078 case BScreen::CenterJustify
:
2079 dx
+= (frame
.label_w
- l
) / 2;
2083 WindowStyle
*style
= screen
->getWindowStyle();
2084 GC text_gc
= (flags
.focused
) ? style
->l_text_focus_gc
:
2085 style
->l_text_unfocus_gc
;
2086 if (i18n
->multibyte())
2087 XmbDrawString(display
, frame
.label
, style
->fontset
, text_gc
, dx
,
2088 (1 - style
->fontset_extents
->max_ink_extent
.y
),
2089 client
.title
, dlen
);
2091 XDrawString(display
, frame
.label
, text_gc
, dx
,
2092 (style
->font
->ascent
+ 1), client
.title
, dlen
);
2096 void OpenboxWindow::redrawAllButtons(void) {
2097 if (frame
.iconify_button
) redrawIconifyButton(False
);
2098 if (frame
.maximize_button
) redrawMaximizeButton(flags
.maximized
);
2099 if (frame
.close_button
) redrawCloseButton(False
);
2103 void OpenboxWindow::redrawIconifyButton(Bool pressed
) {
2105 if (flags
.focused
) {
2107 XSetWindowBackgroundPixmap(display
, frame
.iconify_button
,
2110 XSetWindowBackground(display
, frame
.iconify_button
,
2111 frame
.fbutton_pixel
);
2114 XSetWindowBackgroundPixmap(display
, frame
.iconify_button
,
2117 XSetWindowBackground(display
, frame
.iconify_button
,
2118 frame
.ubutton_pixel
);
2122 XSetWindowBackgroundPixmap(display
, frame
.iconify_button
, frame
.pbutton
);
2124 XSetWindowBackground(display
, frame
.iconify_button
, frame
.pbutton_pixel
);
2126 XClearWindow(display
, frame
.iconify_button
);
2128 XDrawRectangle(display
, frame
.iconify_button
,
2129 ((flags
.focused
) ? screen
->getWindowStyle()->b_pic_focus_gc
:
2130 screen
->getWindowStyle()->b_pic_unfocus_gc
),
2131 2, (frame
.button_h
- 5), (frame
.button_w
- 5), 2);
2135 void OpenboxWindow::redrawMaximizeButton(Bool pressed
) {
2137 if (flags
.focused
) {
2139 XSetWindowBackgroundPixmap(display
, frame
.maximize_button
,
2142 XSetWindowBackground(display
, frame
.maximize_button
,
2143 frame
.fbutton_pixel
);
2146 XSetWindowBackgroundPixmap(display
, frame
.maximize_button
,
2149 XSetWindowBackground(display
, frame
.maximize_button
,
2150 frame
.ubutton_pixel
);
2154 XSetWindowBackgroundPixmap(display
, frame
.maximize_button
,
2157 XSetWindowBackground(display
, frame
.maximize_button
,
2158 frame
.pbutton_pixel
);
2160 XClearWindow(display
, frame
.maximize_button
);
2162 XDrawRectangle(display
, frame
.maximize_button
,
2163 ((flags
.focused
) ? screen
->getWindowStyle()->b_pic_focus_gc
:
2164 screen
->getWindowStyle()->b_pic_unfocus_gc
),
2165 2, 2, (frame
.button_w
- 5), (frame
.button_h
- 5));
2166 XDrawLine(display
, frame
.maximize_button
,
2167 ((flags
.focused
) ? screen
->getWindowStyle()->b_pic_focus_gc
:
2168 screen
->getWindowStyle()->b_pic_unfocus_gc
),
2169 2, 3, (frame
.button_w
- 3), 3);
2173 void OpenboxWindow::redrawCloseButton(Bool pressed
) {
2175 if (flags
.focused
) {
2177 XSetWindowBackgroundPixmap(display
, frame
.close_button
,
2180 XSetWindowBackground(display
, frame
.close_button
,
2181 frame
.fbutton_pixel
);
2184 XSetWindowBackgroundPixmap(display
, frame
.close_button
,
2187 XSetWindowBackground(display
, frame
.close_button
,
2188 frame
.ubutton_pixel
);
2192 XSetWindowBackgroundPixmap(display
, frame
.close_button
, frame
.pbutton
);
2194 XSetWindowBackground(display
, frame
.close_button
, frame
.pbutton_pixel
);
2196 XClearWindow(display
, frame
.close_button
);
2198 XDrawLine(display
, frame
.close_button
,
2199 ((flags
.focused
) ? screen
->getWindowStyle()->b_pic_focus_gc
:
2200 screen
->getWindowStyle()->b_pic_unfocus_gc
), 2, 2,
2201 (frame
.button_w
- 3), (frame
.button_h
- 3));
2202 XDrawLine(display
, frame
.close_button
,
2203 ((flags
.focused
) ? screen
->getWindowStyle()->b_pic_focus_gc
:
2204 screen
->getWindowStyle()->b_pic_unfocus_gc
), 2,
2205 (frame
.button_h
- 3),
2206 (frame
.button_w
- 3), 2);
2210 void OpenboxWindow::mapRequestEvent(XMapRequestEvent
*re
) {
2211 cout
<< "MAP REQUEST " << client
.window
<< " " << client
.title
<< endl
;
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
;
2233 switch (current_state
) {
2238 case WithdrawnState
:
2246 deiconify(False
, True
, True
); // specify that we're initializing the
2256 void OpenboxWindow::mapNotifyEvent(XMapEvent
*ne
) {
2257 if ((ne
->window
== client
.window
) && (! ne
->override_redirect
)
2258 && (flags
.visible
)) {
2260 if (! validateClient()) return;
2262 if (decorations
.titlebar
) positionButtons();
2264 setState(NormalState
);
2268 if (flags
.transient
|| screen
->focusNew())
2271 setFocusFlag(False
);
2273 flags
.visible
= True
;
2274 flags
.iconic
= False
;
2281 void OpenboxWindow::unmapNotifyEvent(XUnmapEvent
*ue
) {
2282 if (ue
->window
== client
.window
) {
2284 fprintf(stderr
, i18n
->getMessage(WindowSet
, WindowUnmapNotify
,
2285 "OpenboxWindow::unmapNotifyEvent() for 0x%lx\n"),
2290 if (! validateClient()) return;
2295 XChangeSaveSet(display
, client
.window
, SetModeDelete
);
2296 XSelectInput(display
, client
.window
, NoEventMask
);
2298 XDeleteProperty(display
, client
.window
, openbox
.getWMStateAtom());
2299 XDeleteProperty(display
, client
.window
,
2300 openbox
.getOpenboxAttributesAtom());
2302 XUnmapWindow(display
, frame
.window
);
2303 XUnmapWindow(display
, client
.window
);
2306 if (! XCheckTypedWindowEvent(display
, client
.window
, ReparentNotify
,
2309 fprintf(stderr
, i18n
->getMessage(WindowSet
, WindowUnmapNotifyReparent
,
2310 "OpenboxWindow::unmapNotifyEvent(): reparent 0x%lx to "
2311 "root.\n"), client
.window
);
2315 XReparentWindow(display
, client
.window
, screen
->getRootWindow(),
2316 client
.x
, client
.y
);
2328 void OpenboxWindow::destroyNotifyEvent(XDestroyWindowEvent
*de
) {
2329 if (de
->window
== client
.window
) {
2332 XUnmapWindow(display
, frame
.window
);
2339 void OpenboxWindow::propertyNotifyEvent(Atom atom
) {
2341 if (! validateClient()) return;
2345 case XA_WM_CLIENT_MACHINE
:
2349 case XA_WM_TRANSIENT_FOR
:
2350 // determine if this is a transient window
2352 if (XGetTransientForHint(display
, client
.window
, &win
)) {
2353 if (win
&& (win
!= client
.window
)) {
2354 if ((client
.transient_for
= openbox
.searchWindow(win
))) {
2355 client
.transient_for
->client
.transient
= this;
2356 flags
.stuck
= client
.transient_for
->flags
.stuck
;
2357 flags
.transient
= True
;
2358 } else if (win
== client
.window_group
) {
2359 //jr This doesn't look quite right...
2360 if ((client
.transient_for
= openbox
.searchGroup(win
, this))) {
2361 client
.transient_for
->client
.transient
= this;
2362 flags
.stuck
= client
.transient_for
->flags
.stuck
;
2363 flags
.transient
= True
;
2368 if (win
== screen
->getRootWindow()) flags
.modal
= True
;
2371 // adjust the window decorations based on transience
2372 if (flags
.transient
)
2373 decorations
.maximize
= decorations
.handle
= functions
.maximize
= False
;
2383 case XA_WM_ICON_NAME
:
2385 if (flags
.iconic
) screen
->iconUpdate();
2391 if (decorations
.titlebar
)
2395 screen
->getWorkspace(workspace_number
)->update();
2399 case XA_WM_NORMAL_HINTS
: {
2402 if ((client
.normal_hint_flags
& PMinSize
) &&
2403 (client
.normal_hint_flags
& PMaxSize
)) {
2404 if (client
.max_width
<= client
.min_width
&&
2405 client
.max_height
<= client
.min_height
)
2406 decorations
.maximize
= decorations
.handle
=
2407 functions
.resize
= functions
.maximize
= False
;
2409 decorations
.maximize
= decorations
.handle
=
2410 functions
.resize
= functions
.maximize
= True
;
2413 int x
= frame
.x
, y
= frame
.y
;
2414 unsigned int w
= frame
.width
, h
= frame
.height
;
2418 if ((x
!= frame
.x
) || (y
!= frame
.y
) ||
2419 (w
!= frame
.width
) || (h
!= frame
.height
))
2426 if (atom
== openbox
.getWMProtocolsAtom()) {
2429 if (decorations
.close
&& (! frame
.close_button
)) {
2430 createCloseButton();
2431 if (decorations
.titlebar
) positionButtons(True
);
2432 if (windowmenu
) windowmenu
->reconfigure();
2443 void OpenboxWindow::exposeEvent(XExposeEvent
*ee
) {
2444 if (frame
.label
== ee
->window
&& decorations
.titlebar
)
2446 else if (frame
.close_button
== ee
->window
)
2447 redrawCloseButton(False
);
2448 else if (frame
.maximize_button
== ee
->window
)
2449 redrawMaximizeButton(flags
.maximized
);
2450 else if (frame
.iconify_button
== ee
->window
)
2451 redrawIconifyButton(False
);
2455 void OpenboxWindow::configureRequestEvent(XConfigureRequestEvent
*cr
) {
2456 if (cr
->window
== client
.window
) {
2458 if (! validateClient()) return;
2460 int cx
= frame
.x
, cy
= frame
.y
;
2461 unsigned int cw
= frame
.width
, ch
= frame
.height
;
2463 if (cr
->value_mask
& CWBorderWidth
)
2464 client
.old_bw
= cr
->border_width
;
2466 if (cr
->value_mask
& CWX
)
2467 cx
= cr
->x
- frame
.mwm_border_w
- frame
.border_w
;
2469 if (cr
->value_mask
& CWY
)
2470 cy
= cr
->y
- frame
.y_border
- frame
.mwm_border_w
-
2473 if (cr
->value_mask
& CWWidth
)
2474 cw
= cr
->width
+ (frame
.mwm_border_w
* 2);
2476 if (cr
->value_mask
& CWHeight
)
2477 ch
= cr
->height
+ frame
.y_border
+ (frame
.mwm_border_w
* 2) +
2478 (frame
.border_w
* decorations
.handle
) + frame
.handle_h
;
2480 if (frame
.x
!= cx
|| frame
.y
!= cy
||
2481 frame
.width
!= cw
|| frame
.height
!= ch
)
2482 configure(cx
, cy
, cw
, ch
);
2484 if (cr
->value_mask
& CWStackMode
) {
2485 switch (cr
->detail
) {
2489 if (flags
.iconic
) deiconify();
2490 screen
->getWorkspace(workspace_number
)->raiseWindow(this);
2495 if (flags
.iconic
) deiconify();
2496 screen
->getWorkspace(workspace_number
)->lowerWindow(this);
2506 void OpenboxWindow::buttonPressEvent(XButtonEvent
*be
) {
2508 if (! validateClient())
2511 int stack_change
= 1; // < 0 means to lower the window
2512 // > 0 means to raise the window
2513 // 0 means to leave it where it is
2515 // alt + left/right click begins interactively moving/resizing the window
2516 // when the mouse is moved
2517 if (be
->state
== Mod1Mask
&& (be
->button
== 1 || be
->button
== 3)) {
2518 if (be
->button
== 3) {
2519 if (screen
->getWindowZones() == 4 &&
2520 be
->y
< (signed) frame
.height
/ 2) {
2521 resize_zone
= ZoneTop
;
2523 resize_zone
= ZoneBottom
;
2525 if (screen
->getWindowZones() >= 2 &&
2526 be
->x
< (signed) frame
.width
/ 2) {
2527 resize_zone
|= ZoneLeft
;
2529 resize_zone
|= ZoneRight
;
2532 // control + left click on the titlebar shades the window
2533 } else if (be
->state
== ControlMask
&& be
->button
== 1) {
2534 if (be
->window
== frame
.title
||
2535 be
->window
== frame
.label
)
2538 } else if (be
->state
== 0 && be
->button
== 1) {
2539 if (windowmenu
&& windowmenu
->isVisible())
2542 if (be
->window
== frame
.maximize_button
) {
2543 redrawMaximizeButton(True
);
2544 } else if (be
->window
== frame
.iconify_button
) {
2545 redrawIconifyButton(True
);
2546 } else if (be
->window
== frame
.close_button
) {
2547 redrawCloseButton(True
);
2548 } else if (be
->window
== frame
.plate
) {
2549 XAllowEvents(display
, ReplayPointer
, be
->time
);
2550 } else if (be
->window
== frame
.title
||
2551 be
->window
== frame
.label
) {
2552 // shade the window when the titlebar is double clicked
2553 if ( (be
->time
- lastButtonPressTime
) <=
2554 openbox
.getDoubleClickInterval()) {
2555 lastButtonPressTime
= 0;
2558 lastButtonPressTime
= be
->time
;
2560 // clicking and dragging on the titlebar moves the window, so on a click
2561 // we need to save the coords of the click in case the user drags
2562 frame
.grab_x
= be
->x_root
- frame
.x
- frame
.border_w
;
2563 frame
.grab_y
= be
->y_root
- frame
.y
- frame
.border_w
;
2564 } else if (be
->window
== frame
.handle
||
2565 be
->window
== frame
.left_grip
||
2566 be
->window
== frame
.right_grip
||
2567 be
->window
== frame
.window
) {
2568 // clicking and dragging on the window's frame moves the window, so on a
2569 // click we need to save the coords of the click in case the user drags
2570 frame
.grab_x
= be
->x_root
- frame
.x
- frame
.border_w
;
2571 frame
.grab_y
= be
->y_root
- frame
.y
- frame
.border_w
;
2572 if (be
->window
== frame
.left_grip
)
2573 resize_zone
= ZoneBottom
| ZoneLeft
;
2574 else if (be
->window
== frame
.right_grip
)
2575 resize_zone
= ZoneBottom
| ZoneRight
;
2578 } else if (be
->state
== 0 && be
->button
== 2) {
2579 if (be
->window
== frame
.maximize_button
) {
2580 redrawMaximizeButton(True
);
2581 // a middle click anywhere on the window's frame except for on the buttons
2582 // will lower the window
2583 } else if (! (be
->window
== frame
.iconify_button
||
2584 be
->window
== frame
.close_button
) ) {
2588 } else if (be
->state
== 0 && be
->button
== 3) {
2589 if (be
->window
== frame
.maximize_button
) {
2590 redrawMaximizeButton(True
);
2591 // a right click on the window's frame will show or hide the window's
2593 } else if (be
->window
== frame
.title
||
2594 be
->window
== frame
.label
||
2595 be
->window
== frame
.handle
||
2596 be
->window
== frame
.window
) {
2599 if (windowmenu
->isVisible()) {
2602 // get the coords for the menu
2603 mx
= be
->x_root
- windowmenu
->getWidth() / 2;
2604 if (be
->window
== frame
.title
|| be
->window
== frame
.label
) {
2605 my
= frame
.y
+ frame
.title_h
;
2606 } else if (be
->window
== frame
.handle
) {
2607 my
= frame
.y
+ frame
.y_handle
- windowmenu
->getHeight();
2608 } else { // (be->window == frame.window)
2609 if (be
->y
<= (signed) frame
.bevel_w
) {
2610 my
= frame
.y
+ frame
.y_border
;
2612 my
= be
->y_root
- (windowmenu
->getHeight() / 2);
2616 if (mx
> (signed) (frame
.x
+ frame
.width
-
2617 windowmenu
->getWidth())) {
2618 mx
= frame
.x
+ frame
.width
- windowmenu
->getWidth();
2619 } else if (mx
< frame
.x
) {
2623 if (my
> (signed) (frame
.y
+ frame
.y_handle
-
2624 windowmenu
->getHeight())) {
2625 my
= frame
.y
+ frame
.y_handle
- windowmenu
->getHeight();
2626 } else if (my
< (signed) (frame
.y
+
2627 ((decorations
.titlebar
) ? frame
.title_h
: frame
.y_border
))) {
2629 ((decorations
.titlebar
) ? frame
.title_h
: frame
.y_border
);
2632 windowmenu
->move(mx
, my
);
2634 XRaiseWindow(display
, windowmenu
->getWindowID());
2635 XRaiseWindow(display
, windowmenu
->getSendToMenu()->getWindowID());
2636 stack_change
= 0; // dont raise the window overtop of the menu
2641 } else if (be
->state
== 0 && be
->button
== 4) {
2642 if ((be
->window
== frame
.label
||
2643 be
->window
== frame
.title
) &&
2647 } else if (be
->state
== 0 && be
->button
== 5) {
2648 if ((be
->window
== frame
.label
||
2649 be
->window
== frame
.title
) &&
2654 if (! (flags
.focused
|| screen
->sloppyFocus()) ) {
2655 setInputFocus(); // any click focus' the window in 'click to focus'
2657 if (stack_change
< 0) {
2658 screen
->getWorkspace(workspace_number
)->lowerWindow(this);
2659 } else if (stack_change
> 0) {
2660 screen
->getWorkspace(workspace_number
)->raiseWindow(this);
2667 void OpenboxWindow::buttonReleaseEvent(XButtonEvent
*re
) {
2669 if (! validateClient())
2672 // alt + middle button released
2673 if (re
->state
== (Mod1Mask
& Button2Mask
) && re
->button
== 2) {
2674 if (re
->window
== frame
.window
) {
2675 XUngrabPointer(display
, CurrentTime
); // why? i dont know
2677 // left button released
2678 } else if (re
->button
== 1) {
2679 if (re
->window
== frame
.maximize_button
) {
2680 if (re
->state
== Button1Mask
&& // only the left button was depressed
2681 (re
->x
>= 0) && ((unsigned) re
->x
<= frame
.button_w
) &&
2682 (re
->y
>= 0) && ((unsigned) re
->y
<= frame
.button_h
)) {
2683 maximize(re
->button
);
2685 redrawMaximizeButton(False
);
2687 } else if (re
->window
== frame
.iconify_button
) {
2688 if (re
->state
== Button1Mask
&& // only the left button was depressed
2689 (re
->x
>= 0) && ((unsigned) re
->x
<= frame
.button_w
) &&
2690 (re
->y
>= 0) && ((unsigned) re
->y
<= frame
.button_h
)) {
2693 redrawIconifyButton(False
);
2695 } else if (re
->window
== frame
.close_button
) {
2696 if (re
->state
== Button1Mask
&& // only the left button was depressed
2697 (re
->x
>= 0) && ((unsigned) re
->x
<= frame
.button_w
) &&
2698 (re
->y
>= 0) && ((unsigned) re
->y
<= frame
.button_h
)) {
2701 //we should always redraw the close button. some applications
2702 //eg. acroread don't honour the close.
2703 redrawCloseButton(False
);
2705 // middle button released
2706 } else if (re
->button
== 2) {
2707 if (re
->window
== frame
.maximize_button
) {
2708 if (re
->state
== Button2Mask
&& // only the middle button was depressed
2709 (re
->x
>= 0) && ((unsigned) re
->x
<= frame
.button_w
) &&
2710 (re
->y
>= 0) && ((unsigned) re
->y
<= frame
.button_h
)) {
2711 maximize(re
->button
);
2713 redrawMaximizeButton(False
);
2716 // right button released
2717 } else if (re
->button
== 3) {
2718 if (re
->window
== frame
.maximize_button
) {
2719 if (re
->state
== Button3Mask
&& // only the right button was depressed
2720 (re
->x
>= 0) && ((unsigned) re
->x
<= frame
.button_w
) &&
2721 (re
->y
>= 0) && ((unsigned) re
->y
<= frame
.button_h
)) {
2722 maximize(re
->button
);
2724 redrawMaximizeButton(False
);
2729 // when the window is being interactively moved, a button release stops the
2733 // when the window is being interactively resized, a button release stops the
2735 } else if (flags
.resizing
) {
2736 flags
.resizing
= False
;
2737 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2738 frame
.resize_x
, frame
.resize_y
,
2739 frame
.resize_w
- 1, frame
.resize_h
- 1);
2740 screen
->hideGeometry();
2741 if (resize_zone
& ZoneLeft
) {
2743 } else { // when resizing with "Alt+Button3", the resize is the same as if
2744 // done with the right grip (the right side of the window is what
2748 // unset maximized state when resized after fully maximized
2749 if (flags
.maximized
== 1) {
2752 configure(frame
.resize_x
, frame
.resize_y
,
2753 frame
.resize_w
- (frame
.border_w
* 2),
2754 frame
.resize_h
- (frame
.border_w
* 2));
2756 XUngrabPointer(display
, CurrentTime
);
2764 void OpenboxWindow::startMove(int x
, int y
) {
2765 ASSERT(!flags
.moving
);
2767 // make sure only one window is moving at a time
2768 OpenboxWindow
*w
= openbox
.getMaskedWindow();
2769 if (w
!= (OpenboxWindow
*) 0 && w
->flags
.moving
)
2772 XGrabPointer(display
, frame
.window
, False
, PointerMotionMask
|
2773 ButtonReleaseMask
, GrabModeAsync
, GrabModeAsync
,
2774 None
, openbox
.getMoveCursor(), CurrentTime
);
2776 if (windowmenu
&& windowmenu
->isVisible())
2779 flags
.moving
= True
;
2781 openbox
.maskWindowEvents(client
.window
, this);
2783 if (! screen
->opaqueMove()) {
2786 frame
.move_x
= frame
.x
;
2787 frame
.move_y
= frame
.y
;
2788 frame
.resize_w
= frame
.width
+ (frame
.border_w
* 2);
2789 frame
.resize_h
= ((flags
.shaded
) ? frame
.title_h
: frame
.height
) +
2790 (frame
.border_w
* 2);
2792 screen
->showPosition(frame
.x
, frame
.y
);
2794 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2795 frame
.move_x
, frame
.move_y
,
2796 frame
.resize_w
- 1, frame
.resize_h
- 1);
2798 frame
.grab_x
= x
- frame
.x
- frame
.border_w
;
2799 frame
.grab_y
= y
- frame
.y
- frame
.border_w
;
2800 cout
<< "START MOVE " << client
.window
<< " " << client
.title
<< endl
;
2804 void OpenboxWindow::doMove(int x
, int y
) {
2805 ASSERT(flags
.moving
);
2807 int dx
= x
- frame
.grab_x
, dy
= y
- frame
.grab_y
;
2809 dx
-= frame
.border_w
;
2810 dy
-= frame
.border_w
;
2812 int snap_distance
= screen
->edgeSnapThreshold();
2813 // width/height of the snapping window
2814 unsigned int snap_w
= frame
.width
+ (frame
.border_w
* 2);
2815 unsigned int snap_h
= area().h() + (frame
.border_w
* 2);
2816 if (snap_distance
) {
2817 int drx
= screen
->size().w() - (dx
+ snap_w
);
2819 if (dx
< drx
&& (dx
> 0 && dx
< snap_distance
) ||
2820 (dx
< 0 && dx
> -snap_distance
) )
2822 else if ( (drx
> 0 && drx
< snap_distance
) ||
2823 (drx
< 0 && drx
> -snap_distance
) )
2824 dx
= screen
->size().w() - snap_w
;
2826 int dtty
, dbby
, dty
, dby
;
2827 switch (screen
->getToolbar()->placement()) {
2828 case Toolbar::TopLeft
:
2829 case Toolbar::TopCenter
:
2830 case Toolbar::TopRight
:
2831 dtty
= screen
->getToolbar()->getExposedHeight() +
2833 dbby
= screen
->size().h();
2838 dbby
= screen
->getToolbar()->area().y();
2843 dby
= dbby
- (dy
+ snap_h
);
2845 if ( (dy
> 0 && dty
< snap_distance
) ||
2846 (dy
< 0 && dty
> -snap_distance
) )
2848 else if ( (dby
> 0 && dby
< snap_distance
) ||
2849 (dby
< 0 && dby
> -snap_distance
) )
2853 if (screen
->opaqueMove()) {
2854 configure(dx
, dy
, frame
.width
, frame
.height
);
2856 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2857 frame
.move_x
, frame
.move_y
, frame
.resize_w
- 1,
2858 frame
.resize_h
- 1);
2863 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2864 frame
.move_x
, frame
.move_y
, frame
.resize_w
- 1,
2865 frame
.resize_h
- 1);
2868 screen
->showPosition(dx
, dy
);
2872 void OpenboxWindow::endMove() {
2873 ASSERT(flags
.moving
);
2875 flags
.moving
= False
;
2877 openbox
.maskWindowEvents(0, (OpenboxWindow
*) 0);
2878 if (!screen
->opaqueMove()) {
2879 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2880 frame
.move_x
, frame
.move_y
, frame
.resize_w
- 1,
2881 frame
.resize_h
- 1);
2883 configure(frame
.move_x
, frame
.move_y
, frame
.width
, frame
.height
);
2886 configure(frame
.x
, frame
.y
, frame
.width
, frame
.height
);
2888 screen
->hideGeometry();
2889 XUngrabPointer(display
, CurrentTime
);
2890 // if there are any left over motions from the move, drop them now cuz they
2893 while (XCheckTypedWindowEvent(display
, frame
.window
, MotionNotify
, &e
));
2894 cout
<< "END MOVE " << client
.window
<< " " << client
.title
<< endl
;
2898 void OpenboxWindow::motionNotifyEvent(XMotionEvent
*me
) {
2900 doMove(me
->x_root
, me
->y_root
);
2901 else if (!flags
.resizing
&& (me
->state
& Button1Mask
) && functions
.move
&&
2902 (frame
.title
== me
->window
|| frame
.label
== me
->window
||
2903 frame
.handle
== me
->window
|| frame
.window
== me
->window
))
2904 startMove(me
->x_root
, me
->y_root
);
2905 else if (functions
.resize
&&
2906 (((me
->state
& Button1Mask
) && (me
->window
== frame
.right_grip
||
2907 me
->window
== frame
.left_grip
)) ||
2908 (me
->state
== (Mod1Mask
| Button3Mask
) &&
2909 me
->window
== frame
.window
))) {
2910 Bool left
= resize_zone
& ZoneLeft
;
2912 if (! flags
.resizing
) {
2913 cout
<< "START RESIZE " << client
.window
<< " " << client
.title
<< endl
;
2915 if (resize_zone
& ZoneTop
)
2916 cursor
= (resize_zone
& ZoneLeft
) ?
2917 openbox
.getUpperLeftAngleCursor() :
2918 openbox
.getUpperRightAngleCursor();
2920 cursor
= (resize_zone
& ZoneLeft
) ?
2921 openbox
.getLowerLeftAngleCursor() :
2922 openbox
.getLowerRightAngleCursor();
2923 XGrabPointer(display
, me
->window
, False
, ButtonMotionMask
|
2924 ButtonReleaseMask
, GrabModeAsync
, GrabModeAsync
, None
,
2925 cursor
, CurrentTime
);
2927 flags
.resizing
= True
;
2932 if (resize_zone
& ZoneRight
)
2933 frame
.grab_x
= me
->x
- screen
->getBorderWidth();
2935 frame
.grab_x
= me
->x
+ screen
->getBorderWidth();
2936 if (resize_zone
& ZoneTop
)
2937 frame
.grab_y
= me
->y
+ screen
->getBorderWidth() * 2;
2939 frame
.grab_y
= me
->y
- screen
->getBorderWidth() * 2;
2940 frame
.resize_x
= frame
.x
;
2941 frame
.resize_y
= frame
.y
;
2942 frame
.resize_w
= frame
.width
+ (frame
.border_w
* 2);
2943 frame
.resize_h
= frame
.height
+ (frame
.border_w
* 2);
2946 left_fixsize(&gx
, &gy
);
2948 right_fixsize(&gx
, &gy
);
2950 screen
->showGeometry(gx
, gy
);
2952 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2953 frame
.resize_x
, frame
.resize_y
,
2954 frame
.resize_w
- 1, frame
.resize_h
- 1);
2956 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2957 frame
.resize_x
, frame
.resize_y
,
2958 frame
.resize_w
- 1, frame
.resize_h
- 1);
2962 if (resize_zone
& ZoneTop
)
2963 frame
.resize_h
= frame
.height
- (me
->y
- frame
.grab_y
);
2965 frame
.resize_h
= frame
.height
+ (me
->y
- frame
.grab_y
);
2966 if (frame
.resize_h
< 1) frame
.resize_h
= 1;
2969 frame
.resize_x
= me
->x_root
- frame
.grab_x
;
2970 if (frame
.resize_x
> (signed) (frame
.x
+ frame
.width
))
2971 frame
.resize_x
= frame
.resize_x
+ frame
.width
- 1;
2973 left_fixsize(&gx
, &gy
);
2975 frame
.resize_w
= frame
.width
+ (me
->x
- frame
.grab_x
);
2976 if (frame
.resize_w
< 1) frame
.resize_w
= 1;
2978 right_fixsize(&gx
, &gy
);
2981 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2982 frame
.resize_x
, frame
.resize_y
,
2983 frame
.resize_w
- 1, frame
.resize_h
- 1);
2985 screen
->showGeometry(gx
, gy
);
2988 cout
<< "MOTION " << client
.window
<< " " << client
.title
<< endl
;
2993 void OpenboxWindow::shapeEvent(XShapeEvent
*) {
2994 if (openbox
.hasShapeExtensions()) {
2997 if (! validateClient()) return;
2998 XShapeCombineShape(display
, frame
.window
, ShapeBounding
,
2999 frame
.mwm_border_w
, frame
.y_border
+
3000 frame
.mwm_border_w
, client
.window
,
3001 ShapeBounding
, ShapeSet
);
3004 XRectangle xrect
[2];
3005 xrect
[0].x
= xrect
[0].y
= 0;
3006 xrect
[0].width
= frame
.width
;
3007 xrect
[0].height
= frame
.y_border
;
3009 if (decorations
.handle
) {
3011 xrect
[1].y
= frame
.y_handle
;
3012 xrect
[1].width
= frame
.width
;
3013 xrect
[1].height
= frame
.handle_h
+ frame
.border_w
;
3017 XShapeCombineRectangles(display
, frame
.window
, ShapeBounding
, 0, 0,
3018 xrect
, num
, ShapeUnion
, Unsorted
);
3026 Bool
OpenboxWindow::validateClient(void) {
3027 XSync(display
, False
);
3030 if (XCheckTypedWindowEvent(display
, client
.window
, DestroyNotify
, &e
) ||
3031 XCheckTypedWindowEvent(display
, client
.window
, UnmapNotify
, &e
)) {
3032 XPutBackEvent(display
, &e
);
3042 void OpenboxWindow::restore(void) {
3043 XChangeSaveSet(display
, client
.window
, SetModeDelete
);
3044 XSelectInput(display
, client
.window
, NoEventMask
);
3048 XUnmapWindow(display
, frame
.window
);
3049 XUnmapWindow(display
, client
.window
);
3051 XSetWindowBorderWidth(display
, client
.window
, client
.old_bw
);
3052 XReparentWindow(display
, client
.window
, screen
->getRootWindow(),
3053 client
.x
, client
.y
);
3054 XMapWindow(display
, client
.window
);
3060 void OpenboxWindow::timeout(void) {
3061 screen
->getWorkspace(workspace_number
)->raiseWindow(this);
3065 void OpenboxWindow::changeOpenboxHints(OpenboxHints
*net
) {
3066 if ((net
->flags
& AttribShaded
) &&
3067 ((openbox_attrib
.attrib
& AttribShaded
) !=
3068 (net
->attrib
& AttribShaded
)))
3071 if (flags
.visible
&& // watch out for requests when we can not be seen
3072 (net
->flags
& (AttribMaxVert
| AttribMaxHoriz
)) &&
3073 ((openbox_attrib
.attrib
& (AttribMaxVert
| AttribMaxHoriz
)) !=
3074 (net
->attrib
& (AttribMaxVert
| AttribMaxHoriz
)))) {
3075 if (flags
.maximized
) {
3080 if ((net
->flags
& AttribMaxHoriz
) && (net
->flags
& AttribMaxVert
))
3081 button
= ((net
->attrib
& (AttribMaxHoriz
| AttribMaxVert
)) ? 1 : 0);
3082 else if (net
->flags
& AttribMaxVert
)
3083 button
= ((net
->attrib
& AttribMaxVert
) ? 2 : 0);
3084 else if (net
->flags
& AttribMaxHoriz
)
3085 button
= ((net
->attrib
& AttribMaxHoriz
) ? 3 : 0);
3091 if ((net
->flags
& AttribOmnipresent
) &&
3092 ((openbox_attrib
.attrib
& AttribOmnipresent
) !=
3093 (net
->attrib
& AttribOmnipresent
)))
3096 if ((net
->flags
& AttribWorkspace
) &&
3097 (workspace_number
!= (signed) net
->workspace
)) {
3098 screen
->reassociateWindow(this, net
->workspace
, True
);
3100 if (screen
->getCurrentWorkspaceID() != (signed) net
->workspace
) withdraw();
3104 if (net
->flags
& AttribDecoration
) {
3105 switch (net
->decoration
) {
3107 decorations
.titlebar
= decorations
.border
= decorations
.handle
=
3108 decorations
.iconify
= decorations
.maximize
= decorations
.menu
= False
;
3114 decorations
.titlebar
= decorations
.iconify
= decorations
.menu
=
3115 decorations
.border
= True
;
3116 decorations
.handle
= (functions
.resize
&& !flags
.transient
);
3117 decorations
.maximize
= functions
.maximize
;
3122 decorations
.titlebar
= decorations
.iconify
= decorations
.menu
= True
;
3123 decorations
.border
= decorations
.border
= decorations
.handle
= False
;
3124 decorations
.maximize
= functions
.maximize
;
3129 decorations
.titlebar
= decorations
.menu
= True
;
3130 decorations
.iconify
= decorations
.border
= False
;
3131 decorations
.handle
= (functions
.resize
&& !flags
.transient
);
3132 decorations
.maximize
= functions
.maximize
;
3137 XMapSubwindows(display
, frame
.window
);
3138 XMapWindow(display
, frame
.window
);
3142 setState(current_state
);
3148 * Set the sizes of all components of the window frame
3149 * (the window decorations).
3150 * These values are based upon the current style settings and the client
3151 * window's dimentions.
3153 void OpenboxWindow::upsize(void) {
3154 frame
.bevel_w
= screen
->getBevelWidth();
3156 if (decorations
.border
) {
3157 frame
.border_w
= screen
->getBorderWidth();
3158 if (!flags
.transient
)
3159 frame
.mwm_border_w
= screen
->getFrameWidth();
3161 frame
.mwm_border_w
= 0;
3163 frame
.mwm_border_w
= frame
.border_w
= 0;
3166 if (decorations
.titlebar
) {
3167 // the height of the titlebar is based upon the height of the font being
3168 // used to display the window's title
3169 WindowStyle
*style
= screen
->getWindowStyle();
3170 if (i18n
->multibyte())
3171 frame
.title_h
= (style
->fontset_extents
->max_ink_extent
.height
+
3172 (frame
.bevel_w
* 2) + 2);
3174 frame
.title_h
= (style
->font
->ascent
+ style
->font
->descent
+
3175 (frame
.bevel_w
* 2) + 2);
3177 frame
.label_h
= frame
.title_h
- (frame
.bevel_w
* 2);
3178 frame
.button_w
= frame
.button_h
= (frame
.label_h
- 2);
3179 frame
.y_border
= frame
.title_h
+ frame
.border_w
;
3183 frame
.button_w
= frame
.button_h
= 0;
3187 frame
.border_h
= client
.height
+ frame
.mwm_border_w
* 2;
3189 if (decorations
.handle
) {
3190 frame
.y_handle
= frame
.y_border
+ frame
.border_h
+ frame
.border_w
;
3191 frame
.grip_w
= frame
.button_w
* 2;
3192 frame
.grip_h
= frame
.handle_h
= screen
->getHandleWidth();
3194 frame
.y_handle
= frame
.y_border
+ frame
.border_h
;
3196 frame
.grip_w
= frame
.grip_h
= 0;
3199 frame
.width
= client
.width
+ (frame
.mwm_border_w
* 2);
3200 frame
.height
= frame
.y_handle
+ frame
.handle_h
;
3205 * Set the size and position of the client window.
3206 * These values are based upon the current style settings and the frame
3207 * window's dimensions.
3209 void OpenboxWindow::downsize(void) {
3210 frame
.y_handle
= frame
.height
- frame
.handle_h
;
3211 frame
.border_h
= frame
.y_handle
- frame
.y_border
-
3212 (decorations
.handle
? frame
.border_w
: 0);
3214 client
.x
= frame
.x
+ frame
.mwm_border_w
+ frame
.border_w
;
3215 client
.y
= frame
.y
+ frame
.y_border
+ frame
.mwm_border_w
+ frame
.border_w
;
3217 client
.width
= frame
.width
- (frame
.mwm_border_w
* 2);
3218 client
.height
= frame
.height
- frame
.y_border
- (frame
.mwm_border_w
* 2)
3219 - frame
.handle_h
- (decorations
.handle
? frame
.border_w
: 0);
3221 frame
.y_handle
= frame
.border_h
+ frame
.y_border
+ frame
.border_w
;
3225 void OpenboxWindow::right_fixsize(int *gx
, int *gy
) {
3226 // calculate the size of the client window and conform it to the
3227 // size specified by the size hints of the client window...
3228 int dx
= frame
.resize_w
- client
.base_width
- (frame
.mwm_border_w
* 2) -
3229 (frame
.border_w
* 2) + (client
.width_inc
/ 2);
3230 int dy
= frame
.resize_h
- frame
.y_border
- client
.base_height
-
3231 frame
.handle_h
- (frame
.border_w
* 3) - (frame
.mwm_border_w
* 2)
3232 + (client
.height_inc
/ 2);
3234 if (dx
< (signed) client
.min_width
) dx
= client
.min_width
;
3235 if (dy
< (signed) client
.min_height
) dy
= client
.min_height
;
3236 if ((unsigned) dx
> client
.max_width
) dx
= client
.max_width
;
3237 if ((unsigned) dy
> client
.max_height
) dy
= client
.max_height
;
3239 dx
/= client
.width_inc
;
3240 dy
/= client
.height_inc
;
3245 dx
= (dx
* client
.width_inc
) + client
.base_width
;
3246 dy
= (dy
* client
.height_inc
) + client
.base_height
;
3248 frame
.resize_w
= dx
+ (frame
.mwm_border_w
* 2) + (frame
.border_w
* 2);
3249 frame
.resize_h
= dy
+ frame
.y_border
+ frame
.handle_h
+
3250 (frame
.mwm_border_w
* 2) + (frame
.border_w
* 3);
3251 if (resize_zone
& ZoneTop
)
3252 frame
.resize_y
= frame
.y
+ frame
.height
- frame
.resize_h
+
3253 screen
->getBorderWidth() * 2;
3257 void OpenboxWindow::left_fixsize(int *gx
, int *gy
) {
3258 // calculate the size of the client window and conform it to the
3259 // size specified by the size hints of the client window...
3260 int dx
= frame
.x
+ frame
.width
- frame
.resize_x
- client
.base_width
-
3261 (frame
.mwm_border_w
* 2) + (client
.width_inc
/ 2);
3262 int dy
= frame
.resize_h
- frame
.y_border
- client
.base_height
-
3263 frame
.handle_h
- (frame
.border_w
* 3) - (frame
.mwm_border_w
* 2)
3264 + (client
.height_inc
/ 2);
3266 if (dx
< (signed) client
.min_width
) dx
= client
.min_width
;
3267 if (dy
< (signed) client
.min_height
) dy
= client
.min_height
;
3268 if ((unsigned) dx
> client
.max_width
) dx
= client
.max_width
;
3269 if ((unsigned) dy
> client
.max_height
) dy
= client
.max_height
;
3271 dx
/= client
.width_inc
;
3272 dy
/= client
.height_inc
;
3277 dx
= (dx
* client
.width_inc
) + client
.base_width
;
3278 dy
= (dy
* client
.height_inc
) + client
.base_height
;
3280 frame
.resize_w
= dx
+ (frame
.mwm_border_w
* 2) + (frame
.border_w
* 2);
3281 frame
.resize_x
= frame
.x
+ frame
.width
- frame
.resize_w
+
3282 (frame
.border_w
* 2);
3283 frame
.resize_h
= dy
+ frame
.y_border
+ frame
.handle_h
+
3284 (frame
.mwm_border_w
* 2) + (frame
.border_w
* 3);
3285 if (resize_zone
& ZoneTop
)
3286 frame
.resize_y
= frame
.y
+ frame
.height
- frame
.resize_h
+
3287 screen
->getBorderWidth() * 2;