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>
5 // Modified for use and inclusion in bbkeys by Jason 'vanRijn' Kasper
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:
14 // The above copyright notice and this permission notice shall be included in
15 // all copies or substantial portions of the Software.
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.
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
;
39 XWindow::XWindow(Window window
, Netclient
* netclient
,
40 const bt::ScreenInfo
& screenInfo
, bt::Application
& app
)
41 : _window(window
), _netclient(netclient
), _screenInfo(screenInfo
),
46 _display
=_screenInfo
.display().XDisplay();
47 _root
= _screenInfo
.rootWindow();
49 XSelectInput(_display
, _window
,
50 PropertyChangeMask
| StructureNotifyMask
);
52 // add an event handler for our window
53 _app
.insertEventHandler(_window
, this);
55 updateBlackboxAttributes();
69 XSelectInput(_display
, _window
, None
);
71 // tell our main app about our death
72 _app
.removeEventHandler( _window
);
75 // Window configure (size, position, stacking, etc.).
76 void XWindow::configureNotifyEvent(const XConfigureEvent
* const e
) {
80 // Window property changed/added/deleted.
81 void XWindow::propertyNotifyEvent(const XPropertyEvent
* const e
) {
83 if (e
->atom
== XA_WM_NORMAL_HINTS
)
85 else if (e
->atom
== XA_WM_HINTS
)
87 else if (e
->atom
== _netclient
->xaBlackboxAttributes())
88 updateBlackboxAttributes();
89 else if (e
->atom
== _netclient
->wmState() )
91 else if (e
->atom
== _netclient
->wmDesktop() )
93 else if (e
->atom
== _netclient
->wmName() ||
94 e
->atom
== _netclient
->xaWmName() )
96 else if (e
->atom
== _netclient
->xaWmClass() )
101 void XWindow::unmapNotifyEvent(const XUnmapEvent
* const e
) {
106 void XWindow::destroyNotifyEvent(const XDestroyWindowEvent
* const e
) {
110 void XWindow::updateDimensions(const XConfigureEvent
* const e
) {
111 _rect
.setRect(e
->x
, e
->y
, e
->width
, e
->height
);
114 void XWindow::updateDimensions() {
116 XWindowAttributes win_attributes
;
120 _rect
.setRect(0,0,1,1);
122 if (! XGetWindowAttributes(_display
, _window
, &win_attributes
)) {
123 std::cerr
<< "updateDimensions. couldn't get what I needed, so setting to ridiculously wrong values.\n";
127 XTranslateCoordinates (_display
, _window
, win_attributes
.root
,
128 -win_attributes
.border_width
,
129 -win_attributes
.border_width
,
131 _rect
.setRect(rx
, ry
, win_attributes
.width
, win_attributes
.height
);
135 "absolute upper-left x: " << rx
<< endl
<<
136 "absolute upper-left y: " << ry
<< endl
<<
137 "relative upper-left x: " << win_attributes
.x
<< endl
<<
138 "relative upper-left y: " << win_attributes
.y
<< endl
;
143 void XWindow::updateBlackboxAttributes() {
145 unsigned long num
= PropBlackboxAttributesElements
;
149 if (_netclient
->getValue(_window
,
150 _netclient
->xaBlackboxAttributes(),
151 _netclient
->xaBlackboxAttributes(),
153 if (num
== PropBlackboxAttributesElements
)
154 if (data
[0] & AttribDecoration
)
155 _decorated
= (data
[4] != DecorNone
);
160 void XWindow::updateNormalHints() {
165 _gravity
= NorthWestGravity
;
167 _base_x
= _base_y
= 0;
169 if (XGetWMNormalHints(_display
, _window
, &size
, &ret
)) {
170 if (size
.flags
& PWinGravity
)
171 _gravity
= size
.win_gravity
;
172 if (size
.flags
& PBaseSize
) {
173 _base_x
= size
.base_width
;
174 _base_y
= size
.base_height
;
176 if (size
.flags
& PResizeInc
) {
177 _inc_x
= size
.width_inc
;
178 _inc_y
= size
.height_inc
;
184 void XWindow::updateWMHints() {
187 // assume a window takes input if it doesnt specify
190 if ((hints
= XGetWMHints(_display
, _window
)) != NULL
) {
191 if (hints
->flags
& InputHint
)
192 _can_focus
= hints
->input
;
198 void XWindow::updateState() {
200 _shaded
= _iconic
= _max_vert
= _max_horz
= false;
202 unsigned long num
= (unsigned) -1;
204 if (! _netclient
->getValue(_window
, _netclient
->wmState(), XA_ATOM
,
207 for (unsigned long i
= 0; i
< num
; ++i
) {
208 if (state
[i
] == _netclient
->wmStateMaximizedVert())
210 if (state
[i
] == _netclient
->wmStateMaximizedHorz())
212 if (state
[i
] == _netclient
->wmStateShaded())
214 if (state
[i
] == _netclient
->wmStateHidden())
222 void XWindow::updateDesktop() {
223 unsigned long d
= 0ul;
224 if (! _netclient
->getValue(_window
, _netclient
->wmDesktop(), XA_CARDINAL
, d
))
227 _desktop
= static_cast<unsigned int>(d
);
231 void XWindow::updateTitle() {
235 if (! _netclient
->getValue(_window
, _netclient
->wmName(),
236 Netclient::utf8
, _title
)) {
238 _netclient
->getValue(_window
, XA_WM_NAME
, Netclient::ansi
, _title
);
247 void XWindow::updateClass() {
249 _app_name
= _app_class
= "";
251 Netclient::StringVect v
;
252 unsigned long num
= 2;
254 if (! _netclient
->getValue(_window
, XA_WM_CLASS
, Netclient::ansi
, num
, v
))
257 if (num
> 0) _app_name
= v
[0];
258 if (num
> 1) _app_class
= v
[1];
263 void XWindow::shade(const bool sh
) const {
264 _netclient
->sendClientMessage(_root
, _netclient
->wmState(),
265 _window
, (sh
? 1 : 0),
266 _netclient
->wmStateShaded());
269 void XWindow::close() const {
270 _netclient
->sendClientMessage(_root
, _netclient
->closeWindow(),
275 void XWindow::raise() const {
276 XRaiseWindow(_display
, _window
);
279 void XWindow::lower() const {
280 XLowerWindow(_display
, _window
);
283 void XWindow::iconify() const {
284 _netclient
->sendClientMessage(_root
, _netclient
->xaWmChangeState(),
285 _window
, IconicState
);
288 void XWindow::focus(bool raise
) const {
289 // this will cause the window to be uniconified also
292 _netclient
->sendClientMessage(_root
, _netclient
->activeWindow(),
295 XSetInputFocus(_display
, _window
, None
, CurrentTime
);
299 void XWindow::decorate(bool d
) const {
300 _netclient
->sendClientMessage(_root
,
301 _netclient
->xaBlackboxChangeAttributes(),
302 _window
, AttribDecoration
,
303 0, 0, 0, (d
? DecorNormal
: DecorNone
));
306 void XWindow::sendTo(unsigned int dest
) const {
307 _netclient
->sendClientMessage(_root
, _netclient
->wmDesktop(),
312 void XWindow::move(int x
, int y
) const {
314 XWindowAttributes win_attributes
;
319 if (! XGetWindowAttributes(_display
, _window
, &win_attributes
)) {
320 std::cerr
<< "move: couldn't get what I needed. not able to move, sorry.\n";
324 XTranslateCoordinates (_display
, _window
, win_attributes
.root
,
325 -win_attributes
.border_width
,
326 -win_attributes
.border_width
,
331 int dw
= _screenInfo
.width(), dh
= _screenInfo
.height();
334 /* find our window manager frame, if any */
335 Window wmframe
= _window
;
342 status
= XQueryTree(_display
, wmframe
, &root
, &parent
, &childlist
, &ujunk
);
343 if (parent
== root
|| !parent
|| !status
)
346 if (status
&& childlist
)
347 XFree((char *)childlist
);
350 if (wmframe
!= _window
) {
351 /* WM reparented, so find edges of the frame */
352 /* Only works for ICCCM-compliant WMs, and then only if the
353 window has corner gravity. We would need to know the original width
354 of the window to correctly handle the other gravities. */
356 XWindowAttributes frame_attr
;
358 if (!XGetWindowAttributes(_display
, wmframe
, &frame_attr
)) {
359 std::cerr
<< "updateDimensions. error. can't get frame attributes.\n";
363 case NorthWestGravity
: case SouthWestGravity
:
364 case NorthEastGravity
: case SouthEastGravity
:
369 case NorthWestGravity
: case SouthWestGravity
:
370 case NorthEastGravity
: case SouthEastGravity
:
372 xright
= dw
- frame_attr
.x
- frame_attr
.width
-
373 2*frame_attr
.border_width
;
376 case NorthWestGravity
: case SouthWestGravity
:
377 case NorthEastGravity
: case SouthEastGravity
:
382 case NorthWestGravity
: case SouthWestGravity
:
383 case NorthEastGravity
: case SouthEastGravity
:
385 ybelow
= dh
- frame_attr
.y
- frame_attr
.height
-
386 2*frame_attr
.border_width
;
390 int destx
= rx
+x
, desty
= ry
+y
;
393 std::cout
<< "moving window to: +" << destx
<< "+" << desty
<< endl
;
396 XMoveWindow(_display
, _window
, destx
, desty
);
401 void XWindow::resizeRel(int dwidth
, int dheight
) const {
402 // resize in increments if requested by the window
403 unsigned int width
= _rect
.width(), height
= _rect
.height();
405 unsigned int wdest
= width
+ (dwidth
* _inc_x
) / _inc_x
* _inc_x
+ _base_x
;
406 unsigned int hdest
= height
+ (dheight
* _inc_y
) / _inc_y
* _inc_y
+ _base_y
;
408 XResizeWindow(_display
, _window
, wdest
, hdest
);
412 void XWindow::resizeAbs(unsigned int width
, unsigned int height
) const {
413 // resize in increments if requested by the window
415 unsigned int wdest
= width
/ _inc_x
* _inc_x
+ _base_x
;
416 unsigned int hdest
= height
/ _inc_y
* _inc_y
+ _base_y
;
419 while (width
> wdest
)
422 while (width
< wdest
)
425 if (height
> hdest
) {
426 while (height
> hdest
)
429 while (height
< hdest
)
433 XResizeWindow(_display
, _window
, wdest
, hdest
);
437 void XWindow::toggleMaximize(Max max
) const {
441 sendClientMessage(_root
, _netclient
->wmState(),
442 _window
, (_max_vert
== _max_horz
? 2 : 1),
443 _netclient
->wmStateMaximizedHorz(),
444 _netclient
->wmStateMaximizedVert());
449 sendClientMessage(_root
, _netclient
->wmState(),
451 _netclient
->wmStateMaximizedHorz());
456 sendClientMessage(_root
, _netclient
->wmState(),
458 _netclient
->wmStateMaximizedVert());
462 assert(false); // you should not do this. it is pointless and probly a bug
468 void XWindow::maximize(Max max
) const {
472 sendClientMessage(_root
, _netclient
->wmState(),
474 _netclient
->wmStateMaximizedHorz(),
475 _netclient
->wmStateMaximizedVert());
480 sendClientMessage(_root
, _netclient
->wmState(),
482 _netclient
->wmStateMaximizedHorz(),
483 _netclient
->wmStateMaximizedVert());
488 sendClientMessage(_root
, _netclient
->wmState(),
490 _netclient
->wmStateMaximizedHorz());
495 sendClientMessage(_root
, _netclient
->wmState(),
497 _netclient
->wmStateMaximizedVert());