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