]> Dogcows Code - chaz/openbox/blob - src/xeventhandler.cc
new code for bindings/callbacks. much sexier. now passes python classes back to the...
[chaz/openbox] / src / xeventhandler.cc
1 // -*- mode: C++; indent-tabs-mode: nil; -*-
2
3 #ifdef HAVE_CONFIG_H
4 # include "../config.h"
5 #endif
6
7 #include "xeventhandler.hh"
8 #include "client.hh"
9 #include "openbox.hh"
10 #include "screen.hh"
11 #include "frame.hh"
12 #include "otk/display.hh"
13 #include "otk/rect.hh"
14
15 extern "C" {
16 #include <X11/Xlib.h>
17 #include <X11/Xutil.h>
18 }
19
20 namespace ob {
21
22
23 OBXEventHandler::OBXEventHandler()
24 {
25 _lasttime = 1; // 0 is CurrentTime, so set to minimum
26 }
27
28 void OBXEventHandler::buttonPress(const XButtonEvent &e)
29 {
30 _lasttime = e.time;
31
32 }
33
34
35 void OBXEventHandler::buttonRelease(const XButtonEvent &e)
36 {
37 _lasttime = e.time;
38
39 }
40
41
42 void OBXEventHandler::keyPress(const XKeyEvent &e)
43 {
44 _lasttime = e.time;
45 }
46
47
48 void OBXEventHandler::motion(const XMotionEvent &e)
49 {
50 _lasttime = e.time;
51
52 // the pointer is on the wrong screen
53 if (! e.same_screen) return;
54
55 }
56
57
58 void OBXEventHandler::enterNotify(const XCrossingEvent &e)
59 {
60 _lasttime = e.time;
61
62 OBClient *client = Openbox::instance->findClient(e.window);
63 if (!client) return;
64
65 /*
66 BScreen *screen = (BScreen *) 0;
67 BlackboxWindow *win = (BlackboxWindow *) 0;
68
69 if (e->xcrossing.mode == NotifyGrab) break;
70
71 if ((e->xcrossing.window == e->xcrossing.root) &&
72 (screen = searchScreen(e->xcrossing.window))) {
73 screen->getImageControl()->installRootColormap();
74 } else if ((win = searchWindow(e->xcrossing.window))) {
75 if (! no_focus)
76 win->enterNotifyEvent(&e->xcrossing);
77 }
78 */
79 }
80
81
82 void OBXEventHandler::leaveNotify(const XCrossingEvent &e)
83 {
84 _lasttime = e.time;
85
86 OBClient *client = Openbox::instance->findClient(e.window);
87 if (!client) return;
88
89 /*
90 BlackboxWindow *win = (BlackboxWindow *) 0;
91
92 if ((win = searchWindow(e->xcrossing.window)))
93 win->leaveNotifyEvent(&e->xcrossing);
94 */
95 }
96
97
98 void OBXEventHandler::configureRequest(const XConfigureRequestEvent &e)
99 {
100 OBClient *client = Openbox::instance->findClient(e.window);
101 if (!client) return;
102
103 /* BlackboxWindow *win = (BlackboxWindow *) 0;
104
105 if ((win = searchWindow(e->xconfigurerequest.window))) {
106 win->configureRequestEvent(&e->xconfigurerequest);
107 } else {
108 if (validateWindow(e->xconfigurerequest.window)) {
109 XWindowChanges xwc;
110
111 xwc.x = e->xconfigurerequest.x;
112 xwc.y = e->xconfigurerequest.y;
113 xwc.width = e->xconfigurerequest.width;
114 xwc.height = e->xconfigurerequest.height;
115 xwc.border_width = e->xconfigurerequest.border_width;
116 xwc.sibling = e->xconfigurerequest.above;
117 xwc.stack_mode = e->xconfigurerequest.detail;
118
119 XConfigureWindow(otk::OBDisplay::display, e->xconfigurerequest.window,
120 e->xconfigurerequest.value_mask, &xwc);
121 }
122 }
123 */
124 }
125
126
127 void OBXEventHandler::mapRequest(const XMapRequestEvent &e)
128 {
129 #ifdef DEBUG
130 printf("MapRequest for 0x%lx\n", e.window);
131 #endif // DEBUG
132
133 OBClient *client = Openbox::instance->findClient(e.window);
134
135 if (client) {
136 // XXX: uniconify and/or unshade the window
137 } else {
138 int screen = INT_MAX;
139
140 for (int i = 0; i < ScreenCount(otk::OBDisplay::display); ++i)
141 if (otk::OBDisplay::screenInfo(i)->getRootWindow() == e.parent) {
142 screen = i;
143 break;
144 }
145
146 if (screen >= ScreenCount(otk::OBDisplay::display)) {
147 /*
148 we got a map request for a window who's parent isn't root. this
149 can happen in only one circumstance:
150
151 a client window unmapped a managed window, and then remapped it
152 somewhere between unmapping the client window and reparenting it
153 to root.
154
155 regardless of how it happens, we need to find the screen that
156 the window is on
157 */
158 XWindowAttributes wattrib;
159 if (! XGetWindowAttributes(otk::OBDisplay::display, e.window,
160 &wattrib)) {
161 // failed to get the window attributes, perhaps the window has
162 // now been destroyed?
163 return;
164 }
165
166 for (int i = 0; i < ScreenCount(otk::OBDisplay::display); ++i)
167 if (otk::OBDisplay::screenInfo(i)->getRootWindow() == wattrib.root) {
168 screen = i;
169 break;
170 }
171 }
172
173 assert(screen < ScreenCount(otk::OBDisplay::display));
174
175 Openbox::instance->screen(screen)->manageWindow(e.window);
176 }
177
178 /*
179 BlackboxWindow *win = searchWindow(e->xmaprequest.window);
180
181 if (win) {
182 bool focus = False;
183 if (win->isIconic()) {
184 win->deiconify();
185 focus = True;
186 }
187 if (win->isShaded()) {
188 win->shade();
189 focus = True;
190 }
191
192 if (focus && (win->isTransient() || win->getScreen()->doFocusNew()) &&
193 win->isVisible())
194 win->setInputFocus();
195 } else {
196 BScreen *screen = searchScreen(e->xmaprequest.parent);
197
198 if (! screen) {
199 */
200 /*
201 we got a map request for a window who's parent isn't root. this
202 can happen in only one circumstance:
203
204 a client window unmapped a managed window, and then remapped it
205 somewhere between unmapping the client window and reparenting it
206 to root.
207
208 regardless of how it happens, we need to find the screen that
209 the window is on
210 */
211 /*
212 XWindowAttributes wattrib;
213 if (! XGetWindowAttributes(otk::OBDisplay::display,
214 e->xmaprequest.window,
215 &wattrib)) {
216 // failed to get the window attributes, perhaps the window has
217 // now been destroyed?
218 break;
219 }
220
221 screen = searchScreen(wattrib.root);
222 assert(screen != 0); // this should never happen
223 }
224 screen->manageWindow(e->xmaprequest.window);
225 }
226 */
227 }
228
229
230 void OBXEventHandler::unmapNotify(const XUnmapEvent &e)
231 {
232 OBClient *client = Openbox::instance->findClient(e.window);
233 if (!client) return;
234
235 if (client->ignore_unmaps == 0)
236 Openbox::instance->screen(client->screen())->unmanageWindow(client);
237 else
238 client->ignore_unmaps--;
239 }
240
241
242 void OBXEventHandler::destroyNotify(const XDestroyWindowEvent &e)
243 {
244 // XXX: window group leaders can come through here too!
245
246 OBClient *client = Openbox::instance->findClient(e.window);
247 if (!client) return;
248
249 Openbox::instance->screen(client->screen())->unmanageWindow(client);
250 }
251
252
253 void OBXEventHandler::reparentNotify(const XReparentEvent &e)
254 {
255 /*
256 this event is quite rare and is usually handled in unmapNotify
257 however, if the window is unmapped when the reparent event occurs
258 the window manager never sees it because an unmap event is not sent
259 to an already unmapped window.
260 */
261 OBClient *client = Openbox::instance->findClient(e.window);
262 if (!client) return;
263
264 /*
265 BlackboxWindow *win = searchWindow(e->xreparent.window);
266 if (win)
267 win->reparentNotifyEvent(&e->xreparent);
268 */
269 }
270
271
272 void OBXEventHandler::propertyNotify(const XPropertyEvent &e)
273 {
274 _lasttime = e.time;
275
276 OBClient *client = Openbox::instance->findClient(e.window);
277 if (!client) return;
278
279 client->update(e);
280 }
281
282
283 void OBXEventHandler::expose(const XExposeEvent &first)
284 {
285 OBClient *client = Openbox::instance->findClient(first.window);
286 if (!client) return;
287
288 // compress expose events
289 XEvent e; e.xexpose = first;
290 unsigned int i = 0;
291 otk::Rect area(e.xexpose.x, e.xexpose.y, e.xexpose.width,
292 e.xexpose.height);
293 while (XCheckTypedWindowEvent(otk::OBDisplay::display,
294 e.xexpose.window, Expose, &e)) {
295 i++;
296 // merge expose area
297 area |= otk::Rect(e.xexpose.x, e.xexpose.y, e.xexpose.width,
298 e.xexpose.height);
299 }
300 if ( i > 0 ) {
301 // use the merged area
302 e.xexpose.x = area.x();
303 e.xexpose.y = area.y();
304 e.xexpose.width = area.width();
305 e.xexpose.height = area.height();
306 }
307
308 // XXX: make the decorations redraw!
309 }
310
311
312 void OBXEventHandler::colormapNotify(const XColormapEvent &e)
313 {
314 (void)e;
315 /*
316 BScreen *screen = searchScreen(e->xcolormap.window);
317 if (screen)
318 screen->setRootColormapInstalled((e->xcolormap.state ==
319 ColormapInstalled) ? True : False);
320 */
321 }
322
323
324 void OBXEventHandler::focusIn(const XFocusChangeEvent &e)
325 {
326 if (e.detail != NotifyNonlinear &&
327 e.detail != NotifyAncestor) {
328 /*
329 don't process FocusIns when:
330 1. the new focus window isn't an ancestor or inferior of the old
331 focus window (NotifyNonlinear)
332 make sure to allow the FocusIn when the old focus window was an
333 ancestor but didn't have a parent, such as root (NotifyAncestor)
334 */
335 return;
336 }
337 /*
338 BlackboxWindow *win = searchWindow(e.window);
339 if (win) {
340 if (! win->isFocused())
341 win->setFocusFlag(True);
342 */
343 /*
344 set the event window to None. when the FocusOut event handler calls
345 this function recursively, it uses this as an indication that focus
346 has moved to a known window.
347 */
348 /*
349 e->xfocus.window = None;
350
351 no_focus = False; // focusing is back on
352 }
353 */
354 }
355
356
357 void OBXEventHandler::focusOut(const XFocusChangeEvent &e)
358 {
359 if (e.detail != NotifyNonlinear) {
360 /*
361 don't process FocusOuts when:
362 2. the new focus window isn't an ancestor or inferior of the old
363 focus window (NotifyNonlinear)
364 */
365 return;
366 }
367
368 /*
369 BlackboxWindow *win = searchWindow(e->xfocus.window);
370 if (win && win->isFocused()) {
371 */
372 /*
373 before we mark "win" as unfocused, we need to verify that focus is
374 going to a known location, is in a known location, or set focus
375 to a known location.
376 */
377 /*
378 XEvent event;
379 // don't check the current focus if FocusOut was generated during a grab
380 bool check_focus = (e->xfocus.mode == NotifyNormal);
381 */
382 /*
383 First, check if there is a pending FocusIn event waiting. if there
384 is, process it and determine if focus has moved to another window
385 (the FocusIn event handler sets the window in the event
386 structure to None to indicate this).
387 */
388 /*
389 if (XCheckTypedEvent(otk::OBDisplay::display, FocusIn, &event)) {
390
391 process_event(&event);
392 if (event.xfocus.window == None) {
393 // focus has moved
394 check_focus = False;
395 }
396 }
397
398 if (check_focus) {
399 */
400 /*
401 Second, we query the X server for the current input focus.
402 to make sure that we keep a consistent state.
403 */
404 /*
405 BlackboxWindow *focus;
406 Window w;
407 int revert;
408 XGetInputFocus(otk::OBDisplay::display, &w, &revert);
409 focus = searchWindow(w);
410 if (focus) {
411 */
412 /*
413 focus got from "win" to "focus" under some very strange
414 circumstances, and we need to make sure that the focus indication
415 is correct.
416 */
417 /*
418 setFocusedWindow(focus);
419 } else {
420 // we have no idea where focus went... so we set it to somewhere
421 setFocusedWindow(0);
422 }
423 }
424 }
425 */
426 }
427
428
429 #ifdef SHAPE
430 void OBXEventHandler::shapeEvent(const XShapeEvent &e)
431 {
432 printf("ShapeEvent\n");
433 if (e.kind != ShapeBounding) return;
434
435 OBClient *client = Openbox::instance->findClient(e.window);
436 if (!client) return;
437
438 client->update(e);
439 client->frame->update();
440 }
441 #endif // SHAPE
442
443
444 void OBXEventHandler::clientMessage(const XClientMessageEvent &e)
445 {
446 if (e.format != 32)
447 return;
448 /*
449 } else if (e->xclient.message_type ==
450 xatom->getAtom(XAtom::blackbox_change_workspace) ||
451 e->xclient.message_type ==
452 xatom->getAtom(XAtom::net_current_desktop)) {
453 // NET_CURRENT_DESKTOP message
454 BScreen *screen = searchScreen(e->xclient.window);
455
456 unsigned int workspace = e->xclient.data.l[0];
457 if (screen && workspace < screen->getWorkspaceCount())
458 screen->changeWorkspaceID(workspace);
459 } else if (e->xclient.message_type ==
460 xatom->getAtom(XAtom::net_active_window)) {
461 // NET_ACTIVE_WINDOW
462 BlackboxWindow *win = searchWindow(e->xclient.window);
463
464 if (win) {
465 BScreen *screen = win->getScreen();
466
467 if (win->isIconic())
468 win->deiconify(False, False);
469 if (! win->isStuck() &&
470 (win->getWorkspaceNumber() != screen->getCurrentWorkspaceID())) {
471 no_focus = True;
472 screen->changeWorkspaceID(win->getWorkspaceNumber());
473 }
474 if (win->isVisible() && win->setInputFocus()) {
475 win->getScreen()->getWorkspace(win->getWorkspaceNumber())->
476 raiseWindow(win);
477 win->installColormap(True);
478 }
479 }
480 } else if (e->xclient.message_type ==
481 xatom->getAtom(XAtom::net_number_of_desktops)) {
482 // NET_NUMBER_OF_DESKTOPS
483 BScreen *screen = searchScreen(e->xclient.window);
484
485 if (e->xclient.data.l[0] > 0)
486 screen->changeWorkspaceCount((unsigned) e->xclient.data.l[0]);
487 } else if (e->xclient.message_type ==
488 xatom->getAtom(XAtom::net_close_window)) {
489 // NET_CLOSE_WINDOW
490 BlackboxWindow *win = searchWindow(e->xclient.window);
491 if (win && win->validateClient())
492 win->close(); // could this be smarter?
493 } else if (e->xclient.message_type ==
494 xatom->getAtom(XAtom::net_wm_moveresize)) {
495 // NET_WM_MOVERESIZE
496 BlackboxWindow *win = searchWindow(e->xclient.window);
497 if (win && win->validateClient()) {
498 int x_root = e->xclient.data.l[0],
499 y_root = e->xclient.data.l[1];
500 if ((Atom) e->xclient.data.l[2] ==
501 xatom->getAtom(XAtom::net_wm_moveresize_move)) {
502 win->beginMove(x_root, y_root);
503 } else {
504 if ((Atom) e->xclient.data.l[2] ==
505 xatom->getAtom(XAtom::net_wm_moveresize_size_topleft))
506 win->beginResize(x_root, y_root, BlackboxWindow::TopLeft);
507 else if ((Atom) e->xclient.data.l[2] ==
508 xatom->getAtom(XAtom::net_wm_moveresize_size_topright))
509 win->beginResize(x_root, y_root, BlackboxWindow::TopRight);
510 else if ((Atom) e->xclient.data.l[2] ==
511 xatom->getAtom(XAtom::net_wm_moveresize_size_bottomleft))
512 win->beginResize(x_root, y_root, BlackboxWindow::BottomLeft);
513 else if ((Atom) e->xclient.data.l[2] ==
514 xatom->getAtom(XAtom::net_wm_moveresize_size_bottomright))
515 win->beginResize(x_root, y_root, BlackboxWindow::BottomRight);
516 }
517 }
518 }
519 */
520 }
521
522
523 void OBXEventHandler::handle(const XEvent &e)
524 {
525 /* mouse button events can get translated into:
526 press - button was pressed down
527 release - buttons was released
528 click - button was pressed and released on the same window
529 double click - clicked twice on the same widget in a given time and area
530
531 key events are only bindable to presses. key releases are ignored.
532
533 mouse enter/leave can be bound to for the entire window
534 */
535
536 switch (e.type) {
537
538 // These types of XEvent's can be bound to actions by the user, and so end
539 // up getting passed off to the OBBindingMapper class at some point
540 // IOW: THESE WILL HAVE GUILE HOOKS
541 case ButtonPress:
542 buttonPress(e.xbutton);
543 break;
544 case ButtonRelease:
545 buttonRelease(e.xbutton);
546 break;
547 case KeyPress:
548 keyPress(e.xkey);
549 break;
550 case MotionNotify:
551 motion(e.xmotion);
552 break;
553 case EnterNotify:
554 enterNotify(e.xcrossing);
555 break;
556 case LeaveNotify:
557 leaveNotify(e.xcrossing);
558 break;
559
560
561 // These types of XEvent's can not be bound to actions by the user and so
562 // will simply be handled in this class
563 case ConfigureRequest:
564 configureRequest(e.xconfigurerequest);
565 break;
566
567 case MapRequest:
568 mapRequest(e.xmaprequest);
569 break;
570
571 case UnmapNotify:
572 unmapNotify(e.xunmap);
573 break;
574
575 case DestroyNotify:
576 destroyNotify(e.xdestroywindow);
577 break;
578
579 case ReparentNotify:
580 reparentNotify(e.xreparent);
581 break;
582
583 case PropertyNotify:
584 propertyNotify(e.xproperty);
585 break;
586
587 case Expose:
588 expose(e.xexpose);
589 break;
590
591 case ColormapNotify:
592 colormapNotify(e.xcolormap);
593 break;
594
595 case FocusIn:
596 focusIn(e.xfocus);
597 break;
598
599 case FocusOut:
600 focusOut(e.xfocus);
601 break;
602
603 case ClientMessage:
604 clientMessage(e.xclient);
605
606 default:
607 #ifdef SHAPE
608 if (e.type == otk::OBDisplay::shapeEventBase())
609 shapeEvent((*(XShapeEvent*)&e));
610 #endif // SHAPE
611 break;
612
613 /*
614 case ClientMessage: {
615 break;
616 }
617
618 */
619 } // switch
620 }
621
622
623 }
This page took 0.059381 seconds and 4 git commands to generate.