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]);