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