1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
6 #include "otk/display.hh"
7 #include "otk/property.hh"
11 #include <X11/Xutil.h>
16 #define _(str) gettext(str)
21 OBClient::OBClient(BScreen
*screen
, Window window
)
22 : _screen(screen
), _window(window
)
27 // initialize vars to false/invalid values
29 _gravity
= _base_x
= _base_y
= _inc_x
= _inc_y
= _max_x
= _max_y
= _min_x
=
33 _desktop
= 0xffffffff - 1;
34 _can_focus
= _urgent
= _focus_notify
= _shaped
= _modal
= _shaded
=
35 _max_horz
= _max_vert
= _fullscreen
= _floating
= false;
38 // update EVERYTHING the first time!!
46 void OBClient::updateNormalHints()
52 _gravity
= NorthWestGravity
;
54 _base_x
= _base_y
= 0;
56 // get the hints from the window
57 if (XGetWMNormalHints(otk::OBDisplay::display
, _window
, &size
, &ret
)) {
58 if (size
.flags
& PWinGravity
)
59 _gravity
= size
.win_gravity
;
60 if (size
.flags
& PBaseSize
) {
61 _base_x
= size
.base_width
;
62 _base_y
= size
.base_height
;
64 if (size
.flags
& PResizeInc
) {
65 _inc_x
= size
.width_inc
;
66 _inc_y
= size
.height_inc
;
72 void OBClient::updateWMHints()
76 // assume a window takes input if it doesnt specify
80 if ((hints
= XGetWMHints(otk::OBDisplay::display
, _window
)) != NULL
) {
81 if (hints
->flags
& InputHint
)
82 _can_focus
= hints
->input
;
83 if (hints
->flags
& XUrgencyHint
)
85 if (hints
->flags
& WindowGroupHint
)
86 if (hints
->window_group
!= _group
) {
87 // XXX: remove from the old group if there was one
88 _group
= hints
->window_group
;
89 // XXX: do stuff with the group
96 void OBClient::updateTitle()
98 const otk::OBProperty
*property
= Openbox::instance
->property();
103 if (! property
->get(_window
, otk::OBProperty::net_wm_name
,
104 otk::OBProperty::utf8
, &_title
)) {
106 property
->get(_window
, otk::OBProperty::wm_name
,
107 otk::OBProperty::ascii
, &_title
);
111 _title
= _("Unnamed Window");
115 void OBClient::updateClass()
117 const otk::OBProperty
*property
= Openbox::instance
->property();
120 _app_name
= _app_class
= "";
122 otk::OBProperty::StringVect v
;
123 unsigned long num
= 2;
125 if (! property
->get(_window
, otk::OBProperty::wm_class
,
126 otk::OBProperty::ascii
, &num
, &v
))
129 if (num
> 0) _app_name
= v
[0];
130 if (num
> 1) _app_class
= v
[1];
134 void OBClient::update(const XPropertyEvent
&e
)
136 const otk::OBProperty
*property
= Openbox::instance
->property();
138 if (e
.atom
== XA_WM_NORMAL_HINTS
)
140 else if (e
.atom
== XA_WM_HINTS
)
142 else if (e
.atom
== property
->atom(otk::OBProperty::net_wm_name
) ||
143 e
.atom
== property
->atom(otk::OBProperty::wm_name
) ||
144 e
.atom
== property
->atom(otk::OBProperty::net_wm_icon_name
) ||
145 e
.atom
== property
->atom(otk::OBProperty::wm_icon_name
))
147 else if (e
.atom
== property
->atom(otk::OBProperty::wm_class
))
152 void OBClient::setWMState(long state
)
154 if (state
== _state
) return; // no change
158 // XXX: cause it to iconify
161 // XXX: cause it to uniconify
168 void OBClient::setDesktop(long target
)
171 //assert(target == 0xffffffff || target < MAX);
173 // XXX: move the window to the new desktop
178 void OBClient::setState(StateAction action
, long data1
, long data2
)
180 const otk::OBProperty
*property
= Openbox::instance
->property();
182 if (!(action
== State_Add
|| action
== State_Remove
||
183 action
== State_Toggle
))
184 return; // an invalid action was passed to the client message, ignore it
186 for (int i
= 0; i
< 2; ++i
) {
187 Atom state
= i
== 0 ? data1
: data2
;
189 if (! state
) continue;
191 // if toggling, then pick whether we're adding or removing
192 if (action
== State_Toggle
) {
193 if (state
== property
->atom(otk::OBProperty::net_wm_state_modal
))
194 action
= _modal
? State_Remove
: State_Add
;
196 property
->atom(otk::OBProperty::net_wm_state_maximized_vert
))
197 action
= _max_vert
? State_Remove
: State_Add
;
199 property
->atom(otk::OBProperty::net_wm_state_maximized_horz
))
200 action
= _max_horz
? State_Remove
: State_Add
;
201 else if (state
== property
->atom(otk::OBProperty::net_wm_state_shaded
))
202 action
= _shaded
? State_Remove
: State_Add
;
204 property
->atom(otk::OBProperty::net_wm_state_fullscreen
))
205 action
= _fullscreen
? State_Remove
: State_Add
;
206 else if (state
== property
->atom(otk::OBProperty::net_wm_state_floating
))
207 action
= _floating
? State_Remove
: State_Add
;
210 if (action
== State_Add
) {
211 if (state
== property
->atom(otk::OBProperty::net_wm_state_modal
)) {
212 if (_modal
) continue;
214 // XXX: give it focus if another window has focus that shouldnt now
216 property
->atom(otk::OBProperty::net_wm_state_maximized_vert
)){
217 if (_max_vert
) continue;
219 // XXX: resize the window etc
221 property
->atom(otk::OBProperty::net_wm_state_maximized_horz
)){
222 if (_max_horz
) continue;
224 // XXX: resize the window etc
226 property
->atom(otk::OBProperty::net_wm_state_shaded
)) {
227 if (_shaded
) continue;
229 // XXX: hide the client window
231 property
->atom(otk::OBProperty::net_wm_state_fullscreen
)) {
232 if (_fullscreen
) continue;
234 // XXX: raise the window n shit
236 property
->atom(otk::OBProperty::net_wm_state_floating
)) {
237 if (_floating
) continue;
239 // XXX: raise the window n shit
242 } else { // action == State_Remove
243 if (state
== property
->atom(otk::OBProperty::net_wm_state_modal
)) {
244 if (!_modal
) continue;
247 property
->atom(otk::OBProperty::net_wm_state_maximized_vert
)){
248 if (!_max_vert
) continue;
250 // XXX: resize the window etc
252 property
->atom(otk::OBProperty::net_wm_state_maximized_horz
)){
253 if (!_max_horz
) continue;
255 // XXX: resize the window etc
257 property
->atom(otk::OBProperty::net_wm_state_shaded
)) {
258 if (!_shaded
) continue;
260 // XXX: show the client window
262 property
->atom(otk::OBProperty::net_wm_state_fullscreen
)) {
263 if (!_fullscreen
) continue;
265 // XXX: lower the window to its proper layer
267 property
->atom(otk::OBProperty::net_wm_state_floating
)) {
268 if (!_floating
) continue;
270 // XXX: lower the window to its proper layer
277 void OBClient::update(const XClientMessageEvent
&e
)
279 if (e
.format
!= 32) return;
281 const otk::OBProperty
*property
= Openbox::instance
->property();
283 if (e
.message_type
== property
->atom(otk::OBProperty::wm_change_state
))
284 setWMState(e
.data
.l
[0]);
285 else if (e
.message_type
==
286 property
->atom(otk::OBProperty::net_wm_desktop
))
287 setDesktop(e
.data
.l
[0]);
288 else if (e
.message_type
== property
->atom(otk::OBProperty::net_wm_state
))
289 setState((StateAction
)e
.data
.l
[0], e
.data
.l
[1], e
.data
.l
[2]);