]> Dogcows Code - chaz/openbox/blob - src/openbox.cc
handle map events with the Openbox class
[chaz/openbox] / src / openbox.cc
1 // -*- mode: C++; indent-tabs-mode: nil; -*-
2
3 #ifdef HAVE_CONFIG_H
4 # include "../config.h"
5 #endif
6
7 #include "../version.h"
8 #include "openbox.hh"
9 #include "screen.hh"
10 #include "otk/property.hh"
11 #include "otk/display.hh"
12 #include "otk/assassin.hh"
13 #include "otk/util.hh" // TEMPORARY
14
15 extern "C" {
16 #include <X11/cursorfont.h>
17
18 #ifdef HAVE_STDIO_H
19 # include <stdio.h>
20 #endif // HAVE_STDIO_H
21
22 #ifdef HAVE_STDLIB_H
23 # include <stdlib.h>
24 #endif // HAVE_STDLIB_H
25
26 #ifdef HAVE_SIGNAL_H
27 # include <signal.h>
28 #endif // HAVE_SIGNAL_H
29
30 #ifdef HAVE_FCNTL_H
31 # include <fcntl.h>
32 #endif // HAVE_FCNTL_H
33
34 #ifdef HAVE_UNISTD_H
35 # include <sys/types.h>
36 # include <unistd.h>
37 #endif // HAVE_UNISTD_H
38
39 #ifdef HAVE_SYS_SELECT_H
40 # include <sys/select.h>
41 #endif // HAVE_SYS_SELECT_H
42
43 #include "gettext.h"
44 #define _(str) gettext(str)
45 }
46
47 #include <algorithm>
48
49 namespace ob {
50
51 Openbox *Openbox::instance = (Openbox *) 0;
52
53
54 void Openbox::signalHandler(int signal)
55 {
56 switch (signal) {
57 case SIGHUP:
58 // XXX: Do something with HUP? Really shouldn't, we get this when X shuts
59 // down and hangs-up on us.
60
61 case SIGINT:
62 case SIGTERM:
63 case SIGPIPE:
64 printf("Caught signal %d. Exiting.\n", signal);
65 instance->shutdown();
66
67 break;
68 case SIGFPE:
69 case SIGSEGV:
70 printf("Caught signal %d. Aborting and dumping core.\n", signal);
71 abort();
72 }
73 }
74
75
76 Openbox::Openbox(int argc, char **argv)
77 : otk::OtkEventDispatcher(),
78 otk::OtkEventHandler()
79 {
80 struct sigaction action;
81
82 _state = State_Starting; // initializing everything
83
84 Openbox::instance = this;
85
86 _displayreq = (char*) 0;
87 _argv0 = argv[0];
88 _doshutdown = false;
89 _rcfilepath = otk::expandTilde("~/.openbox/rc3");
90
91 parseCommandLine(argc, argv);
92
93 // TEMPORARY: using the xrdb rc3
94 _config.setFile(_rcfilepath);
95 if (!_config.load()) {
96 printf("failed to load rc file %s\n", _config.file().c_str());
97 ::exit(2);
98 }
99 std::string s;
100 _config.getValue("session.styleFile", s);
101 _config.setFile(s);
102 if (!_config.load()) {
103 printf("failed to load style %s\n", _config.file().c_str());
104 ::exit(2);
105 }
106
107 // open the X display (and gets some info about it, and its screens)
108 otk::OBDisplay::initialize(_displayreq);
109 assert(otk::OBDisplay::display);
110
111 // set up the signal handler
112 action.sa_handler = Openbox::signalHandler;
113 action.sa_mask = sigset_t();
114 action.sa_flags = SA_NOCLDSTOP | SA_NODEFER;
115 sigaction(SIGPIPE, &action, (struct sigaction *) 0);
116 sigaction(SIGSEGV, &action, (struct sigaction *) 0);
117 sigaction(SIGFPE, &action, (struct sigaction *) 0);
118 sigaction(SIGTERM, &action, (struct sigaction *) 0);
119 sigaction(SIGINT, &action, (struct sigaction *) 0);
120 sigaction(SIGHUP, &action, (struct sigaction *) 0);
121
122 _property = new otk::OBProperty();
123
124 // set this class as the fallback event handler (for map events)
125 setFallbackHandler(this);
126
127 // create the mouse cursors we'll use
128 _cursors.session = XCreateFontCursor(otk::OBDisplay::display, XC_left_ptr);
129 _cursors.move = XCreateFontCursor(otk::OBDisplay::display, XC_fleur);
130 _cursors.ll_angle = XCreateFontCursor(otk::OBDisplay::display, XC_ll_angle);
131 _cursors.lr_angle = XCreateFontCursor(otk::OBDisplay::display, XC_lr_angle);
132 _cursors.ul_angle = XCreateFontCursor(otk::OBDisplay::display, XC_ul_angle);
133 _cursors.ur_angle = XCreateFontCursor(otk::OBDisplay::display, XC_ur_angle);
134
135 // initialize all the screens
136 OBScreen *screen;
137 screen = new OBScreen(0, _config);
138 if (screen->managed()) {
139 _screens.push_back(screen);
140 _screens[0]->manageExisting();
141 // XXX: "change to" the first workspace on the screen to initialize stuff
142 } else
143 delete screen;
144
145 if (_screens.empty()) {
146 printf(_("No screens were found without a window manager. Exiting.\n"));
147 ::exit(1);
148 }
149
150 _state = State_Normal; // done starting
151 }
152
153
154 Openbox::~Openbox()
155 {
156 _state = State_Exiting; // time to kill everything
157
158 std::for_each(_screens.begin(), _screens.end(), otk::PointerAssassin());
159
160 // close the X display
161 otk::OBDisplay::destroy();
162 }
163
164
165 void Openbox::parseCommandLine(int argc, char **argv)
166 {
167 bool err = false;
168
169 for (int i = 1; i < argc; ++i) {
170 std::string arg(argv[i]);
171
172 if (arg == "-display") {
173 if (++i >= argc)
174 err = true;
175 else
176 _displayreq = argv[i];
177 } else if (arg == "-rc") {
178 if (++i >= argc)
179 err = true;
180 else
181 _rcfilepath = argv[i];
182 } else if (arg == "-menu") {
183 if (++i >= argc)
184 err = true;
185 else
186 _menufilepath = argv[i];
187 } else if (arg == "-version") {
188 showVersion();
189 ::exit(0);
190 } else if (arg == "-help") {
191 showHelp();
192 ::exit(0);
193 } else
194 err = true;
195
196 if (err) {
197 showHelp();
198 exit(1);
199 }
200 }
201 }
202
203
204 void Openbox::showVersion()
205 {
206 printf(_("Openbox - version %s\n"), OPENBOX_VERSION);
207 printf(" (c) 2002 - 2002 Ben Jansens\n\n");
208 }
209
210
211 void Openbox::showHelp()
212 {
213 showVersion(); // show the version string and copyright
214
215 // print program usage and command line options
216 printf(_("Usage: %s [OPTIONS...]\n\
217 Options:\n\
218 -display <string> use display connection.\n\
219 -rc <string> use alternate resource file.\n\
220 -menu <string> use alternate menu file.\n\
221 -version display version and exit.\n\
222 -help display this help text and exit.\n\n"), _argv0);
223
224 printf(_("Compile time options:\n\
225 Debugging: %s\n\
226 Shape: %s\n\
227 Xinerama: %s\n"),
228 #ifdef DEBUG
229 _("yes"),
230 #else // !DEBUG
231 _("no"),
232 #endif // DEBUG
233
234 #ifdef SHAPE
235 _("yes"),
236 #else // !SHAPE
237 _("no"),
238 #endif // SHAPE
239
240 #ifdef XINERAMA
241 _("yes")
242 #else // !XINERAMA
243 _("no")
244 #endif // XINERAMA
245 );
246 }
247
248
249 void Openbox::eventLoop()
250 {
251 while (!_doshutdown) {
252 dispatchEvents(); // from OtkEventDispatcher
253 _timermanager.fire();
254 }
255 }
256
257
258 void Openbox::addClient(Window window, OBClient *client)
259 {
260 _clients[window] = client;
261 }
262
263
264 void Openbox::removeClient(Window window)
265 {
266 ClientMap::iterator it = _clients.find(window);
267 if (it != _clients.end())
268 _clients.erase(it);
269 }
270
271
272 OBClient *Openbox::findClient(Window window)
273 {
274 /*
275 NOTE: we dont use _clients[] to find the value because that will insert
276 a new null into the hash, which really sucks when we want to clean up the
277 hash at shutdown!
278 */
279 ClientMap::iterator it = _clients.find(window);
280 if (it != _clients.end())
281 return it->second;
282 else
283 return (OBClient*) 0;
284 }
285
286
287 void Openbox::mapRequestHandler(const XMapRequestEvent &e)
288 {
289 #ifdef DEBUG
290 printf("MapRequest for 0x%lx\n", e.window);
291 #endif // DEBUG
292
293 otk::OtkEventHandler::mapRequestHandler(e);
294
295 OBClient *client = findClient(e.window);
296
297 if (client) {
298 // XXX: uniconify and/or unshade the window
299 } else {
300 int screen = INT_MAX;
301
302 for (int i = 0; i < ScreenCount(otk::OBDisplay::display); ++i)
303 if (otk::OBDisplay::screenInfo(i)->getRootWindow() == e.parent) {
304 screen = i;
305 break;
306 }
307
308 if (screen >= ScreenCount(otk::OBDisplay::display)) {
309 /*
310 we got a map request for a window who's parent isn't root. this
311 can happen in only one circumstance:
312
313 a client window unmapped a managed window, and then remapped it
314 somewhere between unmapping the client window and reparenting it
315 to root.
316
317 regardless of how it happens, we need to find the screen that
318 the window is on
319 */
320 XWindowAttributes wattrib;
321 if (! XGetWindowAttributes(otk::OBDisplay::display, e.window,
322 &wattrib)) {
323 // failed to get the window attributes, perhaps the window has
324 // now been destroyed?
325 return;
326 }
327
328 for (int i = 0; i < ScreenCount(otk::OBDisplay::display); ++i)
329 if (otk::OBDisplay::screenInfo(i)->getRootWindow() == wattrib.root) {
330 screen = i;
331 break;
332 }
333 }
334
335 assert(screen < static_cast<int>(_screens.size()));
336 _screens[screen]->manageWindow(e.window);
337 }
338 }
339
340 }
341
This page took 0.053278 seconds and 5 git commands to generate.