aboutsummaryrefslogtreecommitdiff
path: root/src/Ewmh.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ewmh.cc')
-rw-r--r--src/Ewmh.cc322
1 files changed, 322 insertions, 0 deletions
diff --git a/src/Ewmh.cc b/src/Ewmh.cc
new file mode 100644
index 0000000..87e55bf
--- /dev/null
+++ b/src/Ewmh.cc
@@ -0,0 +1,322 @@
1// Ewmh.cc for FbPager
2// Copyright (c) 2004 Henrik Kinnunen (fluxgen at users.sourceforge.net)
3//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22#include "Ewmh.hh"
23
24#include "Pager.hh"
25#include "WindowHint.hh"
26
27#include "FbTk/App.hh"
28#include "FbTk/FbWindow.hh"
29#include "FbRootWindow.hh"
30
31#include <X11/Xatom.h>
32
33#include <iostream>
34#include <vector>
35#include <sys/types.h>
36#include <unistd.h>
37#include <memory>
38
39using namespace std;
40
41namespace FbPager {
42
43class Ewmh_priv {
44public:
45 Ewmh_priv() {
46 Display *disp = FbTk::App::instance()->display();
47 state_skip_pager = XInternAtom(disp, "_NET_WM_STATE_SKIP_PAGER", False);
48 state_skip_taskbar = XInternAtom(disp, "_NET_WM_STATE_SKIP_TASKBAR", False);
49 state_sticky = XInternAtom(disp, "_NET_WM_STATE_STICKY", False);
50 state_hidden = XInternAtom(disp, "_NET_WM_STATE_HIDDEN", False);
51 state_shaded = XInternAtom(disp, "_NET_WM_STATE_SHADED", False);
52 state_above = XInternAtom(disp, "_NET_WM_STATE_ABOVE", False);
53 state_below = XInternAtom(disp, "_NET_WM_STATE_BELOW", False);
54 wm_desktop = XInternAtom(disp, "_NET_WM_DESKTOP", False);
55 wm_state = XInternAtom(disp, "_NET_WM_STATE", False);
56 wm_pid = XInternAtom(disp, "_NET_WM_PID", False);
57 wm_type = XInternAtom(disp, "_NET_WM_WINDOW_TYPE", False);
58 type_dock = XInternAtom(disp, "_NET_WM_WINDOW_TYPE_DOCK", False);
59 number_of_desktops = XInternAtom(disp, "_NET_NUMBER_OF_DESKTOPS", False);
60 current_desktop = XInternAtom(disp, "_NET_CURRENT_DESKTOP", False);
61 clientlist = XInternAtom(disp, "_NET_CLIENT_LIST", False);
62 moveresize_window = XInternAtom(disp, "_NET_MOVERESIZE_WINDOW", False);
63 active_window = XInternAtom(disp, "_NET_ACTIVE_WINDOW", False);
64 close_window = XInternAtom(disp, "_NET_CLOSE_WINDOW", False);
65 desktop_layout = XInternAtom(disp, "_NET_DESKTOP_LAYOUT", False);
66 }
67 Atom state_skip_pager, state_skip_taskbar, state_sticky,
68 state_hidden, state_shaded, state_above, state_below;
69 Atom wm_desktop, wm_state, wm_pid, wm_type;
70 Atom type_dock;
71 Atom number_of_desktops, current_desktop;
72 Atom clientlist;
73 Atom moveresize_window;
74 Atom active_window;
75 Atom close_window;
76 Atom above, below;
77 Atom desktop_layout;
78};
79
80Ewmh::Ewmh():
81 m_support(true),
82 m_data(new Ewmh_priv()) {
83
84 //!! TODO
85 // check for ewmh support
86
87}
88
89Ewmh::~Ewmh() {
90}
91
92
93void Ewmh::setFocus(FbTk::FbWindow &win) {
94
95}
96
97void Ewmh::setDesktopLayout(FbTk::FbWindow &root,
98 Orientation orientation,
99 Corner starting_corner,
100 unsigned int columns, unsigned int rows) {
101 unsigned int data[4] = { orientation, columns, rows, starting_corner };
102 root.changeProperty(m_data->desktop_layout,
103 XA_CARDINAL,
104 32,
105 PropModeReplace,
106 (unsigned char*)data, 4 );
107}
108
109void Ewmh::moveResize(FbTk::FbWindow &win) {
110
111 // We can't do this yet, there is a bug in fluxbox 0.9.8
112 // and this makes it crash (it's fixed in cvs though)
113 /*
114 Display *disp = FbTk::App::instance()->display();
115 XEvent event;
116 event.xclient.display = disp;
117 event.xclient.type = ClientMessage;
118 event.xclient.window = RootWindow(disp, win.screenNumber());
119 event.xclient.message_type = m_data->moveresize_window;
120 event.xclient.format = 32;
121 event.xclient.data.l[0] = 0;
122 event.xclient.data.l[1] = win.x();
123 event.xclient.data.l[2] = win.y();
124 event.xclient.data.l[3] = win.width();
125 event.xclient.data.l[4] = win.height();
126
127 XSendEvent(disp, event.xclient.window, False, SubstructureNotifyMask, &event);
128 */
129}
130
131void Ewmh::sendToWorkspace(FbTk::FbWindow &win, int workspace) {
132
133}
134
135void Ewmh::closeWindow(FbTk::FbWindow &win) {
136 Display *disp = FbTk::App::instance()->display();
137 XEvent event;
138 event.xclient.display = disp;
139 event.xclient.type = ClientMessage;
140 event.xclient.window = win.window();
141 event.xclient.message_type = m_data->close_window;
142 event.xclient.format = 32;
143 event.xclient.data.l[0] = 0;
144 XSendEvent(disp, RootWindow(disp, DefaultScreen(disp)), False, SubstructureNotifyMask, &event);
145}
146
147bool Ewmh::clientMessage(Pager &pager, XClientMessageEvent &event) {
148 if (!m_support)
149 return false;
150
151 if (event.message_type == m_data->current_desktop) {
152 pager.setCurrentWorkspace(event.data.l[0]);
153 return true;
154 } else if (event.message_type == m_data->number_of_desktops) {
155 pager.updateWorkspaceCount(event.data.l[0]);
156 return true;
157 } else if (event.message_type == m_data->wm_desktop) {
158 pager.moveToWorkspace(event.window, event.data.l[0]);
159 return true;
160 } else if (event.message_type == m_data->clientlist) {
161 return true;
162 } else if (event.message_type == m_data->active_window) {
163 pager.setFocusedWindow(event.window);
164 return true;
165 }
166
167 return false;
168}
169
170void Ewmh::changeWorkspace(int screen_num, int workspace) {
171 Display *disp = FbTk::App::instance()->display();
172 XEvent event;
173 event.xclient.display = disp;
174 event.xclient.type = ClientMessage;
175 event.xclient.window = RootWindow(disp, screen_num);
176 event.xclient.message_type = m_data->current_desktop;
177 event.xclient.format = 32;
178 event.xclient.data.l[0] = workspace;
179 XSendEvent(disp, event.xclient.window, False, SubstructureNotifyMask, &event);
180}
181
182void Ewmh::setHints(FbTk::FbWindow &win, WindowHint &hint) {
183
184 int data = getpid();
185 win.changeProperty(m_data->wm_pid,
186 XA_CARDINAL,
187 32,
188 PropModeReplace,
189 (unsigned char *)&data, 1);
190
191 if (hint.flags() & WindowHint::WHINT_STICKY) {
192 data = 0xFFFFFFFF;
193 win.changeProperty(m_data->wm_desktop,
194 XA_CARDINAL,
195 32,
196 PropModeReplace,
197 (unsigned char *)&data, 1);
198 }
199
200 if (hint.flags() & WindowHint::WHINT_TYPE_DOCK) {
201 cerr << "Setting type dock." << endl;
202 Atom data = m_data->type_dock;
203 win.changeProperty(m_data->wm_type,
204 XA_ATOM,
205 32,
206 PropModeReplace,
207 (unsigned char *)&data, 1);
208 }
209
210 std::vector<Atom> states;
211 if (hint.flags() & WindowHint::WHINT_SKIP_TASKBAR)
212 states.push_back(m_data->state_skip_taskbar);
213 if (hint.flags() & WindowHint::WHINT_SKIP_PAGER)
214 states.push_back(m_data->state_skip_pager);
215 if (hint.flags() & WindowHint::WHINT_STICKY)
216 states.push_back(m_data->state_sticky);
217 if (hint.flags() & WindowHint::WHINT_HIDDEN)
218 states.push_back(m_data->state_hidden);
219 if (hint.flags() & WindowHint::WHINT_LAYER_TOP){
220 states.push_back(m_data->state_above);
221 cerr << "Setting state above." << endl;
222 }
223 if (hint.flags() & WindowHint::WHINT_LAYER_BOTTOM) {
224 cerr<< "Setting state bottom." << endl;
225 states.push_back(m_data->state_below);
226 }
227
228 Atom *state_atoms = new Atom[states.size()];
229 for (size_t i=0; i < states.size(); ++i)
230 state_atoms[i] = states[i];
231
232 win.changeProperty(m_data->wm_state,
233 XA_ATOM,
234 32,
235 PropModeReplace,
236 (unsigned char *)state_atoms, states.size());
237 delete [] state_atoms;
238}
239
240
241struct PropT {
242 PropT(unsigned char *data, unsigned int num):data(data), num(num) { }
243 ~PropT() {
244 if (data != 0)
245 XFree(data);
246 }
247 unsigned char *data;
248 unsigned int num;
249};
250
251typedef std::auto_ptr<PropT> PropTPtr;
252
253PropT *property(const FbTk::FbWindow &win, Atom atom,
254 Atom type, unsigned int num) {
255 Atom ret_type;
256 int fmt;
257 unsigned long nitems, bytes_after;
258 unsigned char *data = 0;
259 win.property(atom,
260 0, num,
261 False,
262 type,
263 &ret_type, &fmt,
264 &nitems,
265 &bytes_after,
266 &data);
267 return new PropT(data, nitems);
268
269}
270
271void Ewmh::getHints(const FbTk::FbWindow &win, WindowHint &hint) const {
272 PropTPtr p(property(win,
273 m_data->wm_state,
274 XA_ATOM, 0x7FFFFFFF));
275
276 if (p.get() != 0 && p->data != 0) {
277
278 Atom *states = (Atom *)(p->data);
279 for (int i=0; i<p->num; ++i) {
280 if (states[i] == m_data->state_skip_pager)
281 hint.add(WindowHint::WHINT_SKIP_PAGER);
282 else if (states[i] == m_data->state_skip_taskbar)
283 hint.add(WindowHint::WHINT_SKIP_TASKBAR);
284 else if (states[i] == m_data->state_sticky)
285 hint.add(WindowHint::WHINT_STICKY);
286 else if (states[i] == m_data->state_shaded)
287 hint.add(WindowHint::WHINT_SHADED);
288 }
289 }
290
291 p.reset(property(win, m_data->wm_type,
292 XA_ATOM, 0x7FFFFFFF));
293 if (p.get() != 0 && p->data != 0) {
294 // we only care about the first type.
295 Atom *atoms = (Atom *)p->data;
296 if (atoms[0] == m_data->type_dock)
297 hint.add(WindowHint::WHINT_TYPE_DOCK);
298 }
299
300 p.reset(property(win, m_data->wm_desktop,
301 XA_CARDINAL, 1));
302 if (p.get() != 0 && p->data != 0) {
303 int workspace = static_cast<int>(*(p->data));
304 hint.setWorkspace(workspace);
305 }
306}
307
308int Ewmh::numberOfWorkspaces(int screen_num) const {
309
310 PropTPtr p(property(FbRootWindow(screen_num),
311 m_data->number_of_desktops,
312 XA_CARDINAL, 1));
313 if (p.get() == 0 || p->data == 0)
314 return 0;
315 else {
316 int num = static_cast<int>(*(p->data));
317 return num;
318 }
319
320}
321
322} // end namespace FbPager