]>
Dogcows Code - chaz/openbox/blob - src/xeventhandler.cc
1 // -*- mode: C++; indent-tabs-mode: nil; -*-
3 #include "xeventhandler.hh"
4 #include "otk/display.hh"
10 OBXEventHandler::OBXEventHandler()
12 _lasttime
= 1; // 0 is CurrentTime, so set to minimum
15 void OBXEventHandler::buttonPress(const XButtonEvent
&e
)
22 void OBXEventHandler::buttonRelease(const XButtonEvent
&e
)
29 void OBXEventHandler::keyPress(const XKeyEvent
&e
)
35 void OBXEventHandler::motion(const XMotionEvent
&e
)
39 // the pointer is on the wrong screen
40 if (! e
.same_screen
) return;
45 void OBXEventHandler::enterNotify(const XCrossingEvent
&e
)
49 BScreen *screen = (BScreen *) 0;
50 BlackboxWindow *win = (BlackboxWindow *) 0;
52 if (e->xcrossing.mode == NotifyGrab) break;
54 if ((e->xcrossing.window == e->xcrossing.root) &&
55 (screen = searchScreen(e->xcrossing.window))) {
56 screen->getImageControl()->installRootColormap();
57 } else if ((win = searchWindow(e->xcrossing.window))) {
59 win->enterNotifyEvent(&e->xcrossing);
65 void OBXEventHandler::leaveNotify(const XCrossingEvent
&e
)
69 BlackboxWindow *win = (BlackboxWindow *) 0;
71 if ((win = searchWindow(e->xcrossing.window)))
72 win->leaveNotifyEvent(&e->xcrossing);
77 void OBXEventHandler::configureRequest(const XConfigureRequestEvent
&e
)
80 /* BlackboxWindow *win = (BlackboxWindow *) 0;
82 if ((win = searchWindow(e->xconfigurerequest.window))) {
83 win->configureRequestEvent(&e->xconfigurerequest);
85 if (validateWindow(e->xconfigurerequest.window)) {
88 xwc.x = e->xconfigurerequest.x;
89 xwc.y = e->xconfigurerequest.y;
90 xwc.width = e->xconfigurerequest.width;
91 xwc.height = e->xconfigurerequest.height;
92 xwc.border_width = e->xconfigurerequest.border_width;
93 xwc.sibling = e->xconfigurerequest.above;
94 xwc.stack_mode = e->xconfigurerequest.detail;
96 XConfigureWindow(otk::OBDisplay::display, e->xconfigurerequest.window,
97 e->xconfigurerequest.value_mask, &xwc);
104 void OBXEventHandler::mapRequest(const XMapRequestEvent
&e
)
107 printf("MapRequest for 0x%lx\n", e
.window
);
110 BlackboxWindow *win = searchWindow(e->xmaprequest.window);
114 if (win->isIconic()) {
118 if (win->isShaded()) {
123 if (focus && (win->isTransient() || win->getScreen()->doFocusNew()) &&
125 win->setInputFocus();
127 BScreen *screen = searchScreen(e->xmaprequest.parent);
132 we got a map request for a window who's parent isn't root. this
133 can happen in only one circumstance:
135 a client window unmapped a managed window, and then remapped it
136 somewhere between unmapping the client window and reparenting it
139 regardless of how it happens, we need to find the screen that
143 XWindowAttributes wattrib;
144 if (! XGetWindowAttributes(otk::OBDisplay::display,
145 e->xmaprequest.window,
147 // failed to get the window attributes, perhaps the window has
148 // now been destroyed?
152 screen = searchScreen(wattrib.root);
153 assert(screen != 0); // this should never happen
155 screen->manageWindow(e->xmaprequest.window);
161 void OBXEventHandler::unmapNotify(const XUnmapEvent
&e
)
165 BlackboxWindow *win = (BlackboxWindow *) 0;
166 BScreen *screen = (BScreen *) 0;
168 if ((win = searchWindow(e->xunmap.window))) {
169 win->unmapNotifyEvent(&e->xunmap);
170 } else if ((screen = searchSystrayWindow(e->xunmap.window))) {
171 screen->removeSystrayWindow(e->xunmap.window);
177 void OBXEventHandler::destroyNotify(const XDestroyWindowEvent
&e
)
181 BlackboxWindow *win = (BlackboxWindow *) 0;
182 BScreen *screen = (BScreen *) 0;
183 BWindowGroup *group = (BWindowGroup *) 0;
185 if ((win = searchWindow(e->xdestroywindow.window))) {
186 win->destroyNotifyEvent(&e->xdestroywindow);
187 } else if ((group = searchGroup(e->xdestroywindow.window))) {
189 } else if ((screen = searchSystrayWindow(e->xunmap.window))) {
190 screen->removeSystrayWindow(e->xunmap.window);
196 void OBXEventHandler::reparentNotify(const XReparentEvent
&e
)
200 this event is quite rare and is usually handled in unmapNotify
201 however, if the window is unmapped when the reparent event occurs
202 the window manager never sees it because an unmap event is not sent
203 to an already unmapped window.
206 BlackboxWindow *win = searchWindow(e->xreparent.window);
208 win->reparentNotifyEvent(&e->xreparent);
213 void OBXEventHandler::propertyNotify(const XPropertyEvent
&e
)
217 BlackboxWindow *win = (BlackboxWindow *) 0;
218 BScreen *screen = (BScreen *) 0;
220 if ((win = searchWindow(e->xproperty.window)))
221 win->propertyNotifyEvent(&e->xproperty);
222 else if ((screen = searchScreen(e->xproperty.window)))
223 screen->propertyNotifyEvent(&e->xproperty);
228 void OBXEventHandler::expose(const XExposeEvent
&first
)
230 // compress expose events
231 XEvent e
; e
.xexpose
= first
;
233 otk::Rect
area(e
.xexpose
.x
, e
.xexpose
.y
, e
.xexpose
.width
,
235 while (XCheckTypedWindowEvent(otk::OBDisplay::display
,
236 e
.xexpose
.window
, Expose
, &e
)) {
239 area
|= otk::Rect(e
.xexpose
.x
, e
.xexpose
.y
, e
.xexpose
.width
,
243 // use the merged area
244 e
.xexpose
.x
= area
.x();
245 e
.xexpose
.y
= area
.y();
246 e
.xexpose
.width
= area
.width();
247 e
.xexpose
.height
= area
.height();
250 BlackboxWindow *win = (BlackboxWindow *) 0;
252 if ((win = searchWindow(e->xexpose.window)))
253 win->exposeEvent(&e->xexpose);
258 void OBXEventHandler::colormapNotify(const XColormapEvent
&e
)
262 BScreen *screen = searchScreen(e->xcolormap.window);
264 screen->setRootColormapInstalled((e->xcolormap.state ==
265 ColormapInstalled) ? True : False);
270 void OBXEventHandler::focusIn(const XFocusChangeEvent
&e
)
272 if (e
.detail
!= NotifyNonlinear
&&
273 e
.detail
!= NotifyAncestor
) {
275 don't process FocusIns when:
276 1. the new focus window isn't an ancestor or inferior of the old
277 focus window (NotifyNonlinear)
278 make sure to allow the FocusIn when the old focus window was an
279 ancestor but didn't have a parent, such as root (NotifyAncestor)
284 BlackboxWindow *win = searchWindow(e.window);
286 if (! win->isFocused())
287 win->setFocusFlag(True);
290 set the event window to None. when the FocusOut event handler calls
291 this function recursively, it uses this as an indication that focus
292 has moved to a known window.
295 e->xfocus.window = None;
297 no_focus = False; // focusing is back on
303 void OBXEventHandler::focusOut(const XFocusChangeEvent
&e
)
305 if (e
.detail
!= NotifyNonlinear
) {
307 don't process FocusOuts when:
308 2. the new focus window isn't an ancestor or inferior of the old
309 focus window (NotifyNonlinear)
315 BlackboxWindow *win = searchWindow(e->xfocus.window);
316 if (win && win->isFocused()) {
319 before we mark "win" as unfocused, we need to verify that focus is
320 going to a known location, is in a known location, or set focus
325 // don't check the current focus if FocusOut was generated during a grab
326 bool check_focus = (e->xfocus.mode == NotifyNormal);
329 First, check if there is a pending FocusIn event waiting. if there
330 is, process it and determine if focus has moved to another window
331 (the FocusIn event handler sets the window in the event
332 structure to None to indicate this).
335 if (XCheckTypedEvent(otk::OBDisplay::display, FocusIn, &event)) {
337 process_event(&event);
338 if (event.xfocus.window == None) {
347 Second, we query the X server for the current input focus.
348 to make sure that we keep a consistent state.
351 BlackboxWindow *focus;
354 XGetInputFocus(otk::OBDisplay::display, &w, &revert);
355 focus = searchWindow(w);
359 focus got from "win" to "focus" under some very strange
360 circumstances, and we need to make sure that the focus indication
364 setFocusedWindow(focus);
366 // we have no idea where focus went... so we set it to somewhere
376 void OBXEventHandler::shapeEvent(const XShapeEvent
&e
)
378 XShapeEvent
*shape_event
= (XShapeEvent
*) e
;
379 BlackboxWindow
*win
= searchWindow(e
->xany
.window
);
381 if (win
&& shape_event
->kind
== ShapeBounding
)
382 win
->shapeEvent(shape_event
);
387 void OBXEventHandler::clientMessage(const XClientMessageEvent
&e
)
392 if (e->xclient.message_type == xatom->getAtom(XAtom::wm_change_state)) {
393 // WM_CHANGE_STATE message
394 BlackboxWindow *win = searchWindow(e->xclient.window);
395 if (! win || ! win->validateClient()) return;
397 if (e->xclient.data.l[0] == IconicState)
399 if (e->xclient.data.l[0] == NormalState)
401 } else if (e->xclient.message_type ==
402 xatom->getAtom(XAtom::blackbox_change_workspace) ||
403 e->xclient.message_type ==
404 xatom->getAtom(XAtom::net_current_desktop)) {
405 // NET_CURRENT_DESKTOP message
406 BScreen *screen = searchScreen(e->xclient.window);
408 unsigned int workspace = e->xclient.data.l[0];
409 if (screen && workspace < screen->getWorkspaceCount())
410 screen->changeWorkspaceID(workspace);
411 } else if (e->xclient.message_type ==
412 xatom->getAtom(XAtom::blackbox_change_window_focus)) {
413 // TEMP HACK TO KEEP BBKEYS WORKING
414 BlackboxWindow *win = searchWindow(e->xclient.window);
416 if (win && win->isVisible() && win->setInputFocus())
417 win->installColormap(True);
418 } else if (e->xclient.message_type ==
419 xatom->getAtom(XAtom::net_active_window)) {
421 BlackboxWindow *win = searchWindow(e->xclient.window);
424 BScreen *screen = win->getScreen();
427 win->deiconify(False, False);
428 if (! win->isStuck() &&
429 (win->getWorkspaceNumber() != screen->getCurrentWorkspaceID())) {
431 screen->changeWorkspaceID(win->getWorkspaceNumber());
433 if (win->isVisible() && win->setInputFocus()) {
434 win->getScreen()->getWorkspace(win->getWorkspaceNumber())->
436 win->installColormap(True);
439 } else if (e->xclient.message_type ==
440 xatom->getAtom(XAtom::blackbox_cycle_window_focus)) {
441 // BLACKBOX_CYCLE_WINDOW_FOCUS
442 BScreen *screen = searchScreen(e->xclient.window);
445 if (! e->xclient.data.l[0])
450 } else if (e->xclient.message_type ==
451 xatom->getAtom(XAtom::net_wm_desktop)) {
453 BlackboxWindow *win = searchWindow(e->xclient.window);
456 BScreen *screen = win->getScreen();
457 unsigned long wksp = (unsigned) e->xclient.data.l[0];
458 if (wksp < screen->getWorkspaceCount()) {
459 if (win->isIconic()) win->deiconify(False, True);
460 if (win->isStuck()) win->stick();
461 if (wksp != screen->getCurrentWorkspaceID())
465 screen->reassociateWindow(win, wksp, True);
466 } else if (wksp == 0xfffffffe || // XXX: BUG, BUT DOING THIS SO KDE WORKS FOR NOW!!
467 wksp == 0xffffffff) {
468 if (win->isIconic()) win->deiconify(False, True);
469 if (! win->isStuck()) win->stick();
470 if (! win->isVisible()) win->show();
473 } else if (e->xclient.message_type ==
474 xatom->getAtom(XAtom::blackbox_change_attributes)) {
475 // BLACKBOX_CHANGE_ATTRIBUTES
476 BlackboxWindow *win = searchWindow(e->xclient.window);
478 if (win && win->validateClient()) {
480 net.flags = e->xclient.data.l[0];
481 net.attrib = e->xclient.data.l[1];
482 net.workspace = e->xclient.data.l[2];
483 net.stack = e->xclient.data.l[3];
484 net.decoration = e->xclient.data.l[4];
486 win->changeBlackboxHints(&net);
488 } else if (e->xclient.message_type ==
489 xatom->getAtom(XAtom::net_number_of_desktops)) {
490 // NET_NUMBER_OF_DESKTOPS
491 BScreen *screen = searchScreen(e->xclient.window);
493 if (e->xclient.data.l[0] > 0)
494 screen->changeWorkspaceCount((unsigned) e->xclient.data.l[0]);
495 } else if (e->xclient.message_type ==
496 xatom->getAtom(XAtom::net_close_window)) {
498 BlackboxWindow *win = searchWindow(e->xclient.window);
499 if (win && win->validateClient())
500 win->close(); // could this be smarter?
501 } else if (e->xclient.message_type ==
502 xatom->getAtom(XAtom::net_wm_moveresize)) {
504 BlackboxWindow *win = searchWindow(e->xclient.window);
505 if (win && win->validateClient()) {
506 int x_root = e->xclient.data.l[0],
507 y_root = e->xclient.data.l[1];
508 if ((Atom) e->xclient.data.l[2] ==
509 xatom->getAtom(XAtom::net_wm_moveresize_move)) {
510 win->beginMove(x_root, y_root);
512 if ((Atom) e->xclient.data.l[2] ==
513 xatom->getAtom(XAtom::net_wm_moveresize_size_topleft))
514 win->beginResize(x_root, y_root, BlackboxWindow::TopLeft);
515 else if ((Atom) e->xclient.data.l[2] ==
516 xatom->getAtom(XAtom::net_wm_moveresize_size_topright))
517 win->beginResize(x_root, y_root, BlackboxWindow::TopRight);
518 else if ((Atom) e->xclient.data.l[2] ==
519 xatom->getAtom(XAtom::net_wm_moveresize_size_bottomleft))
520 win->beginResize(x_root, y_root, BlackboxWindow::BottomLeft);
521 else if ((Atom) e->xclient.data.l[2] ==
522 xatom->getAtom(XAtom::net_wm_moveresize_size_bottomright))
523 win->beginResize(x_root, y_root, BlackboxWindow::BottomRight);
526 } else if (e->xclient.message_type ==
527 xatom->getAtom(XAtom::net_wm_state)) {
529 BlackboxWindow *win = searchWindow(e->xclient.window);
530 if (win && win->validateClient()) {
531 const Atom action = (Atom) e->xclient.data.l[0];
532 const Atom state[] = { (Atom) e->xclient.data.l[1],
533 (Atom) e->xclient.data.l[2] };
535 for (int i = 0; i < 2; ++i) {
539 if ((Atom) e->xclient.data.l[0] == 1) {
541 if (state[i] == xatom->getAtom(XAtom::net_wm_state_modal)) {
543 } else if (state[i] ==
544 xatom->getAtom(XAtom::net_wm_state_maximized_vert)) {
545 if (win->isMaximizedHoriz()) {
546 win->maximize(0); // unmaximize
547 win->maximize(1); // full
548 } else if (! win->isMaximized()) {
549 win->maximize(2); // vert
551 } else if (state[i] ==
552 xatom->getAtom(XAtom::net_wm_state_maximized_horz)) {
553 if (win->isMaximizedVert()) {
554 win->maximize(0); // unmaximize
555 win->maximize(1); // full
556 } else if (! win->isMaximized()) {
557 win->maximize(3); // horiz
559 } else if (state[i] ==
560 xatom->getAtom(XAtom::net_wm_state_shaded)) {
561 if (! win->isShaded())
563 } else if (state[i] ==
564 xatom->getAtom(XAtom::net_wm_state_skip_taskbar)) {
565 win->setSkipTaskbar(True);
566 } else if (state[i] ==
567 xatom->getAtom(XAtom::net_wm_state_skip_pager)) {
568 win->setSkipPager(True);
569 } else if (state[i] ==
570 xatom->getAtom(XAtom::net_wm_state_fullscreen)) {
571 win->setFullscreen(True);
573 } else if (action == 0) {
575 if (state[i] == xatom->getAtom(XAtom::net_wm_state_modal)) {
576 win->setModal(False);
577 } else if (state[i] ==
578 xatom->getAtom(XAtom::net_wm_state_maximized_vert)) {
579 if (win->isMaximizedFull()) {
580 win->maximize(0); // unmaximize
581 win->maximize(3); // horiz
582 } else if (win->isMaximizedVert()) {
583 win->maximize(0); // unmaximize
585 } else if (state[i] ==
586 xatom->getAtom(XAtom::net_wm_state_maximized_horz)) {
587 if (win->isMaximizedFull()) {
588 win->maximize(0); // unmaximize
589 win->maximize(2); // vert
590 } else if (win->isMaximizedHoriz()) {
591 win->maximize(0); // unmaximize
593 } else if (state[i] ==
594 xatom->getAtom(XAtom::net_wm_state_shaded)) {
597 } else if (state[i] ==
598 xatom->getAtom(XAtom::net_wm_state_skip_taskbar)) {
599 win->setSkipTaskbar(False);
600 } else if (state[i] ==
601 xatom->getAtom(XAtom::net_wm_state_skip_pager)) {
602 win->setSkipPager(False);
603 } else if (state[i] ==
604 xatom->getAtom(XAtom::net_wm_state_fullscreen)) {
605 win->setFullscreen(False);
607 } else if (action == 2) {
609 if (state[i] == xatom->getAtom(XAtom::net_wm_state_modal)) {
610 win->setModal(! win->isModal());
611 } else if (state[i] ==
612 xatom->getAtom(XAtom::net_wm_state_maximized_vert)) {
613 if (win->isMaximizedFull()) {
614 win->maximize(0); // unmaximize
615 win->maximize(3); // horiz
616 } else if (win->isMaximizedVert()) {
617 win->maximize(0); // unmaximize
618 } else if (win->isMaximizedHoriz()) {
619 win->maximize(0); // unmaximize
620 win->maximize(1); // full
622 win->maximize(2); // vert
624 } else if (state[i] ==
625 xatom->getAtom(XAtom::net_wm_state_maximized_horz)) {
626 if (win->isMaximizedFull()) {
627 win->maximize(0); // unmaximize
628 win->maximize(2); // vert
629 } else if (win->isMaximizedHoriz()) {
630 win->maximize(0); // unmaximize
631 } else if (win->isMaximizedVert()) {
632 win->maximize(0); // unmaximize
633 win->maximize(1); // full
635 win->maximize(3); // horiz
637 } else if (state[i] ==
638 xatom->getAtom(XAtom::net_wm_state_shaded)) {
640 } else if (state[i] ==
641 xatom->getAtom(XAtom::net_wm_state_skip_taskbar)) {
642 win->setSkipTaskbar(! win->skipTaskbar());
643 } else if (state[i] ==
644 xatom->getAtom(XAtom::net_wm_state_skip_pager)) {
645 win->setSkipPager(! win->skipPager());
646 } else if (state[i] ==
647 xatom->getAtom(XAtom::net_wm_state_fullscreen)) {
648 win->setFullscreen(! win->isFullscreen());
658 void OBXEventHandler::handle(const XEvent
&e
)
660 /* mouse button events can get translated into:
661 press - button was pressed down
662 release - buttons was released
663 click - button was pressed and released on the same window
664 double click - clicked twice on the same widget in a given time and area
666 key events are only bindable to presses. key releases are ignored.
668 mouse enter/leave can be bound to for the entire window
673 // These types of XEvent's can be bound to actions by the user, and so end
674 // up getting passed off to the OBBindingMapper class at some point
676 buttonPress(e
.xbutton
);
679 buttonRelease(e
.xbutton
);
688 enterNotify(e
.xcrossing
);
691 leaveNotify(e
.xcrossing
);
695 // These types of XEvent's can not be bound to actions by the user and so
696 // will simply be handled in this class
697 case ConfigureRequest
:
698 configureRequest(e
.xconfigurerequest
);
702 mapRequest(e
.xmaprequest
);
706 unmapNotify(e
.xunmap
);
710 destroyNotify(e
.xdestroywindow
);
714 reparentNotify(e
.xreparent
);
718 propertyNotify(e
.xproperty
);
726 colormapNotify(e
.xcolormap
);
738 clientMessage(e
.xclient
);
742 if (e
.type
== otk::OBDisplay::shapeEventBase())
748 case ClientMessage: {
This page took 0.064948 seconds and 4 git commands to generate.