]>
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::handle(const XEvent
&e
)
389 /* mouse button events can get translated into:
390 press - button was pressed down
391 release - buttons was released
392 click - button was pressed and released on the same window
393 double click - clicked twice on the same widget in a given time and area
395 key events are only bindable to presses. key releases are ignored.
397 mouse enter/leave can be bound to for the entire window
402 // These types of XEvent's can be bound to actions by the user, and so end
403 // up getting passed off to the OBBindingMapper class at some point
405 buttonPress(e
.xbutton
);
408 buttonRelease(e
.xbutton
);
417 enterNotify(e
.xcrossing
);
420 leaveNotify(e
.xcrossing
);
424 // These types of XEvent's can not be bound to actions by the user and so
425 // will simply be handled in this class
426 case ConfigureRequest
:
427 configureRequest(e
.xconfigurerequest
);
431 mapRequest(e
.xmaprequest
);
435 unmapNotify(e
.xunmap
);
439 destroyNotify(e
.xdestroywindow
);
443 reparentNotify(e
.xreparent
);
447 propertyNotify(e
.xproperty
);
455 colormapNotify(e
.xcolormap
);
468 if (e
.type
== otk::OBDisplay::shapeEventBase())
474 case ClientMessage: {
475 if (e->xclient.format == 32) {
476 if (e->xclient.message_type == xatom->getAtom(XAtom::wm_change_state)) {
477 // WM_CHANGE_STATE message
478 BlackboxWindow *win = searchWindow(e->xclient.window);
479 if (! win || ! win->validateClient()) return;
481 if (e->xclient.data.l[0] == IconicState)
483 if (e->xclient.data.l[0] == NormalState)
485 } else if (e->xclient.message_type ==
486 xatom->getAtom(XAtom::blackbox_change_workspace) ||
487 e->xclient.message_type ==
488 xatom->getAtom(XAtom::net_current_desktop)) {
489 // NET_CURRENT_DESKTOP message
490 BScreen *screen = searchScreen(e->xclient.window);
492 unsigned int workspace = e->xclient.data.l[0];
493 if (screen && workspace < screen->getWorkspaceCount())
494 screen->changeWorkspaceID(workspace);
495 } else if (e->xclient.message_type ==
496 xatom->getAtom(XAtom::blackbox_change_window_focus)) {
497 // TEMP HACK TO KEEP BBKEYS WORKING
498 BlackboxWindow *win = searchWindow(e->xclient.window);
500 if (win && win->isVisible() && win->setInputFocus())
501 win->installColormap(True);
502 } else if (e->xclient.message_type ==
503 xatom->getAtom(XAtom::net_active_window)) {
505 BlackboxWindow *win = searchWindow(e->xclient.window);
508 BScreen *screen = win->getScreen();
511 win->deiconify(False, False);
512 if (! win->isStuck() &&
513 (win->getWorkspaceNumber() != screen->getCurrentWorkspaceID())) {
515 screen->changeWorkspaceID(win->getWorkspaceNumber());
517 if (win->isVisible() && win->setInputFocus()) {
518 win->getScreen()->getWorkspace(win->getWorkspaceNumber())->
520 win->installColormap(True);
523 } else if (e->xclient.message_type ==
524 xatom->getAtom(XAtom::blackbox_cycle_window_focus)) {
525 // BLACKBOX_CYCLE_WINDOW_FOCUS
526 BScreen *screen = searchScreen(e->xclient.window);
529 if (! e->xclient.data.l[0])
534 } else if (e->xclient.message_type ==
535 xatom->getAtom(XAtom::net_wm_desktop)) {
537 BlackboxWindow *win = searchWindow(e->xclient.window);
540 BScreen *screen = win->getScreen();
541 unsigned long wksp = (unsigned) e->xclient.data.l[0];
542 if (wksp < screen->getWorkspaceCount()) {
543 if (win->isIconic()) win->deiconify(False, True);
544 if (win->isStuck()) win->stick();
545 if (wksp != screen->getCurrentWorkspaceID())
549 screen->reassociateWindow(win, wksp, True);
550 } else if (wksp == 0xfffffffe || // XXX: BUG, BUT DOING THIS SO KDE WORKS FOR NOW!!
551 wksp == 0xffffffff) {
552 if (win->isIconic()) win->deiconify(False, True);
553 if (! win->isStuck()) win->stick();
554 if (! win->isVisible()) win->show();
557 } else if (e->xclient.message_type ==
558 xatom->getAtom(XAtom::blackbox_change_attributes)) {
559 // BLACKBOX_CHANGE_ATTRIBUTES
560 BlackboxWindow *win = searchWindow(e->xclient.window);
562 if (win && win->validateClient()) {
564 net.flags = e->xclient.data.l[0];
565 net.attrib = e->xclient.data.l[1];
566 net.workspace = e->xclient.data.l[2];
567 net.stack = e->xclient.data.l[3];
568 net.decoration = e->xclient.data.l[4];
570 win->changeBlackboxHints(&net);
572 } else if (e->xclient.message_type ==
573 xatom->getAtom(XAtom::net_number_of_desktops)) {
574 // NET_NUMBER_OF_DESKTOPS
575 BScreen *screen = searchScreen(e->xclient.window);
577 if (e->xclient.data.l[0] > 0)
578 screen->changeWorkspaceCount((unsigned) e->xclient.data.l[0]);
579 } else if (e->xclient.message_type ==
580 xatom->getAtom(XAtom::net_close_window)) {
582 BlackboxWindow *win = searchWindow(e->xclient.window);
583 if (win && win->validateClient())
584 win->close(); // could this be smarter?
585 } else if (e->xclient.message_type ==
586 xatom->getAtom(XAtom::net_wm_moveresize)) {
588 BlackboxWindow *win = searchWindow(e->xclient.window);
589 if (win && win->validateClient()) {
590 int x_root = e->xclient.data.l[0],
591 y_root = e->xclient.data.l[1];
592 if ((Atom) e->xclient.data.l[2] ==
593 xatom->getAtom(XAtom::net_wm_moveresize_move)) {
594 win->beginMove(x_root, y_root);
596 if ((Atom) e->xclient.data.l[2] ==
597 xatom->getAtom(XAtom::net_wm_moveresize_size_topleft))
598 win->beginResize(x_root, y_root, BlackboxWindow::TopLeft);
599 else if ((Atom) e->xclient.data.l[2] ==
600 xatom->getAtom(XAtom::net_wm_moveresize_size_topright))
601 win->beginResize(x_root, y_root, BlackboxWindow::TopRight);
602 else if ((Atom) e->xclient.data.l[2] ==
603 xatom->getAtom(XAtom::net_wm_moveresize_size_bottomleft))
604 win->beginResize(x_root, y_root, BlackboxWindow::BottomLeft);
605 else if ((Atom) e->xclient.data.l[2] ==
606 xatom->getAtom(XAtom::net_wm_moveresize_size_bottomright))
607 win->beginResize(x_root, y_root, BlackboxWindow::BottomRight);
610 } else if (e->xclient.message_type ==
611 xatom->getAtom(XAtom::net_wm_state)) {
613 BlackboxWindow *win = searchWindow(e->xclient.window);
614 if (win && win->validateClient()) {
615 const Atom action = (Atom) e->xclient.data.l[0];
616 const Atom state[] = { (Atom) e->xclient.data.l[1],
617 (Atom) e->xclient.data.l[2] };
619 for (int i = 0; i < 2; ++i) {
623 if ((Atom) e->xclient.data.l[0] == 1) {
625 if (state[i] == xatom->getAtom(XAtom::net_wm_state_modal)) {
627 } else if (state[i] ==
628 xatom->getAtom(XAtom::net_wm_state_maximized_vert)) {
629 if (win->isMaximizedHoriz()) {
630 win->maximize(0); // unmaximize
631 win->maximize(1); // full
632 } else if (! win->isMaximized()) {
633 win->maximize(2); // vert
635 } else if (state[i] ==
636 xatom->getAtom(XAtom::net_wm_state_maximized_horz)) {
637 if (win->isMaximizedVert()) {
638 win->maximize(0); // unmaximize
639 win->maximize(1); // full
640 } else if (! win->isMaximized()) {
641 win->maximize(3); // horiz
643 } else if (state[i] ==
644 xatom->getAtom(XAtom::net_wm_state_shaded)) {
645 if (! win->isShaded())
647 } else if (state[i] ==
648 xatom->getAtom(XAtom::net_wm_state_skip_taskbar)) {
649 win->setSkipTaskbar(True);
650 } else if (state[i] ==
651 xatom->getAtom(XAtom::net_wm_state_skip_pager)) {
652 win->setSkipPager(True);
653 } else if (state[i] ==
654 xatom->getAtom(XAtom::net_wm_state_fullscreen)) {
655 win->setFullscreen(True);
657 } else if (action == 0) {
659 if (state[i] == xatom->getAtom(XAtom::net_wm_state_modal)) {
660 win->setModal(False);
661 } else if (state[i] ==
662 xatom->getAtom(XAtom::net_wm_state_maximized_vert)) {
663 if (win->isMaximizedFull()) {
664 win->maximize(0); // unmaximize
665 win->maximize(3); // horiz
666 } else if (win->isMaximizedVert()) {
667 win->maximize(0); // unmaximize
669 } else if (state[i] ==
670 xatom->getAtom(XAtom::net_wm_state_maximized_horz)) {
671 if (win->isMaximizedFull()) {
672 win->maximize(0); // unmaximize
673 win->maximize(2); // vert
674 } else if (win->isMaximizedHoriz()) {
675 win->maximize(0); // unmaximize
677 } else if (state[i] ==
678 xatom->getAtom(XAtom::net_wm_state_shaded)) {
681 } else if (state[i] ==
682 xatom->getAtom(XAtom::net_wm_state_skip_taskbar)) {
683 win->setSkipTaskbar(False);
684 } else if (state[i] ==
685 xatom->getAtom(XAtom::net_wm_state_skip_pager)) {
686 win->setSkipPager(False);
687 } else if (state[i] ==
688 xatom->getAtom(XAtom::net_wm_state_fullscreen)) {
689 win->setFullscreen(False);
691 } else if (action == 2) {
693 if (state[i] == xatom->getAtom(XAtom::net_wm_state_modal)) {
694 win->setModal(! win->isModal());
695 } else if (state[i] ==
696 xatom->getAtom(XAtom::net_wm_state_maximized_vert)) {
697 if (win->isMaximizedFull()) {
698 win->maximize(0); // unmaximize
699 win->maximize(3); // horiz
700 } else if (win->isMaximizedVert()) {
701 win->maximize(0); // unmaximize
702 } else if (win->isMaximizedHoriz()) {
703 win->maximize(0); // unmaximize
704 win->maximize(1); // full
706 win->maximize(2); // vert
708 } else if (state[i] ==
709 xatom->getAtom(XAtom::net_wm_state_maximized_horz)) {
710 if (win->isMaximizedFull()) {
711 win->maximize(0); // unmaximize
712 win->maximize(2); // vert
713 } else if (win->isMaximizedHoriz()) {
714 win->maximize(0); // unmaximize
715 } else if (win->isMaximizedVert()) {
716 win->maximize(0); // unmaximize
717 win->maximize(1); // full
719 win->maximize(3); // horiz
721 } else if (state[i] ==
722 xatom->getAtom(XAtom::net_wm_state_shaded)) {
724 } else if (state[i] ==
725 xatom->getAtom(XAtom::net_wm_state_skip_taskbar)) {
726 win->setSkipTaskbar(! win->skipTaskbar());
727 } else if (state[i] ==
728 xatom->getAtom(XAtom::net_wm_state_skip_pager)) {
729 win->setSkipPager(! win->skipPager());
730 } else if (state[i] ==
731 xatom->getAtom(XAtom::net_wm_state_fullscreen)) {
732 win->setFullscreen(! win->isFullscreen());
744 case ConfigureNotify:
746 break; // not handled, just ignore
This page took 0.075052 seconds and 4 git commands to generate.