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