1 // Window.cc for Openbox
2 // Copyright (c) 2002 - 2002 Ben Jansens (ben at orodu.net)
3 // Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry (shaleh at debian.org)
4 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net)
6 // Permission is hereby granted, free of charge, to any person obtaining a
7 // copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the
11 // Software is furnished to do so, subject to the following conditions:
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 // DEALINGS IN THE SOFTWARE.
24 // stupid macros needed to access some functions in version 2 of the GNU C
31 # include "../config.h"
32 #endif // HAVE_CONFIG_H
34 #include <X11/Xatom.h>
35 #include <X11/keysym.h>
39 #endif // HAVE_STRING_H
44 # endif // HAVE_STDIO_H
53 #include "Windowmenu.h"
54 #include "Workspace.h"
61 * Initializes the class with default values/the window's set initial values.
63 OpenboxWindow::OpenboxWindow(Openbox
&o
, Window w
, BScreen
*s
) : openbox(o
) {
65 fprintf(stderr
, i18n
->getMessage(WindowSet
, WindowCreating
,
66 "OpenboxWindow::OpenboxWindow(): creating 0x%lx\n"),
71 display
= openbox
.getXDisplay();
74 if (! validateClient()) return;
76 // fetch client size and placement
77 XWindowAttributes wattrib
;
78 if ((! XGetWindowAttributes(display
, client
.window
, &wattrib
)) ||
79 (! wattrib
.screen
) || wattrib
.override_redirect
) {
82 i18n
->getMessage(WindowSet
, WindowXGetWindowAttributesFail
,
83 "OpenboxWindow::OpenboxWindow(): XGetWindowAttributes "
94 screen
= openbox
.searchScreen(RootWindowOfScreen(wattrib
.screen
));
97 fprintf(stderr
, i18n
->getMessage(WindowSet
, WindowCannotFindScreen
,
98 "OpenboxWindow::OpenboxWindow(): can't find screen\n"
99 "\tfor root window 0x%lx\n"),
100 RootWindowOfScreen(wattrib
.screen
));
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)
318 screen
->getWorkspace(workspace_number
)->removeWindow(this);
319 else if (flags
.iconic
)
320 screen
->removeIcon(this);
323 if (timer
->isTiming()) timer
->stop();
327 if (windowmenu
) delete windowmenu
;
330 delete [] client
.title
;
332 if (client
.icon_title
)
333 delete [] client
.icon_title
;
336 XFree(client
.mwm_hint
);
338 if (client
.openbox_hint
)
339 XFree(client
.openbox_hint
);
341 if (client
.window_group
)
342 openbox
.removeGroupSearch(client
.window_group
);
344 if (flags
.transient
&& client
.transient_for
)
345 client
.transient_for
->client
.transient
= client
.transient
;
346 if (client
.transient
)
347 client
.transient
->client
.transient_for
= client
.transient_for
;
349 if (frame
.close_button
) {
350 openbox
.removeWindowSearch(frame
.close_button
);
351 XDestroyWindow(display
, frame
.close_button
);
354 if (frame
.iconify_button
) {
355 openbox
.removeWindowSearch(frame
.iconify_button
);
356 XDestroyWindow(display
, frame
.iconify_button
);
359 if (frame
.maximize_button
) {
360 openbox
.removeWindowSearch(frame
.maximize_button
);
361 XDestroyWindow(display
, frame
.maximize_button
);
366 image_ctrl
->removeImage(frame
.ftitle
);
369 image_ctrl
->removeImage(frame
.utitle
);
372 image_ctrl
->removeImage(frame
.flabel
);
375 image_ctrl
->removeImage(frame
.ulabel
);
377 openbox
.removeWindowSearch(frame
.label
);
378 openbox
.removeWindowSearch(frame
.title
);
379 XDestroyWindow(display
, frame
.label
);
380 XDestroyWindow(display
, frame
.title
);
385 image_ctrl
->removeImage(frame
.fhandle
);
388 image_ctrl
->removeImage(frame
.uhandle
);
391 image_ctrl
->removeImage(frame
.fgrip
);
394 image_ctrl
->removeImage(frame
.ugrip
);
396 openbox
.removeWindowSearch(frame
.handle
);
397 openbox
.removeWindowSearch(frame
.right_grip
);
398 openbox
.removeWindowSearch(frame
.left_grip
);
399 XDestroyWindow(display
, frame
.right_grip
);
400 XDestroyWindow(display
, frame
.left_grip
);
401 XDestroyWindow(display
, frame
.handle
);
405 image_ctrl
->removeImage(frame
.fbutton
);
408 image_ctrl
->removeImage(frame
.ubutton
);
411 image_ctrl
->removeImage(frame
.pbutton
);
414 openbox
.removeWindowSearch(frame
.plate
);
415 XDestroyWindow(display
, frame
.plate
);
419 openbox
.removeWindowSearch(frame
.window
);
420 XDestroyWindow(display
, frame
.window
);
424 openbox
.removeWindowSearch(client
.window
);
425 screen
->removeNetizen(client
.window
);
431 * Creates a new top level window, with a given location, size, and border
433 * Returns: the newly created window
435 Window
OpenboxWindow::createToplevelWindow(int x
, int y
, unsigned int width
,
437 unsigned int borderwidth
)
439 XSetWindowAttributes attrib_create
;
440 unsigned long create_mask
= CWBackPixmap
| CWBorderPixel
| CWColormap
|
441 CWOverrideRedirect
| CWEventMask
;
443 attrib_create
.background_pixmap
= None
;
444 attrib_create
.colormap
= screen
->getColormap();
445 attrib_create
.override_redirect
= True
;
446 attrib_create
.event_mask
= ButtonPressMask
| ButtonReleaseMask
|
447 ButtonMotionMask
| EnterWindowMask
;
449 return XCreateWindow(display
, screen
->getRootWindow(), x
, y
, width
, height
,
450 borderwidth
, screen
->getDepth(), InputOutput
,
451 screen
->getVisual(), create_mask
,
457 * Creates a child window, and optionally associates a given cursor with
460 Window
OpenboxWindow::createChildWindow(Window parent
, Cursor cursor
) {
461 XSetWindowAttributes attrib_create
;
462 unsigned long create_mask
= CWBackPixmap
| CWBorderPixel
|
465 attrib_create
.background_pixmap
= None
;
466 attrib_create
.event_mask
= ButtonPressMask
| ButtonReleaseMask
|
467 ButtonMotionMask
| ExposureMask
|
468 EnterWindowMask
| LeaveWindowMask
;
471 create_mask
|= CWCursor
;
472 attrib_create
.cursor
= cursor
;
475 return XCreateWindow(display
, parent
, 0, 0, 1, 1, 0, screen
->getDepth(),
476 InputOutput
, screen
->getVisual(), create_mask
,
481 void OpenboxWindow::associateClientWindow(void) {
482 XSetWindowBorderWidth(display
, client
.window
, 0);
486 XChangeSaveSet(display
, client
.window
, SetModeInsert
);
487 XSetWindowAttributes attrib_set
;
489 XSelectInput(display
, frame
.plate
, NoEventMask
);
490 XReparentWindow(display
, client
.window
, frame
.plate
, 0, 0);
491 XSelectInput(display
, frame
.plate
, SubstructureRedirectMask
);
495 attrib_set
.event_mask
= PropertyChangeMask
| StructureNotifyMask
|
497 attrib_set
.do_not_propagate_mask
= ButtonPressMask
| ButtonReleaseMask
|
500 XChangeWindowAttributes(display
, client
.window
, CWEventMask
|CWDontPropagate
,
504 if (openbox
.hasShapeExtensions()) {
505 XShapeSelectInput(display
, client
.window
, ShapeNotifyMask
);
510 XShapeQueryExtents(display
, client
.window
, &flags
.shaped
, &foo
, &foo
,
511 &ufoo
, &ufoo
, &foo
, &foo
, &foo
, &ufoo
, &ufoo
);
514 XShapeCombineShape(display
, frame
.window
, ShapeBounding
,
515 frame
.mwm_border_w
, frame
.y_border
+
516 frame
.mwm_border_w
, client
.window
,
517 ShapeBounding
, ShapeSet
);
521 xrect
[0].x
= xrect
[0].y
= 0;
522 xrect
[0].width
= frame
.width
;
523 xrect
[0].height
= frame
.y_border
;
525 if (decorations
.handle
) {
527 xrect
[1].y
= frame
.y_handle
;
528 xrect
[1].width
= frame
.width
;
529 xrect
[1].height
= frame
.handle_h
+ frame
.border_w
;
533 XShapeCombineRectangles(display
, frame
.window
, ShapeBounding
, 0, 0,
534 xrect
, num
, ShapeUnion
, Unsorted
);
539 if (decorations
.iconify
) createIconifyButton();
540 if (decorations
.maximize
) createMaximizeButton();
541 if (decorations
.close
) createCloseButton();
545 void OpenboxWindow::decorate(void) {
546 Pixmap tmp
= frame
.fbutton
;
547 BTexture
*texture
= &(screen
->getWindowStyle()->b_focus
);
548 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
549 frame
.fbutton
= None
;
550 frame
.fbutton_pixel
= texture
->getColor()->getPixel();
553 image_ctrl
->renderImage(frame
.button_w
, frame
.button_h
, texture
);
555 if (tmp
) image_ctrl
->removeImage(tmp
);
558 texture
= &(screen
->getWindowStyle()->b_unfocus
);
559 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
560 frame
.ubutton
= None
;
561 frame
.ubutton_pixel
= texture
->getColor()->getPixel();
564 image_ctrl
->renderImage(frame
.button_w
, frame
.button_h
, texture
);
566 if (tmp
) image_ctrl
->removeImage(tmp
);
569 texture
= &(screen
->getWindowStyle()->b_pressed
);
570 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
571 frame
.pbutton
= None
;
572 frame
.pbutton_pixel
= texture
->getColor()->getPixel();
575 image_ctrl
->renderImage(frame
.button_w
, frame
.button_h
, texture
);
577 if (tmp
) image_ctrl
->removeImage(tmp
);
579 if (decorations
.titlebar
) {
581 texture
= &(screen
->getWindowStyle()->t_focus
);
582 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
584 frame
.ftitle_pixel
= texture
->getColor()->getPixel();
587 image_ctrl
->renderImage(frame
.width
, frame
.title_h
, texture
);
589 if (tmp
) image_ctrl
->removeImage(tmp
);
592 texture
= &(screen
->getWindowStyle()->t_unfocus
);
593 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
595 frame
.utitle_pixel
= texture
->getColor()->getPixel();
598 image_ctrl
->renderImage(frame
.width
, frame
.title_h
, texture
);
600 if (tmp
) image_ctrl
->removeImage(tmp
);
602 XSetWindowBorder(display
, frame
.title
,
603 screen
->getBorderColor()->getPixel());
608 if (decorations
.border
) {
609 frame
.fborder_pixel
= screen
->getWindowStyle()->f_focus
.getPixel();
610 frame
.uborder_pixel
= screen
->getWindowStyle()->f_unfocus
.getPixel();
611 openbox_attrib
.flags
|= AttribDecoration
;
612 openbox_attrib
.decoration
= DecorNormal
;
614 openbox_attrib
.flags
|= AttribDecoration
;
615 openbox_attrib
.decoration
= DecorNone
;
618 if (decorations
.handle
) {
620 texture
= &(screen
->getWindowStyle()->h_focus
);
621 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
622 frame
.fhandle
= None
;
623 frame
.fhandle_pixel
= texture
->getColor()->getPixel();
626 image_ctrl
->renderImage(frame
.width
, frame
.handle_h
, texture
);
628 if (tmp
) image_ctrl
->removeImage(tmp
);
631 texture
= &(screen
->getWindowStyle()->h_unfocus
);
632 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
633 frame
.uhandle
= None
;
634 frame
.uhandle_pixel
= texture
->getColor()->getPixel();
637 image_ctrl
->renderImage(frame
.width
, frame
.handle_h
, texture
);
639 if (tmp
) image_ctrl
->removeImage(tmp
);
642 texture
= &(screen
->getWindowStyle()->g_focus
);
643 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
645 frame
.fgrip_pixel
= texture
->getColor()->getPixel();
648 image_ctrl
->renderImage(frame
.grip_w
, frame
.grip_h
, texture
);
650 if (tmp
) image_ctrl
->removeImage(tmp
);
653 texture
= &(screen
->getWindowStyle()->g_unfocus
);
654 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
656 frame
.ugrip_pixel
= texture
->getColor()->getPixel();
659 image_ctrl
->renderImage(frame
.grip_w
, frame
.grip_h
, texture
);
661 if (tmp
) image_ctrl
->removeImage(tmp
);
663 XSetWindowBorder(display
, frame
.handle
,
664 screen
->getBorderColor()->getPixel());
665 XSetWindowBorder(display
, frame
.left_grip
,
666 screen
->getBorderColor()->getPixel());
667 XSetWindowBorder(display
, frame
.right_grip
,
668 screen
->getBorderColor()->getPixel());
671 XSetWindowBorder(display
, frame
.window
,
672 screen
->getBorderColor()->getPixel());
676 void OpenboxWindow::decorateLabel(void) {
677 Pixmap tmp
= frame
.flabel
;
678 BTexture
*texture
= &(screen
->getWindowStyle()->l_focus
);
679 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
681 frame
.flabel_pixel
= texture
->getColor()->getPixel();
684 image_ctrl
->renderImage(frame
.label_w
, frame
.label_h
, texture
);
686 if (tmp
) image_ctrl
->removeImage(tmp
);
689 texture
= &(screen
->getWindowStyle()->l_unfocus
);
690 if (texture
->getTexture() == (BImage_Flat
| BImage_Solid
)) {
692 frame
.ulabel_pixel
= texture
->getColor()->getPixel();
695 image_ctrl
->renderImage(frame
.label_w
, frame
.label_h
, texture
);
697 if (tmp
) image_ctrl
->removeImage(tmp
);
701 void OpenboxWindow::createCloseButton(void) {
702 if (decorations
.close
&& frame
.title
!= None
) {
703 frame
.close_button
= createChildWindow(frame
.title
);
704 openbox
.saveWindowSearch(frame
.close_button
, this);
709 void OpenboxWindow::createIconifyButton(void) {
710 if (decorations
.iconify
&& frame
.title
!= None
) {
711 frame
.iconify_button
= createChildWindow(frame
.title
);
712 openbox
.saveWindowSearch(frame
.iconify_button
, this);
717 void OpenboxWindow::createMaximizeButton(void) {
718 if (decorations
.maximize
&& frame
.title
!= None
) {
719 frame
.maximize_button
= createChildWindow(frame
.title
);
720 openbox
.saveWindowSearch(frame
.maximize_button
, this);
725 void OpenboxWindow::positionButtons() {
726 const char *format
= openbox
.getTitleBarLayout();
727 const unsigned int bw
= frame
.bevel_w
+ 1;
728 const unsigned int by
= frame
.bevel_w
+ 1;
729 unsigned int bx
= frame
.bevel_w
+ 1;
730 unsigned int bcount
= strlen(format
) - 1;
732 if (!decorations
.close
)
734 if (!decorations
.maximize
)
736 if (!decorations
.iconify
)
738 frame
.label_w
= frame
.width
- bx
* 2 - (frame
.button_w
+ bw
) * bcount
;
740 bool hasclose
, hasiconify
, hasmaximize
;
741 hasclose
= hasiconify
= hasmaximize
= false;
743 for (int i
= 0; format
[i
] != '\0' && i
< 4; i
++) {
746 if (decorations
.close
) {
747 if (frame
.close_button
== None
)
749 XMoveResizeWindow(display
, frame
.close_button
, bx
, by
,
750 frame
.button_w
, frame
.button_h
);
751 XMapWindow(display
, frame
.close_button
);
752 XClearWindow(display
, frame
.close_button
);
753 bx
+= frame
.button_w
+ bw
;
758 if (decorations
.iconify
) {
759 if (frame
.iconify_button
== None
)
760 createIconifyButton();
761 XMoveResizeWindow(display
, frame
.iconify_button
, bx
, by
,
762 frame
.button_w
, frame
.button_h
);
763 XMapWindow(display
, frame
.iconify_button
);
764 XClearWindow(display
, frame
.iconify_button
);
765 bx
+= frame
.button_w
+ bw
;
770 if (decorations
.maximize
) {
771 if (frame
.maximize_button
== None
)
772 createMaximizeButton();
773 XMoveResizeWindow(display
, frame
.maximize_button
, bx
, by
,
774 frame
.button_w
, frame
.button_h
);
775 XMapWindow(display
, frame
.maximize_button
);
776 XClearWindow(display
, frame
.maximize_button
);
777 bx
+= frame
.button_w
+ bw
;
782 XMoveResizeWindow(display
, frame
.label
, bx
, by
- 1,
783 frame
.label_w
, frame
.label_h
);
784 bx
+= frame
.label_w
+ bw
;
789 if (!hasclose
&& frame
.close_button
) {
790 openbox
.removeWindowSearch(frame
.close_button
);
791 XDestroyWindow(display
, frame
.close_button
);
792 frame
.close_button
= None
;
794 if (!hasiconify
&& frame
.iconify_button
) {
795 openbox
.removeWindowSearch(frame
.iconify_button
);
796 XDestroyWindow(display
, frame
.iconify_button
);
797 frame
.iconify_button
= None
;
799 if (!hasmaximize
&& frame
.iconify_button
) {
800 openbox
.removeWindowSearch(frame
.maximize_button
);
801 XDestroyWindow(display
, frame
.maximize_button
);
802 frame
.maximize_button
= None
;
810 void OpenboxWindow::reconfigure(void) {
813 client
.x
= frame
.x
+ frame
.mwm_border_w
+ frame
.border_w
;
814 client
.y
= frame
.y
+ frame
.y_border
+ frame
.mwm_border_w
+
818 if (i18n
->multibyte()) {
819 XRectangle ink
, logical
;
820 XmbTextExtents(screen
->getWindowStyle()->fontset
,
821 client
.title
, client
.title_len
, &ink
, &logical
);
822 client
.title_text_w
= logical
.width
;
824 client
.title_text_w
= XTextWidth(screen
->getWindowStyle()->font
,
825 client
.title
, client
.title_len
);
827 client
.title_text_w
+= (frame
.bevel_w
* 4);
833 XClearWindow(display
, frame
.window
);
834 setFocusFlag(flags
.focused
);
836 configure(frame
.x
, frame
.y
, frame
.width
, frame
.height
);
838 if (! screen
->sloppyFocus())
839 openbox
.grabButton(Button1
, 0, frame
.plate
, True
, ButtonPressMask
,
840 GrabModeSync
, GrabModeSync
, None
, None
);
842 openbox
.ungrabButton(Button1
, 0, frame
.plate
);
845 windowmenu
->move(windowmenu
->getX(), frame
.y
+ frame
.title_h
);
846 windowmenu
->reconfigure();
849 // re-get the timeout delay
850 timer
->setTimeout(openbox
.getAutoRaiseDelay());
854 void OpenboxWindow::positionWindows(void) {
855 XResizeWindow(display
, frame
.window
, frame
.width
,
856 ((flags
.shaded
) ? frame
.title_h
: frame
.height
));
857 XSetWindowBorderWidth(display
, frame
.window
, frame
.border_w
);
858 XSetWindowBorderWidth(display
, frame
.plate
, frame
.mwm_border_w
);
859 XMoveResizeWindow(display
, frame
.plate
, 0, frame
.y_border
,
860 client
.width
, client
.height
);
861 XMoveResizeWindow(display
, client
.window
, 0, 0, client
.width
, client
.height
);
863 if (decorations
.titlebar
) {
864 XSetWindowBorderWidth(display
, frame
.title
, frame
.border_w
);
865 XMoveResizeWindow(display
, frame
.title
, -frame
.border_w
,
866 -frame
.border_w
, frame
.width
, frame
.title_h
);
869 } else if (frame
.title
) {
870 XUnmapWindow(display
, frame
.title
);
872 if (decorations
.handle
) {
873 XSetWindowBorderWidth(display
, frame
.handle
, frame
.border_w
);
874 XSetWindowBorderWidth(display
, frame
.left_grip
, frame
.border_w
);
875 XSetWindowBorderWidth(display
, frame
.right_grip
, frame
.border_w
);
877 XMoveResizeWindow(display
, frame
.handle
, -frame
.border_w
,
878 frame
.y_handle
- frame
.border_w
,
879 frame
.width
, frame
.handle_h
);
880 XMoveResizeWindow(display
, frame
.left_grip
, -frame
.border_w
,
881 -frame
.border_w
, frame
.grip_w
, frame
.grip_h
);
882 XMoveResizeWindow(display
, frame
.right_grip
,
883 frame
.width
- frame
.grip_w
- frame
.border_w
,
884 -frame
.border_w
, frame
.grip_w
, frame
.grip_h
);
885 XMapSubwindows(display
, frame
.handle
);
886 } else if (frame
.handle
) {
887 XUnmapWindow(display
, frame
.handle
);
892 void OpenboxWindow::getWMName(void) {
894 delete [] client
.title
;
895 client
.title
= (char *) 0;
898 XTextProperty text_prop
;
902 if (XGetWMName(display
, client
.window
, &text_prop
)) {
903 if (text_prop
.value
&& text_prop
.nitems
> 0) {
904 if (text_prop
.encoding
!= XA_STRING
) {
905 text_prop
.nitems
= strlen((char *) text_prop
.value
);
907 if ((XmbTextPropertyToTextList(display
, &text_prop
,
908 &list
, &num
) == Success
) &&
909 (num
> 0) && *list
) {
910 client
.title
= bstrdup(*list
);
911 XFreeStringList(list
);
913 client
.title
= bstrdup((char *) text_prop
.value
);
916 client
.title
= bstrdup((char *) text_prop
.value
);
918 XFree((char *) text_prop
.value
);
920 client
.title
= bstrdup(i18n
->getMessage(WindowSet
, WindowUnnamed
,
924 client
.title
= bstrdup(i18n
->getMessage(WindowSet
, WindowUnnamed
,
927 client
.title_len
= strlen(client
.title
);
929 if (i18n
->multibyte()) {
930 XRectangle ink
, logical
;
931 XmbTextExtents(screen
->getWindowStyle()->fontset
,
932 client
.title
, client
.title_len
, &ink
, &logical
);
933 client
.title_text_w
= logical
.width
;
935 client
.title_len
= strlen(client
.title
);
936 client
.title_text_w
= XTextWidth(screen
->getWindowStyle()->font
,
937 client
.title
, client
.title_len
);
940 client
.title_text_w
+= (frame
.bevel_w
* 4);
944 void OpenboxWindow::getWMIconName(void) {
945 if (client
.icon_title
) {
946 delete [] client
.icon_title
;
947 client
.icon_title
= (char *) 0;
950 XTextProperty text_prop
;
954 if (XGetWMIconName(display
, client
.window
, &text_prop
)) {
955 if (text_prop
.value
&& text_prop
.nitems
> 0) {
956 if (text_prop
.encoding
!= XA_STRING
) {
957 text_prop
.nitems
= strlen((char *) text_prop
.value
);
959 if ((XmbTextPropertyToTextList(display
, &text_prop
,
960 &list
, &num
) == Success
) &&
961 (num
> 0) && *list
) {
962 client
.icon_title
= bstrdup(*list
);
963 XFreeStringList(list
);
965 client
.icon_title
= bstrdup((char *) text_prop
.value
);
968 client
.icon_title
= bstrdup((char *) text_prop
.value
);
970 XFree((char *) text_prop
.value
);
972 client
.icon_title
= bstrdup(client
.title
);
975 client
.icon_title
= bstrdup(client
.title
);
981 * Retrieve which WM Protocols are supported by the client window.
982 * If the WM_DELETE_WINDOW protocol is supported, add the close button to the
983 * window's decorations and allow the close behavior.
984 * If the WM_TAKE_FOCUS protocol is supported, save a value that indicates
987 void OpenboxWindow::getWMProtocols(void) {
991 if (XGetWMProtocols(display
, client
.window
, &proto
, &num_return
)) {
992 for (int i
= 0; i
< num_return
; ++i
) {
993 if (proto
[i
] == openbox
.getWMDeleteAtom())
994 functions
.close
= decorations
.close
= True
;
995 else if (proto
[i
] == openbox
.getWMTakeFocusAtom())
996 flags
.send_focus_message
= True
;
997 else if (proto
[i
] == openbox
.getOpenboxStructureMessagesAtom())
998 screen
->addNetizen(new Netizen(*screen
, client
.window
));
1007 * Gets the value of the WM_HINTS property.
1008 * If the property is not set, then use a set of default values.
1010 void OpenboxWindow::getWMHints(void) {
1011 XWMHints
*wmhint
= XGetWMHints(display
, client
.window
);
1013 flags
.visible
= True
;
1014 flags
.iconic
= False
;
1015 focus_mode
= F_Passive
;
1016 client
.window_group
= None
;
1017 client
.initial_state
= NormalState
;
1020 client
.wm_hint_flags
= wmhint
->flags
;
1021 if (wmhint
->flags
& InputHint
) {
1022 if (wmhint
->input
== True
) {
1023 if (flags
.send_focus_message
)
1024 focus_mode
= F_LocallyActive
;
1026 focus_mode
= F_Passive
;
1028 if (flags
.send_focus_message
)
1029 focus_mode
= F_GloballyActive
;
1031 focus_mode
= F_NoInput
;
1034 focus_mode
= F_Passive
;
1037 if (wmhint
->flags
& StateHint
)
1038 client
.initial_state
= wmhint
->initial_state
;
1040 client
.initial_state
= NormalState
;
1042 if (wmhint
->flags
& WindowGroupHint
) {
1043 if (! client
.window_group
) {
1044 client
.window_group
= wmhint
->window_group
;
1045 openbox
.saveGroupSearch(client
.window_group
, this);
1048 client
.window_group
= None
;
1055 * Gets the value of the WM_NORMAL_HINTS property.
1056 * If the property is not set, then use a set of default values.
1058 void OpenboxWindow::getWMNormalHints(void) {
1060 XSizeHints sizehint
;
1062 client
.min_width
= client
.min_height
=
1063 client
.base_width
= client
.base_height
=
1064 client
.width_inc
= client
.height_inc
= 1;
1065 client
.max_width
= screen
->size().w();
1066 client
.max_height
= screen
->size().h();
1067 client
.min_aspect_x
= client
.min_aspect_y
=
1068 client
.max_aspect_x
= client
.max_aspect_y
= 1;
1069 client
.win_gravity
= NorthWestGravity
;
1071 if (! XGetWMNormalHints(display
, client
.window
, &sizehint
, &icccm_mask
))
1074 client
.normal_hint_flags
= sizehint
.flags
;
1076 if (sizehint
.flags
& PMinSize
) {
1077 client
.min_width
= sizehint
.min_width
;
1078 client
.min_height
= sizehint
.min_height
;
1081 if (sizehint
.flags
& PMaxSize
) {
1082 client
.max_width
= sizehint
.max_width
;
1083 client
.max_height
= sizehint
.max_height
;
1086 if (sizehint
.flags
& PResizeInc
) {
1087 client
.width_inc
= sizehint
.width_inc
;
1088 client
.height_inc
= sizehint
.height_inc
;
1091 if (sizehint
.flags
& PAspect
) {
1092 client
.min_aspect_x
= sizehint
.min_aspect
.x
;
1093 client
.min_aspect_y
= sizehint
.min_aspect
.y
;
1094 client
.max_aspect_x
= sizehint
.max_aspect
.x
;
1095 client
.max_aspect_y
= sizehint
.max_aspect
.y
;
1098 if (sizehint
.flags
& PBaseSize
) {
1099 client
.base_width
= sizehint
.base_width
;
1100 client
.base_height
= sizehint
.base_height
;
1103 if (sizehint
.flags
& PWinGravity
)
1104 client
.win_gravity
= sizehint
.win_gravity
;
1109 * Gets the MWM hints for the class' contained window.
1110 * This is used while initializing the window to its first state, and not
1112 * Returns: true if the MWM hints are successfully retreived and applied; false
1115 void OpenboxWindow::getMWMHints(void) {
1118 unsigned long num
, len
;
1120 int ret
= XGetWindowProperty(display
, client
.window
,
1121 openbox
.getMotifWMHintsAtom(), 0,
1122 PropMwmHintsElements
, False
,
1123 openbox
.getMotifWMHintsAtom(), &atom_return
,
1124 &format
, &num
, &len
,
1125 (unsigned char **) &client
.mwm_hint
);
1127 if (ret
!= Success
|| !client
.mwm_hint
|| num
!= PropMwmHintsElements
)
1130 if (client
.mwm_hint
->flags
& MwmHintsDecorations
) {
1131 if (client
.mwm_hint
->decorations
& MwmDecorAll
) {
1132 decorations
.titlebar
= decorations
.handle
= decorations
.border
=
1133 decorations
.iconify
= decorations
.maximize
=
1134 decorations
.close
= decorations
.menu
= True
;
1136 decorations
.titlebar
= decorations
.handle
= decorations
.border
=
1137 decorations
.iconify
= decorations
.maximize
=
1138 decorations
.close
= decorations
.menu
= False
;
1140 if (client
.mwm_hint
->decorations
& MwmDecorBorder
)
1141 decorations
.border
= True
;
1142 if (client
.mwm_hint
->decorations
& MwmDecorHandle
)
1143 decorations
.handle
= True
;
1144 if (client
.mwm_hint
->decorations
& MwmDecorTitle
)
1145 decorations
.titlebar
= True
;
1146 if (client
.mwm_hint
->decorations
& MwmDecorMenu
)
1147 decorations
.menu
= True
;
1148 if (client
.mwm_hint
->decorations
& MwmDecorIconify
)
1149 decorations
.iconify
= True
;
1150 if (client
.mwm_hint
->decorations
& MwmDecorMaximize
)
1151 decorations
.maximize
= True
;
1155 if (client
.mwm_hint
->flags
& MwmHintsFunctions
) {
1156 if (client
.mwm_hint
->functions
& MwmFuncAll
) {
1157 functions
.resize
= functions
.move
= functions
.iconify
=
1158 functions
.maximize
= functions
.close
= True
;
1160 functions
.resize
= functions
.move
= functions
.iconify
=
1161 functions
.maximize
= functions
.close
= False
;
1163 if (client
.mwm_hint
->functions
& MwmFuncResize
)
1164 functions
.resize
= True
;
1165 if (client
.mwm_hint
->functions
& MwmFuncMove
)
1166 functions
.move
= True
;
1167 if (client
.mwm_hint
->functions
& MwmFuncIconify
)
1168 functions
.iconify
= True
;
1169 if (client
.mwm_hint
->functions
& MwmFuncMaximize
)
1170 functions
.maximize
= True
;
1171 if (client
.mwm_hint
->functions
& MwmFuncClose
)
1172 functions
.close
= True
;
1179 * Gets the openbox hints from the class' contained window.
1180 * This is used while initializing the window to its first state, and not
1182 * Returns: true if the hints are successfully retreived and applied; false if
1185 void OpenboxWindow::getOpenboxHints(void) {
1188 unsigned long num
, len
;
1190 int ret
= XGetWindowProperty(display
, client
.window
,
1191 openbox
.getOpenboxHintsAtom(), 0,
1192 PropOpenboxHintsElements
, False
,
1193 openbox
.getOpenboxHintsAtom(), &atom_return
,
1194 &format
, &num
, &len
,
1195 (unsigned char **) &client
.openbox_hint
);
1196 if (ret
!= Success
|| !client
.openbox_hint
||
1197 num
!= PropOpenboxHintsElements
)
1200 if (client
.openbox_hint
->flags
& AttribShaded
)
1201 flags
.shaded
= (client
.openbox_hint
->attrib
& AttribShaded
);
1203 if ((client
.openbox_hint
->flags
& AttribMaxHoriz
) &&
1204 (client
.openbox_hint
->flags
& AttribMaxVert
))
1205 flags
.maximized
= (client
.openbox_hint
->attrib
&
1206 (AttribMaxHoriz
| AttribMaxVert
)) ? 1 : 0;
1207 else if (client
.openbox_hint
->flags
& AttribMaxVert
)
1208 flags
.maximized
= (client
.openbox_hint
->attrib
& AttribMaxVert
) ? 2 : 0;
1209 else if (client
.openbox_hint
->flags
& AttribMaxHoriz
)
1210 flags
.maximized
= (client
.openbox_hint
->attrib
& AttribMaxHoriz
) ? 3 : 0;
1212 if (client
.openbox_hint
->flags
& AttribOmnipresent
)
1213 flags
.stuck
= (client
.openbox_hint
->attrib
& AttribOmnipresent
);
1215 if (client
.openbox_hint
->flags
& AttribWorkspace
)
1216 workspace_number
= client
.openbox_hint
->workspace
;
1218 // if (client.openbox_hint->flags & AttribStack)
1219 // don't yet have always on top/bottom for openbox yet... working
1222 if (client
.openbox_hint
->flags
& AttribDecoration
) {
1223 switch (client
.openbox_hint
->decoration
) {
1225 decorations
.titlebar
= decorations
.border
= decorations
.handle
=
1226 decorations
.iconify
= decorations
.maximize
=
1227 decorations
.menu
= False
;
1228 functions
.resize
= functions
.move
= functions
.iconify
=
1229 functions
.maximize
= False
;
1234 decorations
.titlebar
= decorations
.iconify
= decorations
.menu
=
1235 functions
.move
= functions
.iconify
= True
;
1236 decorations
.border
= decorations
.handle
= decorations
.maximize
=
1237 functions
.resize
= functions
.maximize
= False
;
1242 decorations
.titlebar
= decorations
.menu
= functions
.move
= True
;
1243 decorations
.iconify
= decorations
.border
= decorations
.handle
=
1244 decorations
.maximize
= functions
.resize
= functions
.maximize
=
1245 functions
.iconify
= False
;
1251 decorations
.titlebar
= decorations
.border
= decorations
.handle
=
1252 decorations
.iconify
= decorations
.maximize
=
1253 decorations
.menu
= True
;
1254 functions
.resize
= functions
.move
= functions
.iconify
=
1255 functions
.maximize
= True
;
1265 void OpenboxWindow::configure(int dx
, int dy
,
1266 unsigned int dw
, unsigned int dh
) {
1267 Bool send_event
= (frame
.x
!= dx
|| frame
.y
!= dy
);
1269 if ((dw
!= frame
.width
) || (dh
!= frame
.height
)) {
1270 if ((((signed) frame
.width
) + dx
) < 0) dx
= 0;
1271 if ((((signed) frame
.height
) + dy
) < 0) dy
= 0;
1281 if (openbox
.hasShapeExtensions() && flags
.shaped
) {
1282 XShapeCombineShape(display
, frame
.window
, ShapeBounding
,
1283 frame
.mwm_border_w
, frame
.y_border
+
1284 frame
.mwm_border_w
, client
.window
,
1285 ShapeBounding
, ShapeSet
);
1288 XRectangle xrect
[2];
1289 xrect
[0].x
= xrect
[0].y
= 0;
1290 xrect
[0].width
= frame
.width
;
1291 xrect
[0].height
= frame
.y_border
;
1293 if (decorations
.handle
) {
1295 xrect
[1].y
= frame
.y_handle
;
1296 xrect
[1].width
= frame
.width
;
1297 xrect
[1].height
= frame
.handle_h
+ frame
.border_w
;
1301 XShapeCombineRectangles(display
, frame
.window
, ShapeBounding
, 0, 0,
1302 xrect
, num
, ShapeUnion
, Unsorted
);
1306 XMoveWindow(display
, frame
.window
, frame
.x
, frame
.y
);
1308 setFocusFlag(flags
.focused
);
1315 XMoveWindow(display
, frame
.window
, frame
.x
, frame
.y
);
1317 if (! flags
.moving
) send_event
= True
;
1320 if (send_event
&& ! flags
.moving
) {
1321 client
.x
= dx
+ frame
.mwm_border_w
+ frame
.border_w
;
1322 client
.y
= dy
+ frame
.y_border
+ frame
.mwm_border_w
+
1326 event
.type
= ConfigureNotify
;
1328 event
.xconfigure
.display
= display
;
1329 event
.xconfigure
.event
= client
.window
;
1330 event
.xconfigure
.window
= client
.window
;
1331 event
.xconfigure
.x
= client
.x
;
1332 event
.xconfigure
.y
= client
.y
;
1333 event
.xconfigure
.width
= client
.width
;
1334 event
.xconfigure
.height
= client
.height
;
1335 event
.xconfigure
.border_width
= client
.old_bw
;
1336 event
.xconfigure
.above
= frame
.window
;
1337 event
.xconfigure
.override_redirect
= False
;
1339 XSendEvent(display
, client
.window
, True
, NoEventMask
, &event
);
1341 screen
->updateNetizenConfigNotify(&event
);
1346 bool OpenboxWindow::setInputFocus(void) {
1347 if (((signed) (frame
.x
+ frame
.width
)) < 0) {
1348 if (((signed) (frame
.y
+ frame
.y_border
)) < 0)
1349 configure(frame
.border_w
, frame
.border_w
, frame
.width
, frame
.height
);
1350 else if (frame
.y
> (signed) screen
->size().h())
1351 configure(frame
.border_w
, screen
->size().h() - frame
.height
,
1352 frame
.width
, frame
.height
);
1354 configure(frame
.border_w
, frame
.y
+ frame
.border_w
,
1355 frame
.width
, frame
.height
);
1356 } else if (frame
.x
> (signed) screen
->size().w()) {
1357 if (((signed) (frame
.y
+ frame
.y_border
)) < 0)
1358 configure(screen
->size().w() - frame
.width
, frame
.border_w
,
1359 frame
.width
, frame
.height
);
1360 else if (frame
.y
> (signed) screen
->size().h())
1361 configure(screen
->size().w() - frame
.width
,
1362 screen
->size().h() - frame
.height
, frame
.width
, frame
.height
);
1364 configure(screen
->size().w() - frame
.width
,
1365 frame
.y
+ frame
.border_w
, frame
.width
, frame
.height
);
1369 if (! validateClient()) return False
;
1373 if (client
.transient
&& flags
.modal
) {
1374 ret
= client
.transient
->setInputFocus();
1375 } else if (! flags
.focused
) {
1376 if (focus_mode
== F_LocallyActive
|| focus_mode
== F_Passive
) {
1377 XSetInputFocus(display
, client
.window
,
1378 RevertToPointerRoot
, CurrentTime
);
1379 openbox
.focusWindow(this);
1381 if (flags
.send_focus_message
) {
1383 ce
.xclient
.type
= ClientMessage
;
1384 ce
.xclient
.message_type
= openbox
.getWMProtocolsAtom();
1385 ce
.xclient
.display
= display
;
1386 ce
.xclient
.window
= client
.window
;
1387 ce
.xclient
.format
= 32;
1388 ce
.xclient
.data
.l
[0] = openbox
.getWMTakeFocusAtom();
1389 ce
.xclient
.data
.l
[1] = openbox
.getLastTime();
1390 ce
.xclient
.data
.l
[2] = 0l;
1391 ce
.xclient
.data
.l
[3] = 0l;
1392 ce
.xclient
.data
.l
[4] = 0l;
1393 XSendEvent(display
, client
.window
, False
, NoEventMask
, &ce
);
1396 if (screen
->sloppyFocus() && screen
->autoRaise())
1409 void OpenboxWindow::iconify(void) {
1410 if (flags
.iconic
) return;
1415 if (windowmenu
) windowmenu
->hide();
1417 setState(IconicState
);
1419 XSelectInput(display
, client
.window
, NoEventMask
);
1420 XUnmapWindow(display
, client
.window
);
1421 XSelectInput(display
, client
.window
,
1422 PropertyChangeMask
| StructureNotifyMask
| FocusChangeMask
);
1424 XUnmapWindow(display
, frame
.window
);
1425 flags
.visible
= False
;
1426 flags
.iconic
= True
;
1428 screen
->getWorkspace(workspace_number
)->removeWindow(this);
1430 if (flags
.transient
&& client
.transient_for
&&
1431 !client
.transient_for
->flags
.iconic
) {
1432 client
.transient_for
->iconify();
1434 screen
->addIcon(this);
1436 if (client
.transient
&& !client
.transient
->flags
.iconic
) {
1437 client
.transient
->iconify();
1442 void OpenboxWindow::deiconify(bool reassoc
, bool raise
, bool initial
) {
1443 if (flags
.iconic
|| reassoc
)
1444 screen
->reassociateWindow(this, -1, False
);
1445 else if (workspace_number
!= screen
->getCurrentWorkspace()->getWorkspaceID())
1448 setState(NormalState
);
1450 XSelectInput(display
, client
.window
, NoEventMask
);
1451 XMapWindow(display
, client
.window
);
1452 XSelectInput(display
, client
.window
,
1453 PropertyChangeMask
| StructureNotifyMask
| FocusChangeMask
);
1455 XMapSubwindows(display
, frame
.window
);
1456 XMapWindow(display
, frame
.window
);
1458 // if we're using the click to place placement type, then immediately
1459 // after the window is mapped, we need to start interactively moving it
1460 if (initial
&& place_window
&&
1461 screen
->placementPolicy() == BScreen::ClickMousePlacement
) {
1465 XQueryPointer(openbox
.getXDisplay(), screen
->getRootWindow(),
1466 &r
, &c
, &rx
, &ry
, &x
, &y
, &m
);
1470 if (flags
.iconic
&& screen
->focusNew()) setInputFocus();
1472 flags
.visible
= True
;
1473 flags
.iconic
= False
;
1475 if (reassoc
&& client
.transient
) client
.transient
->deiconify(True
, False
);
1478 screen
->getWorkspace(workspace_number
)->raiseWindow(this);
1482 void OpenboxWindow::close(void) {
1484 ce
.xclient
.type
= ClientMessage
;
1485 ce
.xclient
.message_type
= openbox
.getWMProtocolsAtom();
1486 ce
.xclient
.display
= display
;
1487 ce
.xclient
.window
= client
.window
;
1488 ce
.xclient
.format
= 32;
1489 ce
.xclient
.data
.l
[0] = openbox
.getWMDeleteAtom();
1490 ce
.xclient
.data
.l
[1] = CurrentTime
;
1491 ce
.xclient
.data
.l
[2] = 0l;
1492 ce
.xclient
.data
.l
[3] = 0l;
1493 ce
.xclient
.data
.l
[4] = 0l;
1494 XSendEvent(display
, client
.window
, False
, NoEventMask
, &ce
);
1498 void OpenboxWindow::withdraw(void) {
1502 flags
.visible
= False
;
1503 flags
.iconic
= False
;
1505 XUnmapWindow(display
, frame
.window
);
1507 XSelectInput(display
, client
.window
, NoEventMask
);
1508 XUnmapWindow(display
, client
.window
);
1509 XSelectInput(display
, client
.window
,
1510 PropertyChangeMask
| StructureNotifyMask
| FocusChangeMask
);
1512 if (windowmenu
) windowmenu
->hide();
1516 void OpenboxWindow::maximize(unsigned int button
) {
1520 // handle case where menu is open then the max button is used instead
1521 if (windowmenu
&& windowmenu
->isVisible()) windowmenu
->hide();
1523 if (flags
.maximized
) {
1524 flags
.maximized
= 0;
1526 openbox_attrib
.flags
&= ! (AttribMaxHoriz
| AttribMaxVert
);
1527 openbox_attrib
.attrib
&= ! (AttribMaxHoriz
| AttribMaxVert
);
1529 // when a resize is begun, maximize(0) is called to clear any maximization
1530 // flags currently set. Otherwise it still thinks it is maximized.
1531 // so we do not need to call configure() because resizing will handle it
1532 if (!flags
.resizing
)
1533 configure(openbox_attrib
.premax_x
, openbox_attrib
.premax_y
,
1534 openbox_attrib
.premax_w
, openbox_attrib
.premax_h
);
1536 openbox_attrib
.premax_x
= openbox_attrib
.premax_y
= 0;
1537 openbox_attrib
.premax_w
= openbox_attrib
.premax_h
= 0;
1539 redrawMaximizeButton(flags
.maximized
);
1540 setState(current_state
);
1544 openbox_attrib
.premax_x
= frame
.x
;
1545 openbox_attrib
.premax_y
= frame
.y
;
1546 openbox_attrib
.premax_w
= frame
.width
;
1547 openbox_attrib
.premax_h
= frame
.height
;
1549 Rect space
= screen
->availableArea();
1550 unsigned int dw
= space
.w(),
1552 dw
-= frame
.border_w
* 2;
1553 dw
-= frame
.mwm_border_w
* 2;
1554 dw
-= client
.base_width
;
1556 dh
-= frame
.border_w
* 2;
1557 dh
-= frame
.mwm_border_w
* 2;
1558 dh
-= ((frame
.handle_h
+ frame
.border_w
) * decorations
.handle
);
1559 dh
-= client
.base_height
;
1560 dh
-= frame
.y_border
;
1562 if (dw
< client
.min_width
) dw
= client
.min_width
;
1563 if (dh
< client
.min_height
) dh
= client
.min_height
;
1564 if (dw
> client
.max_width
) dw
= client
.max_width
;
1565 if (dh
> client
.max_height
) dh
= client
.max_height
;
1567 dw
-= (dw
% client
.width_inc
);
1568 dw
+= client
.base_width
;
1569 dw
+= frame
.mwm_border_w
* 2;
1571 dh
-= (dh
% client
.height_inc
);
1572 dh
+= client
.base_height
;
1573 dh
+= frame
.y_border
;
1574 dh
+= ((frame
.handle_h
+ frame
.border_w
) * decorations
.handle
);
1575 dh
+= frame
.mwm_border_w
* 2;
1577 int dx
= space
.x() + ((space
.w() - dw
) / 2) - frame
.border_w
,
1578 dy
= space
.y() + ((space
.h() - dh
) / 2) - frame
.border_w
;
1582 openbox_attrib
.flags
|= AttribMaxHoriz
| AttribMaxVert
;
1583 openbox_attrib
.attrib
|= AttribMaxHoriz
| AttribMaxVert
;
1587 openbox_attrib
.flags
|= AttribMaxVert
;
1588 openbox_attrib
.attrib
|= AttribMaxVert
;
1595 openbox_attrib
.flags
|= AttribMaxHoriz
;
1596 openbox_attrib
.attrib
|= AttribMaxHoriz
;
1604 openbox_attrib
.flags
^= AttribShaded
;
1605 openbox_attrib
.attrib
^= AttribShaded
;
1606 flags
.shaded
= False
;
1609 flags
.maximized
= button
;
1611 configure(dx
, dy
, dw
, dh
);
1612 screen
->getWorkspace(workspace_number
)->raiseWindow(this);
1613 redrawMaximizeButton(flags
.maximized
);
1614 setState(current_state
);
1618 void OpenboxWindow::setWorkspace(int n
) {
1619 ASSERT(n
< screen
->getWorkspaceCount());
1620 workspace_number
= n
;
1622 openbox_attrib
.flags
|= AttribWorkspace
;
1623 openbox_attrib
.workspace
= workspace_number
;
1627 void OpenboxWindow::shade(void) {
1628 if (!decorations
.titlebar
)
1632 XResizeWindow(display
, frame
.window
, frame
.width
, frame
.height
);
1633 flags
.shaded
= False
;
1634 openbox_attrib
.flags
^= AttribShaded
;
1635 openbox_attrib
.attrib
^= AttribShaded
;
1637 setState(NormalState
);
1639 XResizeWindow(display
, frame
.window
, frame
.width
, frame
.title_h
);
1640 flags
.shaded
= True
;
1641 openbox_attrib
.flags
|= AttribShaded
;
1642 openbox_attrib
.attrib
|= AttribShaded
;
1644 setState(IconicState
);
1649 void OpenboxWindow::stick(void) {
1651 openbox_attrib
.flags
^= AttribOmnipresent
;
1652 openbox_attrib
.attrib
^= AttribOmnipresent
;
1654 flags
.stuck
= False
;
1657 screen
->reassociateWindow(this, -1, True
);
1659 setState(current_state
);
1663 openbox_attrib
.flags
|= AttribOmnipresent
;
1664 openbox_attrib
.attrib
|= AttribOmnipresent
;
1666 setState(current_state
);
1671 void OpenboxWindow::setFocusFlag(Bool focus
) {
1672 flags
.focused
= focus
;
1674 if (decorations
.titlebar
) {
1675 if (flags
.focused
) {
1677 XSetWindowBackgroundPixmap(display
, frame
.title
, frame
.ftitle
);
1679 XSetWindowBackground(display
, frame
.title
, frame
.ftitle_pixel
);
1682 XSetWindowBackgroundPixmap(display
, frame
.title
, frame
.utitle
);
1684 XSetWindowBackground(display
, frame
.title
, frame
.utitle_pixel
);
1686 XClearWindow(display
, frame
.title
);
1692 if (decorations
.handle
) {
1693 if (flags
.focused
) {
1695 XSetWindowBackgroundPixmap(display
, frame
.handle
, frame
.fhandle
);
1697 XSetWindowBackground(display
, frame
.handle
, frame
.fhandle_pixel
);
1700 XSetWindowBackgroundPixmap(display
, frame
.right_grip
, frame
.fgrip
);
1701 XSetWindowBackgroundPixmap(display
, frame
.left_grip
, frame
.fgrip
);
1703 XSetWindowBackground(display
, frame
.right_grip
, frame
.fgrip_pixel
);
1704 XSetWindowBackground(display
, frame
.left_grip
, frame
.fgrip_pixel
);
1708 XSetWindowBackgroundPixmap(display
, frame
.handle
, frame
.uhandle
);
1710 XSetWindowBackground(display
, frame
.handle
, frame
.uhandle_pixel
);
1713 XSetWindowBackgroundPixmap(display
, frame
.right_grip
, frame
.ugrip
);
1714 XSetWindowBackgroundPixmap(display
, frame
.left_grip
, frame
.ugrip
);
1716 XSetWindowBackground(display
, frame
.right_grip
, frame
.ugrip_pixel
);
1717 XSetWindowBackground(display
, frame
.left_grip
, frame
.ugrip_pixel
);
1720 XClearWindow(display
, frame
.handle
);
1721 XClearWindow(display
, frame
.right_grip
);
1722 XClearWindow(display
, frame
.left_grip
);
1725 if (decorations
.border
) {
1727 XSetWindowBorder(display
, frame
.plate
, frame
.fborder_pixel
);
1729 XSetWindowBorder(display
, frame
.plate
, frame
.uborder_pixel
);
1732 if (screen
->sloppyFocus() && screen
->autoRaise() && timer
->isTiming())
1738 void OpenboxWindow::installColormap(Bool install
) {
1740 if (! validateClient()) return;
1742 int i
= 0, ncmap
= 0;
1743 Colormap
*cmaps
= XListInstalledColormaps(display
, client
.window
, &ncmap
);
1744 XWindowAttributes wattrib
;
1746 if (XGetWindowAttributes(display
, client
.window
, &wattrib
)) {
1748 // install the window's colormap
1749 for (i
= 0; i
< ncmap
; i
++) {
1750 if (*(cmaps
+ i
) == wattrib
.colormap
)
1751 // this window is using an installed color map... do not install
1754 // otherwise, install the window's colormap
1756 XInstallColormap(display
, wattrib
.colormap
);
1758 // uninstall the window's colormap
1759 for (i
= 0; i
< ncmap
; i
++) {
1760 if (*(cmaps
+ i
) == wattrib
.colormap
)
1761 // we found the colormap to uninstall
1762 XUninstallColormap(display
, wattrib
.colormap
);
1774 void OpenboxWindow::setState(unsigned long new_state
) {
1775 current_state
= new_state
;
1777 unsigned long state
[2];
1778 state
[0] = (unsigned long) current_state
;
1779 state
[1] = (unsigned long) None
;
1780 XChangeProperty(display
, client
.window
, openbox
.getWMStateAtom(),
1781 openbox
.getWMStateAtom(), 32, PropModeReplace
,
1782 (unsigned char *) state
, 2);
1784 XChangeProperty(display
, client
.window
,
1785 openbox
.getOpenboxAttributesAtom(),
1786 openbox
.getOpenboxAttributesAtom(), 32, PropModeReplace
,
1787 (unsigned char *) &openbox_attrib
,
1788 PropOpenboxAttributesElements
);
1792 Bool
OpenboxWindow::getState(void) {
1798 unsigned long *state
, ulfoo
, nitems
;
1800 if ((XGetWindowProperty(display
, client
.window
, openbox
.getWMStateAtom(),
1801 0l, 2l, False
, openbox
.getWMStateAtom(),
1802 &atom_return
, &foo
, &nitems
, &ulfoo
,
1803 (unsigned char **) &state
) != Success
) ||
1810 current_state
= (unsigned long) state
[0];
1815 XFree((void *) state
);
1821 void OpenboxWindow::setGravityOffsets(void) {
1822 // x coordinates for each gravity type
1823 const int x_west
= client
.x
;
1824 const int x_east
= client
.x
+ client
.width
- frame
.width
;
1825 const int x_center
= client
.x
+ client
.width
- frame
.width
/2;
1826 // y coordinates for each gravity type
1827 const int y_north
= client
.y
;
1828 const int y_south
= client
.y
+ client
.height
- frame
.height
;
1829 const int y_center
= client
.y
+ client
.height
- frame
.height
/2;
1831 switch (client
.win_gravity
) {
1832 case NorthWestGravity
:
1841 case NorthEastGravity
:
1845 case SouthWestGravity
:
1853 case SouthEastGravity
:
1871 frame
.x
= client
.x
- frame
.mwm_border_w
+ frame
.border_w
;
1872 frame
.y
= client
.y
- frame
.y_border
- frame
.mwm_border_w
- frame
.border_w
;
1878 void OpenboxWindow::restoreAttributes(void) {
1879 if (! getState()) current_state
= NormalState
;
1883 unsigned long ulfoo
, nitems
;
1885 OpenboxAttributes
*net
;
1886 int ret
= XGetWindowProperty(display
, client
.window
,
1887 openbox
.getOpenboxAttributesAtom(), 0l,
1888 PropOpenboxAttributesElements
, False
,
1889 openbox
.getOpenboxAttributesAtom(),
1890 &atom_return
, &foo
, &nitems
, &ulfoo
,
1891 (unsigned char **) &net
);
1892 if (ret
!= Success
|| !net
|| nitems
!= PropOpenboxAttributesElements
)
1895 openbox_attrib
.flags
= net
->flags
;
1896 openbox_attrib
.attrib
= net
->attrib
;
1897 openbox_attrib
.decoration
= net
->decoration
;
1898 openbox_attrib
.workspace
= net
->workspace
;
1899 openbox_attrib
.stack
= net
->stack
;
1900 openbox_attrib
.premax_x
= net
->premax_x
;
1901 openbox_attrib
.premax_y
= net
->premax_y
;
1902 openbox_attrib
.premax_w
= net
->premax_w
;
1903 openbox_attrib
.premax_h
= net
->premax_h
;
1905 XFree((void *) net
);
1907 if (openbox_attrib
.flags
& AttribShaded
&&
1908 openbox_attrib
.attrib
& AttribShaded
) {
1910 ((current_state
== IconicState
) ? NormalState
: current_state
);
1912 flags
.shaded
= False
;
1915 current_state
= save_state
;
1918 if (((int) openbox_attrib
.workspace
!= screen
->getCurrentWorkspaceID()) &&
1919 ((int) openbox_attrib
.workspace
< screen
->getWorkspaceCount())) {
1920 screen
->reassociateWindow(this, openbox_attrib
.workspace
, True
);
1922 if (current_state
== NormalState
) current_state
= WithdrawnState
;
1923 } else if (current_state
== WithdrawnState
) {
1924 current_state
= NormalState
;
1927 if (openbox_attrib
.flags
& AttribOmnipresent
&&
1928 openbox_attrib
.attrib
& AttribOmnipresent
) {
1929 flags
.stuck
= False
;
1932 current_state
= NormalState
;
1935 if ((openbox_attrib
.flags
& AttribMaxHoriz
) ||
1936 (openbox_attrib
.flags
& AttribMaxVert
)) {
1937 int x
= openbox_attrib
.premax_x
, y
= openbox_attrib
.premax_y
;
1938 unsigned int w
= openbox_attrib
.premax_w
, h
= openbox_attrib
.premax_h
;
1939 flags
.maximized
= 0;
1941 unsigned int m
= False
;
1942 if ((openbox_attrib
.flags
& AttribMaxHoriz
) &&
1943 (openbox_attrib
.flags
& AttribMaxVert
))
1944 m
= (openbox_attrib
.attrib
& (AttribMaxHoriz
| AttribMaxVert
)) ? 1 : 0;
1945 else if (openbox_attrib
.flags
& AttribMaxVert
)
1946 m
= (openbox_attrib
.attrib
& AttribMaxVert
) ? 2 : 0;
1947 else if (openbox_attrib
.flags
& AttribMaxHoriz
)
1948 m
= (openbox_attrib
.attrib
& AttribMaxHoriz
) ? 3 : 0;
1952 openbox_attrib
.premax_x
= x
;
1953 openbox_attrib
.premax_y
= y
;
1954 openbox_attrib
.premax_w
= w
;
1955 openbox_attrib
.premax_h
= h
;
1958 setState(current_state
);
1963 * The reverse of the setGravityOffsets function. Uses the frame window's
1964 * position to find the window's reference point.
1966 void OpenboxWindow::restoreGravity(void) {
1967 // x coordinates for each gravity type
1968 const int x_west
= frame
.x
;
1969 const int x_east
= frame
.x
+ frame
.width
- client
.width
;
1970 const int x_center
= frame
.x
+ (frame
.width
/2) - client
.width
;
1971 // y coordinates for each gravity type
1972 const int y_north
= frame
.y
;
1973 const int y_south
= frame
.y
+ frame
.height
- client
.height
;
1974 const int y_center
= frame
.y
+ (frame
.height
/2) - client
.height
;
1976 switch(client
.win_gravity
) {
1978 case NorthWestGravity
:
1983 client
.x
= x_center
;
1986 case NorthEastGravity
:
1990 case SouthWestGravity
:
1995 client
.x
= x_center
;
1998 case SouthEastGravity
:
2004 client
.y
= y_center
;
2008 client
.y
= y_center
;
2011 client
.x
= x_center
;
2012 client
.y
= y_center
;
2016 client
.x
= frame
.x
+ frame
.mwm_border_w
+ frame
.border_w
;
2017 client
.y
= frame
.y
+ frame
.y_border
+ frame
.mwm_border_w
+
2024 void OpenboxWindow::redrawLabel(void) {
2025 int dx
= frame
.bevel_w
* 2, dlen
= client
.title_len
;
2026 unsigned int l
= client
.title_text_w
;
2028 if (flags
.focused
) {
2030 XSetWindowBackgroundPixmap(display
, frame
.label
, frame
.flabel
);
2032 XSetWindowBackground(display
, frame
.label
, frame
.flabel_pixel
);
2035 XSetWindowBackgroundPixmap(display
, frame
.label
, frame
.ulabel
);
2037 XSetWindowBackground(display
, frame
.label
, frame
.ulabel_pixel
);
2039 XClearWindow(display
, frame
.label
);
2041 if (client
.title_text_w
> frame
.label_w
) {
2042 for (; dlen
>= 0; dlen
--) {
2043 if (i18n
->multibyte()) {
2044 XRectangle ink
, logical
;
2045 XmbTextExtents(screen
->getWindowStyle()->fontset
, client
.title
, dlen
,
2049 l
= XTextWidth(screen
->getWindowStyle()->font
, client
.title
, dlen
);
2051 l
+= (frame
.bevel_w
* 4);
2053 if (l
< frame
.label_w
)
2058 switch (screen
->getWindowStyle()->justify
) {
2059 case BScreen::RightJustify
:
2060 dx
+= frame
.label_w
- l
;
2063 case BScreen::CenterJustify
:
2064 dx
+= (frame
.label_w
- l
) / 2;
2068 WindowStyle
*style
= screen
->getWindowStyle();
2069 GC text_gc
= (flags
.focused
) ? style
->l_text_focus_gc
:
2070 style
->l_text_unfocus_gc
;
2071 if (i18n
->multibyte())
2072 XmbDrawString(display
, frame
.label
, style
->fontset
, text_gc
, dx
,
2073 (1 - style
->fontset_extents
->max_ink_extent
.y
),
2074 client
.title
, dlen
);
2076 XDrawString(display
, frame
.label
, text_gc
, dx
,
2077 (style
->font
->ascent
+ 1), client
.title
, dlen
);
2081 void OpenboxWindow::redrawAllButtons(void) {
2082 if (frame
.iconify_button
) redrawIconifyButton(False
);
2083 if (frame
.maximize_button
) redrawMaximizeButton(flags
.maximized
);
2084 if (frame
.close_button
) redrawCloseButton(False
);
2088 void OpenboxWindow::redrawIconifyButton(Bool pressed
) {
2090 if (flags
.focused
) {
2092 XSetWindowBackgroundPixmap(display
, frame
.iconify_button
,
2095 XSetWindowBackground(display
, frame
.iconify_button
,
2096 frame
.fbutton_pixel
);
2099 XSetWindowBackgroundPixmap(display
, frame
.iconify_button
,
2102 XSetWindowBackground(display
, frame
.iconify_button
,
2103 frame
.ubutton_pixel
);
2107 XSetWindowBackgroundPixmap(display
, frame
.iconify_button
, frame
.pbutton
);
2109 XSetWindowBackground(display
, frame
.iconify_button
, frame
.pbutton_pixel
);
2111 XClearWindow(display
, frame
.iconify_button
);
2113 XDrawRectangle(display
, frame
.iconify_button
,
2114 ((flags
.focused
) ? screen
->getWindowStyle()->b_pic_focus_gc
:
2115 screen
->getWindowStyle()->b_pic_unfocus_gc
),
2116 2, (frame
.button_h
- 5), (frame
.button_w
- 5), 2);
2120 void OpenboxWindow::redrawMaximizeButton(Bool pressed
) {
2122 if (flags
.focused
) {
2124 XSetWindowBackgroundPixmap(display
, frame
.maximize_button
,
2127 XSetWindowBackground(display
, frame
.maximize_button
,
2128 frame
.fbutton_pixel
);
2131 XSetWindowBackgroundPixmap(display
, frame
.maximize_button
,
2134 XSetWindowBackground(display
, frame
.maximize_button
,
2135 frame
.ubutton_pixel
);
2139 XSetWindowBackgroundPixmap(display
, frame
.maximize_button
,
2142 XSetWindowBackground(display
, frame
.maximize_button
,
2143 frame
.pbutton_pixel
);
2145 XClearWindow(display
, frame
.maximize_button
);
2147 XDrawRectangle(display
, frame
.maximize_button
,
2148 ((flags
.focused
) ? screen
->getWindowStyle()->b_pic_focus_gc
:
2149 screen
->getWindowStyle()->b_pic_unfocus_gc
),
2150 2, 2, (frame
.button_w
- 5), (frame
.button_h
- 5));
2151 XDrawLine(display
, frame
.maximize_button
,
2152 ((flags
.focused
) ? screen
->getWindowStyle()->b_pic_focus_gc
:
2153 screen
->getWindowStyle()->b_pic_unfocus_gc
),
2154 2, 3, (frame
.button_w
- 3), 3);
2158 void OpenboxWindow::redrawCloseButton(Bool pressed
) {
2160 if (flags
.focused
) {
2162 XSetWindowBackgroundPixmap(display
, frame
.close_button
,
2165 XSetWindowBackground(display
, frame
.close_button
,
2166 frame
.fbutton_pixel
);
2169 XSetWindowBackgroundPixmap(display
, frame
.close_button
,
2172 XSetWindowBackground(display
, frame
.close_button
,
2173 frame
.ubutton_pixel
);
2177 XSetWindowBackgroundPixmap(display
, frame
.close_button
, frame
.pbutton
);
2179 XSetWindowBackground(display
, frame
.close_button
, frame
.pbutton_pixel
);
2181 XClearWindow(display
, frame
.close_button
);
2183 XDrawLine(display
, frame
.close_button
,
2184 ((flags
.focused
) ? screen
->getWindowStyle()->b_pic_focus_gc
:
2185 screen
->getWindowStyle()->b_pic_unfocus_gc
), 2, 2,
2186 (frame
.button_w
- 3), (frame
.button_h
- 3));
2187 XDrawLine(display
, frame
.close_button
,
2188 ((flags
.focused
) ? screen
->getWindowStyle()->b_pic_focus_gc
:
2189 screen
->getWindowStyle()->b_pic_unfocus_gc
), 2,
2190 (frame
.button_h
- 3),
2191 (frame
.button_w
- 3), 2);
2195 void OpenboxWindow::mapRequestEvent(XMapRequestEvent
*re
) {
2196 if (re
->window
== client
.window
) {
2198 fprintf(stderr
, i18n
->getMessage(WindowSet
, WindowMapRequest
,
2199 "OpenboxWindow::mapRequestEvent() for 0x%lx\n"),
2204 if (! validateClient()) return;
2206 Bool get_state_ret
= getState();
2207 if (! (get_state_ret
&& openbox
.isStartup())) {
2208 if ((client
.wm_hint_flags
& StateHint
) &&
2209 (! (current_state
== NormalState
|| current_state
== IconicState
)))
2210 current_state
= client
.initial_state
;
2212 current_state
= NormalState
;
2213 } else if (flags
.iconic
) {
2214 current_state
= NormalState
;
2217 switch (current_state
) {
2222 case WithdrawnState
:
2230 deiconify(False
, True
, True
); // specify that we're initializing the
2240 void OpenboxWindow::mapNotifyEvent(XMapEvent
*ne
) {
2241 if ((ne
->window
== client
.window
) && (! ne
->override_redirect
)
2242 && (flags
.visible
)) {
2244 if (! validateClient()) return;
2246 setState(NormalState
);
2248 if (flags
.transient
|| screen
->focusNew())
2251 setFocusFlag(False
);
2253 flags
.visible
= True
;
2254 flags
.iconic
= False
;
2261 void OpenboxWindow::unmapNotifyEvent(XUnmapEvent
*ue
) {
2262 if (ue
->window
== client
.window
) {
2264 fprintf(stderr
, i18n
->getMessage(WindowSet
, WindowUnmapNotify
,
2265 "OpenboxWindow::unmapNotifyEvent() for 0x%lx\n"),
2270 if (! validateClient()) return;
2275 XChangeSaveSet(display
, client
.window
, SetModeDelete
);
2276 XSelectInput(display
, client
.window
, NoEventMask
);
2278 XDeleteProperty(display
, client
.window
, openbox
.getWMStateAtom());
2279 XDeleteProperty(display
, client
.window
,
2280 openbox
.getOpenboxAttributesAtom());
2282 XUnmapWindow(display
, frame
.window
);
2283 XUnmapWindow(display
, client
.window
);
2286 if (! XCheckTypedWindowEvent(display
, client
.window
, ReparentNotify
,
2289 fprintf(stderr
, i18n
->getMessage(WindowSet
, WindowUnmapNotifyReparent
,
2290 "OpenboxWindow::unmapNotifyEvent(): reparent 0x%lx to "
2291 "root.\n"), client
.window
);
2295 XReparentWindow(display
, client
.window
, screen
->getRootWindow(),
2296 client
.x
, client
.y
);
2308 void OpenboxWindow::destroyNotifyEvent(XDestroyWindowEvent
*de
) {
2309 if (de
->window
== client
.window
) {
2312 XUnmapWindow(display
, frame
.window
);
2319 void OpenboxWindow::propertyNotifyEvent(Atom atom
) {
2321 if (! validateClient()) return;
2325 case XA_WM_CLIENT_MACHINE
:
2329 case XA_WM_TRANSIENT_FOR
:
2330 // determine if this is a transient window
2332 if (XGetTransientForHint(display
, client
.window
, &win
)) {
2333 if (win
&& (win
!= client
.window
)) {
2334 if ((client
.transient_for
= openbox
.searchWindow(win
))) {
2335 client
.transient_for
->client
.transient
= this;
2336 flags
.stuck
= client
.transient_for
->flags
.stuck
;
2337 flags
.transient
= True
;
2338 } else if (win
== client
.window_group
) {
2339 //jr This doesn't look quite right...
2340 if ((client
.transient_for
= openbox
.searchGroup(win
, this))) {
2341 client
.transient_for
->client
.transient
= this;
2342 flags
.stuck
= client
.transient_for
->flags
.stuck
;
2343 flags
.transient
= True
;
2348 if (win
== screen
->getRootWindow()) flags
.modal
= True
;
2351 // adjust the window decorations based on transience
2352 if (flags
.transient
)
2353 decorations
.maximize
= decorations
.handle
= functions
.maximize
= False
;
2363 case XA_WM_ICON_NAME
:
2365 if (flags
.iconic
) screen
->iconUpdate();
2371 if (decorations
.titlebar
)
2375 screen
->getWorkspace(workspace_number
)->update();
2379 case XA_WM_NORMAL_HINTS
: {
2382 if ((client
.normal_hint_flags
& PMinSize
) &&
2383 (client
.normal_hint_flags
& PMaxSize
)) {
2384 if (client
.max_width
<= client
.min_width
&&
2385 client
.max_height
<= client
.min_height
)
2386 decorations
.maximize
= decorations
.handle
=
2387 functions
.resize
= functions
.maximize
= False
;
2389 decorations
.maximize
= decorations
.handle
=
2390 functions
.resize
= functions
.maximize
= True
;
2393 int x
= frame
.x
, y
= frame
.y
;
2394 unsigned int w
= frame
.width
, h
= frame
.height
;
2398 if ((x
!= frame
.x
) || (y
!= frame
.y
) ||
2399 (w
!= frame
.width
) || (h
!= frame
.height
))
2406 if (atom
== openbox
.getWMProtocolsAtom()) {
2409 if (decorations
.close
&& (! frame
.close_button
)) {
2410 createCloseButton();
2411 if (decorations
.titlebar
) {
2415 if (windowmenu
) windowmenu
->reconfigure();
2426 void OpenboxWindow::exposeEvent(XExposeEvent
*ee
) {
2427 if (frame
.label
== ee
->window
&& decorations
.titlebar
)
2429 else if (frame
.close_button
== ee
->window
)
2430 redrawCloseButton(False
);
2431 else if (frame
.maximize_button
== ee
->window
)
2432 redrawMaximizeButton(flags
.maximized
);
2433 else if (frame
.iconify_button
== ee
->window
)
2434 redrawIconifyButton(False
);
2438 void OpenboxWindow::configureRequestEvent(XConfigureRequestEvent
*cr
) {
2439 if (cr
->window
== client
.window
) {
2441 if (! validateClient()) return;
2443 int cx
= frame
.x
, cy
= frame
.y
;
2444 unsigned int cw
= frame
.width
, ch
= frame
.height
;
2446 if (cr
->value_mask
& CWBorderWidth
)
2447 client
.old_bw
= cr
->border_width
;
2449 if (cr
->value_mask
& CWX
)
2450 cx
= cr
->x
- frame
.mwm_border_w
- frame
.border_w
;
2452 if (cr
->value_mask
& CWY
)
2453 cy
= cr
->y
- frame
.y_border
- frame
.mwm_border_w
-
2456 if (cr
->value_mask
& CWWidth
)
2457 cw
= cr
->width
+ (frame
.mwm_border_w
* 2);
2459 if (cr
->value_mask
& CWHeight
)
2460 ch
= cr
->height
+ frame
.y_border
+ (frame
.mwm_border_w
* 2) +
2461 (frame
.border_w
* decorations
.handle
) + frame
.handle_h
;
2463 if (frame
.x
!= cx
|| frame
.y
!= cy
||
2464 frame
.width
!= cw
|| frame
.height
!= ch
)
2465 configure(cx
, cy
, cw
, ch
);
2467 if (cr
->value_mask
& CWStackMode
) {
2468 switch (cr
->detail
) {
2472 if (flags
.iconic
) deiconify();
2473 screen
->getWorkspace(workspace_number
)->raiseWindow(this);
2478 if (flags
.iconic
) deiconify();
2479 screen
->getWorkspace(workspace_number
)->lowerWindow(this);
2489 void OpenboxWindow::buttonPressEvent(XButtonEvent
*be
) {
2491 if (! validateClient())
2494 int stack_change
= 1; // < 0 means to lower the window
2495 // > 0 means to raise the window
2496 // 0 means to leave it where it is
2498 // alt + left/right click begins interactively moving/resizing the window
2499 // when the mouse is moved
2500 if (be
->state
== Mod1Mask
&& (be
->button
== 1 || be
->button
== 3)) {
2501 if (be
->button
== 3) {
2502 if (screen
->getWindowZones() == 4 &&
2503 be
->y
< (signed) frame
.height
/ 2) {
2504 resize_zone
= ZoneTop
;
2506 resize_zone
= ZoneBottom
;
2508 if (screen
->getWindowZones() >= 2 &&
2509 be
->x
< (signed) frame
.width
/ 2) {
2510 resize_zone
|= ZoneLeft
;
2512 resize_zone
|= ZoneRight
;
2515 // control + left click on the titlebar shades the window
2516 } else if (be
->state
== ControlMask
&& be
->button
== 1) {
2517 if (be
->window
== frame
.title
||
2518 be
->window
== frame
.label
)
2521 } else if (be
->state
== 0 && be
->button
== 1) {
2522 if (windowmenu
&& windowmenu
->isVisible())
2525 if (be
->window
== frame
.maximize_button
) {
2526 redrawMaximizeButton(True
);
2527 } else if (be
->window
== frame
.iconify_button
) {
2528 redrawIconifyButton(True
);
2529 } else if (be
->window
== frame
.close_button
) {
2530 redrawCloseButton(True
);
2531 } else if (be
->window
== frame
.plate
) {
2532 XAllowEvents(display
, ReplayPointer
, be
->time
);
2533 } else if (be
->window
== frame
.title
||
2534 be
->window
== frame
.label
) {
2535 // shade the window when the titlebar is double clicked
2536 if ( (be
->time
- lastButtonPressTime
) <=
2537 openbox
.getDoubleClickInterval()) {
2538 lastButtonPressTime
= 0;
2541 lastButtonPressTime
= be
->time
;
2543 // clicking and dragging on the titlebar moves the window, so on a click
2544 // we need to save the coords of the click in case the user drags
2545 frame
.grab_x
= be
->x_root
- frame
.x
- frame
.border_w
;
2546 frame
.grab_y
= be
->y_root
- frame
.y
- frame
.border_w
;
2547 } else if (be
->window
== frame
.handle
||
2548 be
->window
== frame
.left_grip
||
2549 be
->window
== frame
.right_grip
||
2550 be
->window
== frame
.window
) {
2551 // clicking and dragging on the window's frame moves the window, so on a
2552 // click we need to save the coords of the click in case the user drags
2553 frame
.grab_x
= be
->x_root
- frame
.x
- frame
.border_w
;
2554 frame
.grab_y
= be
->y_root
- frame
.y
- frame
.border_w
;
2555 if (be
->window
== frame
.left_grip
)
2556 resize_zone
= ZoneBottom
| ZoneLeft
;
2557 else if (be
->window
== frame
.right_grip
)
2558 resize_zone
= ZoneBottom
| ZoneRight
;
2561 } else if (be
->state
== 0 && be
->button
== 2) {
2562 if (be
->window
== frame
.maximize_button
) {
2563 redrawMaximizeButton(True
);
2564 // a middle click anywhere on the window's frame except for on the buttons
2565 // will lower the window
2566 } else if (! (be
->window
== frame
.iconify_button
||
2567 be
->window
== frame
.close_button
) ) {
2571 } else if (be
->state
== 0 && be
->button
== 3) {
2572 if (be
->window
== frame
.maximize_button
) {
2573 redrawMaximizeButton(True
);
2574 // a right click on the window's frame will show or hide the window's
2576 } else if (be
->window
== frame
.title
||
2577 be
->window
== frame
.label
||
2578 be
->window
== frame
.handle
||
2579 be
->window
== frame
.window
) {
2582 if (windowmenu
->isVisible()) {
2585 // get the coords for the menu
2586 mx
= be
->x_root
- windowmenu
->getWidth() / 2;
2587 if (be
->window
== frame
.title
|| be
->window
== frame
.label
) {
2588 my
= frame
.y
+ frame
.title_h
;
2589 } else if (be
->window
== frame
.handle
) {
2590 my
= frame
.y
+ frame
.y_handle
- windowmenu
->getHeight();
2591 } else { // (be->window == frame.window)
2592 if (be
->y
<= (signed) frame
.bevel_w
) {
2593 my
= frame
.y
+ frame
.y_border
;
2595 my
= be
->y_root
- (windowmenu
->getHeight() / 2);
2599 if (mx
> (signed) (frame
.x
+ frame
.width
-
2600 windowmenu
->getWidth())) {
2601 mx
= frame
.x
+ frame
.width
- windowmenu
->getWidth();
2602 } else if (mx
< frame
.x
) {
2606 if (my
> (signed) (frame
.y
+ frame
.y_handle
-
2607 windowmenu
->getHeight())) {
2608 my
= frame
.y
+ frame
.y_handle
- windowmenu
->getHeight();
2609 } else if (my
< (signed) (frame
.y
+
2610 ((decorations
.titlebar
) ? frame
.title_h
: frame
.y_border
))) {
2612 ((decorations
.titlebar
) ? frame
.title_h
: frame
.y_border
);
2615 windowmenu
->move(mx
, my
);
2617 XRaiseWindow(display
, windowmenu
->getWindowID());
2618 XRaiseWindow(display
, windowmenu
->getSendToMenu()->getWindowID());
2619 stack_change
= 0; // dont raise the window overtop of the menu
2624 } else if (be
->state
== 0 && be
->button
== 4) {
2625 if ((be
->window
== frame
.label
||
2626 be
->window
== frame
.title
) &&
2630 } else if (be
->state
== 0 && be
->button
== 5) {
2631 if ((be
->window
== frame
.label
||
2632 be
->window
== frame
.title
) &&
2637 if (! (flags
.focused
|| screen
->sloppyFocus()) ) {
2638 setInputFocus(); // any click focus' the window in 'click to focus'
2640 if (stack_change
< 0) {
2641 screen
->getWorkspace(workspace_number
)->lowerWindow(this);
2642 } else if (stack_change
> 0) {
2643 screen
->getWorkspace(workspace_number
)->raiseWindow(this);
2650 void OpenboxWindow::buttonReleaseEvent(XButtonEvent
*re
) {
2652 if (! validateClient())
2655 // alt + middle button released
2656 if (re
->state
== (Mod1Mask
& Button2Mask
) && re
->button
== 2) {
2657 if (re
->window
== frame
.window
) {
2658 XUngrabPointer(display
, CurrentTime
); // why? i dont know
2660 // left button released
2661 } else if (re
->button
== 1) {
2662 if (re
->window
== frame
.maximize_button
) {
2663 if (re
->state
== Button1Mask
&& // only the left button was depressed
2664 (re
->x
>= 0) && ((unsigned) re
->x
<= frame
.button_w
) &&
2665 (re
->y
>= 0) && ((unsigned) re
->y
<= frame
.button_h
)) {
2666 maximize(re
->button
);
2668 redrawMaximizeButton(False
);
2670 } else if (re
->window
== frame
.iconify_button
) {
2671 if (re
->state
== Button1Mask
&& // only the left button was depressed
2672 (re
->x
>= 0) && ((unsigned) re
->x
<= frame
.button_w
) &&
2673 (re
->y
>= 0) && ((unsigned) re
->y
<= frame
.button_h
)) {
2676 redrawIconifyButton(False
);
2678 } else if (re
->window
== frame
.close_button
) {
2679 if (re
->state
== Button1Mask
&& // only the left button was depressed
2680 (re
->x
>= 0) && ((unsigned) re
->x
<= frame
.button_w
) &&
2681 (re
->y
>= 0) && ((unsigned) re
->y
<= frame
.button_h
)) {
2684 //we should always redraw the close button. some applications
2685 //eg. acroread don't honour the close.
2686 redrawCloseButton(False
);
2688 // middle button released
2689 } else if (re
->button
== 2) {
2690 if (re
->window
== frame
.maximize_button
) {
2691 if (re
->state
== Button2Mask
&& // only the middle button was depressed
2692 (re
->x
>= 0) && ((unsigned) re
->x
<= frame
.button_w
) &&
2693 (re
->y
>= 0) && ((unsigned) re
->y
<= frame
.button_h
)) {
2694 maximize(re
->button
);
2696 redrawMaximizeButton(False
);
2699 // right button released
2700 } else if (re
->button
== 3) {
2701 if (re
->window
== frame
.maximize_button
) {
2702 if (re
->state
== Button3Mask
&& // only the right button was depressed
2703 (re
->x
>= 0) && ((unsigned) re
->x
<= frame
.button_w
) &&
2704 (re
->y
>= 0) && ((unsigned) re
->y
<= frame
.button_h
)) {
2705 maximize(re
->button
);
2707 redrawMaximizeButton(False
);
2712 // when the window is being interactively moved, a button release stops the
2716 // when the window is being interactively resized, a button release stops the
2718 } else if (flags
.resizing
) {
2719 flags
.resizing
= False
;
2720 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2721 frame
.resize_x
, frame
.resize_y
,
2722 frame
.resize_w
- 1, frame
.resize_h
- 1);
2723 screen
->hideGeometry();
2724 if (resize_zone
& ZoneLeft
) {
2726 } else { // when resizing with "Alt+Button3", the resize is the same as if
2727 // done with the right grip (the right side of the window is what
2731 // unset maximized state when resized after fully maximized
2732 if (flags
.maximized
== 1) {
2735 configure(frame
.resize_x
, frame
.resize_y
,
2736 frame
.resize_w
- (frame
.border_w
* 2),
2737 frame
.resize_h
- (frame
.border_w
* 2));
2739 XUngrabPointer(display
, CurrentTime
);
2747 void OpenboxWindow::startMove(int x
, int y
) {
2748 ASSERT(!flags
.moving
);
2750 // make sure only one window is moving at a time
2751 OpenboxWindow
*w
= openbox
.getMaskedWindow();
2752 if (w
!= (OpenboxWindow
*) 0 && w
->flags
.moving
)
2755 XGrabPointer(display
, frame
.window
, False
, PointerMotionMask
|
2756 ButtonReleaseMask
, GrabModeAsync
, GrabModeAsync
,
2757 None
, openbox
.getMoveCursor(), CurrentTime
);
2759 if (windowmenu
&& windowmenu
->isVisible())
2762 flags
.moving
= True
;
2764 openbox
.maskWindowEvents(client
.window
, this);
2766 if (! screen
->opaqueMove()) {
2769 frame
.move_x
= frame
.x
;
2770 frame
.move_y
= frame
.y
;
2771 frame
.resize_w
= frame
.width
+ (frame
.border_w
* 2);
2772 frame
.resize_h
= ((flags
.shaded
) ? frame
.title_h
: frame
.height
) +
2773 (frame
.border_w
* 2);
2775 screen
->showPosition(frame
.x
, frame
.y
);
2777 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2778 frame
.move_x
, frame
.move_y
,
2779 frame
.resize_w
- 1, frame
.resize_h
- 1);
2781 frame
.grab_x
= x
- frame
.x
- frame
.border_w
;
2782 frame
.grab_y
= y
- frame
.y
- frame
.border_w
;
2786 void OpenboxWindow::doMove(int x
, int y
) {
2787 ASSERT(flags
.moving
);
2789 int dx
= x
- frame
.grab_x
, dy
= y
- frame
.grab_y
;
2791 dx
-= frame
.border_w
;
2792 dy
-= frame
.border_w
;
2794 int snap_distance
= screen
->edgeSnapThreshold();
2795 // width/height of the snapping window
2796 unsigned int snap_w
= frame
.width
+ (frame
.border_w
* 2);
2797 unsigned int snap_h
= area().h() + (frame
.border_w
* 2);
2798 if (snap_distance
) {
2799 int drx
= screen
->size().w() - (dx
+ snap_w
);
2801 if (dx
< drx
&& (dx
> 0 && dx
< snap_distance
) ||
2802 (dx
< 0 && dx
> -snap_distance
) )
2804 else if ( (drx
> 0 && drx
< snap_distance
) ||
2805 (drx
< 0 && drx
> -snap_distance
) )
2806 dx
= screen
->size().w() - snap_w
;
2808 int dtty
, dbby
, dty
, dby
;
2809 switch (screen
->getToolbar()->placement()) {
2810 case Toolbar::TopLeft
:
2811 case Toolbar::TopCenter
:
2812 case Toolbar::TopRight
:
2813 dtty
= screen
->getToolbar()->getExposedHeight() +
2815 dbby
= screen
->size().h();
2820 dbby
= screen
->getToolbar()->area().y();
2825 dby
= dbby
- (dy
+ snap_h
);
2827 if ( (dy
> 0 && dty
< snap_distance
) ||
2828 (dy
< 0 && dty
> -snap_distance
) )
2830 else if ( (dby
> 0 && dby
< snap_distance
) ||
2831 (dby
< 0 && dby
> -snap_distance
) )
2835 if (screen
->opaqueMove()) {
2836 configure(dx
, dy
, frame
.width
, frame
.height
);
2838 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2839 frame
.move_x
, frame
.move_y
, frame
.resize_w
- 1,
2840 frame
.resize_h
- 1);
2845 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2846 frame
.move_x
, frame
.move_y
, frame
.resize_w
- 1,
2847 frame
.resize_h
- 1);
2850 screen
->showPosition(dx
, dy
);
2854 void OpenboxWindow::endMove() {
2855 ASSERT(flags
.moving
);
2857 flags
.moving
= False
;
2859 openbox
.maskWindowEvents(0, (OpenboxWindow
*) 0);
2860 if (!screen
->opaqueMove()) {
2861 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2862 frame
.move_x
, frame
.move_y
, frame
.resize_w
- 1,
2863 frame
.resize_h
- 1);
2865 configure(frame
.move_x
, frame
.move_y
, frame
.width
, frame
.height
);
2868 configure(frame
.x
, frame
.y
, frame
.width
, frame
.height
);
2870 screen
->hideGeometry();
2871 XUngrabPointer(display
, CurrentTime
);
2872 // if there are any left over motions from the move, drop them now cuz they
2875 while (XCheckTypedWindowEvent(display
, frame
.window
, MotionNotify
, &e
));
2879 void OpenboxWindow::motionNotifyEvent(XMotionEvent
*me
) {
2881 doMove(me
->x_root
, me
->y_root
);
2882 else if (!flags
.resizing
&& (me
->state
& Button1Mask
) && functions
.move
&&
2883 (frame
.title
== me
->window
|| frame
.label
== me
->window
||
2884 frame
.handle
== me
->window
|| frame
.window
== me
->window
))
2885 startMove(me
->x_root
, me
->y_root
);
2886 else if (functions
.resize
&&
2887 (((me
->state
& Button1Mask
) && (me
->window
== frame
.right_grip
||
2888 me
->window
== frame
.left_grip
)) ||
2889 (me
->state
== (Mod1Mask
| Button3Mask
) &&
2890 me
->window
== frame
.window
))) {
2891 Bool left
= resize_zone
& ZoneLeft
;
2893 if (! flags
.resizing
) {
2895 if (resize_zone
& ZoneTop
)
2896 cursor
= (resize_zone
& ZoneLeft
) ?
2897 openbox
.getUpperLeftAngleCursor() :
2898 openbox
.getUpperRightAngleCursor();
2900 cursor
= (resize_zone
& ZoneLeft
) ?
2901 openbox
.getLowerLeftAngleCursor() :
2902 openbox
.getLowerRightAngleCursor();
2903 XGrabPointer(display
, me
->window
, False
, ButtonMotionMask
|
2904 ButtonReleaseMask
, GrabModeAsync
, GrabModeAsync
, None
,
2905 cursor
, CurrentTime
);
2907 flags
.resizing
= True
;
2912 if (resize_zone
& ZoneRight
)
2913 frame
.grab_x
= me
->x
- screen
->getBorderWidth();
2915 frame
.grab_x
= me
->x
+ screen
->getBorderWidth();
2916 if (resize_zone
& ZoneTop
)
2917 frame
.grab_y
= me
->y
+ screen
->getBorderWidth() * 2;
2919 frame
.grab_y
= me
->y
- screen
->getBorderWidth() * 2;
2920 frame
.resize_x
= frame
.x
;
2921 frame
.resize_y
= frame
.y
;
2922 frame
.resize_w
= frame
.width
+ (frame
.border_w
* 2);
2923 frame
.resize_h
= frame
.height
+ (frame
.border_w
* 2);
2926 left_fixsize(&gx
, &gy
);
2928 right_fixsize(&gx
, &gy
);
2930 screen
->showGeometry(gx
, gy
);
2932 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2933 frame
.resize_x
, frame
.resize_y
,
2934 frame
.resize_w
- 1, frame
.resize_h
- 1);
2936 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2937 frame
.resize_x
, frame
.resize_y
,
2938 frame
.resize_w
- 1, frame
.resize_h
- 1);
2942 if (resize_zone
& ZoneTop
)
2943 frame
.resize_h
= frame
.height
- (me
->y
- frame
.grab_y
);
2945 frame
.resize_h
= frame
.height
+ (me
->y
- frame
.grab_y
);
2946 if (frame
.resize_h
< 1) frame
.resize_h
= 1;
2949 frame
.resize_x
= me
->x_root
- frame
.grab_x
;
2950 if (frame
.resize_x
> (signed) (frame
.x
+ frame
.width
))
2951 frame
.resize_x
= frame
.resize_x
+ frame
.width
- 1;
2953 left_fixsize(&gx
, &gy
);
2955 frame
.resize_w
= frame
.width
+ (me
->x
- frame
.grab_x
);
2956 if (frame
.resize_w
< 1) frame
.resize_w
= 1;
2958 right_fixsize(&gx
, &gy
);
2961 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2962 frame
.resize_x
, frame
.resize_y
,
2963 frame
.resize_w
- 1, frame
.resize_h
- 1);
2965 screen
->showGeometry(gx
, gy
);
2972 void OpenboxWindow::shapeEvent(XShapeEvent
*) {
2973 if (openbox
.hasShapeExtensions()) {
2976 if (! validateClient()) return;
2977 XShapeCombineShape(display
, frame
.window
, ShapeBounding
,
2978 frame
.mwm_border_w
, frame
.y_border
+
2979 frame
.mwm_border_w
, client
.window
,
2980 ShapeBounding
, ShapeSet
);
2983 XRectangle xrect
[2];
2984 xrect
[0].x
= xrect
[0].y
= 0;
2985 xrect
[0].width
= frame
.width
;
2986 xrect
[0].height
= frame
.y_border
;
2988 if (decorations
.handle
) {
2990 xrect
[1].y
= frame
.y_handle
;
2991 xrect
[1].width
= frame
.width
;
2992 xrect
[1].height
= frame
.handle_h
+ frame
.border_w
;
2996 XShapeCombineRectangles(display
, frame
.window
, ShapeBounding
, 0, 0,
2997 xrect
, num
, ShapeUnion
, Unsorted
);
3005 bool OpenboxWindow::validateClient(void) {
3006 XSync(display
, False
);
3009 if (XCheckTypedWindowEvent(display
, client
.window
, DestroyNotify
, &e
) ||
3010 XCheckTypedWindowEvent(display
, client
.window
, UnmapNotify
, &e
)) {
3011 XPutBackEvent(display
, &e
);
3021 void OpenboxWindow::restore(void) {
3022 XChangeSaveSet(display
, client
.window
, SetModeDelete
);
3023 XSelectInput(display
, client
.window
, NoEventMask
);
3027 XUnmapWindow(display
, frame
.window
);
3028 XUnmapWindow(display
, client
.window
);
3030 XSetWindowBorderWidth(display
, client
.window
, client
.old_bw
);
3031 XReparentWindow(display
, client
.window
, screen
->getRootWindow(),
3032 client
.x
, client
.y
);
3033 XMapWindow(display
, client
.window
);
3041 void OpenboxWindow::timeout(void) {
3042 screen
->getWorkspace(workspace_number
)->raiseWindow(this);
3046 void OpenboxWindow::changeOpenboxHints(OpenboxHints
*net
) {
3047 if ((net
->flags
& AttribShaded
) &&
3048 ((openbox_attrib
.attrib
& AttribShaded
) !=
3049 (net
->attrib
& AttribShaded
)))
3052 if (flags
.visible
&& // watch out for requests when we can not be seen
3053 (net
->flags
& (AttribMaxVert
| AttribMaxHoriz
)) &&
3054 ((openbox_attrib
.attrib
& (AttribMaxVert
| AttribMaxHoriz
)) !=
3055 (net
->attrib
& (AttribMaxVert
| AttribMaxHoriz
)))) {
3056 if (flags
.maximized
) {
3061 if ((net
->flags
& AttribMaxHoriz
) && (net
->flags
& AttribMaxVert
))
3062 button
= ((net
->attrib
& (AttribMaxHoriz
| AttribMaxVert
)) ? 1 : 0);
3063 else if (net
->flags
& AttribMaxVert
)
3064 button
= ((net
->attrib
& AttribMaxVert
) ? 2 : 0);
3065 else if (net
->flags
& AttribMaxHoriz
)
3066 button
= ((net
->attrib
& AttribMaxHoriz
) ? 3 : 0);
3072 if ((net
->flags
& AttribOmnipresent
) &&
3073 ((openbox_attrib
.attrib
& AttribOmnipresent
) !=
3074 (net
->attrib
& AttribOmnipresent
)))
3077 if ((net
->flags
& AttribWorkspace
) &&
3078 (workspace_number
!= (signed) net
->workspace
)) {
3079 screen
->reassociateWindow(this, net
->workspace
, True
);
3081 if (screen
->getCurrentWorkspaceID() != (signed) net
->workspace
) withdraw();
3085 if (net
->flags
& AttribDecoration
) {
3086 switch (net
->decoration
) {
3088 decorations
.titlebar
= decorations
.border
= decorations
.handle
=
3089 decorations
.iconify
= decorations
.maximize
= decorations
.menu
= False
;
3095 decorations
.titlebar
= decorations
.iconify
= decorations
.menu
=
3096 decorations
.border
= True
;
3097 decorations
.handle
= (functions
.resize
&& !flags
.transient
);
3098 decorations
.maximize
= functions
.maximize
;
3103 decorations
.titlebar
= decorations
.iconify
= decorations
.menu
= True
;
3104 decorations
.border
= decorations
.border
= decorations
.handle
= False
;
3105 decorations
.maximize
= functions
.maximize
;
3110 decorations
.titlebar
= decorations
.menu
= True
;
3111 decorations
.iconify
= decorations
.border
= False
;
3112 decorations
.handle
= (functions
.resize
&& !flags
.transient
);
3113 decorations
.maximize
= functions
.maximize
;
3118 XMapSubwindows(display
, frame
.window
);
3119 XMapWindow(display
, frame
.window
);
3123 setState(current_state
);
3129 * Set the sizes of all components of the window frame
3130 * (the window decorations).
3131 * These values are based upon the current style settings and the client
3132 * window's dimentions.
3134 void OpenboxWindow::upsize(void) {
3135 frame
.bevel_w
= screen
->getBevelWidth();
3137 if (decorations
.border
) {
3138 frame
.border_w
= screen
->getBorderWidth();
3139 if (!flags
.transient
)
3140 frame
.mwm_border_w
= screen
->getFrameWidth();
3142 frame
.mwm_border_w
= 0;
3144 frame
.mwm_border_w
= frame
.border_w
= 0;
3147 if (decorations
.titlebar
) {
3148 // the height of the titlebar is based upon the height of the font being
3149 // used to display the window's title
3150 WindowStyle
*style
= screen
->getWindowStyle();
3151 if (i18n
->multibyte())
3152 frame
.title_h
= (style
->fontset_extents
->max_ink_extent
.height
+
3153 (frame
.bevel_w
* 2) + 2);
3155 frame
.title_h
= (style
->font
->ascent
+ style
->font
->descent
+
3156 (frame
.bevel_w
* 2) + 2);
3158 frame
.label_h
= frame
.title_h
- (frame
.bevel_w
* 2);
3159 frame
.button_w
= frame
.button_h
= (frame
.label_h
- 2);
3160 frame
.y_border
= frame
.title_h
+ frame
.border_w
;
3164 frame
.button_w
= frame
.button_h
= 0;
3168 frame
.border_h
= client
.height
+ frame
.mwm_border_w
* 2;
3170 if (decorations
.handle
) {
3171 frame
.y_handle
= frame
.y_border
+ frame
.border_h
+ frame
.border_w
;
3172 frame
.grip_w
= frame
.button_w
* 2;
3173 frame
.grip_h
= frame
.handle_h
= screen
->getHandleWidth();
3175 frame
.y_handle
= frame
.y_border
+ frame
.border_h
;
3177 frame
.grip_w
= frame
.grip_h
= 0;
3180 frame
.width
= client
.width
+ (frame
.mwm_border_w
* 2);
3181 frame
.height
= frame
.y_handle
+ frame
.handle_h
;
3186 * Set the size and position of the client window.
3187 * These values are based upon the current style settings and the frame
3188 * window's dimensions.
3190 void OpenboxWindow::downsize(void) {
3191 frame
.y_handle
= frame
.height
- frame
.handle_h
;
3192 frame
.border_h
= frame
.y_handle
- frame
.y_border
-
3193 (decorations
.handle
? frame
.border_w
: 0);
3195 client
.x
= frame
.x
+ frame
.mwm_border_w
+ frame
.border_w
;
3196 client
.y
= frame
.y
+ frame
.y_border
+ frame
.mwm_border_w
+ frame
.border_w
;
3198 client
.width
= frame
.width
- (frame
.mwm_border_w
* 2);
3199 client
.height
= frame
.height
- frame
.y_border
- (frame
.mwm_border_w
* 2)
3200 - frame
.handle_h
- (decorations
.handle
? frame
.border_w
: 0);
3202 frame
.y_handle
= frame
.border_h
+ frame
.y_border
+ frame
.border_w
;
3206 void OpenboxWindow::right_fixsize(int *gx
, int *gy
) {
3207 // calculate the size of the client window and conform it to the
3208 // size specified by the size hints of the client window...
3209 int dx
= 1 + frame
.resize_w
- client
.base_width
- (frame
.mwm_border_w
* 2) -
3210 (frame
.border_w
* 2) + (client
.width_inc
/ 2);
3211 int dy
= 1 + frame
.resize_h
- frame
.y_border
- client
.base_height
-
3212 frame
.handle_h
- (frame
.border_w
* 3) - (frame
.mwm_border_w
* 2)
3213 + (client
.height_inc
/ 2);
3215 if (dx
< (signed) client
.min_width
) dx
= client
.min_width
;
3216 if (dy
< (signed) client
.min_height
) dy
= client
.min_height
;
3217 if ((unsigned) dx
> client
.max_width
) dx
= client
.max_width
;
3218 if ((unsigned) dy
> client
.max_height
) dy
= client
.max_height
;
3220 dx
/= client
.width_inc
;
3221 dy
/= client
.height_inc
;
3226 dx
= (dx
* client
.width_inc
) + client
.base_width
;
3227 dy
= (dy
* client
.height_inc
) + client
.base_height
;
3229 frame
.resize_w
= dx
+ (frame
.mwm_border_w
* 2) + (frame
.border_w
* 2) - 1;
3230 frame
.resize_h
= dy
+ frame
.y_border
+ frame
.handle_h
+
3231 (frame
.mwm_border_w
* 2) + (frame
.border_w
* 3) - 1;
3232 if (resize_zone
& ZoneTop
)
3233 frame
.resize_y
= frame
.y
+ frame
.height
- frame
.resize_h
+
3234 screen
->getBorderWidth() * 2;
3238 void OpenboxWindow::left_fixsize(int *gx
, int *gy
) {
3239 // calculate the size of the client window and conform it to the
3240 // size specified by the size hints of the client window...
3241 int dx
= 1 + frame
.x
+ frame
.width
- frame
.resize_x
- client
.base_width
-
3242 (frame
.mwm_border_w
* 2) + (client
.width_inc
/ 2);
3243 int dy
= 1 + frame
.resize_h
- frame
.y_border
- client
.base_height
-
3244 frame
.handle_h
- (frame
.border_w
* 3) - (frame
.mwm_border_w
* 2)
3245 + (client
.height_inc
/ 2);
3247 if (dx
< (signed) client
.min_width
) dx
= client
.min_width
;
3248 if (dy
< (signed) client
.min_height
) dy
= client
.min_height
;
3249 if ((unsigned) dx
> client
.max_width
) dx
= client
.max_width
;
3250 if ((unsigned) dy
> client
.max_height
) dy
= client
.max_height
;
3252 dx
/= client
.width_inc
;
3253 dy
/= client
.height_inc
;
3258 dx
= (dx
* client
.width_inc
) + client
.base_width
;
3259 dy
= (dy
* client
.height_inc
) + client
.base_height
;
3261 frame
.resize_w
= dx
+ (frame
.mwm_border_w
* 2) + (frame
.border_w
* 2) - 1;
3262 frame
.resize_x
= frame
.x
+ frame
.width
- frame
.resize_w
+
3263 (frame
.border_w
* 2);
3264 frame
.resize_h
= dy
+ frame
.y_border
+ frame
.handle_h
+
3265 (frame
.mwm_border_w
* 2) + (frame
.border_w
* 3) - 1;
3266 if (resize_zone
& ZoneTop
)
3267 frame
.resize_y
= frame
.y
+ frame
.height
- frame
.resize_h
+
3268 screen
->getBorderWidth() * 2;