]> Dogcows Code - chaz/openbox/blob - src/Window.cc
merge the sticky window fix from 1.2.
[chaz/openbox] / src / Window.cc
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)
5 //
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:
12 //
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
15 //
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.
23
24 // stupid macros needed to access some functions in version 2 of the GNU C
25 // library
26 #ifndef _GNU_SOURCE
27 #define _GNU_SOURCE
28 #endif // _GNU_SOURCE
29
30 #ifdef HAVE_CONFIG_H
31 # include "../config.h"
32 #endif // HAVE_CONFIG_H
33
34 #include <X11/Xatom.h>
35 #include <X11/keysym.h>
36
37 #ifdef HAVE_STRING_H
38 # include <string.h>
39 #endif // HAVE_STRING_H
40
41 #ifdef DEBUG
42 # ifdef HAVE_STDIO_H
43 # include <stdio.h>
44 # endif // HAVE_STDIO_H
45 #endif // DEBUG
46
47 #include "i18n.h"
48 #include "openbox.h"
49 #include "Iconmenu.h"
50 #include "Screen.h"
51 #include "Toolbar.h"
52 #include "Window.h"
53 #include "Windowmenu.h"
54 #include "Workspace.h"
55 #ifdef SLIT
56 # include "Slit.h"
57 #endif // SLIT
58 #include "Util.h"
59
60 /*
61 * Initializes the class with default values/the window's set initial values.
62 */
63 OpenboxWindow::OpenboxWindow(Openbox &o, Window w, BScreen *s) : openbox(o) {
64 #ifdef DEBUG
65 fprintf(stderr, i18n(WindowSet, WindowCreating,
66 "OpenboxWindow::OpenboxWindow(): creating 0x%lx\n"),
67 w);
68 #endif // DEBUG
69
70 client.window = w;
71 display = openbox.getXDisplay();
72
73 openbox.grab();
74 if (! validateClient()) return;
75
76 // fetch client size and placement
77 XWindowAttributes wattrib;
78 if ((! XGetWindowAttributes(display, client.window, &wattrib)) ||
79 (! wattrib.screen) || wattrib.override_redirect) {
80 #ifdef DEBUG
81 fprintf(stderr,
82 i18n(WindowSet, WindowXGetWindowAttributesFail,
83 "OpenboxWindow::OpenboxWindow(): XGetWindowAttributes "
84 "failed\n"));
85 #endif // DEBUG
86
87 openbox.ungrab();
88 return;
89 }
90
91 if (s) {
92 screen = s;
93 } else {
94 screen = openbox.searchScreen(RootWindowOfScreen(wattrib.screen));
95 if (! screen) {
96 #ifdef DEBUG
97 fprintf(stderr, i18n(WindowSet, WindowCannotFindScreen,
98 "OpenboxWindow::OpenboxWindow(): can't find screen\n"
99 "\tfor root window 0x%lx\n"),
100 RootWindowOfScreen(wattrib.screen));
101 #endif // DEBUG
102
103 openbox.ungrab();
104 return;
105 }
106 }
107
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;
112 flags.maximized = 0;
113
114 openbox_attrib.workspace = workspace_number = window_number = -1;
115
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;
120
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;
124
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;
128
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;
134
135 client.wm_hint_flags = client.normal_hint_flags = 0;
136 client.transient_for = client.transient = 0;
137 client.title = 0;
138 client.title_len = 0;
139 client.icon_title = 0;
140 client.mwm_hint = (MwmHints *) 0;
141 client.openbox_hint = (OpenboxHints *) 0;
142
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;
151
152 windowmenu = 0;
153 lastButtonPressTime = 0;
154 image_ctrl = screen->getImageControl();
155
156 timer = new BTimer(openbox, *this);
157 timer->setTimeout(openbox.getAutoRaiseDelay());
158 timer->fireOnce(True);
159
160 getOpenboxHints();
161 if (! client.openbox_hint)
162 getMWMHints();
163
164 // get size, aspect, minimum/maximum size and other hints set by the
165 // client
166 getWMProtocols();
167 getWMHints();
168 getWMNormalHints();
169
170 #ifdef SLIT
171 if (client.initial_state == WithdrawnState) {
172 screen->getSlit()->addClient(client.window);
173 openbox.ungrab();
174 delete this;
175 return;
176 }
177 #endif // SLIT
178
179 flags.managed = True;
180 openbox.saveWindowSearch(client.window, this);
181
182 // determine if this is a transient window
183 Window win;
184 if (XGetTransientForHint(display, client.window, &win)) {
185 if (win && (win != client.window)) {
186 OpenboxWindow *tr;
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;
200 }
201 }
202 }
203
204 if (win == screen->getRootWindow()) flags.modal = True;
205 }
206
207 // adjust the window decorations based on transience and window sizes
208 if (flags.transient)
209 decorations.maximize = decorations.handle = functions.maximize = False;
210
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;
217 }
218 upsize();
219
220 place_window = true;
221 if (openbox.isStartup() || flags.transient ||
222 client.normal_hint_flags & (PPosition|USPosition)) {
223 setGravityOffsets();
224
225 if ((openbox.isStartup()) ||
226 (frame.x >= 0 &&
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;
231 }
232
233 frame.window = createToplevelWindow(frame.x, frame.y, frame.width,
234 frame.height,
235 frame.border_w);
236 openbox.saveWindowSearch(frame.window, this);
237
238 frame.plate = createChildWindow(frame.window);
239 openbox.saveWindowSearch(frame.plate, this);
240
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);
246 }
247
248 if (decorations.handle) {
249 frame.handle = createChildWindow(frame.window);
250 openbox.saveWindowSearch(frame.handle, this);
251
252 frame.left_grip =
253 createChildWindow(frame.handle, openbox.getLowerLeftAngleCursor());
254 openbox.saveWindowSearch(frame.left_grip, this);
255
256 frame.right_grip =
257 createChildWindow(frame.handle, openbox.getLowerRightAngleCursor());
258 openbox.saveWindowSearch(frame.right_grip, this);
259 }
260
261 associateClientWindow();
262
263 if (! screen->sloppyFocus())
264 openbox.grabButton(Button1, 0, frame.plate, True, ButtonPressMask,
265 GrabModeSync, GrabModeSync, frame.plate, None);
266
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);
275
276 positionWindows();
277 XRaiseWindow(display, frame.plate);
278 XMapSubwindows(display, frame.plate);
279 if (decorations.titlebar) XMapSubwindows(display, frame.title);
280 XMapSubwindows(display, frame.window);
281
282 if (decorations.menu)
283 windowmenu = new Windowmenu(*this);
284
285 decorate();
286
287 if (workspace_number < 0 || workspace_number >= screen->getWorkspaceCount())
288 screen->getCurrentWorkspace()->addWindow(this, place_window);
289 else
290 screen->getWorkspace(workspace_number)->addWindow(this, place_window);
291
292 configure(frame.x, frame.y, frame.width, frame.height);
293
294 if (flags.shaded) {
295 flags.shaded = False;
296 shade();
297 }
298
299 if (flags.maximized && functions.maximize) {
300 unsigned int button = flags.maximized;
301 flags.maximized = 0;
302 maximize(button);
303 }
304
305 setFocusFlag(False);
306
307 openbox.ungrab();
308 }
309
310
311 OpenboxWindow::~OpenboxWindow(void) {
312 if (flags.moving || flags.resizing) {
313 screen->hideGeometry();
314 XUngrabPointer(display, CurrentTime);
315 }
316
317 if (workspace_number != -1 && window_number != -1) {
318 if (flags.stuck) {
319 // make sure no other workspaces think that we're focused
320 for (int i=0; i < screen->getWorkspaceCount(); i++)
321 screen->getWorkspace(i)->removeWindow(this);
322 } else
323 screen->getWorkspace(workspace_number)->removeWindow(this);
324 } else if (flags.iconic)
325 screen->removeIcon(this);
326
327 if (timer) {
328 if (timer->isTiming()) timer->stop();
329 delete timer;
330 }
331
332 if (windowmenu) delete windowmenu;
333
334 if (client.title)
335 delete [] client.title;
336
337 if (client.icon_title)
338 delete [] client.icon_title;
339
340 if (client.mwm_hint)
341 XFree(client.mwm_hint);
342
343 if (client.openbox_hint)
344 XFree(client.openbox_hint);
345
346 if (client.window_group)
347 openbox.removeGroupSearch(client.window_group);
348
349 if (flags.transient && client.transient_for)
350 client.transient_for->client.transient = client.transient;
351 if (client.transient)
352 client.transient->client.transient_for = client.transient_for;
353
354 if (frame.close_button) {
355 openbox.removeWindowSearch(frame.close_button);
356 XDestroyWindow(display, frame.close_button);
357 }
358
359 if (frame.iconify_button) {
360 openbox.removeWindowSearch(frame.iconify_button);
361 XDestroyWindow(display, frame.iconify_button);
362 }
363
364 if (frame.maximize_button) {
365 openbox.removeWindowSearch(frame.maximize_button);
366 XDestroyWindow(display, frame.maximize_button);
367 }
368
369 if (frame.title) {
370 if (frame.ftitle)
371 image_ctrl->removeImage(frame.ftitle);
372
373 if (frame.utitle)
374 image_ctrl->removeImage(frame.utitle);
375
376 if (frame.flabel)
377 image_ctrl->removeImage(frame.flabel);
378
379 if( frame.ulabel)
380 image_ctrl->removeImage(frame.ulabel);
381
382 openbox.removeWindowSearch(frame.label);
383 openbox.removeWindowSearch(frame.title);
384 XDestroyWindow(display, frame.label);
385 XDestroyWindow(display, frame.title);
386 }
387
388 if (frame.handle) {
389 if (frame.fhandle)
390 image_ctrl->removeImage(frame.fhandle);
391
392 if (frame.uhandle)
393 image_ctrl->removeImage(frame.uhandle);
394
395 if (frame.fgrip)
396 image_ctrl->removeImage(frame.fgrip);
397
398 if (frame.ugrip)
399 image_ctrl->removeImage(frame.ugrip);
400
401 openbox.removeWindowSearch(frame.handle);
402 openbox.removeWindowSearch(frame.right_grip);
403 openbox.removeWindowSearch(frame.left_grip);
404 XDestroyWindow(display, frame.right_grip);
405 XDestroyWindow(display, frame.left_grip);
406 XDestroyWindow(display, frame.handle);
407 }
408
409 if (frame.fbutton)
410 image_ctrl->removeImage(frame.fbutton);
411
412 if (frame.ubutton)
413 image_ctrl->removeImage(frame.ubutton);
414
415 if (frame.pbutton)
416 image_ctrl->removeImage(frame.pbutton);
417
418 if (frame.plate) {
419 openbox.removeWindowSearch(frame.plate);
420 XDestroyWindow(display, frame.plate);
421 }
422
423 if (frame.window) {
424 openbox.removeWindowSearch(frame.window);
425 XDestroyWindow(display, frame.window);
426 }
427
428 if (flags.managed) {
429 openbox.removeWindowSearch(client.window);
430 screen->removeNetizen(client.window);
431 }
432 }
433
434
435 /*
436 * Creates a new top level window, with a given location, size, and border
437 * width.
438 * Returns: the newly created window
439 */
440 Window OpenboxWindow::createToplevelWindow(int x, int y, unsigned int width,
441 unsigned int height,
442 unsigned int borderwidth)
443 {
444 XSetWindowAttributes attrib_create;
445 unsigned long create_mask = CWBackPixmap | CWBorderPixel | CWColormap |
446 CWOverrideRedirect | CWEventMask;
447
448 attrib_create.background_pixmap = None;
449 attrib_create.colormap = screen->getColormap();
450 attrib_create.override_redirect = True;
451 attrib_create.event_mask = ButtonPressMask | ButtonReleaseMask |
452 ButtonMotionMask | EnterWindowMask;
453
454 return XCreateWindow(display, screen->getRootWindow(), x, y, width, height,
455 borderwidth, screen->getDepth(), InputOutput,
456 screen->getVisual(), create_mask,
457 &attrib_create);
458 }
459
460
461 /*
462 * Creates a child window, and optionally associates a given cursor with
463 * the new window.
464 */
465 Window OpenboxWindow::createChildWindow(Window parent, Cursor cursor) {
466 XSetWindowAttributes attrib_create;
467 unsigned long create_mask = CWBackPixmap | CWBorderPixel |
468 CWEventMask;
469
470 attrib_create.background_pixmap = None;
471 attrib_create.event_mask = ButtonPressMask | ButtonReleaseMask |
472 ButtonMotionMask | ExposureMask |
473 EnterWindowMask | LeaveWindowMask;
474
475 if (cursor) {
476 create_mask |= CWCursor;
477 attrib_create.cursor = cursor;
478 }
479
480 return XCreateWindow(display, parent, 0, 0, 1, 1, 0, screen->getDepth(),
481 InputOutput, screen->getVisual(), create_mask,
482 &attrib_create);
483 }
484
485
486 void OpenboxWindow::associateClientWindow(void) {
487 XSetWindowBorderWidth(display, client.window, 0);
488 getWMName();
489 getWMIconName();
490
491 XChangeSaveSet(display, client.window, SetModeInsert);
492 XSetWindowAttributes attrib_set;
493
494 XSelectInput(display, frame.plate, NoEventMask);
495 XReparentWindow(display, client.window, frame.plate, 0, 0);
496 XSelectInput(display, frame.plate, SubstructureRedirectMask);
497
498 XFlush(display);
499
500 attrib_set.event_mask = PropertyChangeMask | StructureNotifyMask |
501 FocusChangeMask;
502 attrib_set.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask |
503 ButtonMotionMask;
504
505 XChangeWindowAttributes(display, client.window, CWEventMask|CWDontPropagate,
506 &attrib_set);
507
508 #ifdef SHAPE
509 if (openbox.hasShapeExtensions()) {
510 XShapeSelectInput(display, client.window, ShapeNotifyMask);
511
512 int foo;
513 unsigned int ufoo;
514
515 XShapeQueryExtents(display, client.window, &flags.shaped, &foo, &foo,
516 &ufoo, &ufoo, &foo, &foo, &foo, &ufoo, &ufoo);
517
518 if (flags.shaped) {
519 XShapeCombineShape(display, frame.window, ShapeBounding,
520 frame.mwm_border_w, frame.y_border +
521 frame.mwm_border_w, client.window,
522 ShapeBounding, ShapeSet);
523
524 int num = 1;
525 XRectangle xrect[2];
526 xrect[0].x = xrect[0].y = 0;
527 xrect[0].width = frame.width;
528 xrect[0].height = frame.y_border;
529
530 if (decorations.handle) {
531 xrect[1].x = 0;
532 xrect[1].y = frame.y_handle;
533 xrect[1].width = frame.width;
534 xrect[1].height = frame.handle_h + frame.border_w;
535 num++;
536 }
537
538 XShapeCombineRectangles(display, frame.window, ShapeBounding, 0, 0,
539 xrect, num, ShapeUnion, Unsorted);
540 }
541 }
542 #endif // SHAPE
543
544 if (decorations.iconify) createIconifyButton();
545 if (decorations.maximize) createMaximizeButton();
546 if (decorations.close) createCloseButton();
547 }
548
549
550 void OpenboxWindow::decorate(void) {
551 Pixmap tmp = frame.fbutton;
552 BTexture *texture = &(screen->getWindowStyle()->b_focus);
553 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
554 frame.fbutton = None;
555 frame.fbutton_pixel = texture->getColor()->getPixel();
556 } else {
557 frame.fbutton =
558 image_ctrl->renderImage(frame.button_w, frame.button_h, texture);
559 }
560 if (tmp) image_ctrl->removeImage(tmp);
561
562 tmp = frame.ubutton;
563 texture = &(screen->getWindowStyle()->b_unfocus);
564 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
565 frame.ubutton = None;
566 frame.ubutton_pixel = texture->getColor()->getPixel();
567 } else {
568 frame.ubutton =
569 image_ctrl->renderImage(frame.button_w, frame.button_h, texture);
570 }
571 if (tmp) image_ctrl->removeImage(tmp);
572
573 tmp = frame.pbutton;
574 texture = &(screen->getWindowStyle()->b_pressed);
575 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
576 frame.pbutton = None;
577 frame.pbutton_pixel = texture->getColor()->getPixel();
578 } else {
579 frame.pbutton =
580 image_ctrl->renderImage(frame.button_w, frame.button_h, texture);
581 }
582 if (tmp) image_ctrl->removeImage(tmp);
583
584 if (decorations.titlebar) {
585 tmp = frame.ftitle;
586 texture = &(screen->getWindowStyle()->t_focus);
587 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
588 frame.ftitle = None;
589 frame.ftitle_pixel = texture->getColor()->getPixel();
590 } else {
591 frame.ftitle =
592 image_ctrl->renderImage(frame.width, frame.title_h, texture);
593 }
594 if (tmp) image_ctrl->removeImage(tmp);
595
596 tmp = frame.utitle;
597 texture = &(screen->getWindowStyle()->t_unfocus);
598 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
599 frame.utitle = None;
600 frame.utitle_pixel = texture->getColor()->getPixel();
601 } else {
602 frame.utitle =
603 image_ctrl->renderImage(frame.width, frame.title_h, texture);
604 }
605 if (tmp) image_ctrl->removeImage(tmp);
606
607 XSetWindowBorder(display, frame.title,
608 screen->getBorderColor()->getPixel());
609
610 decorateLabel();
611 }
612
613 if (decorations.border) {
614 frame.fborder_pixel = screen->getWindowStyle()->f_focus.getPixel();
615 frame.uborder_pixel = screen->getWindowStyle()->f_unfocus.getPixel();
616 openbox_attrib.flags |= AttribDecoration;
617 openbox_attrib.decoration = DecorNormal;
618 } else {
619 openbox_attrib.flags |= AttribDecoration;
620 openbox_attrib.decoration = DecorNone;
621 }
622
623 if (decorations.handle) {
624 tmp = frame.fhandle;
625 texture = &(screen->getWindowStyle()->h_focus);
626 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
627 frame.fhandle = None;
628 frame.fhandle_pixel = texture->getColor()->getPixel();
629 } else {
630 frame.fhandle =
631 image_ctrl->renderImage(frame.width, frame.handle_h, texture);
632 }
633 if (tmp) image_ctrl->removeImage(tmp);
634
635 tmp = frame.uhandle;
636 texture = &(screen->getWindowStyle()->h_unfocus);
637 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
638 frame.uhandle = None;
639 frame.uhandle_pixel = texture->getColor()->getPixel();
640 } else {
641 frame.uhandle =
642 image_ctrl->renderImage(frame.width, frame.handle_h, texture);
643 }
644 if (tmp) image_ctrl->removeImage(tmp);
645
646 tmp = frame.fgrip;
647 texture = &(screen->getWindowStyle()->g_focus);
648 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
649 frame.fgrip = None;
650 frame.fgrip_pixel = texture->getColor()->getPixel();
651 } else {
652 frame.fgrip =
653 image_ctrl->renderImage(frame.grip_w, frame.grip_h, texture);
654 }
655 if (tmp) image_ctrl->removeImage(tmp);
656
657 tmp = frame.ugrip;
658 texture = &(screen->getWindowStyle()->g_unfocus);
659 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
660 frame.ugrip = None;
661 frame.ugrip_pixel = texture->getColor()->getPixel();
662 } else {
663 frame.ugrip =
664 image_ctrl->renderImage(frame.grip_w, frame.grip_h, texture);
665 }
666 if (tmp) image_ctrl->removeImage(tmp);
667
668 XSetWindowBorder(display, frame.handle,
669 screen->getBorderColor()->getPixel());
670 XSetWindowBorder(display, frame.left_grip,
671 screen->getBorderColor()->getPixel());
672 XSetWindowBorder(display, frame.right_grip,
673 screen->getBorderColor()->getPixel());
674 }
675
676 XSetWindowBorder(display, frame.window,
677 screen->getBorderColor()->getPixel());
678 }
679
680
681 void OpenboxWindow::decorateLabel(void) {
682 Pixmap tmp = frame.flabel;
683 BTexture *texture = &(screen->getWindowStyle()->l_focus);
684 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
685 frame.flabel = None;
686 frame.flabel_pixel = texture->getColor()->getPixel();
687 } else {
688 frame.flabel =
689 image_ctrl->renderImage(frame.label_w, frame.label_h, texture);
690 }
691 if (tmp) image_ctrl->removeImage(tmp);
692
693 tmp = frame.ulabel;
694 texture = &(screen->getWindowStyle()->l_unfocus);
695 if (texture->getTexture() == (BImage_Flat | BImage_Solid)) {
696 frame.ulabel = None;
697 frame.ulabel_pixel = texture->getColor()->getPixel();
698 } else {
699 frame.ulabel =
700 image_ctrl->renderImage(frame.label_w, frame.label_h, texture);
701 }
702 if (tmp) image_ctrl->removeImage(tmp);
703 }
704
705
706 void OpenboxWindow::createCloseButton(void) {
707 if (decorations.close && frame.title != None) {
708 frame.close_button = createChildWindow(frame.title);
709 openbox.saveWindowSearch(frame.close_button, this);
710 }
711 }
712
713
714 void OpenboxWindow::createIconifyButton(void) {
715 if (decorations.iconify && frame.title != None) {
716 frame.iconify_button = createChildWindow(frame.title);
717 openbox.saveWindowSearch(frame.iconify_button, this);
718 }
719 }
720
721
722 void OpenboxWindow::createMaximizeButton(void) {
723 if (decorations.maximize && frame.title != None) {
724 frame.maximize_button = createChildWindow(frame.title);
725 openbox.saveWindowSearch(frame.maximize_button, this);
726 }
727 }
728
729
730 void OpenboxWindow::positionButtons() {
731 const char *format = openbox.getTitleBarLayout();
732 const unsigned int bw = frame.bevel_w + 1;
733 const unsigned int by = frame.bevel_w + 1;
734 unsigned int bx = frame.bevel_w + 1;
735 unsigned int bcount = strlen(format) - 1;
736
737 if (!decorations.close)
738 bcount--;
739 if (!decorations.maximize)
740 bcount--;
741 if (!decorations.iconify)
742 bcount--;
743 frame.label_w = frame.width - bx * 2 - (frame.button_w + bw) * bcount;
744
745 bool hasclose, hasiconify, hasmaximize;
746 hasclose = hasiconify = hasmaximize = false;
747
748 for (int i = 0; format[i] != '\0' && i < 4; i++) {
749 switch(format[i]) {
750 case 'C':
751 if (decorations.close) {
752 if (frame.close_button == None)
753 createCloseButton();
754 XMoveResizeWindow(display, frame.close_button, bx, by,
755 frame.button_w, frame.button_h);
756 XMapWindow(display, frame.close_button);
757 XClearWindow(display, frame.close_button);
758 bx += frame.button_w + bw;
759 hasclose = true;
760 }
761 break;
762 case 'I':
763 if (decorations.iconify) {
764 if (frame.iconify_button == None)
765 createIconifyButton();
766 XMoveResizeWindow(display, frame.iconify_button, bx, by,
767 frame.button_w, frame.button_h);
768 XMapWindow(display, frame.iconify_button);
769 XClearWindow(display, frame.iconify_button);
770 bx += frame.button_w + bw;
771 hasiconify = true;
772 }
773 break;
774 case 'M':
775 if (decorations.maximize) {
776 if (frame.maximize_button == None)
777 createMaximizeButton();
778 XMoveResizeWindow(display, frame.maximize_button, bx, by,
779 frame.button_w, frame.button_h);
780 XMapWindow(display, frame.maximize_button);
781 XClearWindow(display, frame.maximize_button);
782 bx += frame.button_w + bw;
783 hasmaximize = true;
784 }
785 break;
786 case 'L':
787 XMoveResizeWindow(display, frame.label, bx, by - 1,
788 frame.label_w, frame.label_h);
789 bx += frame.label_w + bw;
790 break;
791 }
792 }
793
794 if (!hasclose && frame.close_button) {
795 openbox.removeWindowSearch(frame.close_button);
796 XDestroyWindow(display, frame.close_button);
797 frame.close_button = None;
798 }
799 if (!hasiconify && frame.iconify_button) {
800 openbox.removeWindowSearch(frame.iconify_button);
801 XDestroyWindow(display, frame.iconify_button);
802 frame.iconify_button = None;
803 }
804 if (!hasmaximize && frame.iconify_button) {
805 openbox.removeWindowSearch(frame.maximize_button);
806 XDestroyWindow(display, frame.maximize_button);
807 frame.maximize_button = None;
808 }
809
810 redrawLabel();
811 redrawAllButtons();
812 }
813
814
815 void OpenboxWindow::reconfigure(void) {
816 upsize();
817
818 client.x = frame.x + frame.mwm_border_w + frame.border_w;
819 client.y = frame.y + frame.y_border + frame.mwm_border_w +
820 frame.border_w;
821
822 if (client.title) {
823 if (i18n.multibyte()) {
824 XRectangle ink, logical;
825 XmbTextExtents(screen->getWindowStyle()->fontset,
826 client.title, client.title_len, &ink, &logical);
827 client.title_text_w = logical.width;
828 } else {
829 client.title_text_w = XTextWidth(screen->getWindowStyle()->font,
830 client.title, client.title_len);
831 }
832 client.title_text_w += (frame.bevel_w * 4);
833 }
834
835 positionWindows();
836 decorate();
837
838 XClearWindow(display, frame.window);
839 setFocusFlag(flags.focused);
840
841 configure(frame.x, frame.y, frame.width, frame.height);
842
843 if (! screen->sloppyFocus())
844 openbox.grabButton(Button1, 0, frame.plate, True, ButtonPressMask,
845 GrabModeSync, GrabModeSync, None, None);
846 else
847 openbox.ungrabButton(Button1, 0, frame.plate);
848
849 if (windowmenu) {
850 windowmenu->move(windowmenu->getX(), frame.y + frame.title_h);
851 windowmenu->reconfigure();
852 }
853
854 // re-get the timeout delay
855 timer->setTimeout(openbox.getAutoRaiseDelay());
856 }
857
858
859 void OpenboxWindow::positionWindows(void) {
860 XResizeWindow(display, frame.window, frame.width,
861 ((flags.shaded) ? frame.title_h : frame.height));
862 XSetWindowBorderWidth(display, frame.window, frame.border_w);
863 XSetWindowBorderWidth(display, frame.plate, frame.mwm_border_w);
864 XMoveResizeWindow(display, frame.plate, 0, frame.y_border,
865 client.width, client.height);
866 XMoveResizeWindow(display, client.window, 0, 0, client.width, client.height);
867
868 if (decorations.titlebar) {
869 XSetWindowBorderWidth(display, frame.title, frame.border_w);
870 XMoveResizeWindow(display, frame.title, -frame.border_w,
871 -frame.border_w, frame.width, frame.title_h);
872
873 positionButtons();
874 } else if (frame.title) {
875 XUnmapWindow(display, frame.title);
876 }
877 if (decorations.handle) {
878 XSetWindowBorderWidth(display, frame.handle, frame.border_w);
879 XSetWindowBorderWidth(display, frame.left_grip, frame.border_w);
880 XSetWindowBorderWidth(display, frame.right_grip, frame.border_w);
881
882 XMoveResizeWindow(display, frame.handle, -frame.border_w,
883 frame.y_handle - frame.border_w,
884 frame.width, frame.handle_h);
885 XMoveResizeWindow(display, frame.left_grip, -frame.border_w,
886 -frame.border_w, frame.grip_w, frame.grip_h);
887 XMoveResizeWindow(display, frame.right_grip,
888 frame.width - frame.grip_w - frame.border_w,
889 -frame.border_w, frame.grip_w, frame.grip_h);
890 XMapSubwindows(display, frame.handle);
891 } else if (frame.handle) {
892 XUnmapWindow(display, frame.handle);
893 }
894 }
895
896
897 void OpenboxWindow::getWMName(void) {
898 if (client.title) {
899 delete [] client.title;
900 client.title = (char *) 0;
901 }
902
903 XTextProperty text_prop;
904 char **list;
905 int num;
906
907 if (XGetWMName(display, client.window, &text_prop)) {
908 if (text_prop.value && text_prop.nitems > 0) {
909 if (text_prop.encoding != XA_STRING) {
910 text_prop.nitems = strlen((char *) text_prop.value);
911
912 if ((XmbTextPropertyToTextList(display, &text_prop,
913 &list, &num) == Success) &&
914 (num > 0) && *list) {
915 client.title = bstrdup(*list);
916 XFreeStringList(list);
917 } else {
918 client.title = bstrdup((char *) text_prop.value);
919 }
920 } else {
921 client.title = bstrdup((char *) text_prop.value);
922 }
923 XFree((char *) text_prop.value);
924 } else {
925 client.title = bstrdup(i18n(WindowSet, WindowUnnamed,
926 "Unnamed"));
927 }
928 } else {
929 client.title = bstrdup(i18n(WindowSet, WindowUnnamed,
930 "Unnamed"));
931 }
932 client.title_len = strlen(client.title);
933
934 if (i18n.multibyte()) {
935 XRectangle ink, logical;
936 XmbTextExtents(screen->getWindowStyle()->fontset,
937 client.title, client.title_len, &ink, &logical);
938 client.title_text_w = logical.width;
939 } else {
940 client.title_len = strlen(client.title);
941 client.title_text_w = XTextWidth(screen->getWindowStyle()->font,
942 client.title, client.title_len);
943 }
944
945 client.title_text_w += (frame.bevel_w * 4);
946 }
947
948
949 void OpenboxWindow::getWMIconName(void) {
950 if (client.icon_title) {
951 delete [] client.icon_title;
952 client.icon_title = (char *) 0;
953 }
954
955 XTextProperty text_prop;
956 char **list;
957 int num;
958
959 if (XGetWMIconName(display, client.window, &text_prop)) {
960 if (text_prop.value && text_prop.nitems > 0) {
961 if (text_prop.encoding != XA_STRING) {
962 text_prop.nitems = strlen((char *) text_prop.value);
963
964 if ((XmbTextPropertyToTextList(display, &text_prop,
965 &list, &num) == Success) &&
966 (num > 0) && *list) {
967 client.icon_title = bstrdup(*list);
968 XFreeStringList(list);
969 } else {
970 client.icon_title = bstrdup((char *) text_prop.value);
971 }
972 } else {
973 client.icon_title = bstrdup((char *) text_prop.value);
974 }
975 XFree((char *) text_prop.value);
976 } else {
977 client.icon_title = bstrdup(client.title);
978 }
979 } else {
980 client.icon_title = bstrdup(client.title);
981 }
982 }
983
984
985 /*
986 * Retrieve which WM Protocols are supported by the client window.
987 * If the WM_DELETE_WINDOW protocol is supported, add the close button to the
988 * window's decorations and allow the close behavior.
989 * If the WM_TAKE_FOCUS protocol is supported, save a value that indicates
990 * this.
991 */
992 void OpenboxWindow::getWMProtocols(void) {
993 Atom *proto;
994 int num_return = 0;
995
996 if (XGetWMProtocols(display, client.window, &proto, &num_return)) {
997 for (int i = 0; i < num_return; ++i) {
998 if (proto[i] == openbox.getWMDeleteAtom())
999 functions.close = decorations.close = True;
1000 else if (proto[i] == openbox.getWMTakeFocusAtom())
1001 flags.send_focus_message = True;
1002 else if (proto[i] == openbox.getOpenboxStructureMessagesAtom())
1003 screen->addNetizen(new Netizen(*screen, client.window));
1004 }
1005
1006 XFree(proto);
1007 }
1008 }
1009
1010
1011 /*
1012 * Gets the value of the WM_HINTS property.
1013 * If the property is not set, then use a set of default values.
1014 */
1015 void OpenboxWindow::getWMHints(void) {
1016 XWMHints *wmhint = XGetWMHints(display, client.window);
1017 if (! wmhint) {
1018 flags.visible = True;
1019 flags.iconic = False;
1020 focus_mode = F_Passive;
1021 client.window_group = None;
1022 client.initial_state = NormalState;
1023 return;
1024 }
1025 client.wm_hint_flags = wmhint->flags;
1026 if (wmhint->flags & InputHint) {
1027 if (wmhint->input == True) {
1028 if (flags.send_focus_message)
1029 focus_mode = F_LocallyActive;
1030 else
1031 focus_mode = F_Passive;
1032 } else {
1033 if (flags.send_focus_message)
1034 focus_mode = F_GloballyActive;
1035 else
1036 focus_mode = F_NoInput;
1037 }
1038 } else {
1039 focus_mode = F_Passive;
1040 }
1041
1042 if (wmhint->flags & StateHint)
1043 client.initial_state = wmhint->initial_state;
1044 else
1045 client.initial_state = NormalState;
1046
1047 if (wmhint->flags & WindowGroupHint) {
1048 if (! client.window_group) {
1049 client.window_group = wmhint->window_group;
1050 openbox.saveGroupSearch(client.window_group, this);
1051 }
1052 } else {
1053 client.window_group = None;
1054 }
1055 XFree(wmhint);
1056 }
1057
1058
1059 /*
1060 * Gets the value of the WM_NORMAL_HINTS property.
1061 * If the property is not set, then use a set of default values.
1062 */
1063 void OpenboxWindow::getWMNormalHints(void) {
1064 long icccm_mask;
1065 XSizeHints sizehint;
1066
1067 client.min_width = client.min_height =
1068 client.base_width = client.base_height =
1069 client.width_inc = client.height_inc = 1;
1070 client.max_width = screen->size().w();
1071 client.max_height = screen->size().h();
1072 client.min_aspect_x = client.min_aspect_y =
1073 client.max_aspect_x = client.max_aspect_y = 1;
1074 client.win_gravity = NorthWestGravity;
1075
1076 if (! XGetWMNormalHints(display, client.window, &sizehint, &icccm_mask))
1077 return;
1078
1079 client.normal_hint_flags = sizehint.flags;
1080
1081 if (sizehint.flags & PMinSize) {
1082 client.min_width = sizehint.min_width;
1083 client.min_height = sizehint.min_height;
1084 }
1085
1086 if (sizehint.flags & PMaxSize) {
1087 client.max_width = sizehint.max_width;
1088 client.max_height = sizehint.max_height;
1089 }
1090
1091 if (sizehint.flags & PResizeInc) {
1092 client.width_inc = sizehint.width_inc;
1093 client.height_inc = sizehint.height_inc;
1094 }
1095
1096 if (sizehint.flags & PAspect) {
1097 client.min_aspect_x = sizehint.min_aspect.x;
1098 client.min_aspect_y = sizehint.min_aspect.y;
1099 client.max_aspect_x = sizehint.max_aspect.x;
1100 client.max_aspect_y = sizehint.max_aspect.y;
1101 }
1102
1103 if (sizehint.flags & PBaseSize) {
1104 client.base_width = sizehint.base_width;
1105 client.base_height = sizehint.base_height;
1106 }
1107
1108 if (sizehint.flags & PWinGravity)
1109 client.win_gravity = sizehint.win_gravity;
1110 }
1111
1112
1113 /*
1114 * Gets the MWM hints for the class' contained window.
1115 * This is used while initializing the window to its first state, and not
1116 * thereafter.
1117 * Returns: true if the MWM hints are successfully retreived and applied; false
1118 * if they are not.
1119 */
1120 void OpenboxWindow::getMWMHints(void) {
1121 int format;
1122 Atom atom_return;
1123 unsigned long num, len;
1124
1125 int ret = XGetWindowProperty(display, client.window,
1126 openbox.getMotifWMHintsAtom(), 0,
1127 PropMwmHintsElements, False,
1128 openbox.getMotifWMHintsAtom(), &atom_return,
1129 &format, &num, &len,
1130 (unsigned char **) &client.mwm_hint);
1131
1132 if (ret != Success || !client.mwm_hint || num != PropMwmHintsElements)
1133 return;
1134
1135 if (client.mwm_hint->flags & MwmHintsDecorations) {
1136 if (client.mwm_hint->decorations & MwmDecorAll) {
1137 decorations.titlebar = decorations.handle = decorations.border =
1138 decorations.iconify = decorations.maximize =
1139 decorations.close = decorations.menu = True;
1140 } else {
1141 decorations.titlebar = decorations.handle = decorations.border =
1142 decorations.iconify = decorations.maximize =
1143 decorations.close = decorations.menu = False;
1144
1145 if (client.mwm_hint->decorations & MwmDecorBorder)
1146 decorations.border = True;
1147 if (client.mwm_hint->decorations & MwmDecorHandle)
1148 decorations.handle = True;
1149 if (client.mwm_hint->decorations & MwmDecorTitle)
1150 decorations.titlebar = True;
1151 if (client.mwm_hint->decorations & MwmDecorMenu)
1152 decorations.menu = True;
1153 if (client.mwm_hint->decorations & MwmDecorIconify)
1154 decorations.iconify = True;
1155 if (client.mwm_hint->decorations & MwmDecorMaximize)
1156 decorations.maximize = True;
1157 }
1158 }
1159
1160 if (client.mwm_hint->flags & MwmHintsFunctions) {
1161 if (client.mwm_hint->functions & MwmFuncAll) {
1162 functions.resize = functions.move = functions.iconify =
1163 functions.maximize = functions.close = True;
1164 } else {
1165 functions.resize = functions.move = functions.iconify =
1166 functions.maximize = functions.close = False;
1167
1168 if (client.mwm_hint->functions & MwmFuncResize)
1169 functions.resize = True;
1170 if (client.mwm_hint->functions & MwmFuncMove)
1171 functions.move = True;
1172 if (client.mwm_hint->functions & MwmFuncIconify)
1173 functions.iconify = True;
1174 if (client.mwm_hint->functions & MwmFuncMaximize)
1175 functions.maximize = True;
1176 if (client.mwm_hint->functions & MwmFuncClose)
1177 functions.close = True;
1178 }
1179 }
1180 }
1181
1182
1183 /*
1184 * Gets the openbox hints from the class' contained window.
1185 * This is used while initializing the window to its first state, and not
1186 * thereafter.
1187 * Returns: true if the hints are successfully retreived and applied; false if
1188 * they are not.
1189 */
1190 void OpenboxWindow::getOpenboxHints(void) {
1191 int format;
1192 Atom atom_return;
1193 unsigned long num, len;
1194
1195 int ret = XGetWindowProperty(display, client.window,
1196 openbox.getOpenboxHintsAtom(), 0,
1197 PropOpenboxHintsElements, False,
1198 openbox.getOpenboxHintsAtom(), &atom_return,
1199 &format, &num, &len,
1200 (unsigned char **) &client.openbox_hint);
1201 if (ret != Success || !client.openbox_hint ||
1202 num != PropOpenboxHintsElements)
1203 return;
1204
1205 if (client.openbox_hint->flags & AttribShaded)
1206 flags.shaded = (client.openbox_hint->attrib & AttribShaded);
1207
1208 if ((client.openbox_hint->flags & AttribMaxHoriz) &&
1209 (client.openbox_hint->flags & AttribMaxVert))
1210 flags.maximized = (client.openbox_hint->attrib &
1211 (AttribMaxHoriz | AttribMaxVert)) ? 1 : 0;
1212 else if (client.openbox_hint->flags & AttribMaxVert)
1213 flags.maximized = (client.openbox_hint->attrib & AttribMaxVert) ? 2 : 0;
1214 else if (client.openbox_hint->flags & AttribMaxHoriz)
1215 flags.maximized = (client.openbox_hint->attrib & AttribMaxHoriz) ? 3 : 0;
1216
1217 if (client.openbox_hint->flags & AttribOmnipresent)
1218 flags.stuck = (client.openbox_hint->attrib & AttribOmnipresent);
1219
1220 if (client.openbox_hint->flags & AttribWorkspace)
1221 workspace_number = client.openbox_hint->workspace;
1222
1223 // if (client.openbox_hint->flags & AttribStack)
1224 // don't yet have always on top/bottom for openbox yet... working
1225 // on that
1226
1227 if (client.openbox_hint->flags & AttribDecoration) {
1228 switch (client.openbox_hint->decoration) {
1229 case DecorNone:
1230 decorations.titlebar = decorations.border = decorations.handle =
1231 decorations.iconify = decorations.maximize =
1232 decorations.menu = False;
1233 functions.resize = functions.move = functions.iconify =
1234 functions.maximize = False;
1235
1236 break;
1237
1238 case DecorTiny:
1239 decorations.titlebar = decorations.iconify = decorations.menu =
1240 functions.move = functions.iconify = True;
1241 decorations.border = decorations.handle = decorations.maximize =
1242 functions.resize = functions.maximize = False;
1243
1244 break;
1245
1246 case DecorTool:
1247 decorations.titlebar = decorations.menu = functions.move = True;
1248 decorations.iconify = decorations.border = decorations.handle =
1249 decorations.maximize = functions.resize = functions.maximize =
1250 functions.iconify = False;
1251
1252 break;
1253
1254 case DecorNormal:
1255 default:
1256 decorations.titlebar = decorations.border = decorations.handle =
1257 decorations.iconify = decorations.maximize =
1258 decorations.menu = True;
1259 functions.resize = functions.move = functions.iconify =
1260 functions.maximize = True;
1261
1262 break;
1263 }
1264
1265 reconfigure();
1266 }
1267 }
1268
1269
1270 void OpenboxWindow::configure(int dx, int dy,
1271 unsigned int dw, unsigned int dh) {
1272 Bool send_event = (frame.x != dx || frame.y != dy);
1273
1274 if ((dw != frame.width) || (dh != frame.height)) {
1275 if ((((signed) frame.width) + dx) < 0) dx = 0;
1276 if ((((signed) frame.height) + dy) < 0) dy = 0;
1277
1278 frame.x = dx;
1279 frame.y = dy;
1280 frame.width = dw;
1281 frame.height = dh;
1282
1283 downsize();
1284
1285 #ifdef SHAPE
1286 if (openbox.hasShapeExtensions() && flags.shaped) {
1287 XShapeCombineShape(display, frame.window, ShapeBounding,
1288 frame.mwm_border_w, frame.y_border +
1289 frame.mwm_border_w, client.window,
1290 ShapeBounding, ShapeSet);
1291
1292 int num = 1;
1293 XRectangle xrect[2];
1294 xrect[0].x = xrect[0].y = 0;
1295 xrect[0].width = frame.width;
1296 xrect[0].height = frame.y_border;
1297
1298 if (decorations.handle) {
1299 xrect[1].x = 0;
1300 xrect[1].y = frame.y_handle;
1301 xrect[1].width = frame.width;
1302 xrect[1].height = frame.handle_h + frame.border_w;
1303 num++;
1304 }
1305
1306 XShapeCombineRectangles(display, frame.window, ShapeBounding, 0, 0,
1307 xrect, num, ShapeUnion, Unsorted);
1308 }
1309 #endif // SHAPE
1310
1311 XMoveWindow(display, frame.window, frame.x, frame.y);
1312
1313 setFocusFlag(flags.focused);
1314 positionWindows();
1315 decorate();
1316 } else {
1317 frame.x = dx;
1318 frame.y = dy;
1319
1320 XMoveWindow(display, frame.window, frame.x, frame.y);
1321
1322 if (! flags.moving) send_event = True;
1323 }
1324
1325 if (send_event && ! flags.moving) {
1326 client.x = dx + frame.mwm_border_w + frame.border_w;
1327 client.y = dy + frame.y_border + frame.mwm_border_w +
1328 frame.border_w;
1329
1330 XEvent event;
1331 event.type = ConfigureNotify;
1332
1333 event.xconfigure.display = display;
1334 event.xconfigure.event = client.window;
1335 event.xconfigure.window = client.window;
1336 event.xconfigure.x = client.x;
1337 event.xconfigure.y = client.y;
1338 event.xconfigure.width = client.width;
1339 event.xconfigure.height = client.height;
1340 event.xconfigure.border_width = client.old_bw;
1341 event.xconfigure.above = frame.window;
1342 event.xconfigure.override_redirect = False;
1343
1344 XSendEvent(display, client.window, True, NoEventMask, &event);
1345
1346 screen->updateNetizenConfigNotify(&event);
1347 }
1348 }
1349
1350
1351 bool OpenboxWindow::setInputFocus(void) {
1352 if (((signed) (frame.x + frame.width)) < 0) {
1353 if (((signed) (frame.y + frame.y_border)) < 0)
1354 configure(frame.border_w, frame.border_w, frame.width, frame.height);
1355 else if (frame.y > (signed) screen->size().h())
1356 configure(frame.border_w, screen->size().h() - frame.height,
1357 frame.width, frame.height);
1358 else
1359 configure(frame.border_w, frame.y + frame.border_w,
1360 frame.width, frame.height);
1361 } else if (frame.x > (signed) screen->size().w()) {
1362 if (((signed) (frame.y + frame.y_border)) < 0)
1363 configure(screen->size().w() - frame.width, frame.border_w,
1364 frame.width, frame.height);
1365 else if (frame.y > (signed) screen->size().h())
1366 configure(screen->size().w() - frame.width,
1367 screen->size().h() - frame.height, frame.width, frame.height);
1368 else
1369 configure(screen->size().w() - frame.width,
1370 frame.y + frame.border_w, frame.width, frame.height);
1371 }
1372
1373 openbox.grab();
1374 if (! validateClient()) return False;
1375
1376 bool ret = false;
1377
1378 if (client.transient && flags.modal) {
1379 ret = client.transient->setInputFocus();
1380 } else if (! flags.focused) {
1381 if (focus_mode == F_LocallyActive || focus_mode == F_Passive) {
1382 XSetInputFocus(display, client.window,
1383 RevertToPointerRoot, CurrentTime);
1384 openbox.focusWindow(this);
1385
1386 if (flags.send_focus_message) {
1387 XEvent ce;
1388 ce.xclient.type = ClientMessage;
1389 ce.xclient.message_type = openbox.getWMProtocolsAtom();
1390 ce.xclient.display = display;
1391 ce.xclient.window = client.window;
1392 ce.xclient.format = 32;
1393 ce.xclient.data.l[0] = openbox.getWMTakeFocusAtom();
1394 ce.xclient.data.l[1] = openbox.getLastTime();
1395 ce.xclient.data.l[2] = 0l;
1396 ce.xclient.data.l[3] = 0l;
1397 ce.xclient.data.l[4] = 0l;
1398 XSendEvent(display, client.window, False, NoEventMask, &ce);
1399 }
1400
1401 if (screen->sloppyFocus() && screen->autoRaise())
1402 timer->start();
1403
1404 ret = true;
1405 }
1406 }
1407
1408 openbox.ungrab();
1409
1410 return ret;
1411 }
1412
1413
1414 void OpenboxWindow::iconify(void) {
1415 if (flags.iconic) return;
1416
1417 if (flags.moving)
1418 endMove();
1419
1420 if (windowmenu) windowmenu->hide();
1421
1422 setState(IconicState);
1423
1424 XSelectInput(display, client.window, NoEventMask);
1425 XUnmapWindow(display, client.window);
1426 XSelectInput(display, client.window,
1427 PropertyChangeMask | StructureNotifyMask | FocusChangeMask);
1428
1429 XUnmapWindow(display, frame.window);
1430 flags.visible = False;
1431 flags.iconic = True;
1432
1433 screen->getWorkspace(workspace_number)->removeWindow(this);
1434
1435 if (flags.transient && client.transient_for &&
1436 !client.transient_for->flags.iconic) {
1437 client.transient_for->iconify();
1438 }
1439 screen->addIcon(this);
1440
1441 if (client.transient && !client.transient->flags.iconic) {
1442 client.transient->iconify();
1443 }
1444 }
1445
1446
1447 void OpenboxWindow::deiconify(bool reassoc, bool raise, bool initial) {
1448 if (flags.iconic || reassoc)
1449 screen->reassociateWindow(this, -1, False);
1450 else if (workspace_number != screen->getCurrentWorkspace()->getWorkspaceID())
1451 return;
1452
1453 setState(NormalState);
1454
1455 XSelectInput(display, client.window, NoEventMask);
1456 XMapWindow(display, client.window);
1457 XSelectInput(display, client.window,
1458 PropertyChangeMask | StructureNotifyMask | FocusChangeMask);
1459
1460 XMapSubwindows(display, frame.window);
1461 XMapWindow(display, frame.window);
1462
1463 // if we're using the click to place placement type, then immediately
1464 // after the window is mapped, we need to start interactively moving it
1465 if (initial && place_window &&
1466 screen->placementPolicy() == BScreen::ClickMousePlacement) {
1467 int x, y, rx, ry;
1468 Window c, r;
1469 unsigned int m;
1470 XQueryPointer(openbox.getXDisplay(), screen->getRootWindow(),
1471 &r, &c, &rx, &ry, &x, &y, &m);
1472 startMove(rx, ry);
1473 }
1474
1475 if (flags.iconic && screen->focusNew()) setInputFocus();
1476
1477 flags.visible = True;
1478 flags.iconic = False;
1479
1480 if (reassoc && client.transient) client.transient->deiconify(True, False);
1481
1482 if (raise)
1483 screen->getWorkspace(workspace_number)->raiseWindow(this);
1484 }
1485
1486
1487 void OpenboxWindow::close(void) {
1488 XEvent ce;
1489 ce.xclient.type = ClientMessage;
1490 ce.xclient.message_type = openbox.getWMProtocolsAtom();
1491 ce.xclient.display = display;
1492 ce.xclient.window = client.window;
1493 ce.xclient.format = 32;
1494 ce.xclient.data.l[0] = openbox.getWMDeleteAtom();
1495 ce.xclient.data.l[1] = CurrentTime;
1496 ce.xclient.data.l[2] = 0l;
1497 ce.xclient.data.l[3] = 0l;
1498 ce.xclient.data.l[4] = 0l;
1499 XSendEvent(display, client.window, False, NoEventMask, &ce);
1500 }
1501
1502
1503 void OpenboxWindow::withdraw(void) {
1504 if (flags.moving)
1505 endMove();
1506
1507 flags.visible = False;
1508 flags.iconic = False;
1509
1510 XUnmapWindow(display, frame.window);
1511
1512 XSelectInput(display, client.window, NoEventMask);
1513 XUnmapWindow(display, client.window);
1514 XSelectInput(display, client.window,
1515 PropertyChangeMask | StructureNotifyMask | FocusChangeMask);
1516
1517 if (windowmenu) windowmenu->hide();
1518 }
1519
1520
1521 void OpenboxWindow::maximize(unsigned int button) {
1522 if (flags.moving)
1523 endMove();
1524
1525 // handle case where menu is open then the max button is used instead
1526 if (windowmenu && windowmenu->isVisible()) windowmenu->hide();
1527
1528 if (flags.maximized) {
1529 flags.maximized = 0;
1530
1531 openbox_attrib.flags &= ! (AttribMaxHoriz | AttribMaxVert);
1532 openbox_attrib.attrib &= ! (AttribMaxHoriz | AttribMaxVert);
1533
1534 // when a resize is begun, maximize(0) is called to clear any maximization
1535 // flags currently set. Otherwise it still thinks it is maximized.
1536 // so we do not need to call configure() because resizing will handle it
1537 if (!flags.resizing)
1538 configure(openbox_attrib.premax_x, openbox_attrib.premax_y,
1539 openbox_attrib.premax_w, openbox_attrib.premax_h);
1540
1541 openbox_attrib.premax_x = openbox_attrib.premax_y = 0;
1542 openbox_attrib.premax_w = openbox_attrib.premax_h = 0;
1543
1544 redrawMaximizeButton(flags.maximized);
1545 setState(current_state);
1546 return;
1547 }
1548
1549 openbox_attrib.premax_x = frame.x;
1550 openbox_attrib.premax_y = frame.y;
1551 openbox_attrib.premax_w = frame.width;
1552 openbox_attrib.premax_h = frame.height;
1553
1554 Rect space = screen->availableArea();
1555 unsigned int dw = space.w(),
1556 dh = space.h();
1557 dw -= frame.border_w * 2;
1558 dw -= frame.mwm_border_w * 2;
1559 dw -= client.base_width;
1560
1561 dh -= frame.border_w * 2;
1562 dh -= frame.mwm_border_w * 2;
1563 dh -= ((frame.handle_h + frame.border_w) * decorations.handle);
1564 dh -= client.base_height;
1565 dh -= frame.y_border;
1566
1567 if (dw < client.min_width) dw = client.min_width;
1568 if (dh < client.min_height) dh = client.min_height;
1569 if (dw > client.max_width) dw = client.max_width;
1570 if (dh > client.max_height) dh = client.max_height;
1571
1572 dw -= (dw % client.width_inc);
1573 dw += client.base_width;
1574 dw += frame.mwm_border_w * 2;
1575
1576 dh -= (dh % client.height_inc);
1577 dh += client.base_height;
1578 dh += frame.y_border;
1579 dh += ((frame.handle_h + frame.border_w) * decorations.handle);
1580 dh += frame.mwm_border_w * 2;
1581
1582 int dx = space.x() + ((space.w() - dw) / 2) - frame.border_w,
1583 dy = space.y() + ((space.h() - dh) / 2) - frame.border_w;
1584
1585 switch(button) {
1586 case 1:
1587 openbox_attrib.flags |= AttribMaxHoriz | AttribMaxVert;
1588 openbox_attrib.attrib |= AttribMaxHoriz | AttribMaxVert;
1589 break;
1590
1591 case 2:
1592 openbox_attrib.flags |= AttribMaxVert;
1593 openbox_attrib.attrib |= AttribMaxVert;
1594
1595 dw = frame.width;
1596 dx = frame.x;
1597 break;
1598
1599 case 3:
1600 openbox_attrib.flags |= AttribMaxHoriz;
1601 openbox_attrib.attrib |= AttribMaxHoriz;
1602
1603 dh = frame.height;
1604 dy = frame.y;
1605 break;
1606 }
1607
1608 if (flags.shaded) {
1609 openbox_attrib.flags ^= AttribShaded;
1610 openbox_attrib.attrib ^= AttribShaded;
1611 flags.shaded = False;
1612 }
1613
1614 flags.maximized = button;
1615
1616 configure(dx, dy, dw, dh);
1617 screen->getWorkspace(workspace_number)->raiseWindow(this);
1618 redrawMaximizeButton(flags.maximized);
1619 setState(current_state);
1620 }
1621
1622
1623 void OpenboxWindow::setWorkspace(int n) {
1624 ASSERT(n < screen->getWorkspaceCount());
1625 workspace_number = n;
1626
1627 openbox_attrib.flags |= AttribWorkspace;
1628 openbox_attrib.workspace = workspace_number;
1629 }
1630
1631
1632 void OpenboxWindow::shade(void) {
1633 if (!decorations.titlebar)
1634 return;
1635
1636 if (flags.shaded) {
1637 XResizeWindow(display, frame.window, frame.width, frame.height);
1638 flags.shaded = False;
1639 openbox_attrib.flags ^= AttribShaded;
1640 openbox_attrib.attrib ^= AttribShaded;
1641
1642 setState(NormalState);
1643 } else {
1644 XResizeWindow(display, frame.window, frame.width, frame.title_h);
1645 flags.shaded = True;
1646 openbox_attrib.flags |= AttribShaded;
1647 openbox_attrib.attrib |= AttribShaded;
1648
1649 setState(IconicState);
1650 }
1651 }
1652
1653
1654 void OpenboxWindow::stick(void) {
1655 if (flags.stuck) {
1656 openbox_attrib.flags ^= AttribOmnipresent;
1657 openbox_attrib.attrib ^= AttribOmnipresent;
1658
1659 flags.stuck = False;
1660
1661 if (! flags.iconic)
1662 screen->reassociateWindow(this, -1, True);
1663
1664 setState(current_state);
1665 } else {
1666 flags.stuck = True;
1667
1668 openbox_attrib.flags |= AttribOmnipresent;
1669 openbox_attrib.attrib |= AttribOmnipresent;
1670
1671 setState(current_state);
1672 }
1673 }
1674
1675
1676 void OpenboxWindow::setFocusFlag(Bool focus) {
1677 flags.focused = focus;
1678
1679 if (decorations.titlebar) {
1680 if (flags.focused) {
1681 if (frame.ftitle)
1682 XSetWindowBackgroundPixmap(display, frame.title, frame.ftitle);
1683 else
1684 XSetWindowBackground(display, frame.title, frame.ftitle_pixel);
1685 } else {
1686 if (frame.utitle)
1687 XSetWindowBackgroundPixmap(display, frame.title, frame.utitle);
1688 else
1689 XSetWindowBackground(display, frame.title, frame.utitle_pixel);
1690 }
1691 XClearWindow(display, frame.title);
1692
1693 redrawLabel();
1694 redrawAllButtons();
1695 }
1696
1697 if (decorations.handle) {
1698 if (flags.focused) {
1699 if (frame.fhandle)
1700 XSetWindowBackgroundPixmap(display, frame.handle, frame.fhandle);
1701 else
1702 XSetWindowBackground(display, frame.handle, frame.fhandle_pixel);
1703
1704 if (frame.fgrip) {
1705 XSetWindowBackgroundPixmap(display, frame.right_grip, frame.fgrip);
1706 XSetWindowBackgroundPixmap(display, frame.left_grip, frame.fgrip);
1707 } else {
1708 XSetWindowBackground(display, frame.right_grip, frame.fgrip_pixel);
1709 XSetWindowBackground(display, frame.left_grip, frame.fgrip_pixel);
1710 }
1711 } else {
1712 if (frame.uhandle)
1713 XSetWindowBackgroundPixmap(display, frame.handle, frame.uhandle);
1714 else
1715 XSetWindowBackground(display, frame.handle, frame.uhandle_pixel);
1716
1717 if (frame.ugrip) {
1718 XSetWindowBackgroundPixmap(display, frame.right_grip, frame.ugrip);
1719 XSetWindowBackgroundPixmap(display, frame.left_grip, frame.ugrip);
1720 } else {
1721 XSetWindowBackground(display, frame.right_grip, frame.ugrip_pixel);
1722 XSetWindowBackground(display, frame.left_grip, frame.ugrip_pixel);
1723 }
1724 }
1725 XClearWindow(display, frame.handle);
1726 XClearWindow(display, frame.right_grip);
1727 XClearWindow(display, frame.left_grip);
1728 }
1729
1730 if (decorations.border) {
1731 if (flags.focused)
1732 XSetWindowBorder(display, frame.plate, frame.fborder_pixel);
1733 else
1734 XSetWindowBorder(display, frame.plate, frame.uborder_pixel);
1735 }
1736
1737 if (screen->sloppyFocus() && screen->autoRaise() && timer->isTiming())
1738 timer->stop();
1739
1740 }
1741
1742
1743 void OpenboxWindow::installColormap(Bool install) {
1744 openbox.grab();
1745 if (! validateClient()) return;
1746
1747 int i = 0, ncmap = 0;
1748 Colormap *cmaps = XListInstalledColormaps(display, client.window, &ncmap);
1749 XWindowAttributes wattrib;
1750 if (cmaps) {
1751 if (XGetWindowAttributes(display, client.window, &wattrib)) {
1752 if (install) {
1753 // install the window's colormap
1754 for (i = 0; i < ncmap; i++) {
1755 if (*(cmaps + i) == wattrib.colormap)
1756 // this window is using an installed color map... do not install
1757 install = False;
1758 }
1759 // otherwise, install the window's colormap
1760 if (install)
1761 XInstallColormap(display, wattrib.colormap);
1762 } else {
1763 // uninstall the window's colormap
1764 for (i = 0; i < ncmap; i++) {
1765 if (*(cmaps + i) == wattrib.colormap)
1766 // we found the colormap to uninstall
1767 XUninstallColormap(display, wattrib.colormap);
1768 }
1769 }
1770 }
1771
1772 XFree(cmaps);
1773 }
1774
1775 openbox.ungrab();
1776 }
1777
1778
1779 void OpenboxWindow::setState(unsigned long new_state) {
1780 current_state = new_state;
1781
1782 unsigned long state[2];
1783 state[0] = (unsigned long) current_state;
1784 state[1] = (unsigned long) None;
1785 XChangeProperty(display, client.window, openbox.getWMStateAtom(),
1786 openbox.getWMStateAtom(), 32, PropModeReplace,
1787 (unsigned char *) state, 2);
1788
1789 XChangeProperty(display, client.window,
1790 openbox.getOpenboxAttributesAtom(),
1791 openbox.getOpenboxAttributesAtom(), 32, PropModeReplace,
1792 (unsigned char *) &openbox_attrib,
1793 PropOpenboxAttributesElements);
1794 }
1795
1796
1797 Bool OpenboxWindow::getState(void) {
1798 current_state = 0;
1799
1800 Atom atom_return;
1801 Bool ret = False;
1802 int foo;
1803 unsigned long *state, ulfoo, nitems;
1804
1805 if ((XGetWindowProperty(display, client.window, openbox.getWMStateAtom(),
1806 0l, 2l, False, openbox.getWMStateAtom(),
1807 &atom_return, &foo, &nitems, &ulfoo,
1808 (unsigned char **) &state) != Success) ||
1809 (! state)) {
1810 openbox.ungrab();
1811 return False;
1812 }
1813
1814 if (nitems >= 1) {
1815 current_state = (unsigned long) state[0];
1816
1817 ret = True;
1818 }
1819
1820 XFree((void *) state);
1821
1822 return ret;
1823 }
1824
1825
1826 void OpenboxWindow::setGravityOffsets(void) {
1827 // x coordinates for each gravity type
1828 const int x_west = client.x;
1829 const int x_east = client.x + client.width - frame.width;
1830 const int x_center = client.x + client.width - frame.width/2;
1831 // y coordinates for each gravity type
1832 const int y_north = client.y;
1833 const int y_south = client.y + client.height - frame.height;
1834 const int y_center = client.y + client.height - frame.height/2;
1835
1836 switch (client.win_gravity) {
1837 case NorthWestGravity:
1838 default:
1839 frame.x = x_west;
1840 frame.y = y_north;
1841 break;
1842 case NorthGravity:
1843 frame.x = x_center;
1844 frame.y = y_north;
1845 break;
1846 case NorthEastGravity:
1847 frame.x = x_east;
1848 frame.y = y_north;
1849 break;
1850 case SouthWestGravity:
1851 frame.x = x_west;
1852 frame.y = y_south;
1853 break;
1854 case SouthGravity:
1855 frame.x = x_center;
1856 frame.y = y_south;
1857 break;
1858 case SouthEastGravity:
1859 frame.x = x_east;
1860 frame.y = y_south;
1861 break;
1862 case WestGravity:
1863 frame.x = x_west;
1864 frame.y = y_center;
1865 break;
1866 case EastGravity:
1867 frame.x = x_east;
1868 frame.y = y_center;
1869 break;
1870 case CenterGravity:
1871 frame.x = x_center;
1872 frame.y = y_center;
1873 break;
1874 case ForgetGravity:
1875 case StaticGravity:
1876 frame.x = client.x - frame.mwm_border_w + frame.border_w;
1877 frame.y = client.y - frame.y_border - frame.mwm_border_w - frame.border_w;
1878 break;
1879 }
1880 }
1881
1882
1883 void OpenboxWindow::restoreAttributes(void) {
1884 if (! getState()) current_state = NormalState;
1885
1886 Atom atom_return;
1887 int foo;
1888 unsigned long ulfoo, nitems;
1889
1890 OpenboxAttributes *net;
1891 int ret = XGetWindowProperty(display, client.window,
1892 openbox.getOpenboxAttributesAtom(), 0l,
1893 PropOpenboxAttributesElements, False,
1894 openbox.getOpenboxAttributesAtom(),
1895 &atom_return, &foo, &nitems, &ulfoo,
1896 (unsigned char **) &net);
1897 if (ret != Success || !net || nitems != PropOpenboxAttributesElements)
1898 return;
1899
1900 openbox_attrib.flags = net->flags;
1901 openbox_attrib.attrib = net->attrib;
1902 openbox_attrib.decoration = net->decoration;
1903 openbox_attrib.workspace = net->workspace;
1904 openbox_attrib.stack = net->stack;
1905 openbox_attrib.premax_x = net->premax_x;
1906 openbox_attrib.premax_y = net->premax_y;
1907 openbox_attrib.premax_w = net->premax_w;
1908 openbox_attrib.premax_h = net->premax_h;
1909
1910 XFree((void *) net);
1911
1912 if (openbox_attrib.flags & AttribShaded &&
1913 openbox_attrib.attrib & AttribShaded) {
1914 int save_state =
1915 ((current_state == IconicState) ? NormalState : current_state);
1916
1917 flags.shaded = False;
1918 shade();
1919
1920 current_state = save_state;
1921 }
1922
1923 if (((int) openbox_attrib.workspace != screen->getCurrentWorkspaceID()) &&
1924 ((int) openbox_attrib.workspace < screen->getWorkspaceCount())) {
1925 screen->reassociateWindow(this, openbox_attrib.workspace, True);
1926
1927 if (current_state == NormalState) current_state = WithdrawnState;
1928 } else if (current_state == WithdrawnState) {
1929 current_state = NormalState;
1930 }
1931
1932 if (openbox_attrib.flags & AttribOmnipresent &&
1933 openbox_attrib.attrib & AttribOmnipresent) {
1934 flags.stuck = False;
1935 stick();
1936
1937 current_state = NormalState;
1938 }
1939
1940 if ((openbox_attrib.flags & AttribMaxHoriz) ||
1941 (openbox_attrib.flags & AttribMaxVert)) {
1942 int x = openbox_attrib.premax_x, y = openbox_attrib.premax_y;
1943 unsigned int w = openbox_attrib.premax_w, h = openbox_attrib.premax_h;
1944 flags.maximized = 0;
1945
1946 unsigned int m = False;
1947 if ((openbox_attrib.flags & AttribMaxHoriz) &&
1948 (openbox_attrib.flags & AttribMaxVert))
1949 m = (openbox_attrib.attrib & (AttribMaxHoriz | AttribMaxVert)) ? 1 : 0;
1950 else if (openbox_attrib.flags & AttribMaxVert)
1951 m = (openbox_attrib.attrib & AttribMaxVert) ? 2 : 0;
1952 else if (openbox_attrib.flags & AttribMaxHoriz)
1953 m = (openbox_attrib.attrib & AttribMaxHoriz) ? 3 : 0;
1954
1955 if (m) maximize(m);
1956
1957 openbox_attrib.premax_x = x;
1958 openbox_attrib.premax_y = y;
1959 openbox_attrib.premax_w = w;
1960 openbox_attrib.premax_h = h;
1961 }
1962
1963 setState(current_state);
1964 }
1965
1966
1967 /*
1968 * The reverse of the setGravityOffsets function. Uses the frame window's
1969 * position to find the window's reference point.
1970 */
1971 void OpenboxWindow::restoreGravity(void) {
1972 // x coordinates for each gravity type
1973 const int x_west = frame.x;
1974 const int x_east = frame.x + frame.width - client.width;
1975 const int x_center = frame.x + (frame.width/2) - client.width;
1976 // y coordinates for each gravity type
1977 const int y_north = frame.y;
1978 const int y_south = frame.y + frame.height - client.height;
1979 const int y_center = frame.y + (frame.height/2) - client.height;
1980
1981 switch(client.win_gravity) {
1982 default:
1983 case NorthWestGravity:
1984 client.x = x_west;
1985 client.y = y_north;
1986 break;
1987 case NorthGravity:
1988 client.x = x_center;
1989 client.y = y_north;
1990 break;
1991 case NorthEastGravity:
1992 client.x = x_east;
1993 client.y = y_north;
1994 break;
1995 case SouthWestGravity:
1996 client.x = x_west;
1997 client.y = y_south;
1998 break;
1999 case SouthGravity:
2000 client.x = x_center;
2001 client.y = y_south;
2002 break;
2003 case SouthEastGravity:
2004 client.x = x_east;
2005 client.y = y_south;
2006 break;
2007 case WestGravity:
2008 client.x = x_west;
2009 client.y = y_center;
2010 break;
2011 case EastGravity:
2012 client.x = x_east;
2013 client.y = y_center;
2014 break;
2015 case CenterGravity:
2016 client.x = x_center;
2017 client.y = y_center;
2018 break;
2019 case ForgetGravity:
2020 case StaticGravity:
2021 client.x = frame.x + frame.mwm_border_w + frame.border_w;
2022 client.y = frame.y + frame.y_border + frame.mwm_border_w +
2023 frame.border_w;
2024 break;
2025 }
2026 }
2027
2028
2029 void OpenboxWindow::redrawLabel(void) {
2030 int dx = frame.bevel_w * 2, dlen = client.title_len;
2031 unsigned int l = client.title_text_w;
2032
2033 if (flags.focused) {
2034 if (frame.flabel)
2035 XSetWindowBackgroundPixmap(display, frame.label, frame.flabel);
2036 else
2037 XSetWindowBackground(display, frame.label, frame.flabel_pixel);
2038 } else {
2039 if (frame.ulabel)
2040 XSetWindowBackgroundPixmap(display, frame.label, frame.ulabel);
2041 else
2042 XSetWindowBackground(display, frame.label, frame.ulabel_pixel);
2043 }
2044 XClearWindow(display, frame.label);
2045
2046 if (client.title_text_w > frame.label_w) {
2047 for (; dlen >= 0; dlen--) {
2048 if (i18n.multibyte()) {
2049 XRectangle ink, logical;
2050 XmbTextExtents(screen->getWindowStyle()->fontset, client.title, dlen,
2051 &ink, &logical);
2052 l = logical.width;
2053 } else {
2054 l = XTextWidth(screen->getWindowStyle()->font, client.title, dlen);
2055 }
2056 l += (frame.bevel_w * 4);
2057
2058 if (l < frame.label_w)
2059 break;
2060 }
2061 }
2062
2063 switch (screen->getWindowStyle()->justify) {
2064 case BScreen::RightJustify:
2065 dx += frame.label_w - l;
2066 break;
2067
2068 case BScreen::CenterJustify:
2069 dx += (frame.label_w - l) / 2;
2070 break;
2071 }
2072
2073 WindowStyle *style = screen->getWindowStyle();
2074 GC text_gc = (flags.focused) ? style->l_text_focus_gc :
2075 style->l_text_unfocus_gc;
2076 if (i18n.multibyte())
2077 XmbDrawString(display, frame.label, style->fontset, text_gc, dx,
2078 (1 - style->fontset_extents->max_ink_extent.y),
2079 client.title, dlen);
2080 else
2081 XDrawString(display, frame.label, text_gc, dx,
2082 (style->font->ascent + 1), client.title, dlen);
2083 }
2084
2085
2086 void OpenboxWindow::redrawAllButtons(void) {
2087 if (frame.iconify_button) redrawIconifyButton(False);
2088 if (frame.maximize_button) redrawMaximizeButton(flags.maximized);
2089 if (frame.close_button) redrawCloseButton(False);
2090 }
2091
2092
2093 void OpenboxWindow::redrawIconifyButton(Bool pressed) {
2094 if (! pressed) {
2095 if (flags.focused) {
2096 if (frame.fbutton)
2097 XSetWindowBackgroundPixmap(display, frame.iconify_button,
2098 frame.fbutton);
2099 else
2100 XSetWindowBackground(display, frame.iconify_button,
2101 frame.fbutton_pixel);
2102 } else {
2103 if (frame.ubutton)
2104 XSetWindowBackgroundPixmap(display, frame.iconify_button,
2105 frame.ubutton);
2106 else
2107 XSetWindowBackground(display, frame.iconify_button,
2108 frame.ubutton_pixel);
2109 }
2110 } else {
2111 if (frame.pbutton)
2112 XSetWindowBackgroundPixmap(display, frame.iconify_button, frame.pbutton);
2113 else
2114 XSetWindowBackground(display, frame.iconify_button, frame.pbutton_pixel);
2115 }
2116 XClearWindow(display, frame.iconify_button);
2117
2118 XDrawRectangle(display, frame.iconify_button,
2119 ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc :
2120 screen->getWindowStyle()->b_pic_unfocus_gc),
2121 2, (frame.button_h - 5), (frame.button_w - 5), 2);
2122 }
2123
2124
2125 void OpenboxWindow::redrawMaximizeButton(Bool pressed) {
2126 if (! pressed) {
2127 if (flags.focused) {
2128 if (frame.fbutton)
2129 XSetWindowBackgroundPixmap(display, frame.maximize_button,
2130 frame.fbutton);
2131 else
2132 XSetWindowBackground(display, frame.maximize_button,
2133 frame.fbutton_pixel);
2134 } else {
2135 if (frame.ubutton)
2136 XSetWindowBackgroundPixmap(display, frame.maximize_button,
2137 frame.ubutton);
2138 else
2139 XSetWindowBackground(display, frame.maximize_button,
2140 frame.ubutton_pixel);
2141 }
2142 } else {
2143 if (frame.pbutton)
2144 XSetWindowBackgroundPixmap(display, frame.maximize_button,
2145 frame.pbutton);
2146 else
2147 XSetWindowBackground(display, frame.maximize_button,
2148 frame.pbutton_pixel);
2149 }
2150 XClearWindow(display, frame.maximize_button);
2151
2152 XDrawRectangle(display, frame.maximize_button,
2153 ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc :
2154 screen->getWindowStyle()->b_pic_unfocus_gc),
2155 2, 2, (frame.button_w - 5), (frame.button_h - 5));
2156 XDrawLine(display, frame.maximize_button,
2157 ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc :
2158 screen->getWindowStyle()->b_pic_unfocus_gc),
2159 2, 3, (frame.button_w - 3), 3);
2160 }
2161
2162
2163 void OpenboxWindow::redrawCloseButton(Bool pressed) {
2164 if (! pressed) {
2165 if (flags.focused) {
2166 if (frame.fbutton)
2167 XSetWindowBackgroundPixmap(display, frame.close_button,
2168 frame.fbutton);
2169 else
2170 XSetWindowBackground(display, frame.close_button,
2171 frame.fbutton_pixel);
2172 } else {
2173 if (frame.ubutton)
2174 XSetWindowBackgroundPixmap(display, frame.close_button,
2175 frame.ubutton);
2176 else
2177 XSetWindowBackground(display, frame.close_button,
2178 frame.ubutton_pixel);
2179 }
2180 } else {
2181 if (frame.pbutton)
2182 XSetWindowBackgroundPixmap(display, frame.close_button, frame.pbutton);
2183 else
2184 XSetWindowBackground(display, frame.close_button, frame.pbutton_pixel);
2185 }
2186 XClearWindow(display, frame.close_button);
2187
2188 XDrawLine(display, frame.close_button,
2189 ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc :
2190 screen->getWindowStyle()->b_pic_unfocus_gc), 2, 2,
2191 (frame.button_w - 3), (frame.button_h - 3));
2192 XDrawLine(display, frame.close_button,
2193 ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc :
2194 screen->getWindowStyle()->b_pic_unfocus_gc), 2,
2195 (frame.button_h - 3),
2196 (frame.button_w - 3), 2);
2197 }
2198
2199
2200 void OpenboxWindow::mapRequestEvent(XMapRequestEvent *re) {
2201 if (re->window == client.window) {
2202 #ifdef DEBUG
2203 fprintf(stderr, i18n(WindowSet, WindowMapRequest,
2204 "OpenboxWindow::mapRequestEvent() for 0x%lx\n"),
2205 client.window);
2206 #endif // DEBUG
2207
2208 openbox.grab();
2209 if (! validateClient()) return;
2210
2211 Bool get_state_ret = getState();
2212 if (! (get_state_ret && openbox.isStartup())) {
2213 if ((client.wm_hint_flags & StateHint) &&
2214 (! (current_state == NormalState || current_state == IconicState)))
2215 current_state = client.initial_state;
2216 else
2217 current_state = NormalState;
2218 } else if (flags.iconic) {
2219 current_state = NormalState;
2220 }
2221
2222 switch (current_state) {
2223 case IconicState:
2224 iconify();
2225 break;
2226
2227 case WithdrawnState:
2228 withdraw();
2229 break;
2230
2231 case NormalState:
2232 case InactiveState:
2233 case ZoomState:
2234 default:
2235 deiconify(False, True, True); // specify that we're initializing the
2236 // window
2237 break;
2238 }
2239
2240 openbox.ungrab();
2241 }
2242 }
2243
2244
2245 void OpenboxWindow::mapNotifyEvent(XMapEvent *ne) {
2246 if ((ne->window == client.window) && (! ne->override_redirect)
2247 && (flags.visible)) {
2248 openbox.grab();
2249 if (! validateClient()) return;
2250
2251 setState(NormalState);
2252
2253 if (flags.transient || screen->focusNew())
2254 setInputFocus();
2255 else
2256 setFocusFlag(False);
2257
2258 flags.visible = True;
2259 flags.iconic = False;
2260
2261 openbox.ungrab();
2262 }
2263 }
2264
2265
2266 void OpenboxWindow::unmapNotifyEvent(XUnmapEvent *ue) {
2267 if (ue->window == client.window) {
2268 #ifdef DEBUG
2269 fprintf(stderr, i18n(WindowSet, WindowUnmapNotify,
2270 "OpenboxWindow::unmapNotifyEvent() for 0x%lx\n"),
2271 client.window);
2272 #endif // DEBUG
2273
2274 openbox.grab();
2275 if (! validateClient()) return;
2276
2277 if (flags.moving)
2278 endMove();
2279
2280 XChangeSaveSet(display, client.window, SetModeDelete);
2281 XSelectInput(display, client.window, NoEventMask);
2282
2283 XDeleteProperty(display, client.window, openbox.getWMStateAtom());
2284 XDeleteProperty(display, client.window,
2285 openbox.getOpenboxAttributesAtom());
2286
2287 XUnmapWindow(display, frame.window);
2288 XUnmapWindow(display, client.window);
2289
2290 XEvent dummy;
2291 if (! XCheckTypedWindowEvent(display, client.window, ReparentNotify,
2292 &dummy)) {
2293 #ifdef DEBUG
2294 fprintf(stderr, i18n(WindowSet, WindowUnmapNotifyReparent,
2295 "OpenboxWindow::unmapNotifyEvent(): reparent 0x%lx to "
2296 "root.\n"), client.window);
2297 #endif // DEBUG
2298
2299 restoreGravity();
2300 XReparentWindow(display, client.window, screen->getRootWindow(),
2301 client.x, client.y);
2302 }
2303
2304 XFlush(display);
2305
2306 openbox.ungrab();
2307
2308 delete this;
2309 }
2310 }
2311
2312
2313 void OpenboxWindow::destroyNotifyEvent(XDestroyWindowEvent *de) {
2314 if (de->window == client.window) {
2315 if (flags.moving)
2316 endMove();
2317 XUnmapWindow(display, frame.window);
2318
2319 delete this;
2320 }
2321 }
2322
2323
2324 void OpenboxWindow::propertyNotifyEvent(Atom atom) {
2325 openbox.grab();
2326 if (! validateClient()) return;
2327
2328 switch(atom) {
2329 case XA_WM_CLASS:
2330 case XA_WM_CLIENT_MACHINE:
2331 case XA_WM_COMMAND:
2332 break;
2333
2334 case XA_WM_TRANSIENT_FOR:
2335 // determine if this is a transient window
2336 Window win;
2337 if (XGetTransientForHint(display, client.window, &win)) {
2338 if (win && (win != client.window)) {
2339 if ((client.transient_for = openbox.searchWindow(win))) {
2340 client.transient_for->client.transient = this;
2341 flags.stuck = client.transient_for->flags.stuck;
2342 flags.transient = True;
2343 } else if (win == client.window_group) {
2344 //jr This doesn't look quite right...
2345 if ((client.transient_for = openbox.searchGroup(win, this))) {
2346 client.transient_for->client.transient = this;
2347 flags.stuck = client.transient_for->flags.stuck;
2348 flags.transient = True;
2349 }
2350 }
2351 }
2352
2353 if (win == screen->getRootWindow()) flags.modal = True;
2354 }
2355
2356 // adjust the window decorations based on transience
2357 if (flags.transient)
2358 decorations.maximize = decorations.handle = functions.maximize = False;
2359
2360 reconfigure();
2361
2362 break;
2363
2364 case XA_WM_HINTS:
2365 getWMHints();
2366 break;
2367
2368 case XA_WM_ICON_NAME:
2369 getWMIconName();
2370 if (flags.iconic) screen->iconUpdate();
2371 break;
2372
2373 case XA_WM_NAME:
2374 getWMName();
2375
2376 if (decorations.titlebar)
2377 redrawLabel();
2378
2379 if (! flags.iconic)
2380 screen->getWorkspace(workspace_number)->update();
2381
2382 break;
2383
2384 case XA_WM_NORMAL_HINTS: {
2385 getWMNormalHints();
2386
2387 if ((client.normal_hint_flags & PMinSize) &&
2388 (client.normal_hint_flags & PMaxSize)) {
2389 if (client.max_width <= client.min_width &&
2390 client.max_height <= client.min_height)
2391 decorations.maximize = decorations.handle =
2392 functions.resize = functions.maximize = False;
2393 else
2394 decorations.maximize = decorations.handle =
2395 functions.resize = functions.maximize = True;
2396 }
2397
2398 int x = frame.x, y = frame.y;
2399 unsigned int w = frame.width, h = frame.height;
2400
2401 upsize();
2402
2403 if ((x != frame.x) || (y != frame.y) ||
2404 (w != frame.width) || (h != frame.height))
2405 reconfigure();
2406
2407 break;
2408 }
2409
2410 default:
2411 if (atom == openbox.getWMProtocolsAtom()) {
2412 getWMProtocols();
2413
2414 if (decorations.close && (! frame.close_button)) {
2415 createCloseButton();
2416 if (decorations.titlebar) {
2417 positionButtons();
2418 decorateLabel();
2419 }
2420 if (windowmenu) windowmenu->reconfigure();
2421 }
2422 }
2423
2424 break;
2425 }
2426
2427 openbox.ungrab();
2428 }
2429
2430
2431 void OpenboxWindow::exposeEvent(XExposeEvent *ee) {
2432 if (frame.label == ee->window && decorations.titlebar)
2433 redrawLabel();
2434 else if (frame.close_button == ee->window)
2435 redrawCloseButton(False);
2436 else if (frame.maximize_button == ee->window)
2437 redrawMaximizeButton(flags.maximized);
2438 else if (frame.iconify_button == ee->window)
2439 redrawIconifyButton(False);
2440 }
2441
2442
2443 void OpenboxWindow::configureRequestEvent(XConfigureRequestEvent *cr) {
2444 if (cr->window == client.window) {
2445 openbox.grab();
2446 if (! validateClient()) return;
2447
2448 int cx = frame.x, cy = frame.y;
2449 unsigned int cw = frame.width, ch = frame.height;
2450
2451 if (cr->value_mask & CWBorderWidth)
2452 client.old_bw = cr->border_width;
2453
2454 if (cr->value_mask & CWX)
2455 cx = cr->x - frame.mwm_border_w - frame.border_w;
2456
2457 if (cr->value_mask & CWY)
2458 cy = cr->y - frame.y_border - frame.mwm_border_w -
2459 frame.border_w;
2460
2461 if (cr->value_mask & CWWidth)
2462 cw = cr->width + (frame.mwm_border_w * 2);
2463
2464 if (cr->value_mask & CWHeight)
2465 ch = cr->height + frame.y_border + (frame.mwm_border_w * 2) +
2466 (frame.border_w * decorations.handle) + frame.handle_h;
2467
2468 if (frame.x != cx || frame.y != cy ||
2469 frame.width != cw || frame.height != ch)
2470 configure(cx, cy, cw, ch);
2471
2472 if (cr->value_mask & CWStackMode) {
2473 switch (cr->detail) {
2474 case Above:
2475 case TopIf:
2476 default:
2477 if (flags.iconic) deiconify();
2478 screen->getWorkspace(workspace_number)->raiseWindow(this);
2479 break;
2480
2481 case Below:
2482 case BottomIf:
2483 if (flags.iconic) deiconify();
2484 screen->getWorkspace(workspace_number)->lowerWindow(this);
2485 break;
2486 }
2487 }
2488
2489 openbox.ungrab();
2490 }
2491 }
2492
2493
2494 void OpenboxWindow::buttonPressEvent(XButtonEvent *be) {
2495 openbox.grab();
2496 if (! validateClient())
2497 return;
2498
2499 int stack_change = 1; // < 0 means to lower the window
2500 // > 0 means to raise the window
2501 // 0 means to leave it where it is
2502
2503 // alt + left/right click begins interactively moving/resizing the window
2504 // when the mouse is moved
2505 if (be->state == Mod1Mask && (be->button == 1 || be->button == 3)) {
2506 if (be->button == 3) {
2507 if (screen->getWindowZones() == 4 &&
2508 be->y < (signed) frame.height / 2) {
2509 resize_zone = ZoneTop;
2510 } else {
2511 resize_zone = ZoneBottom;
2512 }
2513 if (screen->getWindowZones() >= 2 &&
2514 be->x < (signed) frame.width / 2) {
2515 resize_zone |= ZoneLeft;
2516 } else {
2517 resize_zone |= ZoneRight;
2518 }
2519 }
2520 // control + left click on the titlebar shades the window
2521 } else if (be->state == ControlMask && be->button == 1) {
2522 if (be->window == frame.title ||
2523 be->window == frame.label)
2524 shade();
2525 // left click
2526 } else if (be->state == 0 && be->button == 1) {
2527 if (windowmenu && windowmenu->isVisible())
2528 windowmenu->hide();
2529
2530 if (be->window == frame.maximize_button) {
2531 redrawMaximizeButton(True);
2532 } else if (be->window == frame.iconify_button) {
2533 redrawIconifyButton(True);
2534 } else if (be->window == frame.close_button) {
2535 redrawCloseButton(True);
2536 } else if (be->window == frame.plate) {
2537 XAllowEvents(display, ReplayPointer, be->time);
2538 } else if (be->window == frame.title ||
2539 be->window == frame.label) {
2540 // shade the window when the titlebar is double clicked
2541 if ( (be->time - lastButtonPressTime) <=
2542 openbox.getDoubleClickInterval()) {
2543 lastButtonPressTime = 0;
2544 shade();
2545 } else {
2546 lastButtonPressTime = be->time;
2547 }
2548 // clicking and dragging on the titlebar moves the window, so on a click
2549 // we need to save the coords of the click in case the user drags
2550 frame.grab_x = be->x_root - frame.x - frame.border_w;
2551 frame.grab_y = be->y_root - frame.y - frame.border_w;
2552 } else if (be->window == frame.handle ||
2553 be->window == frame.left_grip ||
2554 be->window == frame.right_grip ||
2555 be->window == frame.window) {
2556 // clicking and dragging on the window's frame moves the window, so on a
2557 // click we need to save the coords of the click in case the user drags
2558 frame.grab_x = be->x_root - frame.x - frame.border_w;
2559 frame.grab_y = be->y_root - frame.y - frame.border_w;
2560 if (be->window == frame.left_grip)
2561 resize_zone = ZoneBottom | ZoneLeft;
2562 else if (be->window == frame.right_grip)
2563 resize_zone = ZoneBottom | ZoneRight;
2564 }
2565 // middle click
2566 } else if (be->state == 0 && be->button == 2) {
2567 if (be->window == frame.maximize_button) {
2568 redrawMaximizeButton(True);
2569 // a middle click anywhere on the window's frame except for on the buttons
2570 // will lower the window
2571 } else if (! (be->window == frame.iconify_button ||
2572 be->window == frame.close_button) ) {
2573 stack_change = -1;
2574 }
2575 // right click
2576 } else if (be->state == 0 && be->button == 3) {
2577 if (be->window == frame.maximize_button) {
2578 redrawMaximizeButton(True);
2579 // a right click on the window's frame will show or hide the window's
2580 // windowmenu
2581 } else if (be->window == frame.title ||
2582 be->window == frame.label ||
2583 be->window == frame.handle ||
2584 be->window == frame.window) {
2585 int mx, my;
2586 if (windowmenu) {
2587 if (windowmenu->isVisible()) {
2588 windowmenu->hide();
2589 } else {
2590 // get the coords for the menu
2591 mx = be->x_root - windowmenu->getWidth() / 2;
2592 if (be->window == frame.title || be->window == frame.label) {
2593 my = frame.y + frame.title_h;
2594 } else if (be->window == frame.handle) {
2595 my = frame.y + frame.y_handle - windowmenu->getHeight();
2596 } else { // (be->window == frame.window)
2597 if (be->y <= (signed) frame.bevel_w) {
2598 my = frame.y + frame.y_border;
2599 } else {
2600 my = be->y_root - (windowmenu->getHeight() / 2);
2601 }
2602 }
2603
2604 if (mx > (signed) (frame.x + frame.width -
2605 windowmenu->getWidth())) {
2606 mx = frame.x + frame.width - windowmenu->getWidth();
2607 } else if (mx < frame.x) {
2608 mx = frame.x;
2609 }
2610
2611 if (my > (signed) (frame.y + frame.y_handle -
2612 windowmenu->getHeight())) {
2613 my = frame.y + frame.y_handle - windowmenu->getHeight();
2614 } else if (my < (signed) (frame.y +
2615 ((decorations.titlebar) ? frame.title_h : frame.y_border))) {
2616 my = frame.y +
2617 ((decorations.titlebar) ? frame.title_h : frame.y_border);
2618 }
2619
2620 windowmenu->move(mx, my);
2621 windowmenu->show();
2622 XRaiseWindow(display, windowmenu->getWindowID());
2623 XRaiseWindow(display, windowmenu->getSendToMenu()->getWindowID());
2624 stack_change = 0; // dont raise the window overtop of the menu
2625 }
2626 }
2627 }
2628 // mouse wheel up
2629 } else if (be->state == 0 && be->button == 4) {
2630 if ((be->window == frame.label ||
2631 be->window == frame.title) &&
2632 !flags.shaded)
2633 shade();
2634 // mouse wheel down
2635 } else if (be->state == 0 && be->button == 5) {
2636 if ((be->window == frame.label ||
2637 be->window == frame.title) &&
2638 flags.shaded)
2639 shade();
2640 }
2641
2642 if (! (flags.focused || screen->sloppyFocus()) ) {
2643 setInputFocus(); // any click focus' the window in 'click to focus'
2644 }
2645 if (stack_change < 0) {
2646 screen->getWorkspace(workspace_number)->lowerWindow(this);
2647 } else if (stack_change > 0) {
2648 screen->getWorkspace(workspace_number)->raiseWindow(this);
2649 }
2650
2651 openbox.ungrab();
2652 }
2653
2654
2655 void OpenboxWindow::buttonReleaseEvent(XButtonEvent *re) {
2656 openbox.grab();
2657 if (! validateClient())
2658 return;
2659
2660 // alt + middle button released
2661 if (re->state == (Mod1Mask & Button2Mask) && re->button == 2) {
2662 if (re->window == frame.window) {
2663 XUngrabPointer(display, CurrentTime); // why? i dont know
2664 }
2665 // left button released
2666 } else if (re->button == 1) {
2667 if (re->window == frame.maximize_button) {
2668 if (re->state == Button1Mask && // only the left button was depressed
2669 (re->x >= 0) && ((unsigned) re->x <= frame.button_w) &&
2670 (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) {
2671 maximize(re->button);
2672 } else {
2673 redrawMaximizeButton(False);
2674 }
2675 } else if (re->window == frame.iconify_button) {
2676 if (re->state == Button1Mask && // only the left button was depressed
2677 (re->x >= 0) && ((unsigned) re->x <= frame.button_w) &&
2678 (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) {
2679 iconify();
2680 } else {
2681 redrawIconifyButton(False);
2682 }
2683 } else if (re->window == frame.close_button) {
2684 if (re->state == Button1Mask && // only the left button was depressed
2685 (re->x >= 0) && ((unsigned) re->x <= frame.button_w) &&
2686 (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) {
2687 close();
2688 }
2689 //we should always redraw the close button. some applications
2690 //eg. acroread don't honour the close.
2691 redrawCloseButton(False);
2692 }
2693 // middle button released
2694 } else if (re->button == 2) {
2695 if (re->window == frame.maximize_button) {
2696 if (re->state == Button2Mask && // only the middle button was depressed
2697 (re->x >= 0) && ((unsigned) re->x <= frame.button_w) &&
2698 (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) {
2699 maximize(re->button);
2700 } else {
2701 redrawMaximizeButton(False);
2702 }
2703 }
2704 // right button released
2705 } else if (re->button == 3) {
2706 if (re->window == frame.maximize_button) {
2707 if (re->state == Button3Mask && // only the right button was depressed
2708 (re->x >= 0) && ((unsigned) re->x <= frame.button_w) &&
2709 (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) {
2710 maximize(re->button);
2711 } else {
2712 redrawMaximizeButton(False);
2713 }
2714 }
2715 }
2716
2717 // when the window is being interactively moved, a button release stops the
2718 // move where it is
2719 if (flags.moving) {
2720 endMove();
2721 // when the window is being interactively resized, a button release stops the
2722 // resizing
2723 } else if (flags.resizing) {
2724 flags.resizing = False;
2725 XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
2726 frame.resize_x, frame.resize_y,
2727 frame.resize_w - 1, frame.resize_h - 1);
2728 screen->hideGeometry();
2729 if (resize_zone & ZoneLeft) {
2730 left_fixsize();
2731 } else { // when resizing with "Alt+Button3", the resize is the same as if
2732 // done with the right grip (the right side of the window is what
2733 // moves)
2734 right_fixsize();
2735 }
2736 // unset maximized state when resized after fully maximized
2737 if (flags.maximized == 1) {
2738 maximize(0);
2739 }
2740 configure(frame.resize_x, frame.resize_y,
2741 frame.resize_w - (frame.border_w * 2),
2742 frame.resize_h - (frame.border_w * 2));
2743 openbox.ungrab();
2744 XUngrabPointer(display, CurrentTime);
2745 resize_zone = 0;
2746 }
2747
2748 openbox.ungrab();
2749 }
2750
2751
2752 void OpenboxWindow::startMove(int x, int y) {
2753 ASSERT(!flags.moving);
2754
2755 // make sure only one window is moving at a time
2756 OpenboxWindow *w = openbox.getMaskedWindow();
2757 if (w != (OpenboxWindow *) 0 && w->flags.moving)
2758 w->endMove();
2759
2760 XGrabPointer(display, frame.window, False, PointerMotionMask |
2761 ButtonReleaseMask, GrabModeAsync, GrabModeAsync,
2762 None, openbox.getMoveCursor(), CurrentTime);
2763
2764 if (windowmenu && windowmenu->isVisible())
2765 windowmenu->hide();
2766
2767 flags.moving = True;
2768
2769 openbox.maskWindowEvents(client.window, this);
2770
2771 if (! screen->opaqueMove()) {
2772 openbox.grab();
2773
2774 frame.move_x = frame.x;
2775 frame.move_y = frame.y;
2776 frame.resize_w = frame.width + (frame.border_w * 2);
2777 frame.resize_h = ((flags.shaded) ? frame.title_h : frame.height) +
2778 (frame.border_w * 2);
2779
2780 screen->showPosition(frame.x, frame.y);
2781
2782 XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
2783 frame.move_x, frame.move_y,
2784 frame.resize_w - 1, frame.resize_h - 1);
2785 }
2786 frame.grab_x = x - frame.x - frame.border_w;
2787 frame.grab_y = y - frame.y - frame.border_w;
2788 }
2789
2790
2791 void OpenboxWindow::doMove(int x, int y) {
2792 ASSERT(flags.moving);
2793
2794 int dx = x - frame.grab_x, dy = y - frame.grab_y;
2795
2796 dx -= frame.border_w;
2797 dy -= frame.border_w;
2798
2799 int snap_distance = screen->edgeSnapThreshold();
2800 // width/height of the snapping window
2801 unsigned int snap_w = frame.width + (frame.border_w * 2);
2802 unsigned int snap_h = area().h() + (frame.border_w * 2);
2803 if (snap_distance) {
2804 int drx = screen->size().w() - (dx + snap_w);
2805
2806 if (dx < drx && (dx > 0 && dx < snap_distance) ||
2807 (dx < 0 && dx > -snap_distance) )
2808 dx = 0;
2809 else if ( (drx > 0 && drx < snap_distance) ||
2810 (drx < 0 && drx > -snap_distance) )
2811 dx = screen->size().w() - snap_w;
2812
2813 int dtty, dbby, dty, dby;
2814 switch (screen->getToolbar()->placement()) {
2815 case Toolbar::TopLeft:
2816 case Toolbar::TopCenter:
2817 case Toolbar::TopRight:
2818 dtty = screen->getToolbar()->getExposedHeight() +
2819 frame.border_w;
2820 dbby = screen->size().h();
2821 break;
2822
2823 default:
2824 dtty = 0;
2825 dbby = screen->getToolbar()->area().y();
2826 break;
2827 }
2828
2829 dty = dy - dtty;
2830 dby = dbby - (dy + snap_h);
2831
2832 if ( (dy > 0 && dty < snap_distance) ||
2833 (dy < 0 && dty > -snap_distance) )
2834 dy = dtty;
2835 else if ( (dby > 0 && dby < snap_distance) ||
2836 (dby < 0 && dby > -snap_distance) )
2837 dy = dbby - snap_h;
2838 }
2839
2840 if (screen->opaqueMove()) {
2841 configure(dx, dy, frame.width, frame.height);
2842 } else {
2843 XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
2844 frame.move_x, frame.move_y, frame.resize_w - 1,
2845 frame.resize_h - 1);
2846
2847 frame.move_x = dx;
2848 frame.move_y = dy;
2849
2850 XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
2851 frame.move_x, frame.move_y, frame.resize_w - 1,
2852 frame.resize_h - 1);
2853 }
2854
2855 screen->showPosition(dx, dy);
2856 }
2857
2858
2859 void OpenboxWindow::endMove() {
2860 ASSERT(flags.moving);
2861
2862 flags.moving = False;
2863
2864 openbox.maskWindowEvents(0, (OpenboxWindow *) 0);
2865 if (!screen->opaqueMove()) {
2866 XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
2867 frame.move_x, frame.move_y, frame.resize_w - 1,
2868 frame.resize_h - 1);
2869
2870 configure(frame.move_x, frame.move_y, frame.width, frame.height);
2871 openbox.ungrab();
2872 } else {
2873 configure(frame.x, frame.y, frame.width, frame.height);
2874 }
2875 screen->hideGeometry();
2876 XUngrabPointer(display, CurrentTime);
2877 // if there are any left over motions from the move, drop them now cuz they
2878 // cause problems
2879 XEvent e;
2880 while (XCheckTypedWindowEvent(display, frame.window, MotionNotify, &e));
2881 }
2882
2883
2884 void OpenboxWindow::motionNotifyEvent(XMotionEvent *me) {
2885 if (flags.moving)
2886 doMove(me->x_root, me->y_root);
2887 else if (!flags.resizing && (me->state & Button1Mask) && functions.move &&
2888 (frame.title == me->window || frame.label == me->window ||
2889 frame.handle == me->window || frame.window == me->window))
2890 startMove(me->x_root, me->y_root);
2891 else if (functions.resize &&
2892 (((me->state & Button1Mask) && (me->window == frame.right_grip ||
2893 me->window == frame.left_grip)) ||
2894 (me->state == (Mod1Mask | Button3Mask) &&
2895 me->window == frame.window))) {
2896 Bool left = resize_zone & ZoneLeft;
2897
2898 if (! flags.resizing) {
2899 Cursor cursor;
2900 if (resize_zone & ZoneTop)
2901 cursor = (resize_zone & ZoneLeft) ?
2902 openbox.getUpperLeftAngleCursor() :
2903 openbox.getUpperRightAngleCursor();
2904 else
2905 cursor = (resize_zone & ZoneLeft) ?
2906 openbox.getLowerLeftAngleCursor() :
2907 openbox.getLowerRightAngleCursor();
2908 XGrabPointer(display, me->window, False, ButtonMotionMask |
2909 ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None,
2910 cursor, CurrentTime);
2911
2912 flags.resizing = True;
2913
2914 openbox.grab();
2915
2916 int gx, gy;
2917 if (resize_zone & ZoneRight)
2918 frame.grab_x = me->x - screen->getBorderWidth();
2919 else
2920 frame.grab_x = me->x + screen->getBorderWidth();
2921 if (resize_zone & ZoneTop)
2922 frame.grab_y = me->y + screen->getBorderWidth() * 2;
2923 else
2924 frame.grab_y = me->y - screen->getBorderWidth() * 2;
2925 frame.resize_x = frame.x;
2926 frame.resize_y = frame.y;
2927 frame.resize_w = frame.width + (frame.border_w * 2);
2928 frame.resize_h = frame.height + (frame.border_w * 2);
2929
2930 if (left)
2931 left_fixsize(&gx, &gy);
2932 else
2933 right_fixsize(&gx, &gy);
2934
2935 screen->showGeometry(gx, gy);
2936
2937 XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
2938 frame.resize_x, frame.resize_y,
2939 frame.resize_w - 1, frame.resize_h - 1);
2940 } else {
2941 XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
2942 frame.resize_x, frame.resize_y,
2943 frame.resize_w - 1, frame.resize_h - 1);
2944
2945 int gx, gy;
2946
2947 if (resize_zone & ZoneTop)
2948 frame.resize_h = frame.height - (me->y - frame.grab_y);
2949 else
2950 frame.resize_h = frame.height + (me->y - frame.grab_y);
2951 if (frame.resize_h < 1) frame.resize_h = 1;
2952
2953 if (left) {
2954 frame.resize_x = me->x_root - frame.grab_x;
2955 if (frame.resize_x > (signed) (frame.x + frame.width))
2956 frame.resize_x = frame.resize_x + frame.width - 1;
2957
2958 left_fixsize(&gx, &gy);
2959 } else {
2960 frame.resize_w = frame.width + (me->x - frame.grab_x);
2961 if (frame.resize_w < 1) frame.resize_w = 1;
2962
2963 right_fixsize(&gx, &gy);
2964 }
2965
2966 XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(),
2967 frame.resize_x, frame.resize_y,
2968 frame.resize_w - 1, frame.resize_h - 1);
2969
2970 screen->showGeometry(gx, gy);
2971 }
2972 }
2973 }
2974
2975
2976 #ifdef SHAPE
2977 void OpenboxWindow::shapeEvent(XShapeEvent *) {
2978 if (openbox.hasShapeExtensions()) {
2979 if (flags.shaped) {
2980 openbox.grab();
2981 if (! validateClient()) return;
2982 XShapeCombineShape(display, frame.window, ShapeBounding,
2983 frame.mwm_border_w, frame.y_border +
2984 frame.mwm_border_w, client.window,
2985 ShapeBounding, ShapeSet);
2986
2987 int num = 1;
2988 XRectangle xrect[2];
2989 xrect[0].x = xrect[0].y = 0;
2990 xrect[0].width = frame.width;
2991 xrect[0].height = frame.y_border;
2992
2993 if (decorations.handle) {
2994 xrect[1].x = 0;
2995 xrect[1].y = frame.y_handle;
2996 xrect[1].width = frame.width;
2997 xrect[1].height = frame.handle_h + frame.border_w;
2998 num++;
2999 }
3000
3001 XShapeCombineRectangles(display, frame.window, ShapeBounding, 0, 0,
3002 xrect, num, ShapeUnion, Unsorted);
3003 openbox.ungrab();
3004 }
3005 }
3006 }
3007 #endif // SHAPE
3008
3009
3010 bool OpenboxWindow::validateClient(void) {
3011 XSync(display, False);
3012
3013 XEvent e;
3014 if (XCheckTypedWindowEvent(display, client.window, DestroyNotify, &e) ||
3015 XCheckTypedWindowEvent(display, client.window, UnmapNotify, &e)) {
3016 XPutBackEvent(display, &e);
3017 openbox.ungrab();
3018
3019 return false;
3020 }
3021
3022 return true;
3023 }
3024
3025
3026 void OpenboxWindow::restore(void) {
3027 XChangeSaveSet(display, client.window, SetModeDelete);
3028 XSelectInput(display, client.window, NoEventMask);
3029
3030 restoreGravity();
3031
3032 XUnmapWindow(display, frame.window);
3033 XUnmapWindow(display, client.window);
3034
3035 XSetWindowBorderWidth(display, client.window, client.old_bw);
3036 XReparentWindow(display, client.window, screen->getRootWindow(),
3037 client.x, client.y);
3038 XMapWindow(display, client.window);
3039
3040 XFlush(display);
3041
3042 delete this;
3043 }
3044
3045
3046 void OpenboxWindow::timeout(void) {
3047 screen->getWorkspace(workspace_number)->raiseWindow(this);
3048 }
3049
3050
3051 void OpenboxWindow::changeOpenboxHints(OpenboxHints *net) {
3052 if ((net->flags & AttribShaded) &&
3053 ((openbox_attrib.attrib & AttribShaded) !=
3054 (net->attrib & AttribShaded)))
3055 shade();
3056
3057 if (flags.visible && // watch out for requests when we can not be seen
3058 (net->flags & (AttribMaxVert | AttribMaxHoriz)) &&
3059 ((openbox_attrib.attrib & (AttribMaxVert | AttribMaxHoriz)) !=
3060 (net->attrib & (AttribMaxVert | AttribMaxHoriz)))) {
3061 if (flags.maximized) {
3062 maximize(0);
3063 } else {
3064 int button = 0;
3065
3066 if ((net->flags & AttribMaxHoriz) && (net->flags & AttribMaxVert))
3067 button = ((net->attrib & (AttribMaxHoriz | AttribMaxVert)) ? 1 : 0);
3068 else if (net->flags & AttribMaxVert)
3069 button = ((net->attrib & AttribMaxVert) ? 2 : 0);
3070 else if (net->flags & AttribMaxHoriz)
3071 button = ((net->attrib & AttribMaxHoriz) ? 3 : 0);
3072
3073 maximize(button);
3074 }
3075 }
3076
3077 if ((net->flags & AttribOmnipresent) &&
3078 ((openbox_attrib.attrib & AttribOmnipresent) !=
3079 (net->attrib & AttribOmnipresent)))
3080 stick();
3081
3082 if ((net->flags & AttribWorkspace) &&
3083 (workspace_number != (signed) net->workspace)) {
3084 screen->reassociateWindow(this, net->workspace, True);
3085
3086 if (screen->getCurrentWorkspaceID() != (signed) net->workspace) withdraw();
3087 else deiconify();
3088 }
3089
3090 if (net->flags & AttribDecoration) {
3091 switch (net->decoration) {
3092 case DecorNone:
3093 decorations.titlebar = decorations.border = decorations.handle =
3094 decorations.iconify = decorations.maximize = decorations.menu = False;
3095
3096 break;
3097
3098 default:
3099 case DecorNormal:
3100 decorations.titlebar = decorations.iconify = decorations.menu =
3101 decorations.border = True;
3102 decorations.handle = (functions.resize && !flags.transient);
3103 decorations.maximize = functions.maximize;
3104
3105 break;
3106
3107 case DecorTiny:
3108 decorations.titlebar = decorations.iconify = decorations.menu = True;
3109 decorations.border = decorations.border = decorations.handle = False;
3110 decorations.maximize = functions.maximize;
3111
3112 break;
3113
3114 case DecorTool:
3115 decorations.titlebar = decorations.menu = True;
3116 decorations.iconify = decorations.border = False;
3117 decorations.handle = (functions.resize && !flags.transient);
3118 decorations.maximize = functions.maximize;
3119
3120 break;
3121 }
3122 if (frame.window) {
3123 XMapSubwindows(display, frame.window);
3124 XMapWindow(display, frame.window);
3125 }
3126
3127 reconfigure();
3128 setState(current_state);
3129 }
3130 }
3131
3132
3133 /*
3134 * Set the sizes of all components of the window frame
3135 * (the window decorations).
3136 * These values are based upon the current style settings and the client
3137 * window's dimentions.
3138 */
3139 void OpenboxWindow::upsize(void) {
3140 frame.bevel_w = screen->getBevelWidth();
3141
3142 if (decorations.border) {
3143 frame.border_w = screen->getBorderWidth();
3144 if (!flags.transient)
3145 frame.mwm_border_w = screen->getFrameWidth();
3146 else
3147 frame.mwm_border_w = 0;
3148 } else {
3149 frame.mwm_border_w = frame.border_w = 0;
3150 }
3151
3152 if (decorations.titlebar) {
3153 // the height of the titlebar is based upon the height of the font being
3154 // used to display the window's title
3155 WindowStyle *style = screen->getWindowStyle();
3156 if (i18n.multibyte())
3157 frame.title_h = (style->fontset_extents->max_ink_extent.height +
3158 (frame.bevel_w * 2) + 2);
3159 else
3160 frame.title_h = (style->font->ascent + style->font->descent +
3161 (frame.bevel_w * 2) + 2);
3162
3163 frame.label_h = frame.title_h - (frame.bevel_w * 2);
3164 frame.button_w = frame.button_h = (frame.label_h - 2);
3165 frame.y_border = frame.title_h + frame.border_w;
3166 } else {
3167 frame.title_h = 0;
3168 frame.label_h = 0;
3169 frame.button_w = frame.button_h = 0;
3170 frame.y_border = 0;
3171 }
3172
3173 frame.border_h = client.height + frame.mwm_border_w * 2;
3174
3175 if (decorations.handle) {
3176 frame.y_handle = frame.y_border + frame.border_h + frame.border_w;
3177 frame.grip_w = frame.button_w * 2;
3178 frame.grip_h = frame.handle_h = screen->getHandleWidth();
3179 } else {
3180 frame.y_handle = frame.y_border + frame.border_h;
3181 frame.handle_h = 0;
3182 frame.grip_w = frame.grip_h = 0;
3183 }
3184
3185 frame.width = client.width + (frame.mwm_border_w * 2);
3186 frame.height = frame.y_handle + frame.handle_h;
3187 }
3188
3189
3190 /*
3191 * Set the size and position of the client window.
3192 * These values are based upon the current style settings and the frame
3193 * window's dimensions.
3194 */
3195 void OpenboxWindow::downsize(void) {
3196 frame.y_handle = frame.height - frame.handle_h;
3197 frame.border_h = frame.y_handle - frame.y_border -
3198 (decorations.handle ? frame.border_w : 0);
3199
3200 client.x = frame.x + frame.mwm_border_w + frame.border_w;
3201 client.y = frame.y + frame.y_border + frame.mwm_border_w + frame.border_w;
3202
3203 client.width = frame.width - (frame.mwm_border_w * 2);
3204 client.height = frame.height - frame.y_border - (frame.mwm_border_w * 2)
3205 - frame.handle_h - (decorations.handle ? frame.border_w : 0);
3206
3207 frame.y_handle = frame.border_h + frame.y_border + frame.border_w;
3208 }
3209
3210
3211 void OpenboxWindow::right_fixsize(int *gx, int *gy) {
3212 // calculate the size of the client window and conform it to the
3213 // size specified by the size hints of the client window...
3214 int dx = 1 + frame.resize_w - client.base_width - (frame.mwm_border_w * 2) -
3215 (frame.border_w * 2) + (client.width_inc / 2);
3216 int dy = 1 + frame.resize_h - frame.y_border - client.base_height -
3217 frame.handle_h - (frame.border_w * 3) - (frame.mwm_border_w * 2)
3218 + (client.height_inc / 2);
3219
3220 if (dx < (signed) client.min_width) dx = client.min_width;
3221 if (dy < (signed) client.min_height) dy = client.min_height;
3222 if ((unsigned) dx > client.max_width) dx = client.max_width;
3223 if ((unsigned) dy > client.max_height) dy = client.max_height;
3224
3225 dx /= client.width_inc;
3226 dy /= client.height_inc;
3227
3228 if (gx) *gx = dx;
3229 if (gy) *gy = dy;
3230
3231 dx = (dx * client.width_inc) + client.base_width;
3232 dy = (dy * client.height_inc) + client.base_height;
3233
3234 frame.resize_w = dx + (frame.mwm_border_w * 2) + (frame.border_w * 2) - 1;
3235 frame.resize_h = dy + frame.y_border + frame.handle_h +
3236 (frame.mwm_border_w * 2) + (frame.border_w * 3) - 1;
3237 if (resize_zone & ZoneTop)
3238 frame.resize_y = frame.y + frame.height - frame.resize_h +
3239 screen->getBorderWidth() * 2;
3240 }
3241
3242
3243 void OpenboxWindow::left_fixsize(int *gx, int *gy) {
3244 // calculate the size of the client window and conform it to the
3245 // size specified by the size hints of the client window...
3246 int dx = 1 + frame.x + frame.width - frame.resize_x - client.base_width -
3247 (frame.mwm_border_w * 2) + (client.width_inc / 2);
3248 int dy = 1 + frame.resize_h - frame.y_border - client.base_height -
3249 frame.handle_h - (frame.border_w * 3) - (frame.mwm_border_w * 2)
3250 + (client.height_inc / 2);
3251
3252 if (dx < (signed) client.min_width) dx = client.min_width;
3253 if (dy < (signed) client.min_height) dy = client.min_height;
3254 if ((unsigned) dx > client.max_width) dx = client.max_width;
3255 if ((unsigned) dy > client.max_height) dy = client.max_height;
3256
3257 dx /= client.width_inc;
3258 dy /= client.height_inc;
3259
3260 if (gx) *gx = dx;
3261 if (gy) *gy = dy;
3262
3263 dx = (dx * client.width_inc) + client.base_width;
3264 dy = (dy * client.height_inc) + client.base_height;
3265
3266 frame.resize_w = dx + (frame.mwm_border_w * 2) + (frame.border_w * 2) - 1;
3267 frame.resize_x = frame.x + frame.width - frame.resize_w +
3268 (frame.border_w * 2);
3269 frame.resize_h = dy + frame.y_border + frame.handle_h +
3270 (frame.mwm_border_w * 2) + (frame.border_w * 3) - 1;
3271 if (resize_zone & ZoneTop)
3272 frame.resize_y = frame.y + frame.height - frame.resize_h +
3273 screen->getBorderWidth() * 2;
3274
3275 }
This page took 0.197633 seconds and 5 git commands to generate.