]> Dogcows Code - chaz/openbox/blob - src/client.cc
253fd235034b0d71947b6d73e15cc68784517f8b
[chaz/openbox] / src / client.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #include "client.hh"
4 #include "screen.hh"
5 #include "openbox.hh"
6 #include "otk/display.hh"
7 #include "otk/property.hh"
8
9 extern "C" {
10 #include <X11/Xlib.h>
11 #include <X11/Xutil.h>
12
13 #include <assert.h>
14
15 #include "gettext.h"
16 #define _(str) gettext(str)
17 }
18
19 namespace ob {
20
21 OBClient::OBClient(Window window)
22 : _window(window)
23 {
24 assert(window);
25
26 // initialize vars to false/invalid values
27 _group = 0;
28 _gravity = _base_x = _base_y = _inc_x = _inc_y = _max_x = _max_y = _min_x =
29 _min_y = -1;
30 _state = -1;
31 _type = Type_Normal;
32 _desktop = 0xffffffff - 1;
33 _can_focus = _urgent = _focus_notify = _shaped = _modal = _shaded =
34 _max_horz = _max_vert = _fullscreen = _floating = false;
35
36
37 // update EVERYTHING the first time!!
38 }
39
40 OBClient::~OBClient()
41 {
42 }
43
44
45 void OBClient::updateNormalHints()
46 {
47 XSizeHints size;
48 long ret;
49
50 // defaults
51 _gravity = NorthWestGravity;
52 _inc_x = _inc_y = 1;
53 _base_x = _base_y = 0;
54
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;
62 }
63 if (size.flags & PResizeInc) {
64 _inc_x = size.width_inc;
65 _inc_y = size.height_inc;
66 }
67 }
68 }
69
70
71 void OBClient::updateWMHints()
72 {
73 XWMHints *hints;
74
75 // assume a window takes input if it doesnt specify
76 _can_focus = true;
77 _urgent = false;
78
79 if ((hints = XGetWMHints(otk::OBDisplay::display, _window)) != NULL) {
80 if (hints->flags & InputHint)
81 _can_focus = hints->input;
82 if (hints->flags & XUrgencyHint)
83 _urgent = true;
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
89 }
90 XFree(hints);
91 }
92 }
93
94
95 void OBClient::updateTitle()
96 {
97 const otk::OBProperty *property = Openbox::instance->property();
98
99 _title = "";
100
101 // try netwm
102 if (! property->get(_window, otk::OBProperty::net_wm_name,
103 otk::OBProperty::utf8, &_title)) {
104 // try old x stuff
105 property->get(_window, otk::OBProperty::wm_name,
106 otk::OBProperty::ascii, &_title);
107 }
108
109 if (_title.empty())
110 _title = _("Unnamed Window");
111 }
112
113
114 void OBClient::updateClass()
115 {
116 const otk::OBProperty *property = Openbox::instance->property();
117
118 // set the defaults
119 _app_name = _app_class = "";
120
121 otk::OBProperty::StringVect v;
122 unsigned long num = 2;
123
124 if (! property->get(_window, otk::OBProperty::wm_class,
125 otk::OBProperty::ascii, &num, &v))
126 return;
127
128 if (num > 0) _app_name = v[0];
129 if (num > 1) _app_class = v[1];
130 }
131
132
133 void OBClient::update(const XPropertyEvent &e)
134 {
135 const otk::OBProperty *property = Openbox::instance->property();
136
137 if (e.atom == XA_WM_NORMAL_HINTS)
138 updateNormalHints();
139 else if (e.atom == XA_WM_HINTS)
140 updateWMHints();
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))
145 updateTitle();
146 else if (e.atom == property->atom(otk::OBProperty::wm_class))
147 updateClass();
148 }
149
150
151 void OBClient::setWMState(long state)
152 {
153 if (state == _state) return; // no change
154
155 switch (state) {
156 case IconicState:
157 // XXX: cause it to iconify
158 break;
159 case NormalState:
160 // XXX: cause it to uniconify
161 break;
162 }
163 _state = state;
164 }
165
166
167 void OBClient::setDesktop(long target)
168 {
169 assert(target >= 0);
170 //assert(target == 0xffffffff || target < MAX);
171
172 // XXX: move the window to the new desktop
173 _desktop = target;
174 }
175
176
177 void OBClient::setState(StateAction action, long data1, long data2)
178 {
179 const otk::OBProperty *property = Openbox::instance->property();
180
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
184
185 for (int i = 0; i < 2; ++i) {
186 Atom state = i == 0 ? data1 : data2;
187
188 if (! state) continue;
189
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;
194 else if (state ==
195 property->atom(otk::OBProperty::net_wm_state_maximized_vert))
196 action = _max_vert ? State_Remove : State_Add;
197 else if (state ==
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;
202 else if (state ==
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;
207 }
208
209 if (action == State_Add) {
210 if (state == property->atom(otk::OBProperty::net_wm_state_modal)) {
211 if (_modal) continue;
212 _modal = true;
213 // XXX: give it focus if another window has focus that shouldnt now
214 } else if (state ==
215 property->atom(otk::OBProperty::net_wm_state_maximized_vert)){
216 if (_max_vert) continue;
217 _max_vert = true;
218 // XXX: resize the window etc
219 } else if (state ==
220 property->atom(otk::OBProperty::net_wm_state_maximized_horz)){
221 if (_max_horz) continue;
222 _max_horz = true;
223 // XXX: resize the window etc
224 } else if (state ==
225 property->atom(otk::OBProperty::net_wm_state_shaded)) {
226 if (_shaded) continue;
227 _shaded = true;
228 // XXX: hide the client window
229 } else if (state ==
230 property->atom(otk::OBProperty::net_wm_state_fullscreen)) {
231 if (_fullscreen) continue;
232 _fullscreen = true;
233 // XXX: raise the window n shit
234 } else if (state ==
235 property->atom(otk::OBProperty::net_wm_state_floating)) {
236 if (_floating) continue;
237 _floating = true;
238 // XXX: raise the window n shit
239 }
240
241 } else { // action == State_Remove
242 if (state == property->atom(otk::OBProperty::net_wm_state_modal)) {
243 if (!_modal) continue;
244 _modal = false;
245 } else if (state ==
246 property->atom(otk::OBProperty::net_wm_state_maximized_vert)){
247 if (!_max_vert) continue;
248 _max_vert = false;
249 // XXX: resize the window etc
250 } else if (state ==
251 property->atom(otk::OBProperty::net_wm_state_maximized_horz)){
252 if (!_max_horz) continue;
253 _max_horz = false;
254 // XXX: resize the window etc
255 } else if (state ==
256 property->atom(otk::OBProperty::net_wm_state_shaded)) {
257 if (!_shaded) continue;
258 _shaded = false;
259 // XXX: show the client window
260 } else if (state ==
261 property->atom(otk::OBProperty::net_wm_state_fullscreen)) {
262 if (!_fullscreen) continue;
263 _fullscreen = false;
264 // XXX: lower the window to its proper layer
265 } else if (state ==
266 property->atom(otk::OBProperty::net_wm_state_floating)) {
267 if (!_floating) continue;
268 _floating = false;
269 // XXX: lower the window to its proper layer
270 }
271 }
272 }
273 }
274
275
276 void OBClient::update(const XClientMessageEvent &e)
277 {
278 if (e.format != 32) return;
279
280 const otk::OBProperty *property = Openbox::instance->property();
281
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]);
289 }
290
291 }
This page took 0.045146 seconds and 4 git commands to generate.