]> Dogcows Code - chaz/openbox/blob - src/screen.cc
51e3aa169f34975862ece70d7b6ec7b6cf2f8dca
[chaz/openbox] / src / screen.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #ifdef HAVE_CONFIG_H
4 # include "../config.h"
5 #endif
6
7 extern "C" {
8 #ifdef HAVE_STDIO_H
9 # include <stdio.h>
10 #endif // HAVE_STDIO_H
11
12 #ifdef HAVE_UNISTD_H
13 # include <sys/types.h>
14 # include <unistd.h>
15 #endif // HAVE_UNISTD_H
16
17 #include "gettext.h"
18 #define _(str) gettext(str)
19 }
20
21 #include "screen.hh"
22 #include "client.hh"
23 #include "openbox.hh"
24 #include "otk/display.hh"
25
26 static bool running;
27 static int anotherWMRunning(Display *display, XErrorEvent *) {
28 printf(_("Another window manager already running on display %s.\n"),
29 DisplayString(display));
30 running = true;
31 return -1;
32 }
33
34
35 namespace ob {
36
37
38 OBScreen::OBScreen(int screen)
39 : _number(screen)
40 {
41 assert(screen >= 0); assert(screen < ScreenCount(otk::OBDisplay::display));
42 _info = otk::OBDisplay::screenInfo(screen);
43
44 ::running = false;
45 XErrorHandler old = XSetErrorHandler(::anotherWMRunning);
46 XSelectInput(otk::OBDisplay::display, _info->getRootWindow(),
47 OBScreen::event_mask);
48 XSync(otk::OBDisplay::display, false);
49 XSetErrorHandler(old);
50
51 _managed = !::running;
52 if (! _managed) return; // was unable to manage the screen
53
54 printf(_("Managing screen %d: visual 0x%lx, depth %d\n"),
55 _number, XVisualIDFromVisual(_info->getVisual()), _info->getDepth());
56
57 Openbox::instance->property()->set(_info->getRootWindow(),
58 otk::OBProperty::openbox_pid,
59 otk::OBProperty::Atom_Cardinal,
60 (unsigned long) getpid());
61
62 // set the mouse cursor for the root window (the default cursor)
63 XDefineCursor(otk::OBDisplay::display, _info->getRootWindow(),
64 Openbox::instance->cursors().session);
65
66 _image_control = new otk::BImageControl(Openbox::instance->timerManager(),
67 _info, true);
68 _image_control->installRootColormap();
69 _root_cmap_installed = True;
70
71 _style.setImageControl(_image_control);
72
73
74 // Set the netwm atoms for geomtery and viewport
75 unsigned long geometry[] = { _size.x(),
76 _size.y() };
77 Openbox::instance->property()->set(_info->getRootWindow(),
78 otk::OBProperty::net_desktop_geometry,
79 otk::OBProperty::Atom_Cardinal,
80 geometry, 2);
81 unsigned long viewport[] = { 0, 0 };
82 Openbox::instance->property()->set(_info->getRootWindow(),
83 otk::OBProperty::net_desktop_viewport,
84 otk::OBProperty::Atom_Cardinal,
85 viewport, 2);
86
87 // these may be further updated if any pre-existing windows are found in
88 // the manageExising() function
89 setClientList(); // initialize the client lists, which will be empty
90 calcArea(); // initialize the available working area
91
92 manageExisting();
93
94 // XXX: "change to" the first workspace to initialize stuff
95 }
96
97
98 OBScreen::~OBScreen()
99 {
100 if (! _managed) return;
101
102 delete _image_control;
103 }
104
105
106 void OBScreen::manageExisting()
107 {
108 unsigned int i, j, nchild;
109 Window r, p, *children;
110 XQueryTree(otk::OBDisplay::display, _info->getRootWindow(), &r, &p,
111 &children, &nchild);
112
113 // preen the window list of all icon windows... for better dockapp support
114 for (i = 0; i < nchild; i++) {
115 if (children[i] == None) continue;
116
117 XWMHints *wmhints = XGetWMHints(otk::OBDisplay::display,
118 children[i]);
119
120 if (wmhints) {
121 if ((wmhints->flags & IconWindowHint) &&
122 (wmhints->icon_window != children[i])) {
123 for (j = 0; j < nchild; j++) {
124 if (children[j] == wmhints->icon_window) {
125 children[j] = None;
126 break;
127 }
128 }
129 }
130
131 XFree(wmhints);
132 }
133 }
134
135 // manage shown windows
136 for (i = 0; i < nchild; ++i) {
137 if (children[i] == None)
138 continue;
139
140 XWindowAttributes attrib;
141 if (XGetWindowAttributes(otk::OBDisplay::display, children[i], &attrib)) {
142 if (attrib.override_redirect) continue;
143
144 if (attrib.map_state != IsUnmapped) {
145 // XXX: manageWindow(children[i]);
146 }
147 }
148 }
149
150 XFree(children);
151 }
152
153
154 //! Adds a window's strut to the screen's list of reserved spaces
155 void OBScreen::addStrut(otk::Strut *strut)
156 {
157 _struts.push_back(strut);
158 }
159
160
161 //! Removes a window's strut from the screen's list of reserved spaces
162 void OBScreen::removeStrut(otk::Strut *strut)
163 {
164 _struts.remove(strut);
165 }
166
167
168 void OBScreen::calcArea()
169 {
170 otk::Rect old_area = _area;
171
172 /*
173 #ifdef XINERAMA
174 // reset to the full areas
175 if (isXineramaActive())
176 xineramaUsableArea = getXineramaAreas();
177 #endif // XINERAMA
178 */
179
180 /* these values represent offsets from the screen edge
181 * we look for the biggest offset on each edge and then apply them
182 * all at once
183 * do not be confused by the similarity to the names of Rect's members
184 */
185 unsigned int current_left = 0, current_right = 0, current_top = 0,
186 current_bottom = 0;
187
188 StrutList::const_iterator it = _struts.begin(), end = _struts.end();
189
190 for(; it != end; ++it) {
191 otk::Strut *strut = *it;
192 if (strut->left > current_left)
193 current_left = strut->left;
194 if (strut->top > current_top)
195 current_top = strut->top;
196 if (strut->right > current_right)
197 current_right = strut->right;
198 if (strut->bottom > current_bottom)
199 current_bottom = strut->bottom;
200 }
201
202 _area.setRect(current_left, current_top,
203 _info->getWidth() - (current_left + current_right),
204 _info->getHeight() - (current_top + current_bottom));
205
206 /*
207 #ifdef XINERAMA
208 if (isXineramaActive()) {
209 // keep each of the ximerama-defined areas inside the strut
210 RectList::iterator xit, xend = xineramaUsableArea.end();
211 for (xit = xineramaUsableArea.begin(); xit != xend; ++xit) {
212 if (xit->x() < usableArea.x()) {
213 xit->setX(usableArea.x());
214 xit->setWidth(xit->width() - usableArea.x());
215 }
216 if (xit->y() < usableArea.y()) {
217 xit->setY(usableArea.y());
218 xit->setHeight(xit->height() - usableArea.y());
219 }
220 if (xit->x() + xit->width() > usableArea.width())
221 xit->setWidth(usableArea.width() - xit->x());
222 if (xit->y() + xit->height() > usableArea.height())
223 xit->setHeight(usableArea.height() - xit->y());
224 }
225 }
226 #endif // XINERAMA
227 */
228
229 if (old_area != _area)
230 // XXX: re-maximize windows
231
232 setWorkArea();
233 }
234
235
236 void OBScreen::setClientList()
237 {
238 Window *windows;
239
240 // create an array of the window ids
241 if (_clients.size() > 0) {
242 Window *win_it;
243
244 windows = new Window[_clients.size()];
245 win_it = windows;
246 ClientList::const_iterator it = _clients.begin();
247 const ClientList::const_iterator end = _clients.end();
248 for (; it != end; ++it, ++win_it)
249 *win_it = (*it)->window();
250 } else
251 windows = (Window*) 0;
252
253 Openbox::instance->property()->set(_info->getRootWindow(),
254 otk::OBProperty::net_client_list,
255 otk::OBProperty::Atom_Window,
256 windows, _clients.size());
257
258 if (_clients.size())
259 delete [] windows;
260
261 setStackingList();
262 }
263
264
265 void OBScreen::setStackingList()
266 {
267 // The below comment is wrong now hopefully :> but ill keep it here for
268 // reference anyways
269 /*
270 Get the stacking order from all of the workspaces.
271 We start with the current workspace so that the sticky windows will be
272 in the right order on the current workspace.
273 */
274 /*
275 Openbox::instance->property()->set(_info->getRootWindow(),
276 otk::OBProperty::net_client_list_stacking,
277 otk::OBProperty::Atom_Window,
278 _stacking, _stacking.size());
279 */
280 }
281
282
283 void OBScreen::setWorkArea() {
284 unsigned long area[] = { _area.x(), _area.y(),
285 _area.width(), _area.height() };
286 Openbox::instance->property()->set(_info->getRootWindow(),
287 otk::OBProperty::net_workarea,
288 otk::OBProperty::Atom_Cardinal,
289 area, 4);
290 /*
291 if (workspacesList.size() > 0) {
292 unsigned long *dims = new unsigned long[4 * workspacesList.size()];
293 for (unsigned int i = 0, m = workspacesList.size(); i < m; ++i) {
294 // XXX: this could be different for each workspace
295 const otk::Rect &area = availableArea();
296 dims[(i * 4) + 0] = area.x();
297 dims[(i * 4) + 1] = area.y();
298 dims[(i * 4) + 2] = area.width();
299 dims[(i * 4) + 3] = area.height();
300 }
301 xatom->set(getRootWindow(), otk::OBProperty::net_workarea,
302 otk::OBProperty::Atom_Cardinal,
303 dims, 4 * workspacesList.size());
304 delete [] dims;
305 } else
306 xatom->set(getRootWindow(), otk::OBProperty::net_workarea,
307 otk::OBProperty::Atom_Cardinal, 0, 0);
308 */
309 }
310
311
312 void OBScreen::loadStyle(const otk::Configuration &config)
313 {
314 _style.load(config);
315 if (Openbox::instance->state() == Openbox::State_Starting)
316 return;
317
318 // XXX: make stuff redraw!
319 }
320
321
322 }
This page took 0.04964 seconds and 3 git commands to generate.