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