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