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(Window window
)
26 // initialize vars to false/invalid values
28 _gravity
= _base_x
= _base_y
= _inc_x
= _inc_y
= _max_x
= _max_y
= _min_x
=
32 _desktop
= 0xffffffff - 1;
33 _can_focus
= _urgent
= _focus_notify
= _shaped
= _modal
= _shaded
=
34 _max_horz
= _max_vert
= _fullscreen
= _floating
= false;
37 // update EVERYTHING the first time!!
45 void OBClient::updateNormalHints()
51 _gravity
= NorthWestGravity
;
53 _base_x
= _base_y
= 0;
55 // get the hints from the window
56 if (XGetWMNormalHints(otk::OBDisplay::display
, _window
, &size
, &ret
)) {
57 if (size
.flags
& PWinGravity
)
58 _gravity
= size
.win_gravity
;
59 if (size
.flags
& PBaseSize
) {
60 _base_x
= size
.base_width
;
61 _base_y
= size
.base_height
;
63 if (size
.flags
& PResizeInc
) {
64 _inc_x
= size
.width_inc
;
65 _inc_y
= size
.height_inc
;
71 void OBClient::updateWMHints()
75 // assume a window takes input if it doesnt specify
79 if ((hints
= XGetWMHints(otk::OBDisplay::display
, _window
)) != NULL
) {
80 if (hints
->flags
& InputHint
)
81 _can_focus
= hints
->input
;
82 if (hints
->flags
& XUrgencyHint
)
84 if (hints
->flags
& WindowGroupHint
)
85 if (hints
->window_group
!= _group
) {
86 // XXX: remove from the old group if there was one
87 _group
= hints
->window_group
;
88 // XXX: do stuff with the group
95 void OBClient::updateTitle()
97 const otk::OBProperty
*property
= Openbox::instance
->property();
102 if (! property
->get(_window
, otk::OBProperty::net_wm_name
,
103 otk::OBProperty::utf8
, &_title
)) {
105 property
->get(_window
, otk::OBProperty::wm_name
,
106 otk::OBProperty::ascii
, &_title
);
110 _title
= _("Unnamed Window");
114 void OBClient::updateClass()
116 const otk::OBProperty
*property
= Openbox::instance
->property();
119 _app_name
= _app_class
= "";
121 otk::OBProperty::StringVect v
;
122 unsigned long num
= 2;
124 if (! property
->get(_window
, otk::OBProperty::wm_class
,
125 otk::OBProperty::ascii
, &num
, &v
))
128 if (num
> 0) _app_name
= v
[0];
129 if (num
> 1) _app_class
= v
[1];
133 void OBClient::update(const XPropertyEvent
&e
)
135 const otk::OBProperty
*property
= Openbox::instance
->property();
137 if (e
.atom
== XA_WM_NORMAL_HINTS
)
139 else if (e
.atom
== XA_WM_HINTS
)
141 else if (e
.atom
== property
->atom(otk::OBProperty::net_wm_name
) ||
142 e
.atom
== property
->atom(otk::OBProperty::wm_name
) ||
143 e
.atom
== property
->atom(otk::OBProperty::net_wm_icon_name
) ||
144 e
.atom
== property
->atom(otk::OBProperty::wm_icon_name
))
146 else if (e
.atom
== property
->atom(otk::OBProperty::wm_class
))
151 void OBClient::setWMState(long state
)
153 if (state
== _state
) return; // no change
157 // XXX: cause it to iconify
160 // XXX: cause it to uniconify
167 void OBClient::setDesktop(long target
)
170 //assert(target == 0xffffffff || target < MAX);
172 // XXX: move the window to the new desktop
177 void OBClient::setState(StateAction action
, long data1
, long data2
)
179 const otk::OBProperty
*property
= Openbox::instance
->property();
181 if (!(action
== State_Add
|| action
== State_Remove
||
182 action
== State_Toggle
))
183 return; // an invalid action was passed to the client message, ignore it
185 for (int i
= 0; i
< 2; ++i
) {
186 Atom state
= i
== 0 ? data1
: data2
;
188 if (! state
) continue;
190 // if toggling, then pick whether we're adding or removing
191 if (action
== State_Toggle
) {
192 if (state
== property
->atom(otk::OBProperty::net_wm_state_modal
))
193 action
= _modal
? State_Remove
: State_Add
;
195 property
->atom(otk::OBProperty::net_wm_state_maximized_vert
))
196 action
= _max_vert
? State_Remove
: State_Add
;
198 property
->atom(otk::OBProperty::net_wm_state_maximized_horz
))
199 action
= _max_horz
? State_Remove
: State_Add
;
200 else if (state
== property
->atom(otk::OBProperty::net_wm_state_shaded
))
201 action
= _shaded
? State_Remove
: State_Add
;
203 property
->atom(otk::OBProperty::net_wm_state_fullscreen
))
204 action
= _fullscreen
? State_Remove
: State_Add
;
205 else if (state
== property
->atom(otk::OBProperty::net_wm_state_floating
))
206 action
= _floating
? State_Remove
: State_Add
;
209 if (action
== State_Add
) {
210 if (state
== property
->atom(otk::OBProperty::net_wm_state_modal
)) {
211 if (_modal
) continue;
213 // XXX: give it focus if another window has focus that shouldnt now
215 property
->atom(otk::OBProperty::net_wm_state_maximized_vert
)){
216 if (_max_vert
) continue;
218 // XXX: resize the window etc
220 property
->atom(otk::OBProperty::net_wm_state_maximized_horz
)){
221 if (_max_horz
) continue;
223 // XXX: resize the window etc
225 property
->atom(otk::OBProperty::net_wm_state_shaded
)) {
226 if (_shaded
) continue;
228 // XXX: hide the client window
230 property
->atom(otk::OBProperty::net_wm_state_fullscreen
)) {
231 if (_fullscreen
) continue;
233 // XXX: raise the window n shit
235 property
->atom(otk::OBProperty::net_wm_state_floating
)) {
236 if (_floating
) continue;
238 // XXX: raise the window n shit
241 } else { // action == State_Remove
242 if (state
== property
->atom(otk::OBProperty::net_wm_state_modal
)) {
243 if (!_modal
) continue;
246 property
->atom(otk::OBProperty::net_wm_state_maximized_vert
)){
247 if (!_max_vert
) continue;
249 // XXX: resize the window etc
251 property
->atom(otk::OBProperty::net_wm_state_maximized_horz
)){
252 if (!_max_horz
) continue;
254 // XXX: resize the window etc
256 property
->atom(otk::OBProperty::net_wm_state_shaded
)) {
257 if (!_shaded
) continue;
259 // XXX: show the client window
261 property
->atom(otk::OBProperty::net_wm_state_fullscreen
)) {
262 if (!_fullscreen
) continue;
264 // XXX: lower the window to its proper layer
266 property
->atom(otk::OBProperty::net_wm_state_floating
)) {
267 if (!_floating
) continue;
269 // XXX: lower the window to its proper layer
276 void OBClient::update(const XClientMessageEvent
&e
)
278 if (e
.format
!= 32) return;
280 const otk::OBProperty
*property
= Openbox::instance
->property();
282 if (e
.message_type
== property
->atom(otk::OBProperty::wm_change_state
))
283 setWMState(e
.data
.l
[0]);
284 else if (e
.message_type
==
285 property
->atom(otk::OBProperty::net_wm_desktop
))
286 setDesktop(e
.data
.l
[0]);
287 else if (e
.message_type
== property
->atom(otk::OBProperty::net_wm_state
))
288 setState((StateAction
)e
.data
.l
[0], e
.data
.l
[1], e
.data
.l
[2]);