"Fossies" - the Fresh Open Source Software Archive 
Member "bbkeys-0.9.1/src/window.cc" (6 Dec 2007, 15821 Bytes) of package /linux/privat/old/bbkeys-0.9.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "window.cc" see the
Fossies "Dox" file reference documentation.
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // window.cc for Epistrophy - a key handler for NETWM/EWMH window managers.
3 // Copyright (c) 2002 - 2002 Ben Jansens <ben at orodu.net>
4 //
5 // Modified for use and inclusion in bbkeys by Jason 'vanRijn' Kasper
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a
8 // copy of this software and associated documentation files (the "Software"),
9 // to deal in the Software without restriction, including without limitation
10 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 // and/or sell copies of the Software, and to permit persons to whom the
12 // Software is furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in
15 // all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 // DEALINGS IN THE SOFTWARE.
24
25 #include <iostream>
26
27 using std::cout;
28 using std::endl;
29
30 #include "window.hh"
31
32 // defined by black/openbox
33 const unsigned long XWindow::PropBlackboxAttributesElements;
34 const unsigned long XWindow::AttribDecoration;
35 const unsigned long XWindow::DecorNone;
36 const unsigned long XWindow::DecorNormal;
37
38
39 XWindow::XWindow(Window window, Netclient * netclient,
40 const bt::ScreenInfo & screenInfo, bt::Application & app)
41 : _window(window), _netclient(netclient), _screenInfo(screenInfo),
42 _app(app) {
43
44 _unmapped = false;
45
46 _display=_screenInfo.display().XDisplay();
47 _root = _screenInfo.rootWindow();
48
49 XSelectInput(_display, _window,
50 PropertyChangeMask | StructureNotifyMask);
51
52 // add an event handler for our window
53 _app.insertEventHandler(_window, this);
54
55 updateBlackboxAttributes();
56 updateNormalHints();
57 updateWMHints();
58 updateMotifHints();
59 updateDimensions();
60 updateState();
61 updateDesktop();
62 updateTitle();
63 updateClass();
64
65 }
66
67
68 XWindow::~XWindow() {
69 if (! _unmapped)
70 XSelectInput(_display, _window, None);
71
72 // tell our main app about our death
73 _app.removeEventHandler( _window );
74 }
75
76 // Window configure (size, position, stacking, etc.).
77 void XWindow::configureNotifyEvent(const XConfigureEvent * const e) {
78 updateDimensions();
79 }
80
81 // Window property changed/added/deleted.
82 void XWindow::propertyNotifyEvent(const XPropertyEvent * const e) {
83
84 if (e->atom == XA_WM_NORMAL_HINTS)
85 updateNormalHints();
86 else if (e->atom == XA_WM_HINTS)
87 updateWMHints();
88 else if (e->atom == _netclient->xaBlackboxAttributes())
89 updateBlackboxAttributes();
90 else if (e->atom == _netclient->wmState() )
91 updateState();
92 else if (e->atom == _netclient->wmDesktop() )
93 updateDesktop();
94 else if (e->atom == _netclient->wmName() ||
95 e->atom == _netclient->xaWmName() )
96 updateTitle();
97 else if (e->atom == _netclient->xaWmClass() )
98 updateClass();
99 else if (e->atom == _netclient->xaMotifWmHints() )
100 updateMotifHints();
101 }
102
103 // Window hidden.
104 void XWindow::unmapNotifyEvent(const XUnmapEvent * const e) {
105 _unmapped = true;
106 }
107
108 // Window destroyed.
109 void XWindow::destroyNotifyEvent(const XDestroyWindowEvent * const e) {
110 _unmapped = true;
111 }
112
113 void XWindow::updateDimensions(const XConfigureEvent * const e) {
114 _rect.setRect(e->x, e->y, e->width, e->height);
115 }
116
117 void XWindow::updateDimensions() {
118
119 XWindowAttributes win_attributes;
120 Window junkwin;
121 int rx, ry;
122
123 _rect.setRect(0,0,1,1);
124
125 if (! XGetWindowAttributes(_display, _window, &win_attributes)) {
126 std::cerr << BBTOOL << ": " << "updateDimensions. couldn't get what I needed, so setting to ridiculously wrong values.\n";
127 return;
128 }
129
130 XTranslateCoordinates (_display, _window, win_attributes.root,
131 -win_attributes.border_width,
132 -win_attributes.border_width,
133 &rx, &ry, &junkwin);
134 _rect.setRect(rx, ry, win_attributes.width, win_attributes.height);
135
136 }
137
138 void XWindow::updateBlackboxAttributes() {
139 unsigned long *data;
140 unsigned long num = PropBlackboxAttributesElements;
141
142 _decorated = true;
143
144 if (_netclient->getValue(_window,
145 _netclient->xaBlackboxAttributes(),
146 _netclient->xaBlackboxAttributes(),
147 num, &data)) {
148 if (num == PropBlackboxAttributesElements)
149 if (data[0] & AttribDecoration)
150 _decorated = (data[4] != DecorNone);
151 delete data;
152 }
153 }
154
155 void XWindow::updateNormalHints() {
156 XSizeHints size;
157 long ret;
158
159 // defaults
160 _gravity = NorthWestGravity;
161 _inc_x = _inc_y = 1;
162 _base_x = _base_y = 0;
163
164 if (XGetWMNormalHints(_display, _window, &size, &ret)) {
165 if (size.flags & PWinGravity)
166 _gravity = size.win_gravity;
167 if (size.flags & PBaseSize) {
168 _base_x = size.base_width;
169 _base_y = size.base_height;
170 }
171 if (size.flags & PResizeInc) {
172 _inc_x = size.width_inc;
173 _inc_y = size.height_inc;
174 }
175 }
176 }
177
178
179 void XWindow::updateMotifHints() {
180
181 // copied straight from blackbox's Window.cc, but hopefully nyz will move
182 // this somewhere shareable.... =:D
183
184 /*
185 this structure only contains 3 elements, even though the Motif 2.0
186 structure contains 5, because we only use the first 3
187 */
188 struct PropMotifhints {
189 unsigned long flags;
190 unsigned long functions;
191 unsigned long decorations;
192 };
193 static const unsigned int PROP_MWM_HINTS_ELEMENTS = 3u;
194 enum { // MWM flags
195 MWM_HINTS_FUNCTIONS = 1<<0,
196 MWM_HINTS_DECORATIONS = 1<<1
197 };
198 enum { // MWM functions
199 MWM_FUNC_ALL = 1<<0,
200 MWM_FUNC_RESIZE = 1<<1,
201 MWM_FUNC_MOVE = 1<<2,
202 MWM_FUNC_MINIMIZE = 1<<3,
203 MWM_FUNC_MAXIMIZE = 1<<4,
204 MWM_FUNC_CLOSE = 1<<5
205 };
206 enum { // MWM decorations
207 MWM_DECOR_ALL = 1<<0,
208 MWM_DECOR_BORDER = 1<<1,
209 MWM_DECOR_RESIZEH = 1<<2,
210 MWM_DECOR_TITLE = 1<<3,
211 MWM_DECOR_MENU = 1<<4,
212 MWM_DECOR_MINIMIZE = 1<<5,
213 MWM_DECOR_MAXIMIZE = 1<<6
214 };
215
216 Atom atom_return;
217 PropMotifhints *prop = 0;
218 int format;
219 unsigned long num, len;
220 int ret = XGetWindowProperty(_display, _window,
221 _netclient->xaMotifWmHints(), 0,
222 PROP_MWM_HINTS_ELEMENTS, False,
223 _netclient->xaMotifWmHints(), &atom_return,
224 &format, &num, &len,
225 (unsigned char **) &prop);
226
227 if (ret != Success || !prop || num != PROP_MWM_HINTS_ELEMENTS) {
228 if (prop) XFree(prop);
229 return;
230 }
231
232 if (prop->flags & MWM_HINTS_DECORATIONS) {
233 if (prop->decorations & MWM_DECOR_ALL) {
234 _decorated = true;
235 } else {
236 _decorated = false;
237 }
238 }
239
240 XFree(prop);
241
242
243 }
244
245 void XWindow::updateWMHints() {
246 XWMHints *hints;
247
248 // assume a window takes input if it doesnt specify
249 _can_focus = True;
250
251 if ((hints = XGetWMHints(_display, _window)) != NULL) {
252 if (hints->flags & InputHint)
253 _can_focus = hints->input;
254 XFree(hints);
255 }
256 }
257
258
259 void XWindow::updateState() {
260 // set the defaults
261 _shaded = _skip_pager = _iconic = _max_vert = _max_horz = false;
262
263 unsigned long num = (unsigned) -1;
264 Atom *state;
265 if (! _netclient->getValue(_window, _netclient->wmState(), XA_ATOM,
266 num, &state))
267 return;
268 for (unsigned long i = 0; i < num; ++i) {
269 if (state[i] == _netclient->wmStateMaximizedVert())
270 _max_vert = true;
271 if (state[i] == _netclient->wmStateMaximizedHorz())
272 _max_horz = true;
273 if (state[i] == _netclient->wmStateShaded())
274 _shaded = true;
275 if (state[i] == _netclient->wmStateHidden())
276 _iconic = true;
277 if (state[i] == _netclient->wmStateSkipPager())
278 _skip_pager = true;
279 }
280
281 delete [] state;
282 }
283
284
285 void XWindow::updateDesktop() {
286 unsigned long d = 0ul;
287 if (! _netclient->getValue(_window, _netclient->wmDesktop(), XA_CARDINAL, d))
288 d = 0ul;
289
290 _desktop = static_cast<unsigned int>(d);
291
292 }
293
294
295 void XWindow::updateTitle() {
296 _title = bt::toUnicode("");
297
298 // try netwm
299 std::string s;
300 if (_netclient->getValue(_window, _netclient->wmName(),
301 Netclient::utf8, s)) {
302 _title = bt::toUtf32(s);
303 } else {
304 // try old x stuff
305 if (_netclient->getValue(_window, XA_WM_NAME, Netclient::ansi, s))
306 _title = bt::toUnicode(s);
307 }
308
309 if (_title.empty())
310 _title = bt::toUnicode("Unnamed");
311
312 }
313
314
315 void XWindow::updateClass() {
316 // set the defaults
317 _app_name = _app_class = "";
318
319 Netclient::StringVect v;
320 unsigned long num = 2;
321
322 if (! _netclient->getValue(_window, XA_WM_CLASS, Netclient::ansi, num, v))
323 return;
324
325 if (num > 0) _app_name = v[0];
326 if (num > 1) _app_class = v[1];
327 }
328
329
330
331 void XWindow::shade(const bool sh) const {
332 _netclient->sendClientMessage(_root, _netclient->wmState(),
333 _window, (sh ? 1 : 0),
334 _netclient->wmStateShaded());
335 }
336
337 void XWindow::close() const {
338 _netclient->sendClientMessage(_root, _netclient->closeWindow(),
339 _window);
340 }
341
342
343 void XWindow::raise() const {
344 XRaiseWindow(_display, _window);
345 }
346
347 void XWindow::lower() const {
348 XLowerWindow(_display, _window);
349 }
350
351 void XWindow::iconify() const {
352 _netclient->sendClientMessage(_root, _netclient->xaWmChangeState(),
353 _window, IconicState);
354 }
355
356 void XWindow::focus(bool raise) const {
357 // this will cause the window to be uniconified also
358
359 if (raise) {
360 _netclient->sendClientMessage(_root, _netclient->activeWindow(),
361 _window);
362 } else {
363 XSetInputFocus(_display, _window, None, CurrentTime);
364 }
365 }
366
367 void XWindow::decorate(bool d) const {
368
369 // YAY trolltech!!! =:)
370 // http://lists.trolltech.com/qt-interest/1999-06/thread00047-0.html
371 long prop[5] = {2, 1, 1, 0, 0};
372
373 if (_decorated)
374 prop[2] = 0;
375 else
376 prop[2] = 1;
377
378 XChangeProperty(_display, _window,
379 _netclient->xaMotifWmHints(),
380 _netclient->xaMotifWmHints(),
381 32, 0, (unsigned char *) prop, 5);
382 }
383
384 void XWindow::sendTo(unsigned int dest) const {
385 _netclient->sendClientMessage(_root, _netclient->wmDesktop(),
386 _window, dest);
387 }
388
389
390 void XWindow::move(int x, int y) const {
391
392 XWindowAttributes win_attributes;
393 Window junkwin;
394 int rx, ry;
395
396
397 if (! XGetWindowAttributes(_display, _window, &win_attributes)) {
398 std::cerr << BBTOOL << ": " << "move: couldn't get what I needed. not able to move, sorry.\n";
399 return;
400 }
401
402 XTranslateCoordinates (_display, _window, win_attributes.root,
403 -win_attributes.border_width,
404 -win_attributes.border_width,
405 &rx, &ry, &junkwin);
406
407 Status status;
408 int xright, ybelow;
409 int dw = _screenInfo.width(), dh = _screenInfo.height();
410
411
412 /* find our window manager frame, if any */
413 Window wmframe = _window;
414
415 while (True) {
416 Window root, parent;
417 Window *childlist;
418 unsigned int ujunk;
419
420 status = XQueryTree(_display, wmframe, &root, &parent, &childlist, &ujunk);
421 if (parent == root || !parent || !status)
422 break;
423 wmframe = parent;
424 if (status && childlist)
425 XFree((char *)childlist);
426 }
427
428 if (wmframe != _window) {
429 /* WM reparented, so find edges of the frame */
430 /* Only works for ICCCM-compliant WMs, and then only if the
431 window has corner gravity. We would need to know the original width
432 of the window to correctly handle the other gravities. */
433
434 XWindowAttributes frame_attr;
435
436 if (!XGetWindowAttributes(_display, wmframe, &frame_attr)) {
437 std::cerr << BBTOOL << ": " << "updateDimensions. error. can't get frame attributes.\n";
438 }
439
440 switch (_gravity) {
441 case NorthWestGravity: case SouthWestGravity:
442 case NorthEastGravity: case SouthEastGravity:
443 case WestGravity:
444 rx = frame_attr.x;
445 }
446 switch (_gravity) {
447 case NorthWestGravity: case SouthWestGravity:
448 case NorthEastGravity: case SouthEastGravity:
449 case EastGravity:
450 xright = dw - frame_attr.x - frame_attr.width -
451 2*frame_attr.border_width;
452 }
453 switch (_gravity) {
454 case NorthWestGravity: case SouthWestGravity:
455 case NorthEastGravity: case SouthEastGravity:
456 case NorthGravity:
457 ry = frame_attr.y;
458 }
459 switch (_gravity) {
460 case NorthWestGravity: case SouthWestGravity:
461 case NorthEastGravity: case SouthEastGravity:
462 case SouthGravity:
463 ybelow = dh - frame_attr.y - frame_attr.height -
464 2*frame_attr.border_width;
465 }
466 }
467
468 int destx = rx +x, desty = ry +y;
469
470 XMoveWindow(_display, _window, destx, desty);
471
472 }
473
474
475 void XWindow::resizeRel(int dwidth, int dheight) const {
476 // resize in increments if requested by the window
477 unsigned int width = _rect.width(), height = _rect.height();
478
479 unsigned int wdest = width + (dwidth * _inc_x) / _inc_x * _inc_x + _base_x;
480 unsigned int hdest = height + (dheight * _inc_y) / _inc_y * _inc_y + _base_y;
481
482 XResizeWindow(_display, _window, wdest, hdest);
483 }
484
485
486 void XWindow::resizeAbs(unsigned int width, unsigned int height) const {
487 // resize in increments if requested by the window
488
489 unsigned int wdest = width / _inc_x * _inc_x + _base_x;
490 unsigned int hdest = height / _inc_y * _inc_y + _base_y;
491
492 if (width > wdest) {
493 while (width > wdest)
494 wdest += _inc_x;
495 } else {
496 while (width < wdest)
497 wdest -= _inc_x;
498 }
499 if (height > hdest) {
500 while (height > hdest)
501 hdest += _inc_y;
502 } else {
503 while (height < hdest)
504 hdest -= _inc_y;
505 }
506
507 XResizeWindow(_display, _window, wdest, hdest);
508 }
509
510
511 void XWindow::toggleMaximize(Max max) const {
512 switch (max) {
513 case Max_Full:
514 _netclient->
515 sendClientMessage(_root, _netclient->wmState(),
516 _window, (_max_vert == _max_horz ? 2 : 1),
517 _netclient->wmStateMaximizedHorz(),
518 _netclient->wmStateMaximizedVert());
519 break;
520
521 case Max_Horz:
522 _netclient->
523 sendClientMessage(_root, _netclient->wmState(),
524 _window, 2,
525 _netclient->wmStateMaximizedHorz());
526 break;
527
528 case Max_Vert:
529 _netclient->
530 sendClientMessage(_root, _netclient->wmState(),
531 _window, 2,
532 _netclient->wmStateMaximizedVert());
533 break;
534
535 case Max_None:
536 assert(false); // you should not do this. it is pointless and probly a bug
537 break;
538 }
539 }
540
541
542 void XWindow::maximize(Max max) const {
543 switch (max) {
544 case Max_None:
545 _netclient->
546 sendClientMessage(_root, _netclient->wmState(),
547 _window, 0,
548 _netclient->wmStateMaximizedHorz(),
549 _netclient->wmStateMaximizedVert());
550 break;
551
552 case Max_Full:
553 _netclient->
554 sendClientMessage(_root, _netclient->wmState(),
555 _window, 1,
556 _netclient->wmStateMaximizedHorz(),
557 _netclient->wmStateMaximizedVert());
558 break;
559
560 case Max_Horz:
561 _netclient->
562 sendClientMessage(_root, _netclient->wmState(),
563 _window, 1,
564 _netclient->wmStateMaximizedHorz());
565 break;
566
567 case Max_Vert:
568 _netclient->
569 sendClientMessage(_root, _netclient->wmState(),
570 _window, 1,
571 _netclient->wmStateMaximizedVert());
572 break;
573 }
574 }
575