aboutsummaryrefslogtreecommitdiff
path: root/src/Gnome.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/Gnome.cc')
-rw-r--r--src/Gnome.cc438
1 files changed, 438 insertions, 0 deletions
diff --git a/src/Gnome.cc b/src/Gnome.cc
new file mode 100644
index 0000000..86f7f75
--- /dev/null
+++ b/src/Gnome.cc
@@ -0,0 +1,438 @@
1// Gnome.cc for fluxbox
2// Copyright (c) 2002 - 2003 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// $Id: Gnome.cc,v 1.32 2003/10/02 16:14:41 rathnor Exp $
23
24#include "Gnome.hh"
25
26#include "fluxbox.hh"
27#include "Window.hh"
28#include "Screen.hh"
29#include "WinClient.hh"
30#include "Workspace.hh"
31
32#include <iostream>
33#include <new>
34using namespace std;
35
36Gnome::Gnome() {
37 createAtoms();
38 enableUpdate();
39}
40
41Gnome::~Gnome() {
42 // destroy gnome windows
43 while (!m_gnomewindows.empty()) {
44 XDestroyWindow(FbTk::App::instance()->display(), m_gnomewindows.back());
45 m_gnomewindows.pop_back();
46 }
47}
48
49
50void Gnome::initForScreen(BScreen &screen) {
51 Display *disp = FbTk::App::instance()->display();
52 // create the GNOME window
53 Window gnome_win = XCreateSimpleWindow(disp,
54 screen.rootWindow().window(), 0, 0, 5, 5, 0, 0, 0);
55 // supported WM check
56 screen.rootWindow().changeProperty(m_gnome_wm_supporting_wm_check,
57 XA_CARDINAL, 32,
58 PropModeReplace, (unsigned char *) &gnome_win, 1);
59
60 XChangeProperty(disp, gnome_win,
61 m_gnome_wm_supporting_wm_check,
62 XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &gnome_win, 1);
63
64 // supported gnome atoms
65 Atom gnomeatomlist[] = {
66 m_gnome_wm_supporting_wm_check,
67 m_gnome_wm_win_workspace_names,
68 m_gnome_wm_win_client_list,
69 m_gnome_wm_win_state,
70 m_gnome_wm_win_hints,
71 m_gnome_wm_win_layer
72 };
73 //list atoms that we support
74 screen.rootWindow().changeProperty(m_gnome_wm_prot,
75 XA_ATOM, 32, PropModeReplace,
76 (unsigned char *)gnomeatomlist,
77 (sizeof gnomeatomlist)/sizeof gnomeatomlist[0]);
78
79 m_gnomewindows.push_back(gnome_win);
80
81 updateClientList(screen);
82 updateWorkspaceNames(screen);
83 updateWorkspaceCount(screen);
84 updateCurrentWorkspace(screen);
85
86}
87
88void Gnome::setupFrame(FluxboxWindow &win) {
89 // load gnome state (take queues from the main window of the frame)
90 Display *disp = FbTk::App::instance()->display();
91 Atom ret_type;
92 int fmt;
93 unsigned long nitems, bytes_after;
94 long flags, *data = 0;
95
96 if (win.winClient().property(m_gnome_wm_win_state, 0, 1, False, XA_CARDINAL,
97 &ret_type, &fmt, &nitems, &bytes_after,
98 (unsigned char **) &data) && data) {
99 flags = *data;
100 setState(&win, flags);
101 XFree (data);
102 } else {
103 updateState(win);
104 }
105
106 // load gnome layer atom
107 if (XGetWindowProperty(disp, win.clientWindow(),
108 m_gnome_wm_win_layer, 0, 1, False, XA_CARDINAL,
109 &ret_type, &fmt, &nitems, &bytes_after,
110 (unsigned char **) &data) == Success && data) {
111 flags = *data;
112 setLayer(&win, flags);
113 XFree (data);
114 } else {
115 updateLayer(win);
116 }
117
118 // load gnome workspace atom
119 if (XGetWindowProperty(disp, win.clientWindow(),
120 m_gnome_wm_win_workspace, 0, 1, False, XA_CARDINAL,
121 &ret_type, &fmt, &nitems, &bytes_after,
122 (unsigned char **) &data) == Success && data) {
123 unsigned int workspace_num = *data;
124 if (win.workspaceNumber() != workspace_num)
125 win.screen().reassociateWindow(&win, workspace_num, false);
126 XFree (data);
127 } else {
128 updateWorkspace(win);
129 }
130
131}
132
133void Gnome::updateClientList(BScreen &screen) {
134 size_t num=0;
135
136 // count window clients in each workspace
137 BScreen::Workspaces::const_iterator workspace_it =
138 screen.getWorkspacesList().begin();
139 BScreen::Workspaces::const_iterator workspace_it_end =
140 screen.getWorkspacesList().end();
141 for (; workspace_it != workspace_it_end; ++workspace_it) {
142 Workspace::Windows::iterator win_it =
143 (*workspace_it)->windowList().begin();
144 Workspace::Windows::iterator win_it_end =
145 (*workspace_it)->windowList().end();
146 for (; win_it != win_it_end; ++win_it)
147 num += (*win_it)->numClients();
148 }
149
150 Window *wl = new Window[num];
151 if (wl == 0) {
152 cerr<<"Fatal: Out of memory, can't allocate ("<<num*sizeof (Window)<<") for gnome client list"<<endl;
153 return;
154 }
155
156 //add client windows to buffer
157 workspace_it = screen.getWorkspacesList().begin();
158 int win=0;
159 for (; workspace_it != workspace_it_end; ++workspace_it) {
160
161 // Fill in array of window ID's
162 Workspace::Windows::const_iterator it =
163 (*workspace_it)->windowList().begin();
164 Workspace::Windows::const_iterator it_end =
165 (*workspace_it)->windowList().end();
166 for (; it != it_end; ++it) {
167 // TODO!
168 //check if the window don't want to be visible in the list
169 //if (! ( (*it)->getGnomeHints() & WIN_STATE_HIDDEN) ) {
170 std::list<WinClient *>::iterator client_it =
171 (*it)->clientList().begin();
172 std::list<WinClient *>::iterator client_it_end =
173 (*it)->clientList().end();
174 for (; client_it != client_it_end; ++client_it)
175 wl[win++] = (*client_it)->window();
176
177 }
178 }
179 //number of windows to show in client list
180 num = win;
181 screen.rootWindow().changeProperty(m_gnome_wm_win_client_list,
182 XA_CARDINAL, 32,
183 PropModeReplace, (unsigned char *)wl, num);
184
185 delete[] wl;
186}
187
188void Gnome::updateWorkspaceNames(BScreen &screen) {
189
190 int number_of_desks = screen.getWorkspaceNames().size();
191 const BScreen::WorkspaceNames &workspace_names = screen.getWorkspaceNames();
192 // convert our desktop names to a char * so we can send it
193 char *names[number_of_desks];
194
195 for (int i = 0; i < number_of_desks; i++) {
196 names[i] = new char[workspace_names[i].size() + 1];
197 strcpy(names[i], workspace_names[i].c_str());
198 }
199
200 XTextProperty text;
201 if (XStringListToTextProperty(names, number_of_desks, &text)) {
202 XSetTextProperty(FbTk::App::instance()->display(), screen.rootWindow().window(),
203 &text, m_gnome_wm_win_workspace_names);
204 XFree(text.value);
205 }
206
207 // destroy name buffers
208 for (int i = 0; i < number_of_desks; i++)
209 delete [] names[i];
210}
211
212void Gnome::updateCurrentWorkspace(BScreen &screen) {
213 int workspace = screen.currentWorkspaceID();
214 screen.rootWindow().changeProperty(m_gnome_wm_win_workspace, XA_CARDINAL, 32, PropModeReplace,
215 (unsigned char *)&workspace, 1);
216
217 updateClientList(screen); // make sure the client list is updated too
218}
219
220void Gnome::updateWorkspaceCount(BScreen &screen) {
221 int numworkspaces = screen.getCount();
222 screen.rootWindow().changeProperty(m_gnome_wm_win_workspace_count, XA_CARDINAL, 32, PropModeReplace,
223 (unsigned char *)&numworkspaces, 1);
224}
225
226void Gnome::updateWorkspace(FluxboxWindow &win) {
227 int val = win.workspaceNumber();
228 if (win.isStuck()) {
229 val = -1;
230 }
231#ifdef DEBUG
232 cerr<<__FILE__<<"("<<__LINE__<<"): setting workspace("<<val<<
233 ") for window("<<&win<<")"<<endl;
234#endif // DEBUG
235
236 FluxboxWindow::ClientList::iterator client_it = win.clientList().begin();
237 FluxboxWindow::ClientList::iterator client_it_end = win.clientList().end();
238 for (; client_it != client_it_end; ++client_it)
239 (*client_it)->changeProperty(m_gnome_wm_win_workspace,
240 XA_CARDINAL, 32, PropModeReplace,
241 (unsigned char *)&val, 1);
242}
243
244void Gnome::updateState(FluxboxWindow &win) {
245 //translate to gnome win state
246 int state=0;
247 if (win.isStuck())
248 state |= WIN_STATE_STICKY;
249 if (win.isIconic())
250 state |= WIN_STATE_MINIMIZED;
251 if (win.isShaded())
252 state |= WIN_STATE_SHADED;
253
254 FluxboxWindow::ClientList::iterator client_it = win.clientList().begin();
255 FluxboxWindow::ClientList::iterator client_it_end = win.clientList().end();
256 for (; client_it != client_it_end; ++client_it)
257 (*client_it)->changeProperty(m_gnome_wm_win_state,
258 XA_CARDINAL, 32,
259 PropModeReplace, (unsigned char *)&state, 1);
260}
261
262void Gnome::updateLayer(FluxboxWindow &win) {
263 //TODO - map from flux layers to gnome ones
264 // our layers are in the opposite direction to GNOME
265 int layernum = Fluxbox::instance()->getDesktopLayer() - win.layerNum();
266
267 FluxboxWindow::ClientList::iterator client_it = win.clientList().begin();
268 FluxboxWindow::ClientList::iterator client_it_end = win.clientList().end();
269 for (; client_it != client_it_end; ++client_it)
270 (*client_it)->changeProperty(m_gnome_wm_win_layer,
271 XA_CARDINAL, 32, PropModeReplace,
272 (unsigned char *)&layernum, 1);
273
274}
275
276void Gnome::updateHints(FluxboxWindow &win) {
277 //TODO
278
279}
280
281bool Gnome::checkClientMessage(const XClientMessageEvent &ce, BScreen * screen, WinClient * const winclient) {
282 if (ce.message_type == m_gnome_wm_win_workspace) {
283#ifdef DEBUG
284 cerr<<__FILE__<<"("<<__LINE__<<"): Got workspace atom="<<ce.data.l[0]<<endl;
285#endif//!DEBUG
286 if ( winclient !=0 && // the message sent to client window?
287 ce.data.l[0] >= 0 &&
288 ce.data.l[0] < (signed)winclient->screen().getCount()) {
289 winclient->screen().changeWorkspaceID(ce.data.l[0]);
290
291 } else if (screen!=0 && //the message sent to root window?
292 ce.data.l[0] >= 0 &&
293 ce.data.l[0] < (signed)screen->getCount())
294 screen->changeWorkspaceID(ce.data.l[0]);
295 return true;
296 } else if (winclient == 0)
297 return false;
298
299
300 if (ce.message_type == m_gnome_wm_win_state) {
301#ifdef DEBUG
302 cerr<<__FILE__<<"("<<__LINE__<<"): _WIN_STATE"<<endl;
303#endif // DEBUG
304
305#ifdef DEBUG
306 cerr<<__FILE__<<"("<<__LINE__<<"): Mask of members to change:"<<
307 hex<<ce.data.l[0]<<dec<<endl; // mask_of_members_to_change
308 cerr<<"New members:"<<ce.data.l[1]<<endl;
309#endif // DEBUG
310
311 if (winclient && winclient->fbwindow()) {
312 //get new states
313 int flag = ce.data.l[0] & ce.data.l[1];
314 //don't update this when when we set new state
315 disableUpdate();
316 // convert to Fluxbox state
317 setState(winclient->fbwindow(), flag);
318 // enable update of atom states
319 enableUpdate();
320 }
321 } else if (ce.message_type == m_gnome_wm_win_hints) {
322#ifdef DEBUG
323 cerr<<__FILE__<<"("<<__LINE__<<"): _WIN_HINTS"<<endl;
324#endif // DEBUG
325
326 } else if (ce.message_type == m_gnome_wm_win_layer) {
327#ifdef DEBUG
328 cerr<<__FILE__<<"("<<__LINE__<<"): _WIN_LAYER"<<endl;
329#endif // DEBUG
330
331 if (winclient && winclient->fbwindow())
332 setLayer(winclient->fbwindow(), ce.data.l[0]);
333 } else
334 return false; //the gnome atom wasn't found or not supported
335
336 return true; // we handled the atom
337}
338
339void Gnome::setState(FluxboxWindow *win, int state) {
340#ifdef DEBUG
341 cerr<<"Gnome: state=0x"<<hex<<state<<dec<<endl;
342#endif // DEBUG
343
344 if (state & WIN_STATE_STICKY) {
345#ifdef DEBUG
346 cerr<<"Gnome state: Sticky"<<endl;
347#endif // DEBUG
348 if (!win->isStuck())
349 win->stick();
350 } else if (win->isStuck())
351 win->stick();
352
353 if (state & WIN_STATE_MINIMIZED) {
354#ifdef DEBUG
355 cerr<<"Gnome state: Minimized"<<endl;
356#endif // DEBUG
357 if (win->isIconic())
358 win->iconify();
359 } else if (win->isIconic())
360 win->deiconify(true, true);
361
362 if (state & WIN_STATE_SHADED) {
363#ifdef DEBUG
364 cerr<<"Gnome state: Shade"<<endl;
365#endif // DEBUG
366 if (!win->isShaded())
367 win->shade();
368 } else if (win->isShaded())
369 win->shade();
370
371 /* TODO
372 if (state & WIN_STATE_MAXIMIZED_VERT)
373 cerr<<"Maximize Vert"<<endl;
374 if (state & WIN_STATE_MAXIMIZED_HORIZ)
375 cerr<<"Maximize Horiz"<<endl;
376 if (state & WIN_STATE_HIDDEN)
377 cerr<<"Hidden"<<endl;
378 if (state & WIN_STATE_HID_WORKSPACE)
379 cerr<<"HID Workspace"<<endl;
380 if (state & WIN_STATE_HID_TRANSIENT)
381 cerr<<"HID Transient"<<endl;
382 if (state & WIN_STATE_FIXED_POSITION)
383 cerr<<"Fixed Position"<<endl;
384 if (state & WIN_STATE_ARRANGE_IGNORE)
385 cerr<<"Arrange Ignore"<<endl;
386 */
387}
388
389void Gnome::setLayer(FluxboxWindow *win, int layer) {
390 if (!win) return;
391
392
393 switch (layer) {
394 case WIN_LAYER_DESKTOP:
395 layer = Fluxbox::instance()->getDesktopLayer();
396 break;
397 case WIN_LAYER_BELOW:
398 layer = Fluxbox::instance()->getBottomLayer();
399 break;
400 case WIN_LAYER_NORMAL:
401 layer = Fluxbox::instance()->getNormalLayer();
402 break;
403 case WIN_LAYER_ONTOP:
404 layer = Fluxbox::instance()->getTopLayer();
405 break;
406 case WIN_LAYER_DOCK:
407 layer = Fluxbox::instance()->getDockLayer();
408 break;
409 case WIN_LAYER_ABOVE_DOCK:
410 layer = Fluxbox::instance()->getAboveDockLayer();
411 break;
412 case WIN_LAYER_MENU:
413 layer = Fluxbox::instance()->getMenuLayer();
414 break;
415 default:
416 // our windows are in the opposite direction to gnome
417 layer = Fluxbox::instance()->getDesktopLayer() - layer;
418 break;
419 }
420 win->moveToLayer(layer);
421
422}
423
424void Gnome::createAtoms() {
425 Display *disp = FbTk::App::instance()->display();
426 m_gnome_wm_win_layer = XInternAtom(disp, "_WIN_LAYER", False);
427 m_gnome_wm_win_state = XInternAtom(disp, "_WIN_STATE", False);
428 m_gnome_wm_win_hints = XInternAtom(disp, "_WIN_HINTS", False);
429 m_gnome_wm_win_app_state = XInternAtom(disp, "_WIN_APP_STATE", False);
430 m_gnome_wm_win_expanded_size = XInternAtom(disp, "_WIN_EXPANDED_SIZE", False);
431 m_gnome_wm_win_icons = XInternAtom(disp, "_WIN_ICONS", False);
432 m_gnome_wm_win_workspace = XInternAtom(disp, "_WIN_WORKSPACE", False);
433 m_gnome_wm_win_workspace_count = XInternAtom(disp, "_WIN_WORKSPACE_COUNT", False);
434 m_gnome_wm_win_workspace_names = XInternAtom(disp, "_WIN_WORKSPACE_NAMES", False);
435 m_gnome_wm_win_client_list = XInternAtom(disp, "_WIN_CLIENT_LIST", False);
436 m_gnome_wm_prot = XInternAtom(disp, "_WIN_PROTOCOLS", False);
437 m_gnome_wm_supporting_wm_check = XInternAtom(disp, "_WIN_SUPPORTING_WM_CHECK", False);
438}