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