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();
851 void OpenboxWindow::positionWindows(void) {
852 XResizeWindow(display
, frame
.window
, frame
.width
,
853 ((flags
.shaded
) ? frame
.title_h
: frame
.height
));
854 XSetWindowBorderWidth(display
, frame
.window
, frame
.border_w
);
855 XSetWindowBorderWidth(display
, frame
.plate
, frame
.mwm_border_w
);
856 XMoveResizeWindow(display
, frame
.plate
, 0, frame
.y_border
,
857 client
.width
, client
.height
);
858 XMoveResizeWindow(display
, client
.window
, 0, 0, client
.width
, client
.height
);
860 if (decorations
.titlebar
) {
861 XSetWindowBorderWidth(display
, frame
.title
, frame
.border_w
);
862 XMoveResizeWindow(display
, frame
.title
, -frame
.border_w
,
863 -frame
.border_w
, frame
.width
, frame
.title_h
);
866 } else if (frame
.title
) {
867 XUnmapWindow(display
, frame
.title
);
869 if (decorations
.handle
) {
870 XSetWindowBorderWidth(display
, frame
.handle
, frame
.border_w
);
871 XSetWindowBorderWidth(display
, frame
.left_grip
, frame
.border_w
);
872 XSetWindowBorderWidth(display
, frame
.right_grip
, frame
.border_w
);
874 XMoveResizeWindow(display
, frame
.handle
, -frame
.border_w
,
875 frame
.y_handle
- frame
.border_w
,
876 frame
.width
, frame
.handle_h
);
877 XMoveResizeWindow(display
, frame
.left_grip
, -frame
.border_w
,
878 -frame
.border_w
, frame
.grip_w
, frame
.grip_h
);
879 XMoveResizeWindow(display
, frame
.right_grip
,
880 frame
.width
- frame
.grip_w
- frame
.border_w
,
881 -frame
.border_w
, frame
.grip_w
, frame
.grip_h
);
882 XMapSubwindows(display
, frame
.handle
);
883 } else if (frame
.handle
) {
884 XUnmapWindow(display
, frame
.handle
);
889 void OpenboxWindow::getWMName(void) {
891 delete [] client
.title
;
892 client
.title
= (char *) 0;
895 XTextProperty text_prop
;
899 if (XGetWMName(display
, client
.window
, &text_prop
)) {
900 if (text_prop
.value
&& text_prop
.nitems
> 0) {
901 if (text_prop
.encoding
!= XA_STRING
) {
902 text_prop
.nitems
= strlen((char *) text_prop
.value
);
904 if ((XmbTextPropertyToTextList(display
, &text_prop
,
905 &list
, &num
) == Success
) &&
906 (num
> 0) && *list
) {
907 client
.title
= bstrdup(*list
);
908 XFreeStringList(list
);
910 client
.title
= bstrdup((char *) text_prop
.value
);
913 client
.title
= bstrdup((char *) text_prop
.value
);
915 XFree((char *) text_prop
.value
);
917 client
.title
= bstrdup(i18n
->getMessage(WindowSet
, WindowUnnamed
,
921 client
.title
= bstrdup(i18n
->getMessage(WindowSet
, WindowUnnamed
,
924 client
.title_len
= strlen(client
.title
);
926 if (i18n
->multibyte()) {
927 XRectangle ink
, logical
;
928 XmbTextExtents(screen
->getWindowStyle()->fontset
,
929 client
.title
, client
.title_len
, &ink
, &logical
);
930 client
.title_text_w
= logical
.width
;
932 client
.title_len
= strlen(client
.title
);
933 client
.title_text_w
= XTextWidth(screen
->getWindowStyle()->font
,
934 client
.title
, client
.title_len
);
937 client
.title_text_w
+= (frame
.bevel_w
* 4);
941 void OpenboxWindow::getWMIconName(void) {
942 if (client
.icon_title
) {
943 delete [] client
.icon_title
;
944 client
.icon_title
= (char *) 0;
947 XTextProperty text_prop
;
951 if (XGetWMIconName(display
, client
.window
, &text_prop
)) {
952 if (text_prop
.value
&& text_prop
.nitems
> 0) {
953 if (text_prop
.encoding
!= XA_STRING
) {
954 text_prop
.nitems
= strlen((char *) text_prop
.value
);
956 if ((XmbTextPropertyToTextList(display
, &text_prop
,
957 &list
, &num
) == Success
) &&
958 (num
> 0) && *list
) {
959 client
.icon_title
= bstrdup(*list
);
960 XFreeStringList(list
);
962 client
.icon_title
= bstrdup((char *) text_prop
.value
);
965 client
.icon_title
= bstrdup((char *) text_prop
.value
);
967 XFree((char *) text_prop
.value
);
969 client
.icon_title
= bstrdup(client
.title
);
972 client
.icon_title
= bstrdup(client
.title
);
978 * Retrieve which WM Protocols are supported by the client window.
979 * If the WM_DELETE_WINDOW protocol is supported, add the close button to the
980 * window's decorations and allow the close behavior.
981 * If the WM_TAKE_FOCUS protocol is supported, save a value that indicates
984 void OpenboxWindow::getWMProtocols(void) {
988 if (XGetWMProtocols(display
, client
.window
, &proto
, &num_return
)) {
989 for (int i
= 0; i
< num_return
; ++i
) {
990 if (proto
[i
] == openbox
.getWMDeleteAtom())
991 functions
.close
= decorations
.close
= True
;
992 else if (proto
[i
] == openbox
.getWMTakeFocusAtom())
993 flags
.send_focus_message
= True
;
994 else if (proto
[i
] == openbox
.getOpenboxStructureMessagesAtom())
995 screen
->addNetizen(new Netizen(*screen
, client
.window
));
1004 * Gets the value of the WM_HINTS property.
1005 * If the property is not set, then use a set of default values.
1007 void OpenboxWindow::getWMHints(void) {
1008 XWMHints
*wmhint
= XGetWMHints(display
, client
.window
);
1010 flags
.visible
= True
;
1011 flags
.iconic
= False
;
1012 focus_mode
= F_Passive
;
1013 client
.window_group
= None
;
1014 client
.initial_state
= NormalState
;
1017 client
.wm_hint_flags
= wmhint
->flags
;
1018 if (wmhint
->flags
& InputHint
) {
1019 if (wmhint
->input
== True
) {
1020 if (flags
.send_focus_message
)
1021 focus_mode
= F_LocallyActive
;
1023 focus_mode
= F_Passive
;
1025 if (flags
.send_focus_message
)
1026 focus_mode
= F_GloballyActive
;
1028 focus_mode
= F_NoInput
;
1031 focus_mode
= F_Passive
;
1034 if (wmhint
->flags
& StateHint
)
1035 client
.initial_state
= wmhint
->initial_state
;
1037 client
.initial_state
= NormalState
;
1039 if (wmhint
->flags
& WindowGroupHint
) {
1040 if (! client
.window_group
) {
1041 client
.window_group
= wmhint
->window_group
;
1042 openbox
.saveGroupSearch(client
.window_group
, this);
1045 client
.window_group
= None
;
1052 * Gets the value of the WM_NORMAL_HINTS property.
1053 * If the property is not set, then use a set of default values.
1055 void OpenboxWindow::getWMNormalHints(void) {
1057 XSizeHints sizehint
;
1059 client
.min_width
= client
.min_height
=
1060 client
.base_width
= client
.base_height
=
1061 client
.width_inc
= client
.height_inc
= 1;
1062 client
.max_width
= screen
->size().w();
1063 client
.max_height
= screen
->size().h();
1064 client
.min_aspect_x
= client
.min_aspect_y
=
1065 client
.max_aspect_x
= client
.max_aspect_y
= 1;
1066 client
.win_gravity
= NorthWestGravity
;
1068 if (! XGetWMNormalHints(display
, client
.window
, &sizehint
, &icccm_mask
))
1071 client
.normal_hint_flags
= sizehint
.flags
;
1073 if (sizehint
.flags
& PMinSize
) {
1074 client
.min_width
= sizehint
.min_width
;
1075 client
.min_height
= sizehint
.min_height
;
1078 if (sizehint
.flags
& PMaxSize
) {
1079 client
.max_width
= sizehint
.max_width
;
1080 client
.max_height
= sizehint
.max_height
;
1083 if (sizehint
.flags
& PResizeInc
) {
1084 client
.width_inc
= sizehint
.width_inc
;
1085 client
.height_inc
= sizehint
.height_inc
;
1088 if (sizehint
.flags
& PAspect
) {
1089 client
.min_aspect_x
= sizehint
.min_aspect
.x
;
1090 client
.min_aspect_y
= sizehint
.min_aspect
.y
;
1091 client
.max_aspect_x
= sizehint
.max_aspect
.x
;
1092 client
.max_aspect_y
= sizehint
.max_aspect
.y
;
1095 if (sizehint
.flags
& PBaseSize
) {
1096 client
.base_width
= sizehint
.base_width
;
1097 client
.base_height
= sizehint
.base_height
;
1100 if (sizehint
.flags
& PWinGravity
)
1101 client
.win_gravity
= sizehint
.win_gravity
;
1106 * Gets the MWM hints for the class' contained window.
1107 * This is used while initializing the window to its first state, and not
1109 * Returns: true if the MWM hints are successfully retreived and applied; false
1112 void OpenboxWindow::getMWMHints(void) {
1115 unsigned long num
, len
;
1117 int ret
= XGetWindowProperty(display
, client
.window
,
1118 openbox
.getMotifWMHintsAtom(), 0,
1119 PropMwmHintsElements
, False
,
1120 openbox
.getMotifWMHintsAtom(), &atom_return
,
1121 &format
, &num
, &len
,
1122 (unsigned char **) &client
.mwm_hint
);
1124 if (ret
!= Success
|| !client
.mwm_hint
|| num
!= PropMwmHintsElements
)
1127 if (client
.mwm_hint
->flags
& MwmHintsDecorations
) {
1128 if (client
.mwm_hint
->decorations
& MwmDecorAll
) {
1129 decorations
.titlebar
= decorations
.handle
= decorations
.border
=
1130 decorations
.iconify
= decorations
.maximize
=
1131 decorations
.close
= decorations
.menu
= True
;
1133 decorations
.titlebar
= decorations
.handle
= decorations
.border
=
1134 decorations
.iconify
= decorations
.maximize
=
1135 decorations
.close
= decorations
.menu
= False
;
1137 if (client
.mwm_hint
->decorations
& MwmDecorBorder
)
1138 decorations
.border
= True
;
1139 if (client
.mwm_hint
->decorations
& MwmDecorHandle
)
1140 decorations
.handle
= True
;
1141 if (client
.mwm_hint
->decorations
& MwmDecorTitle
)
1142 decorations
.titlebar
= True
;
1143 if (client
.mwm_hint
->decorations
& MwmDecorMenu
)
1144 decorations
.menu
= True
;
1145 if (client
.mwm_hint
->decorations
& MwmDecorIconify
)
1146 decorations
.iconify
= True
;
1147 if (client
.mwm_hint
->decorations
& MwmDecorMaximize
)
1148 decorations
.maximize
= True
;
1152 if (client
.mwm_hint
->flags
& MwmHintsFunctions
) {
1153 if (client
.mwm_hint
->functions
& MwmFuncAll
) {
1154 functions
.resize
= functions
.move
= functions
.iconify
=
1155 functions
.maximize
= functions
.close
= True
;
1157 functions
.resize
= functions
.move
= functions
.iconify
=
1158 functions
.maximize
= functions
.close
= False
;
1160 if (client
.mwm_hint
->functions
& MwmFuncResize
)
1161 functions
.resize
= True
;
1162 if (client
.mwm_hint
->functions
& MwmFuncMove
)
1163 functions
.move
= True
;
1164 if (client
.mwm_hint
->functions
& MwmFuncIconify
)
1165 functions
.iconify
= True
;
1166 if (client
.mwm_hint
->functions
& MwmFuncMaximize
)
1167 functions
.maximize
= True
;
1168 if (client
.mwm_hint
->functions
& MwmFuncClose
)
1169 functions
.close
= True
;
1176 * Gets the openbox hints from the class' contained window.
1177 * This is used while initializing the window to its first state, and not
1179 * Returns: true if the hints are successfully retreived and applied; false if
1182 void OpenboxWindow::getOpenboxHints(void) {
1185 unsigned long num
, len
;
1187 int ret
= XGetWindowProperty(display
, client
.window
,
1188 openbox
.getOpenboxHintsAtom(), 0,
1189 PropOpenboxHintsElements
, False
,
1190 openbox
.getOpenboxHintsAtom(), &atom_return
,
1191 &format
, &num
, &len
,
1192 (unsigned char **) &client
.openbox_hint
);
1193 if (ret
!= Success
|| !client
.openbox_hint
||
1194 num
!= PropOpenboxHintsElements
)
1197 if (client
.openbox_hint
->flags
& AttribShaded
)
1198 flags
.shaded
= (client
.openbox_hint
->attrib
& AttribShaded
);
1200 if ((client
.openbox_hint
->flags
& AttribMaxHoriz
) &&
1201 (client
.openbox_hint
->flags
& AttribMaxVert
))
1202 flags
.maximized
= (client
.openbox_hint
->attrib
&
1203 (AttribMaxHoriz
| AttribMaxVert
)) ? 1 : 0;
1204 else if (client
.openbox_hint
->flags
& AttribMaxVert
)
1205 flags
.maximized
= (client
.openbox_hint
->attrib
& AttribMaxVert
) ? 2 : 0;
1206 else if (client
.openbox_hint
->flags
& AttribMaxHoriz
)
1207 flags
.maximized
= (client
.openbox_hint
->attrib
& AttribMaxHoriz
) ? 3 : 0;
1209 if (client
.openbox_hint
->flags
& AttribOmnipresent
)
1210 flags
.stuck
= (client
.openbox_hint
->attrib
& AttribOmnipresent
);
1212 if (client
.openbox_hint
->flags
& AttribWorkspace
)
1213 workspace_number
= client
.openbox_hint
->workspace
;
1215 // if (client.openbox_hint->flags & AttribStack)
1216 // don't yet have always on top/bottom for openbox yet... working
1219 if (client
.openbox_hint
->flags
& AttribDecoration
) {
1220 switch (client
.openbox_hint
->decoration
) {
1222 decorations
.titlebar
= decorations
.border
= decorations
.handle
=
1223 decorations
.iconify
= decorations
.maximize
=
1224 decorations
.menu
= False
;
1225 functions
.resize
= functions
.move
= functions
.iconify
=
1226 functions
.maximize
= False
;
1231 decorations
.titlebar
= decorations
.iconify
= decorations
.menu
=
1232 functions
.move
= functions
.iconify
= True
;
1233 decorations
.border
= decorations
.handle
= decorations
.maximize
=
1234 functions
.resize
= functions
.maximize
= False
;
1239 decorations
.titlebar
= decorations
.menu
= functions
.move
= True
;
1240 decorations
.iconify
= decorations
.border
= decorations
.handle
=
1241 decorations
.maximize
= functions
.resize
= functions
.maximize
=
1242 functions
.iconify
= False
;
1248 decorations
.titlebar
= decorations
.border
= decorations
.handle
=
1249 decorations
.iconify
= decorations
.maximize
=
1250 decorations
.menu
= True
;
1251 functions
.resize
= functions
.move
= functions
.iconify
=
1252 functions
.maximize
= True
;
1262 void OpenboxWindow::configure(int dx
, int dy
,
1263 unsigned int dw
, unsigned int dh
) {
1264 Bool send_event
= (frame
.x
!= dx
|| frame
.y
!= dy
);
1266 if ((dw
!= frame
.width
) || (dh
!= frame
.height
)) {
1267 if ((((signed) frame
.width
) + dx
) < 0) dx
= 0;
1268 if ((((signed) frame
.height
) + dy
) < 0) dy
= 0;
1278 if (openbox
.hasShapeExtensions() && flags
.shaped
) {
1279 XShapeCombineShape(display
, frame
.window
, ShapeBounding
,
1280 frame
.mwm_border_w
, frame
.y_border
+
1281 frame
.mwm_border_w
, client
.window
,
1282 ShapeBounding
, ShapeSet
);
1285 XRectangle xrect
[2];
1286 xrect
[0].x
= xrect
[0].y
= 0;
1287 xrect
[0].width
= frame
.width
;
1288 xrect
[0].height
= frame
.y_border
;
1290 if (decorations
.handle
) {
1292 xrect
[1].y
= frame
.y_handle
;
1293 xrect
[1].width
= frame
.width
;
1294 xrect
[1].height
= frame
.handle_h
+ frame
.border_w
;
1298 XShapeCombineRectangles(display
, frame
.window
, ShapeBounding
, 0, 0,
1299 xrect
, num
, ShapeUnion
, Unsorted
);
1303 XMoveWindow(display
, frame
.window
, frame
.x
, frame
.y
);
1305 setFocusFlag(flags
.focused
);
1312 XMoveWindow(display
, frame
.window
, frame
.x
, frame
.y
);
1314 if (! flags
.moving
) send_event
= True
;
1317 if (send_event
&& ! flags
.moving
) {
1318 client
.x
= dx
+ frame
.mwm_border_w
+ frame
.border_w
;
1319 client
.y
= dy
+ frame
.y_border
+ frame
.mwm_border_w
+
1323 event
.type
= ConfigureNotify
;
1325 event
.xconfigure
.display
= display
;
1326 event
.xconfigure
.event
= client
.window
;
1327 event
.xconfigure
.window
= client
.window
;
1328 event
.xconfigure
.x
= client
.x
;
1329 event
.xconfigure
.y
= client
.y
;
1330 event
.xconfigure
.width
= client
.width
;
1331 event
.xconfigure
.height
= client
.height
;
1332 event
.xconfigure
.border_width
= client
.old_bw
;
1333 event
.xconfigure
.above
= frame
.window
;
1334 event
.xconfigure
.override_redirect
= False
;
1336 XSendEvent(display
, client
.window
, True
, NoEventMask
, &event
);
1338 screen
->updateNetizenConfigNotify(&event
);
1343 bool OpenboxWindow::setInputFocus(void) {
1344 if (((signed) (frame
.x
+ frame
.width
)) < 0) {
1345 if (((signed) (frame
.y
+ frame
.y_border
)) < 0)
1346 configure(frame
.border_w
, frame
.border_w
, frame
.width
, frame
.height
);
1347 else if (frame
.y
> (signed) screen
->size().h())
1348 configure(frame
.border_w
, screen
->size().h() - frame
.height
,
1349 frame
.width
, frame
.height
);
1351 configure(frame
.border_w
, frame
.y
+ frame
.border_w
,
1352 frame
.width
, frame
.height
);
1353 } else if (frame
.x
> (signed) screen
->size().w()) {
1354 if (((signed) (frame
.y
+ frame
.y_border
)) < 0)
1355 configure(screen
->size().w() - frame
.width
, frame
.border_w
,
1356 frame
.width
, frame
.height
);
1357 else if (frame
.y
> (signed) screen
->size().h())
1358 configure(screen
->size().w() - frame
.width
,
1359 screen
->size().h() - frame
.height
, frame
.width
, frame
.height
);
1361 configure(screen
->size().w() - frame
.width
,
1362 frame
.y
+ frame
.border_w
, frame
.width
, frame
.height
);
1366 if (! validateClient()) return False
;
1370 if (client
.transient
&& flags
.modal
) {
1371 ret
= client
.transient
->setInputFocus();
1372 } else if (! flags
.focused
) {
1373 if (focus_mode
== F_LocallyActive
|| focus_mode
== F_Passive
) {
1374 XSetInputFocus(display
, client
.window
,
1375 RevertToPointerRoot
, CurrentTime
);
1376 openbox
.focusWindow(this);
1378 if (flags
.send_focus_message
) {
1380 ce
.xclient
.type
= ClientMessage
;
1381 ce
.xclient
.message_type
= openbox
.getWMProtocolsAtom();
1382 ce
.xclient
.display
= display
;
1383 ce
.xclient
.window
= client
.window
;
1384 ce
.xclient
.format
= 32;
1385 ce
.xclient
.data
.l
[0] = openbox
.getWMTakeFocusAtom();
1386 ce
.xclient
.data
.l
[1] = openbox
.getLastTime();
1387 ce
.xclient
.data
.l
[2] = 0l;
1388 ce
.xclient
.data
.l
[3] = 0l;
1389 ce
.xclient
.data
.l
[4] = 0l;
1390 XSendEvent(display
, client
.window
, False
, NoEventMask
, &ce
);
1393 if (screen
->sloppyFocus() && screen
->autoRaise())
1406 void OpenboxWindow::iconify(void) {
1407 if (flags
.iconic
) return;
1412 if (windowmenu
) windowmenu
->hide();
1414 setState(IconicState
);
1416 XSelectInput(display
, client
.window
, NoEventMask
);
1417 XUnmapWindow(display
, client
.window
);
1418 XSelectInput(display
, client
.window
,
1419 PropertyChangeMask
| StructureNotifyMask
| FocusChangeMask
);
1421 XUnmapWindow(display
, frame
.window
);
1422 flags
.visible
= False
;
1423 flags
.iconic
= True
;
1425 screen
->getWorkspace(workspace_number
)->removeWindow(this);
1427 if (flags
.transient
&& client
.transient_for
&&
1428 !client
.transient_for
->flags
.iconic
) {
1429 client
.transient_for
->iconify();
1431 screen
->addIcon(this);
1433 if (client
.transient
&& !client
.transient
->flags
.iconic
) {
1434 client
.transient
->iconify();
1439 void OpenboxWindow::deiconify(bool reassoc
, bool raise
, bool initial
) {
1440 if (flags
.iconic
|| reassoc
)
1441 screen
->reassociateWindow(this, -1, False
);
1442 else if (workspace_number
!= screen
->getCurrentWorkspace()->getWorkspaceID())
1445 setState(NormalState
);
1447 XSelectInput(display
, client
.window
, NoEventMask
);
1448 XMapWindow(display
, client
.window
);
1449 XSelectInput(display
, client
.window
,
1450 PropertyChangeMask
| StructureNotifyMask
| FocusChangeMask
);
1452 XMapSubwindows(display
, frame
.window
);
1453 XMapWindow(display
, frame
.window
);
1455 // if we're using the click to place placement type, then immediately
1456 // after the window is mapped, we need to start interactively moving it
1457 if (initial
&& place_window
&&
1458 screen
->placementPolicy() == BScreen::ClickMousePlacement
) {
1462 XQueryPointer(openbox
.getXDisplay(), screen
->getRootWindow(),
1463 &r
, &c
, &rx
, &ry
, &x
, &y
, &m
);
1467 if (flags
.iconic
&& screen
->focusNew()) setInputFocus();
1469 flags
.visible
= True
;
1470 flags
.iconic
= False
;
1472 if (reassoc
&& client
.transient
) client
.transient
->deiconify(True
, False
);
1475 screen
->getWorkspace(workspace_number
)->raiseWindow(this);
1479 void OpenboxWindow::close(void) {
1481 ce
.xclient
.type
= ClientMessage
;
1482 ce
.xclient
.message_type
= openbox
.getWMProtocolsAtom();
1483 ce
.xclient
.display
= display
;
1484 ce
.xclient
.window
= client
.window
;
1485 ce
.xclient
.format
= 32;
1486 ce
.xclient
.data
.l
[0] = openbox
.getWMDeleteAtom();
1487 ce
.xclient
.data
.l
[1] = CurrentTime
;
1488 ce
.xclient
.data
.l
[2] = 0l;
1489 ce
.xclient
.data
.l
[3] = 0l;
1490 ce
.xclient
.data
.l
[4] = 0l;
1491 XSendEvent(display
, client
.window
, False
, NoEventMask
, &ce
);
1495 void OpenboxWindow::withdraw(void) {
1499 flags
.visible
= False
;
1500 flags
.iconic
= False
;
1502 XUnmapWindow(display
, frame
.window
);
1504 XSelectInput(display
, client
.window
, NoEventMask
);
1505 XUnmapWindow(display
, client
.window
);
1506 XSelectInput(display
, client
.window
,
1507 PropertyChangeMask
| StructureNotifyMask
| FocusChangeMask
);
1509 if (windowmenu
) windowmenu
->hide();
1513 void OpenboxWindow::maximize(unsigned int button
) {
1517 // handle case where menu is open then the max button is used instead
1518 if (windowmenu
&& windowmenu
->isVisible()) windowmenu
->hide();
1520 if (flags
.maximized
) {
1521 flags
.maximized
= 0;
1523 openbox_attrib
.flags
&= ! (AttribMaxHoriz
| AttribMaxVert
);
1524 openbox_attrib
.attrib
&= ! (AttribMaxHoriz
| AttribMaxVert
);
1526 // when a resize is begun, maximize(0) is called to clear any maximization
1527 // flags currently set. Otherwise it still thinks it is maximized.
1528 // so we do not need to call configure() because resizing will handle it
1529 if (!flags
.resizing
)
1530 configure(openbox_attrib
.premax_x
, openbox_attrib
.premax_y
,
1531 openbox_attrib
.premax_w
, openbox_attrib
.premax_h
);
1533 openbox_attrib
.premax_x
= openbox_attrib
.premax_y
= 0;
1534 openbox_attrib
.premax_w
= openbox_attrib
.premax_h
= 0;
1536 redrawMaximizeButton(flags
.maximized
);
1537 setState(current_state
);
1541 openbox_attrib
.premax_x
= frame
.x
;
1542 openbox_attrib
.premax_y
= frame
.y
;
1543 openbox_attrib
.premax_w
= frame
.width
;
1544 openbox_attrib
.premax_h
= frame
.height
;
1546 Rect space
= screen
->availableArea();
1547 unsigned int dw
= space
.w(),
1549 dw
-= frame
.border_w
* 2;
1550 dw
-= frame
.mwm_border_w
* 2;
1551 dw
-= client
.base_width
;
1553 dh
-= frame
.border_w
* 2;
1554 dh
-= frame
.mwm_border_w
* 2;
1555 dh
-= ((frame
.handle_h
+ frame
.border_w
) * decorations
.handle
);
1556 dh
-= client
.base_height
;
1557 dh
-= frame
.y_border
;
1559 if (dw
< client
.min_width
) dw
= client
.min_width
;
1560 if (dh
< client
.min_height
) dh
= client
.min_height
;
1561 if (dw
> client
.max_width
) dw
= client
.max_width
;
1562 if (dh
> client
.max_height
) dh
= client
.max_height
;
1564 dw
-= (dw
% client
.width_inc
);
1565 dw
+= client
.base_width
;
1566 dw
+= frame
.mwm_border_w
* 2;
1568 dh
-= (dh
% client
.height_inc
);
1569 dh
+= client
.base_height
;
1570 dh
+= frame
.y_border
;
1571 dh
+= ((frame
.handle_h
+ frame
.border_w
) * decorations
.handle
);
1572 dh
+= frame
.mwm_border_w
* 2;
1574 int dx
= space
.x() + ((space
.w() - dw
) / 2) - frame
.border_w
,
1575 dy
= space
.y() + ((space
.h() - dh
) / 2) - frame
.border_w
;
1579 openbox_attrib
.flags
|= AttribMaxHoriz
| AttribMaxVert
;
1580 openbox_attrib
.attrib
|= AttribMaxHoriz
| AttribMaxVert
;
1584 openbox_attrib
.flags
|= AttribMaxVert
;
1585 openbox_attrib
.attrib
|= AttribMaxVert
;
1592 openbox_attrib
.flags
|= AttribMaxHoriz
;
1593 openbox_attrib
.attrib
|= AttribMaxHoriz
;
1601 openbox_attrib
.flags
^= AttribShaded
;
1602 openbox_attrib
.attrib
^= AttribShaded
;
1603 flags
.shaded
= False
;
1606 flags
.maximized
= button
;
1608 configure(dx
, dy
, dw
, dh
);
1609 screen
->getWorkspace(workspace_number
)->raiseWindow(this);
1610 redrawMaximizeButton(flags
.maximized
);
1611 setState(current_state
);
1615 void OpenboxWindow::setWorkspace(int n
) {
1616 ASSERT(n
< screen
->getWorkspaceCount());
1617 workspace_number
= n
;
1619 openbox_attrib
.flags
|= AttribWorkspace
;
1620 openbox_attrib
.workspace
= workspace_number
;
1624 void OpenboxWindow::shade(void) {
1625 if (!decorations
.titlebar
)
1629 XResizeWindow(display
, frame
.window
, frame
.width
, frame
.height
);
1630 flags
.shaded
= False
;
1631 openbox_attrib
.flags
^= AttribShaded
;
1632 openbox_attrib
.attrib
^= AttribShaded
;
1634 setState(NormalState
);
1636 XResizeWindow(display
, frame
.window
, frame
.width
, frame
.title_h
);
1637 flags
.shaded
= True
;
1638 openbox_attrib
.flags
|= AttribShaded
;
1639 openbox_attrib
.attrib
|= AttribShaded
;
1641 setState(IconicState
);
1646 void OpenboxWindow::stick(void) {
1648 openbox_attrib
.flags
^= AttribOmnipresent
;
1649 openbox_attrib
.attrib
^= AttribOmnipresent
;
1651 flags
.stuck
= False
;
1654 screen
->reassociateWindow(this, -1, True
);
1656 setState(current_state
);
1660 openbox_attrib
.flags
|= AttribOmnipresent
;
1661 openbox_attrib
.attrib
|= AttribOmnipresent
;
1663 setState(current_state
);
1668 void OpenboxWindow::setFocusFlag(Bool focus
) {
1669 flags
.focused
= focus
;
1671 if (decorations
.titlebar
) {
1672 if (flags
.focused
) {
1674 XSetWindowBackgroundPixmap(display
, frame
.title
, frame
.ftitle
);
1676 XSetWindowBackground(display
, frame
.title
, frame
.ftitle_pixel
);
1679 XSetWindowBackgroundPixmap(display
, frame
.title
, frame
.utitle
);
1681 XSetWindowBackground(display
, frame
.title
, frame
.utitle_pixel
);
1683 XClearWindow(display
, frame
.title
);
1689 if (decorations
.handle
) {
1690 if (flags
.focused
) {
1692 XSetWindowBackgroundPixmap(display
, frame
.handle
, frame
.fhandle
);
1694 XSetWindowBackground(display
, frame
.handle
, frame
.fhandle_pixel
);
1697 XSetWindowBackgroundPixmap(display
, frame
.right_grip
, frame
.fgrip
);
1698 XSetWindowBackgroundPixmap(display
, frame
.left_grip
, frame
.fgrip
);
1700 XSetWindowBackground(display
, frame
.right_grip
, frame
.fgrip_pixel
);
1701 XSetWindowBackground(display
, frame
.left_grip
, frame
.fgrip_pixel
);
1705 XSetWindowBackgroundPixmap(display
, frame
.handle
, frame
.uhandle
);
1707 XSetWindowBackground(display
, frame
.handle
, frame
.uhandle_pixel
);
1710 XSetWindowBackgroundPixmap(display
, frame
.right_grip
, frame
.ugrip
);
1711 XSetWindowBackgroundPixmap(display
, frame
.left_grip
, frame
.ugrip
);
1713 XSetWindowBackground(display
, frame
.right_grip
, frame
.ugrip_pixel
);
1714 XSetWindowBackground(display
, frame
.left_grip
, frame
.ugrip_pixel
);
1717 XClearWindow(display
, frame
.handle
);
1718 XClearWindow(display
, frame
.right_grip
);
1719 XClearWindow(display
, frame
.left_grip
);
1722 if (decorations
.border
) {
1724 XSetWindowBorder(display
, frame
.plate
, frame
.fborder_pixel
);
1726 XSetWindowBorder(display
, frame
.plate
, frame
.uborder_pixel
);
1729 if (screen
->sloppyFocus() && screen
->autoRaise() && timer
->isTiming())
1735 void OpenboxWindow::installColormap(Bool install
) {
1737 if (! validateClient()) return;
1739 int i
= 0, ncmap
= 0;
1740 Colormap
*cmaps
= XListInstalledColormaps(display
, client
.window
, &ncmap
);
1741 XWindowAttributes wattrib
;
1743 if (XGetWindowAttributes(display
, client
.window
, &wattrib
)) {
1745 // install the window's colormap
1746 for (i
= 0; i
< ncmap
; i
++) {
1747 if (*(cmaps
+ i
) == wattrib
.colormap
)
1748 // this window is using an installed color map... do not install
1751 // otherwise, install the window's colormap
1753 XInstallColormap(display
, wattrib
.colormap
);
1755 // uninstall the window's colormap
1756 for (i
= 0; i
< ncmap
; i
++) {
1757 if (*(cmaps
+ i
) == wattrib
.colormap
)
1758 // we found the colormap to uninstall
1759 XUninstallColormap(display
, wattrib
.colormap
);
1771 void OpenboxWindow::setState(unsigned long new_state
) {
1772 current_state
= new_state
;
1774 unsigned long state
[2];
1775 state
[0] = (unsigned long) current_state
;
1776 state
[1] = (unsigned long) None
;
1777 XChangeProperty(display
, client
.window
, openbox
.getWMStateAtom(),
1778 openbox
.getWMStateAtom(), 32, PropModeReplace
,
1779 (unsigned char *) state
, 2);
1781 XChangeProperty(display
, client
.window
,
1782 openbox
.getOpenboxAttributesAtom(),
1783 openbox
.getOpenboxAttributesAtom(), 32, PropModeReplace
,
1784 (unsigned char *) &openbox_attrib
,
1785 PropOpenboxAttributesElements
);
1789 Bool
OpenboxWindow::getState(void) {
1795 unsigned long *state
, ulfoo
, nitems
;
1797 if ((XGetWindowProperty(display
, client
.window
, openbox
.getWMStateAtom(),
1798 0l, 2l, False
, openbox
.getWMStateAtom(),
1799 &atom_return
, &foo
, &nitems
, &ulfoo
,
1800 (unsigned char **) &state
) != Success
) ||
1807 current_state
= (unsigned long) state
[0];
1812 XFree((void *) state
);
1818 void OpenboxWindow::setGravityOffsets(void) {
1819 // x coordinates for each gravity type
1820 const int x_west
= client
.x
;
1821 const int x_east
= client
.x
+ client
.width
- frame
.width
;
1822 const int x_center
= client
.x
+ client
.width
- frame
.width
/2;
1823 // y coordinates for each gravity type
1824 const int y_north
= client
.y
;
1825 const int y_south
= client
.y
+ client
.height
- frame
.height
;
1826 const int y_center
= client
.y
+ client
.height
- frame
.height
/2;
1828 switch (client
.win_gravity
) {
1829 case NorthWestGravity
:
1838 case NorthEastGravity
:
1842 case SouthWestGravity
:
1850 case SouthEastGravity
:
1868 frame
.x
= client
.x
- frame
.mwm_border_w
+ frame
.border_w
;
1869 frame
.y
= client
.y
- frame
.y_border
- frame
.mwm_border_w
- frame
.border_w
;
1875 void OpenboxWindow::restoreAttributes(void) {
1876 if (! getState()) current_state
= NormalState
;
1880 unsigned long ulfoo
, nitems
;
1882 OpenboxAttributes
*net
;
1883 int ret
= XGetWindowProperty(display
, client
.window
,
1884 openbox
.getOpenboxAttributesAtom(), 0l,
1885 PropOpenboxAttributesElements
, False
,
1886 openbox
.getOpenboxAttributesAtom(),
1887 &atom_return
, &foo
, &nitems
, &ulfoo
,
1888 (unsigned char **) &net
);
1889 if (ret
!= Success
|| !net
|| nitems
!= PropOpenboxAttributesElements
)
1892 openbox_attrib
.flags
= net
->flags
;
1893 openbox_attrib
.attrib
= net
->attrib
;
1894 openbox_attrib
.decoration
= net
->decoration
;
1895 openbox_attrib
.workspace
= net
->workspace
;
1896 openbox_attrib
.stack
= net
->stack
;
1897 openbox_attrib
.premax_x
= net
->premax_x
;
1898 openbox_attrib
.premax_y
= net
->premax_y
;
1899 openbox_attrib
.premax_w
= net
->premax_w
;
1900 openbox_attrib
.premax_h
= net
->premax_h
;
1902 XFree((void *) net
);
1904 if (openbox_attrib
.flags
& AttribShaded
&&
1905 openbox_attrib
.attrib
& AttribShaded
) {
1907 ((current_state
== IconicState
) ? NormalState
: current_state
);
1909 flags
.shaded
= False
;
1912 current_state
= save_state
;
1915 if (((int) openbox_attrib
.workspace
!= screen
->getCurrentWorkspaceID()) &&
1916 ((int) openbox_attrib
.workspace
< screen
->getWorkspaceCount())) {
1917 screen
->reassociateWindow(this, openbox_attrib
.workspace
, True
);
1919 if (current_state
== NormalState
) current_state
= WithdrawnState
;
1920 } else if (current_state
== WithdrawnState
) {
1921 current_state
= NormalState
;
1924 if (openbox_attrib
.flags
& AttribOmnipresent
&&
1925 openbox_attrib
.attrib
& AttribOmnipresent
) {
1926 flags
.stuck
= False
;
1929 current_state
= NormalState
;
1932 if ((openbox_attrib
.flags
& AttribMaxHoriz
) ||
1933 (openbox_attrib
.flags
& AttribMaxVert
)) {
1934 int x
= openbox_attrib
.premax_x
, y
= openbox_attrib
.premax_y
;
1935 unsigned int w
= openbox_attrib
.premax_w
, h
= openbox_attrib
.premax_h
;
1936 flags
.maximized
= 0;
1938 unsigned int m
= False
;
1939 if ((openbox_attrib
.flags
& AttribMaxHoriz
) &&
1940 (openbox_attrib
.flags
& AttribMaxVert
))
1941 m
= (openbox_attrib
.attrib
& (AttribMaxHoriz
| AttribMaxVert
)) ? 1 : 0;
1942 else if (openbox_attrib
.flags
& AttribMaxVert
)
1943 m
= (openbox_attrib
.attrib
& AttribMaxVert
) ? 2 : 0;
1944 else if (openbox_attrib
.flags
& AttribMaxHoriz
)
1945 m
= (openbox_attrib
.attrib
& AttribMaxHoriz
) ? 3 : 0;
1949 openbox_attrib
.premax_x
= x
;
1950 openbox_attrib
.premax_y
= y
;
1951 openbox_attrib
.premax_w
= w
;
1952 openbox_attrib
.premax_h
= h
;
1955 setState(current_state
);
1960 * The reverse of the setGravityOffsets function. Uses the frame window's
1961 * position to find the window's reference point.
1963 void OpenboxWindow::restoreGravity(void) {
1964 // x coordinates for each gravity type
1965 const int x_west
= frame
.x
;
1966 const int x_east
= frame
.x
+ frame
.width
- client
.width
;
1967 const int x_center
= frame
.x
+ (frame
.width
/2) - client
.width
;
1968 // y coordinates for each gravity type
1969 const int y_north
= frame
.y
;
1970 const int y_south
= frame
.y
+ frame
.height
- client
.height
;
1971 const int y_center
= frame
.y
+ (frame
.height
/2) - client
.height
;
1973 switch(client
.win_gravity
) {
1975 case NorthWestGravity
:
1980 client
.x
= x_center
;
1983 case NorthEastGravity
:
1987 case SouthWestGravity
:
1992 client
.x
= x_center
;
1995 case SouthEastGravity
:
2001 client
.y
= y_center
;
2005 client
.y
= y_center
;
2008 client
.x
= x_center
;
2009 client
.y
= y_center
;
2013 client
.x
= frame
.x
+ frame
.mwm_border_w
+ frame
.border_w
;
2014 client
.y
= frame
.y
+ frame
.y_border
+ frame
.mwm_border_w
+
2021 void OpenboxWindow::redrawLabel(void) {
2022 int dx
= frame
.bevel_w
* 2, dlen
= client
.title_len
;
2023 unsigned int l
= client
.title_text_w
;
2025 if (flags
.focused
) {
2027 XSetWindowBackgroundPixmap(display
, frame
.label
, frame
.flabel
);
2029 XSetWindowBackground(display
, frame
.label
, frame
.flabel_pixel
);
2032 XSetWindowBackgroundPixmap(display
, frame
.label
, frame
.ulabel
);
2034 XSetWindowBackground(display
, frame
.label
, frame
.ulabel_pixel
);
2036 XClearWindow(display
, frame
.label
);
2038 if (client
.title_text_w
> frame
.label_w
) {
2039 for (; dlen
>= 0; dlen
--) {
2040 if (i18n
->multibyte()) {
2041 XRectangle ink
, logical
;
2042 XmbTextExtents(screen
->getWindowStyle()->fontset
, client
.title
, dlen
,
2046 l
= XTextWidth(screen
->getWindowStyle()->font
, client
.title
, dlen
);
2048 l
+= (frame
.bevel_w
* 4);
2050 if (l
< frame
.label_w
)
2055 switch (screen
->getWindowStyle()->justify
) {
2056 case BScreen::RightJustify
:
2057 dx
+= frame
.label_w
- l
;
2060 case BScreen::CenterJustify
:
2061 dx
+= (frame
.label_w
- l
) / 2;
2065 WindowStyle
*style
= screen
->getWindowStyle();
2066 GC text_gc
= (flags
.focused
) ? style
->l_text_focus_gc
:
2067 style
->l_text_unfocus_gc
;
2068 if (i18n
->multibyte())
2069 XmbDrawString(display
, frame
.label
, style
->fontset
, text_gc
, dx
,
2070 (1 - style
->fontset_extents
->max_ink_extent
.y
),
2071 client
.title
, dlen
);
2073 XDrawString(display
, frame
.label
, text_gc
, dx
,
2074 (style
->font
->ascent
+ 1), client
.title
, dlen
);
2078 void OpenboxWindow::redrawAllButtons(void) {
2079 if (frame
.iconify_button
) redrawIconifyButton(False
);
2080 if (frame
.maximize_button
) redrawMaximizeButton(flags
.maximized
);
2081 if (frame
.close_button
) redrawCloseButton(False
);
2085 void OpenboxWindow::redrawIconifyButton(Bool pressed
) {
2087 if (flags
.focused
) {
2089 XSetWindowBackgroundPixmap(display
, frame
.iconify_button
,
2092 XSetWindowBackground(display
, frame
.iconify_button
,
2093 frame
.fbutton_pixel
);
2096 XSetWindowBackgroundPixmap(display
, frame
.iconify_button
,
2099 XSetWindowBackground(display
, frame
.iconify_button
,
2100 frame
.ubutton_pixel
);
2104 XSetWindowBackgroundPixmap(display
, frame
.iconify_button
, frame
.pbutton
);
2106 XSetWindowBackground(display
, frame
.iconify_button
, frame
.pbutton_pixel
);
2108 XClearWindow(display
, frame
.iconify_button
);
2110 XDrawRectangle(display
, frame
.iconify_button
,
2111 ((flags
.focused
) ? screen
->getWindowStyle()->b_pic_focus_gc
:
2112 screen
->getWindowStyle()->b_pic_unfocus_gc
),
2113 2, (frame
.button_h
- 5), (frame
.button_w
- 5), 2);
2117 void OpenboxWindow::redrawMaximizeButton(Bool pressed
) {
2119 if (flags
.focused
) {
2121 XSetWindowBackgroundPixmap(display
, frame
.maximize_button
,
2124 XSetWindowBackground(display
, frame
.maximize_button
,
2125 frame
.fbutton_pixel
);
2128 XSetWindowBackgroundPixmap(display
, frame
.maximize_button
,
2131 XSetWindowBackground(display
, frame
.maximize_button
,
2132 frame
.ubutton_pixel
);
2136 XSetWindowBackgroundPixmap(display
, frame
.maximize_button
,
2139 XSetWindowBackground(display
, frame
.maximize_button
,
2140 frame
.pbutton_pixel
);
2142 XClearWindow(display
, frame
.maximize_button
);
2144 XDrawRectangle(display
, frame
.maximize_button
,
2145 ((flags
.focused
) ? screen
->getWindowStyle()->b_pic_focus_gc
:
2146 screen
->getWindowStyle()->b_pic_unfocus_gc
),
2147 2, 2, (frame
.button_w
- 5), (frame
.button_h
- 5));
2148 XDrawLine(display
, frame
.maximize_button
,
2149 ((flags
.focused
) ? screen
->getWindowStyle()->b_pic_focus_gc
:
2150 screen
->getWindowStyle()->b_pic_unfocus_gc
),
2151 2, 3, (frame
.button_w
- 3), 3);
2155 void OpenboxWindow::redrawCloseButton(Bool pressed
) {
2157 if (flags
.focused
) {
2159 XSetWindowBackgroundPixmap(display
, frame
.close_button
,
2162 XSetWindowBackground(display
, frame
.close_button
,
2163 frame
.fbutton_pixel
);
2166 XSetWindowBackgroundPixmap(display
, frame
.close_button
,
2169 XSetWindowBackground(display
, frame
.close_button
,
2170 frame
.ubutton_pixel
);
2174 XSetWindowBackgroundPixmap(display
, frame
.close_button
, frame
.pbutton
);
2176 XSetWindowBackground(display
, frame
.close_button
, frame
.pbutton_pixel
);
2178 XClearWindow(display
, frame
.close_button
);
2180 XDrawLine(display
, frame
.close_button
,
2181 ((flags
.focused
) ? screen
->getWindowStyle()->b_pic_focus_gc
:
2182 screen
->getWindowStyle()->b_pic_unfocus_gc
), 2, 2,
2183 (frame
.button_w
- 3), (frame
.button_h
- 3));
2184 XDrawLine(display
, frame
.close_button
,
2185 ((flags
.focused
) ? screen
->getWindowStyle()->b_pic_focus_gc
:
2186 screen
->getWindowStyle()->b_pic_unfocus_gc
), 2,
2187 (frame
.button_h
- 3),
2188 (frame
.button_w
- 3), 2);
2192 void OpenboxWindow::mapRequestEvent(XMapRequestEvent
*re
) {
2193 if (re
->window
== client
.window
) {
2195 fprintf(stderr
, i18n
->getMessage(WindowSet
, WindowMapRequest
,
2196 "OpenboxWindow::mapRequestEvent() for 0x%lx\n"),
2201 if (! validateClient()) return;
2203 Bool get_state_ret
= getState();
2204 if (! (get_state_ret
&& openbox
.isStartup())) {
2205 if ((client
.wm_hint_flags
& StateHint
) &&
2206 (! (current_state
== NormalState
|| current_state
== IconicState
)))
2207 current_state
= client
.initial_state
;
2209 current_state
= NormalState
;
2210 } else if (flags
.iconic
) {
2211 current_state
= NormalState
;
2214 switch (current_state
) {
2219 case WithdrawnState
:
2227 deiconify(False
, True
, True
); // specify that we're initializing the
2237 void OpenboxWindow::mapNotifyEvent(XMapEvent
*ne
) {
2238 if ((ne
->window
== client
.window
) && (! ne
->override_redirect
)
2239 && (flags
.visible
)) {
2241 if (! validateClient()) return;
2243 setState(NormalState
);
2245 if (flags
.transient
|| screen
->focusNew())
2248 setFocusFlag(False
);
2250 flags
.visible
= True
;
2251 flags
.iconic
= False
;
2258 void OpenboxWindow::unmapNotifyEvent(XUnmapEvent
*ue
) {
2259 if (ue
->window
== client
.window
) {
2261 fprintf(stderr
, i18n
->getMessage(WindowSet
, WindowUnmapNotify
,
2262 "OpenboxWindow::unmapNotifyEvent() for 0x%lx\n"),
2267 if (! validateClient()) return;
2272 XChangeSaveSet(display
, client
.window
, SetModeDelete
);
2273 XSelectInput(display
, client
.window
, NoEventMask
);
2275 XDeleteProperty(display
, client
.window
, openbox
.getWMStateAtom());
2276 XDeleteProperty(display
, client
.window
,
2277 openbox
.getOpenboxAttributesAtom());
2279 XUnmapWindow(display
, frame
.window
);
2280 XUnmapWindow(display
, client
.window
);
2283 if (! XCheckTypedWindowEvent(display
, client
.window
, ReparentNotify
,
2286 fprintf(stderr
, i18n
->getMessage(WindowSet
, WindowUnmapNotifyReparent
,
2287 "OpenboxWindow::unmapNotifyEvent(): reparent 0x%lx to "
2288 "root.\n"), client
.window
);
2292 XReparentWindow(display
, client
.window
, screen
->getRootWindow(),
2293 client
.x
, client
.y
);
2305 void OpenboxWindow::destroyNotifyEvent(XDestroyWindowEvent
*de
) {
2306 if (de
->window
== client
.window
) {
2309 XUnmapWindow(display
, frame
.window
);
2316 void OpenboxWindow::propertyNotifyEvent(Atom atom
) {
2318 if (! validateClient()) return;
2322 case XA_WM_CLIENT_MACHINE
:
2326 case XA_WM_TRANSIENT_FOR
:
2327 // determine if this is a transient window
2329 if (XGetTransientForHint(display
, client
.window
, &win
)) {
2330 if (win
&& (win
!= client
.window
)) {
2331 if ((client
.transient_for
= openbox
.searchWindow(win
))) {
2332 client
.transient_for
->client
.transient
= this;
2333 flags
.stuck
= client
.transient_for
->flags
.stuck
;
2334 flags
.transient
= True
;
2335 } else if (win
== client
.window_group
) {
2336 //jr This doesn't look quite right...
2337 if ((client
.transient_for
= openbox
.searchGroup(win
, this))) {
2338 client
.transient_for
->client
.transient
= this;
2339 flags
.stuck
= client
.transient_for
->flags
.stuck
;
2340 flags
.transient
= True
;
2345 if (win
== screen
->getRootWindow()) flags
.modal
= True
;
2348 // adjust the window decorations based on transience
2349 if (flags
.transient
)
2350 decorations
.maximize
= decorations
.handle
= functions
.maximize
= False
;
2360 case XA_WM_ICON_NAME
:
2362 if (flags
.iconic
) screen
->iconUpdate();
2368 if (decorations
.titlebar
)
2372 screen
->getWorkspace(workspace_number
)->update();
2376 case XA_WM_NORMAL_HINTS
: {
2379 if ((client
.normal_hint_flags
& PMinSize
) &&
2380 (client
.normal_hint_flags
& PMaxSize
)) {
2381 if (client
.max_width
<= client
.min_width
&&
2382 client
.max_height
<= client
.min_height
)
2383 decorations
.maximize
= decorations
.handle
=
2384 functions
.resize
= functions
.maximize
= False
;
2386 decorations
.maximize
= decorations
.handle
=
2387 functions
.resize
= functions
.maximize
= True
;
2390 int x
= frame
.x
, y
= frame
.y
;
2391 unsigned int w
= frame
.width
, h
= frame
.height
;
2395 if ((x
!= frame
.x
) || (y
!= frame
.y
) ||
2396 (w
!= frame
.width
) || (h
!= frame
.height
))
2403 if (atom
== openbox
.getWMProtocolsAtom()) {
2406 if (decorations
.close
&& (! frame
.close_button
)) {
2407 createCloseButton();
2408 if (decorations
.titlebar
) {
2412 if (windowmenu
) windowmenu
->reconfigure();
2423 void OpenboxWindow::exposeEvent(XExposeEvent
*ee
) {
2424 if (frame
.label
== ee
->window
&& decorations
.titlebar
)
2426 else if (frame
.close_button
== ee
->window
)
2427 redrawCloseButton(False
);
2428 else if (frame
.maximize_button
== ee
->window
)
2429 redrawMaximizeButton(flags
.maximized
);
2430 else if (frame
.iconify_button
== ee
->window
)
2431 redrawIconifyButton(False
);
2435 void OpenboxWindow::configureRequestEvent(XConfigureRequestEvent
*cr
) {
2436 if (cr
->window
== client
.window
) {
2438 if (! validateClient()) return;
2440 int cx
= frame
.x
, cy
= frame
.y
;
2441 unsigned int cw
= frame
.width
, ch
= frame
.height
;
2443 if (cr
->value_mask
& CWBorderWidth
)
2444 client
.old_bw
= cr
->border_width
;
2446 if (cr
->value_mask
& CWX
)
2447 cx
= cr
->x
- frame
.mwm_border_w
- frame
.border_w
;
2449 if (cr
->value_mask
& CWY
)
2450 cy
= cr
->y
- frame
.y_border
- frame
.mwm_border_w
-
2453 if (cr
->value_mask
& CWWidth
)
2454 cw
= cr
->width
+ (frame
.mwm_border_w
* 2);
2456 if (cr
->value_mask
& CWHeight
)
2457 ch
= cr
->height
+ frame
.y_border
+ (frame
.mwm_border_w
* 2) +
2458 (frame
.border_w
* decorations
.handle
) + frame
.handle_h
;
2460 if (frame
.x
!= cx
|| frame
.y
!= cy
||
2461 frame
.width
!= cw
|| frame
.height
!= ch
)
2462 configure(cx
, cy
, cw
, ch
);
2464 if (cr
->value_mask
& CWStackMode
) {
2465 switch (cr
->detail
) {
2469 if (flags
.iconic
) deiconify();
2470 screen
->getWorkspace(workspace_number
)->raiseWindow(this);
2475 if (flags
.iconic
) deiconify();
2476 screen
->getWorkspace(workspace_number
)->lowerWindow(this);
2486 void OpenboxWindow::buttonPressEvent(XButtonEvent
*be
) {
2488 if (! validateClient())
2491 int stack_change
= 1; // < 0 means to lower the window
2492 // > 0 means to raise the window
2493 // 0 means to leave it where it is
2495 // alt + left/right click begins interactively moving/resizing the window
2496 // when the mouse is moved
2497 if (be
->state
== Mod1Mask
&& (be
->button
== 1 || be
->button
== 3)) {
2498 if (be
->button
== 3) {
2499 if (screen
->getWindowZones() == 4 &&
2500 be
->y
< (signed) frame
.height
/ 2) {
2501 resize_zone
= ZoneTop
;
2503 resize_zone
= ZoneBottom
;
2505 if (screen
->getWindowZones() >= 2 &&
2506 be
->x
< (signed) frame
.width
/ 2) {
2507 resize_zone
|= ZoneLeft
;
2509 resize_zone
|= ZoneRight
;
2512 // control + left click on the titlebar shades the window
2513 } else if (be
->state
== ControlMask
&& be
->button
== 1) {
2514 if (be
->window
== frame
.title
||
2515 be
->window
== frame
.label
)
2518 } else if (be
->state
== 0 && be
->button
== 1) {
2519 if (windowmenu
&& windowmenu
->isVisible())
2522 if (be
->window
== frame
.maximize_button
) {
2523 redrawMaximizeButton(True
);
2524 } else if (be
->window
== frame
.iconify_button
) {
2525 redrawIconifyButton(True
);
2526 } else if (be
->window
== frame
.close_button
) {
2527 redrawCloseButton(True
);
2528 } else if (be
->window
== frame
.plate
) {
2529 XAllowEvents(display
, ReplayPointer
, be
->time
);
2530 } else if (be
->window
== frame
.title
||
2531 be
->window
== frame
.label
) {
2532 // shade the window when the titlebar is double clicked
2533 if ( (be
->time
- lastButtonPressTime
) <=
2534 openbox
.getDoubleClickInterval()) {
2535 lastButtonPressTime
= 0;
2538 lastButtonPressTime
= be
->time
;
2540 // clicking and dragging on the titlebar moves the window, so on a click
2541 // we need to save the coords of the click in case the user drags
2542 frame
.grab_x
= be
->x_root
- frame
.x
- frame
.border_w
;
2543 frame
.grab_y
= be
->y_root
- frame
.y
- frame
.border_w
;
2544 } else if (be
->window
== frame
.handle
||
2545 be
->window
== frame
.left_grip
||
2546 be
->window
== frame
.right_grip
||
2547 be
->window
== frame
.window
) {
2548 // clicking and dragging on the window's frame moves the window, so on a
2549 // click we need to save the coords of the click in case the user drags
2550 frame
.grab_x
= be
->x_root
- frame
.x
- frame
.border_w
;
2551 frame
.grab_y
= be
->y_root
- frame
.y
- frame
.border_w
;
2552 if (be
->window
== frame
.left_grip
)
2553 resize_zone
= ZoneBottom
| ZoneLeft
;
2554 else if (be
->window
== frame
.right_grip
)
2555 resize_zone
= ZoneBottom
| ZoneRight
;
2558 } else if (be
->state
== 0 && be
->button
== 2) {
2559 if (be
->window
== frame
.maximize_button
) {
2560 redrawMaximizeButton(True
);
2561 // a middle click anywhere on the window's frame except for on the buttons
2562 // will lower the window
2563 } else if (! (be
->window
== frame
.iconify_button
||
2564 be
->window
== frame
.close_button
) ) {
2568 } else if (be
->state
== 0 && be
->button
== 3) {
2569 if (be
->window
== frame
.maximize_button
) {
2570 redrawMaximizeButton(True
);
2571 // a right click on the window's frame will show or hide the window's
2573 } else if (be
->window
== frame
.title
||
2574 be
->window
== frame
.label
||
2575 be
->window
== frame
.handle
||
2576 be
->window
== frame
.window
) {
2579 if (windowmenu
->isVisible()) {
2582 // get the coords for the menu
2583 mx
= be
->x_root
- windowmenu
->getWidth() / 2;
2584 if (be
->window
== frame
.title
|| be
->window
== frame
.label
) {
2585 my
= frame
.y
+ frame
.title_h
;
2586 } else if (be
->window
== frame
.handle
) {
2587 my
= frame
.y
+ frame
.y_handle
- windowmenu
->getHeight();
2588 } else { // (be->window == frame.window)
2589 if (be
->y
<= (signed) frame
.bevel_w
) {
2590 my
= frame
.y
+ frame
.y_border
;
2592 my
= be
->y_root
- (windowmenu
->getHeight() / 2);
2596 if (mx
> (signed) (frame
.x
+ frame
.width
-
2597 windowmenu
->getWidth())) {
2598 mx
= frame
.x
+ frame
.width
- windowmenu
->getWidth();
2599 } else if (mx
< frame
.x
) {
2603 if (my
> (signed) (frame
.y
+ frame
.y_handle
-
2604 windowmenu
->getHeight())) {
2605 my
= frame
.y
+ frame
.y_handle
- windowmenu
->getHeight();
2606 } else if (my
< (signed) (frame
.y
+
2607 ((decorations
.titlebar
) ? frame
.title_h
: frame
.y_border
))) {
2609 ((decorations
.titlebar
) ? frame
.title_h
: frame
.y_border
);
2612 windowmenu
->move(mx
, my
);
2614 XRaiseWindow(display
, windowmenu
->getWindowID());
2615 XRaiseWindow(display
, windowmenu
->getSendToMenu()->getWindowID());
2616 stack_change
= 0; // dont raise the window overtop of the menu
2621 } else if (be
->state
== 0 && be
->button
== 4) {
2622 if ((be
->window
== frame
.label
||
2623 be
->window
== frame
.title
) &&
2627 } else if (be
->state
== 0 && be
->button
== 5) {
2628 if ((be
->window
== frame
.label
||
2629 be
->window
== frame
.title
) &&
2634 if (! (flags
.focused
|| screen
->sloppyFocus()) ) {
2635 setInputFocus(); // any click focus' the window in 'click to focus'
2637 if (stack_change
< 0) {
2638 screen
->getWorkspace(workspace_number
)->lowerWindow(this);
2639 } else if (stack_change
> 0) {
2640 screen
->getWorkspace(workspace_number
)->raiseWindow(this);
2647 void OpenboxWindow::buttonReleaseEvent(XButtonEvent
*re
) {
2649 if (! validateClient())
2652 // alt + middle button released
2653 if (re
->state
== (Mod1Mask
& Button2Mask
) && re
->button
== 2) {
2654 if (re
->window
== frame
.window
) {
2655 XUngrabPointer(display
, CurrentTime
); // why? i dont know
2657 // left button released
2658 } else if (re
->button
== 1) {
2659 if (re
->window
== frame
.maximize_button
) {
2660 if (re
->state
== Button1Mask
&& // only the left button was depressed
2661 (re
->x
>= 0) && ((unsigned) re
->x
<= frame
.button_w
) &&
2662 (re
->y
>= 0) && ((unsigned) re
->y
<= frame
.button_h
)) {
2663 maximize(re
->button
);
2665 redrawMaximizeButton(False
);
2667 } else if (re
->window
== frame
.iconify_button
) {
2668 if (re
->state
== Button1Mask
&& // only the left button was depressed
2669 (re
->x
>= 0) && ((unsigned) re
->x
<= frame
.button_w
) &&
2670 (re
->y
>= 0) && ((unsigned) re
->y
<= frame
.button_h
)) {
2673 redrawIconifyButton(False
);
2675 } else if (re
->window
== frame
.close_button
) {
2676 if (re
->state
== Button1Mask
&& // only the left button was depressed
2677 (re
->x
>= 0) && ((unsigned) re
->x
<= frame
.button_w
) &&
2678 (re
->y
>= 0) && ((unsigned) re
->y
<= frame
.button_h
)) {
2681 //we should always redraw the close button. some applications
2682 //eg. acroread don't honour the close.
2683 redrawCloseButton(False
);
2685 // middle button released
2686 } else if (re
->button
== 2) {
2687 if (re
->window
== frame
.maximize_button
) {
2688 if (re
->state
== Button2Mask
&& // only the middle button was depressed
2689 (re
->x
>= 0) && ((unsigned) re
->x
<= frame
.button_w
) &&
2690 (re
->y
>= 0) && ((unsigned) re
->y
<= frame
.button_h
)) {
2691 maximize(re
->button
);
2693 redrawMaximizeButton(False
);
2696 // right button released
2697 } else if (re
->button
== 3) {
2698 if (re
->window
== frame
.maximize_button
) {
2699 if (re
->state
== Button3Mask
&& // only the right button was depressed
2700 (re
->x
>= 0) && ((unsigned) re
->x
<= frame
.button_w
) &&
2701 (re
->y
>= 0) && ((unsigned) re
->y
<= frame
.button_h
)) {
2702 maximize(re
->button
);
2704 redrawMaximizeButton(False
);
2709 // when the window is being interactively moved, a button release stops the
2713 // when the window is being interactively resized, a button release stops the
2715 } else if (flags
.resizing
) {
2716 flags
.resizing
= False
;
2717 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2718 frame
.resize_x
, frame
.resize_y
,
2719 frame
.resize_w
- 1, frame
.resize_h
- 1);
2720 screen
->hideGeometry();
2721 if (resize_zone
& ZoneLeft
) {
2723 } else { // when resizing with "Alt+Button3", the resize is the same as if
2724 // done with the right grip (the right side of the window is what
2728 // unset maximized state when resized after fully maximized
2729 if (flags
.maximized
== 1) {
2732 configure(frame
.resize_x
, frame
.resize_y
,
2733 frame
.resize_w
- (frame
.border_w
* 2),
2734 frame
.resize_h
- (frame
.border_w
* 2));
2736 XUngrabPointer(display
, CurrentTime
);
2744 void OpenboxWindow::startMove(int x
, int y
) {
2745 ASSERT(!flags
.moving
);
2747 // make sure only one window is moving at a time
2748 OpenboxWindow
*w
= openbox
.getMaskedWindow();
2749 if (w
!= (OpenboxWindow
*) 0 && w
->flags
.moving
)
2752 XGrabPointer(display
, frame
.window
, False
, PointerMotionMask
|
2753 ButtonReleaseMask
, GrabModeAsync
, GrabModeAsync
,
2754 None
, openbox
.getMoveCursor(), CurrentTime
);
2756 if (windowmenu
&& windowmenu
->isVisible())
2759 flags
.moving
= True
;
2761 openbox
.maskWindowEvents(client
.window
, this);
2763 if (! screen
->opaqueMove()) {
2766 frame
.move_x
= frame
.x
;
2767 frame
.move_y
= frame
.y
;
2768 frame
.resize_w
= frame
.width
+ (frame
.border_w
* 2);
2769 frame
.resize_h
= ((flags
.shaded
) ? frame
.title_h
: frame
.height
) +
2770 (frame
.border_w
* 2);
2772 screen
->showPosition(frame
.x
, frame
.y
);
2774 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2775 frame
.move_x
, frame
.move_y
,
2776 frame
.resize_w
- 1, frame
.resize_h
- 1);
2778 frame
.grab_x
= x
- frame
.x
- frame
.border_w
;
2779 frame
.grab_y
= y
- frame
.y
- frame
.border_w
;
2783 void OpenboxWindow::doMove(int x
, int y
) {
2784 ASSERT(flags
.moving
);
2786 int dx
= x
- frame
.grab_x
, dy
= y
- frame
.grab_y
;
2788 dx
-= frame
.border_w
;
2789 dy
-= frame
.border_w
;
2791 int snap_distance
= screen
->edgeSnapThreshold();
2792 // width/height of the snapping window
2793 unsigned int snap_w
= frame
.width
+ (frame
.border_w
* 2);
2794 unsigned int snap_h
= area().h() + (frame
.border_w
* 2);
2795 if (snap_distance
) {
2796 int drx
= screen
->size().w() - (dx
+ snap_w
);
2798 if (dx
< drx
&& (dx
> 0 && dx
< snap_distance
) ||
2799 (dx
< 0 && dx
> -snap_distance
) )
2801 else if ( (drx
> 0 && drx
< snap_distance
) ||
2802 (drx
< 0 && drx
> -snap_distance
) )
2803 dx
= screen
->size().w() - snap_w
;
2805 int dtty
, dbby
, dty
, dby
;
2806 switch (screen
->getToolbar()->placement()) {
2807 case Toolbar::TopLeft
:
2808 case Toolbar::TopCenter
:
2809 case Toolbar::TopRight
:
2810 dtty
= screen
->getToolbar()->getExposedHeight() +
2812 dbby
= screen
->size().h();
2817 dbby
= screen
->getToolbar()->area().y();
2822 dby
= dbby
- (dy
+ snap_h
);
2824 if ( (dy
> 0 && dty
< snap_distance
) ||
2825 (dy
< 0 && dty
> -snap_distance
) )
2827 else if ( (dby
> 0 && dby
< snap_distance
) ||
2828 (dby
< 0 && dby
> -snap_distance
) )
2832 if (screen
->opaqueMove()) {
2833 configure(dx
, dy
, frame
.width
, frame
.height
);
2835 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2836 frame
.move_x
, frame
.move_y
, frame
.resize_w
- 1,
2837 frame
.resize_h
- 1);
2842 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2843 frame
.move_x
, frame
.move_y
, frame
.resize_w
- 1,
2844 frame
.resize_h
- 1);
2847 screen
->showPosition(dx
, dy
);
2851 void OpenboxWindow::endMove() {
2852 ASSERT(flags
.moving
);
2854 flags
.moving
= False
;
2856 openbox
.maskWindowEvents(0, (OpenboxWindow
*) 0);
2857 if (!screen
->opaqueMove()) {
2858 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2859 frame
.move_x
, frame
.move_y
, frame
.resize_w
- 1,
2860 frame
.resize_h
- 1);
2862 configure(frame
.move_x
, frame
.move_y
, frame
.width
, frame
.height
);
2865 configure(frame
.x
, frame
.y
, frame
.width
, frame
.height
);
2867 screen
->hideGeometry();
2868 XUngrabPointer(display
, CurrentTime
);
2869 // if there are any left over motions from the move, drop them now cuz they
2872 while (XCheckTypedWindowEvent(display
, frame
.window
, MotionNotify
, &e
));
2876 void OpenboxWindow::motionNotifyEvent(XMotionEvent
*me
) {
2878 doMove(me
->x_root
, me
->y_root
);
2879 else if (!flags
.resizing
&& (me
->state
& Button1Mask
) && functions
.move
&&
2880 (frame
.title
== me
->window
|| frame
.label
== me
->window
||
2881 frame
.handle
== me
->window
|| frame
.window
== me
->window
))
2882 startMove(me
->x_root
, me
->y_root
);
2883 else if (functions
.resize
&&
2884 (((me
->state
& Button1Mask
) && (me
->window
== frame
.right_grip
||
2885 me
->window
== frame
.left_grip
)) ||
2886 (me
->state
== (Mod1Mask
| Button3Mask
) &&
2887 me
->window
== frame
.window
))) {
2888 Bool left
= resize_zone
& ZoneLeft
;
2890 if (! flags
.resizing
) {
2892 if (resize_zone
& ZoneTop
)
2893 cursor
= (resize_zone
& ZoneLeft
) ?
2894 openbox
.getUpperLeftAngleCursor() :
2895 openbox
.getUpperRightAngleCursor();
2897 cursor
= (resize_zone
& ZoneLeft
) ?
2898 openbox
.getLowerLeftAngleCursor() :
2899 openbox
.getLowerRightAngleCursor();
2900 XGrabPointer(display
, me
->window
, False
, ButtonMotionMask
|
2901 ButtonReleaseMask
, GrabModeAsync
, GrabModeAsync
, None
,
2902 cursor
, CurrentTime
);
2904 flags
.resizing
= True
;
2909 if (resize_zone
& ZoneRight
)
2910 frame
.grab_x
= me
->x
- screen
->getBorderWidth();
2912 frame
.grab_x
= me
->x
+ screen
->getBorderWidth();
2913 if (resize_zone
& ZoneTop
)
2914 frame
.grab_y
= me
->y
+ screen
->getBorderWidth() * 2;
2916 frame
.grab_y
= me
->y
- screen
->getBorderWidth() * 2;
2917 frame
.resize_x
= frame
.x
;
2918 frame
.resize_y
= frame
.y
;
2919 frame
.resize_w
= frame
.width
+ (frame
.border_w
* 2);
2920 frame
.resize_h
= frame
.height
+ (frame
.border_w
* 2);
2923 left_fixsize(&gx
, &gy
);
2925 right_fixsize(&gx
, &gy
);
2927 screen
->showGeometry(gx
, gy
);
2929 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2930 frame
.resize_x
, frame
.resize_y
,
2931 frame
.resize_w
- 1, frame
.resize_h
- 1);
2933 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2934 frame
.resize_x
, frame
.resize_y
,
2935 frame
.resize_w
- 1, frame
.resize_h
- 1);
2939 if (resize_zone
& ZoneTop
)
2940 frame
.resize_h
= frame
.height
- (me
->y
- frame
.grab_y
);
2942 frame
.resize_h
= frame
.height
+ (me
->y
- frame
.grab_y
);
2943 if (frame
.resize_h
< 1) frame
.resize_h
= 1;
2946 frame
.resize_x
= me
->x_root
- frame
.grab_x
;
2947 if (frame
.resize_x
> (signed) (frame
.x
+ frame
.width
))
2948 frame
.resize_x
= frame
.resize_x
+ frame
.width
- 1;
2950 left_fixsize(&gx
, &gy
);
2952 frame
.resize_w
= frame
.width
+ (me
->x
- frame
.grab_x
);
2953 if (frame
.resize_w
< 1) frame
.resize_w
= 1;
2955 right_fixsize(&gx
, &gy
);
2958 XDrawRectangle(display
, screen
->getRootWindow(), screen
->getOpGC(),
2959 frame
.resize_x
, frame
.resize_y
,
2960 frame
.resize_w
- 1, frame
.resize_h
- 1);
2962 screen
->showGeometry(gx
, gy
);
2969 void OpenboxWindow::shapeEvent(XShapeEvent
*) {
2970 if (openbox
.hasShapeExtensions()) {
2973 if (! validateClient()) return;
2974 XShapeCombineShape(display
, frame
.window
, ShapeBounding
,
2975 frame
.mwm_border_w
, frame
.y_border
+
2976 frame
.mwm_border_w
, client
.window
,
2977 ShapeBounding
, ShapeSet
);
2980 XRectangle xrect
[2];
2981 xrect
[0].x
= xrect
[0].y
= 0;
2982 xrect
[0].width
= frame
.width
;
2983 xrect
[0].height
= frame
.y_border
;
2985 if (decorations
.handle
) {
2987 xrect
[1].y
= frame
.y_handle
;
2988 xrect
[1].width
= frame
.width
;
2989 xrect
[1].height
= frame
.handle_h
+ frame
.border_w
;
2993 XShapeCombineRectangles(display
, frame
.window
, ShapeBounding
, 0, 0,
2994 xrect
, num
, ShapeUnion
, Unsorted
);
3002 bool OpenboxWindow::validateClient(void) {
3003 XSync(display
, False
);
3006 if (XCheckTypedWindowEvent(display
, client
.window
, DestroyNotify
, &e
) ||
3007 XCheckTypedWindowEvent(display
, client
.window
, UnmapNotify
, &e
)) {
3008 XPutBackEvent(display
, &e
);
3018 void OpenboxWindow::restore(void) {
3019 XChangeSaveSet(display
, client
.window
, SetModeDelete
);
3020 XSelectInput(display
, client
.window
, NoEventMask
);
3024 XUnmapWindow(display
, frame
.window
);
3025 XUnmapWindow(display
, client
.window
);
3027 XSetWindowBorderWidth(display
, client
.window
, client
.old_bw
);
3028 XReparentWindow(display
, client
.window
, screen
->getRootWindow(),
3029 client
.x
, client
.y
);
3030 XMapWindow(display
, client
.window
);
3038 void OpenboxWindow::timeout(void) {
3039 screen
->getWorkspace(workspace_number
)->raiseWindow(this);
3043 void OpenboxWindow::changeOpenboxHints(OpenboxHints
*net
) {
3044 if ((net
->flags
& AttribShaded
) &&
3045 ((openbox_attrib
.attrib
& AttribShaded
) !=
3046 (net
->attrib
& AttribShaded
)))
3049 if (flags
.visible
&& // watch out for requests when we can not be seen
3050 (net
->flags
& (AttribMaxVert
| AttribMaxHoriz
)) &&
3051 ((openbox_attrib
.attrib
& (AttribMaxVert
| AttribMaxHoriz
)) !=
3052 (net
->attrib
& (AttribMaxVert
| AttribMaxHoriz
)))) {
3053 if (flags
.maximized
) {
3058 if ((net
->flags
& AttribMaxHoriz
) && (net
->flags
& AttribMaxVert
))
3059 button
= ((net
->attrib
& (AttribMaxHoriz
| AttribMaxVert
)) ? 1 : 0);
3060 else if (net
->flags
& AttribMaxVert
)
3061 button
= ((net
->attrib
& AttribMaxVert
) ? 2 : 0);
3062 else if (net
->flags
& AttribMaxHoriz
)
3063 button
= ((net
->attrib
& AttribMaxHoriz
) ? 3 : 0);
3069 if ((net
->flags
& AttribOmnipresent
) &&
3070 ((openbox_attrib
.attrib
& AttribOmnipresent
) !=
3071 (net
->attrib
& AttribOmnipresent
)))
3074 if ((net
->flags
& AttribWorkspace
) &&
3075 (workspace_number
!= (signed) net
->workspace
)) {
3076 screen
->reassociateWindow(this, net
->workspace
, True
);
3078 if (screen
->getCurrentWorkspaceID() != (signed) net
->workspace
) withdraw();
3082 if (net
->flags
& AttribDecoration
) {
3083 switch (net
->decoration
) {
3085 decorations
.titlebar
= decorations
.border
= decorations
.handle
=
3086 decorations
.iconify
= decorations
.maximize
= decorations
.menu
= False
;
3092 decorations
.titlebar
= decorations
.iconify
= decorations
.menu
=
3093 decorations
.border
= True
;
3094 decorations
.handle
= (functions
.resize
&& !flags
.transient
);
3095 decorations
.maximize
= functions
.maximize
;
3100 decorations
.titlebar
= decorations
.iconify
= decorations
.menu
= True
;
3101 decorations
.border
= decorations
.border
= decorations
.handle
= False
;
3102 decorations
.maximize
= functions
.maximize
;
3107 decorations
.titlebar
= decorations
.menu
= True
;
3108 decorations
.iconify
= decorations
.border
= False
;
3109 decorations
.handle
= (functions
.resize
&& !flags
.transient
);
3110 decorations
.maximize
= functions
.maximize
;
3115 XMapSubwindows(display
, frame
.window
);
3116 XMapWindow(display
, frame
.window
);
3120 setState(current_state
);
3126 * Set the sizes of all components of the window frame
3127 * (the window decorations).
3128 * These values are based upon the current style settings and the client
3129 * window's dimentions.
3131 void OpenboxWindow::upsize(void) {
3132 frame
.bevel_w
= screen
->getBevelWidth();
3134 if (decorations
.border
) {
3135 frame
.border_w
= screen
->getBorderWidth();
3136 if (!flags
.transient
)
3137 frame
.mwm_border_w
= screen
->getFrameWidth();
3139 frame
.mwm_border_w
= 0;
3141 frame
.mwm_border_w
= frame
.border_w
= 0;
3144 if (decorations
.titlebar
) {
3145 // the height of the titlebar is based upon the height of the font being
3146 // used to display the window's title
3147 WindowStyle
*style
= screen
->getWindowStyle();
3148 if (i18n
->multibyte())
3149 frame
.title_h
= (style
->fontset_extents
->max_ink_extent
.height
+
3150 (frame
.bevel_w
* 2) + 2);
3152 frame
.title_h
= (style
->font
->ascent
+ style
->font
->descent
+
3153 (frame
.bevel_w
* 2) + 2);
3155 frame
.label_h
= frame
.title_h
- (frame
.bevel_w
* 2);
3156 frame
.button_w
= frame
.button_h
= (frame
.label_h
- 2);
3157 frame
.y_border
= frame
.title_h
+ frame
.border_w
;
3161 frame
.button_w
= frame
.button_h
= 0;
3165 frame
.border_h
= client
.height
+ frame
.mwm_border_w
* 2;
3167 if (decorations
.handle
) {
3168 frame
.y_handle
= frame
.y_border
+ frame
.border_h
+ frame
.border_w
;
3169 frame
.grip_w
= frame
.button_w
* 2;
3170 frame
.grip_h
= frame
.handle_h
= screen
->getHandleWidth();
3172 frame
.y_handle
= frame
.y_border
+ frame
.border_h
;
3174 frame
.grip_w
= frame
.grip_h
= 0;
3177 frame
.width
= client
.width
+ (frame
.mwm_border_w
* 2);
3178 frame
.height
= frame
.y_handle
+ frame
.handle_h
;
3183 * Set the size and position of the client window.
3184 * These values are based upon the current style settings and the frame
3185 * window's dimensions.
3187 void OpenboxWindow::downsize(void) {
3188 frame
.y_handle
= frame
.height
- frame
.handle_h
;
3189 frame
.border_h
= frame
.y_handle
- frame
.y_border
-
3190 (decorations
.handle
? frame
.border_w
: 0);
3192 client
.x
= frame
.x
+ frame
.mwm_border_w
+ frame
.border_w
;
3193 client
.y
= frame
.y
+ frame
.y_border
+ frame
.mwm_border_w
+ frame
.border_w
;
3195 client
.width
= frame
.width
- (frame
.mwm_border_w
* 2);
3196 client
.height
= frame
.height
- frame
.y_border
- (frame
.mwm_border_w
* 2)
3197 - frame
.handle_h
- (decorations
.handle
? frame
.border_w
: 0);
3199 frame
.y_handle
= frame
.border_h
+ frame
.y_border
+ frame
.border_w
;
3203 void OpenboxWindow::right_fixsize(int *gx
, int *gy
) {
3204 // calculate the size of the client window and conform it to the
3205 // size specified by the size hints of the client window...
3206 int dx
= 1 + frame
.resize_w
- client
.base_width
- (frame
.mwm_border_w
* 2) -
3207 (frame
.border_w
* 2) + (client
.width_inc
/ 2);
3208 int dy
= 1 + frame
.resize_h
- frame
.y_border
- client
.base_height
-
3209 frame
.handle_h
- (frame
.border_w
* 3) - (frame
.mwm_border_w
* 2)
3210 + (client
.height_inc
/ 2);
3212 if (dx
< (signed) client
.min_width
) dx
= client
.min_width
;
3213 if (dy
< (signed) client
.min_height
) dy
= client
.min_height
;
3214 if ((unsigned) dx
> client
.max_width
) dx
= client
.max_width
;
3215 if ((unsigned) dy
> client
.max_height
) dy
= client
.max_height
;
3217 dx
/= client
.width_inc
;
3218 dy
/= client
.height_inc
;
3223 dx
= (dx
* client
.width_inc
) + client
.base_width
;
3224 dy
= (dy
* client
.height_inc
) + client
.base_height
;
3226 frame
.resize_w
= dx
+ (frame
.mwm_border_w
* 2) + (frame
.border_w
* 2) - 1;
3227 frame
.resize_h
= dy
+ frame
.y_border
+ frame
.handle_h
+
3228 (frame
.mwm_border_w
* 2) + (frame
.border_w
* 3) - 1;
3229 if (resize_zone
& ZoneTop
)
3230 frame
.resize_y
= frame
.y
+ frame
.height
- frame
.resize_h
+
3231 screen
->getBorderWidth() * 2;
3235 void OpenboxWindow::left_fixsize(int *gx
, int *gy
) {
3236 // calculate the size of the client window and conform it to the
3237 // size specified by the size hints of the client window...
3238 int dx
= 1 + frame
.x
+ frame
.width
- frame
.resize_x
- client
.base_width
-
3239 (frame
.mwm_border_w
* 2) + (client
.width_inc
/ 2);
3240 int dy
= 1 + frame
.resize_h
- frame
.y_border
- client
.base_height
-
3241 frame
.handle_h
- (frame
.border_w
* 3) - (frame
.mwm_border_w
* 2)
3242 + (client
.height_inc
/ 2);
3244 if (dx
< (signed) client
.min_width
) dx
= client
.min_width
;
3245 if (dy
< (signed) client
.min_height
) dy
= client
.min_height
;
3246 if ((unsigned) dx
> client
.max_width
) dx
= client
.max_width
;
3247 if ((unsigned) dy
> client
.max_height
) dy
= client
.max_height
;
3249 dx
/= client
.width_inc
;
3250 dy
/= client
.height_inc
;
3255 dx
= (dx
* client
.width_inc
) + client
.base_width
;
3256 dy
= (dy
* client
.height_inc
) + client
.base_height
;
3258 frame
.resize_w
= dx
+ (frame
.mwm_border_w
* 2) + (frame
.border_w
* 2) - 1;
3259 frame
.resize_x
= frame
.x
+ frame
.width
- frame
.resize_w
+
3260 (frame
.border_w
* 2);
3261 frame
.resize_h
= dy
+ frame
.y_border
+ frame
.handle_h
+
3262 (frame
.mwm_border_w
* 2) + (frame
.border_w
* 3) - 1;
3263 if (resize_zone
& ZoneTop
)
3264 frame
.resize_y
= frame
.y
+ frame
.height
- frame
.resize_h
+
3265 screen
->getBorderWidth() * 2;