#include "menu.h"
#include "framerender.h"
#include "focus.h"
+#include "moveresize.h"
#include "stacking.h"
#include "extensions.h"
#include "timer.h"
static void event_handle_client(Client *c, XEvent *e);
static void event_handle_menu(Menu *menu, XEvent *e);
+#define INVALID_FOCUSIN(e) ((e)->xfocus.detail == NotifyInferior || \
+ (e)->xfocus.detail > NotifyNonlinearVirtual)
+#define INVALID_FOCUSOUT(e) ((e)->xfocus.mode == NotifyGrab || \
+ (e)->xfocus.detail == NotifyInferior || \
+ (e)->xfocus.detail == NotifyAncestor || \
+ (e)->xfocus.detail > NotifyNonlinearVirtual)
+
Time event_lasttime = 0;
/*! The value of the mask for the NumLock modifier */
XEvent e;
int x_fd;
struct timeval *wait;
+ gboolean had_event = FALSE;
while (TRUE) {
/*
XNextEvent(ob_display, &e);
event_process(&e);
+ had_event = TRUE;
+ }
+
+ if (!had_event) {
+ timer_dispatch((GTimeVal**)&wait);
+ x_fd = ConnectionNumber(ob_display);
+ FD_ZERO(&selset);
+ FD_SET(x_fd, &selset);
+ select(x_fd + 1, &selset, NULL, NULL, wait);
}
-
- timer_dispatch((GTimeVal**)&wait);
- x_fd = ConnectionNumber(ob_display);
- FD_ZERO(&selset);
- FD_SET(x_fd, &selset);
- select(x_fd + 1, &selset, NULL, NULL, wait);
}
static Window event_get_window(XEvent *e)
{
switch(e->type) {
case FocusIn:
-#ifdef DEBUG_FOCUS
- g_message("FocusIn on %lx mode %d detail %d", window,
- e->xfocus.mode, e->xfocus.detail);
-#endif
/* NotifyAncestor is not ignored in FocusIn like it is in FocusOut
because of RevertToPointerRoot. If the focus ends up reverting to
pointer root on a workspace change, then the FocusIn event that we
want will be of type NotifyAncestor. This situation does not occur
for FocusOut, so it is safely ignored there.
*/
- if (e->xfocus.detail == NotifyInferior ||
- e->xfocus.detail > NotifyNonlinearVirtual ||
+ if (INVALID_FOCUSIN(e) ||
client == NULL) {
+#ifdef DEBUG_FOCUS
+ g_message("FocusIn on %lx mode %d detail %d IGNORED", e->xfocus.window,
+ e->xfocus.mode, e->xfocus.detail);
+#endif
/* says a client was not found for the event (or a valid FocusIn
event was not found.
*/
}
#ifdef DEBUG_FOCUS
- g_message("FocusIn on %lx", window);
+ g_message("FocusIn on %lx mode %d detail %d", e->xfocus.window,
+ e->xfocus.mode, e->xfocus.detail);
#endif
break;
case FocusOut:
+ if (INVALID_FOCUSOUT(e)) {
#ifdef DEBUG_FOCUS
- g_message("FocusOut on %lx mode %d detail %d", window,
- e->xfocus.mode, e->xfocus.detail);
+ g_message("FocusOut on %lx mode %d detail %d IGNORED",
+ e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
#endif
- if (e->xfocus.mode == NotifyGrab ||
- e->xfocus.detail == NotifyInferior ||
- e->xfocus.detail == NotifyAncestor ||
- e->xfocus.detail > NotifyNonlinearVirtual) return TRUE;
-
+ return TRUE;
+ }
+
#ifdef DEBUG_FOCUS
- g_message("FocusOut on %lx", window);
+ g_message("FocusOut on %lx mode %d detail %d",
+ e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
#endif
+
/* Try process a FocusIn first, and if a legit one isn't found, then
do the fallback shiznit. */
{
- XEvent fi, fo;
- gboolean isfo = FALSE;
-
- if (XCheckTypedEvent(ob_display, FocusIn, &fi)) {
- event_process(&fi);
-
- /* when we have gotten a fi/fo pair, then see if there are any
- more fo's coming. if there are, then don't fallback just yet
- */
- if ((isfo = XCheckTypedEvent(ob_display, FocusOut, &fo)))
- XPutBackEvent(ob_display, &fo);
-
- /* secret magic way of event_process telling us that no client
- was found for the FocusIn event. ^_^ */
- if (!isfo && fi.xfocus.window == None)
- focus_fallback(Fallback_NoFocus);
- if (fi.xfocus.window == e->xfocus.window)
- return TRUE;
- } else
+ XEvent fe;
+ gboolean fallback = TRUE;
+
+ while (TRUE) {
+ if (!XCheckTypedEvent(ob_display, FocusOut, &fe))
+ if (!XCheckTypedEvent(ob_display, FocusIn, &fe))
+ break;
+ if (fe.type == FocusOut) {
+#ifdef DEBUG_FOCUS
+ g_message("found pending FocusOut");
+#endif
+ if (!INVALID_FOCUSOUT(&fe)) {
+ /* if there is a VALID FocusOut still coming, don't
+ fallback focus yet, we'll deal with it then */
+ XPutBackEvent(ob_display, &fe);
+ fallback = FALSE;
+ break;
+ }
+ } else {
+#ifdef DEBUG_FOCUS
+ g_message("found pending FocusIn");
+#endif
+ /* once all the FocusOut's have been dealt with, if there
+ is a FocusIn still left and it is valid, then use it */
+ event_process(&fe);
+ /* secret magic way of event_process telling us that no
+ client was found for the FocusIn event. ^_^ */
+ if (fe.xfocus.window != None) {
+ fallback = FALSE;
+ break;
+ }
+ }
+ }
+ if (fallback) {
+#ifdef DEBUG_FOCUS
+ g_message("no valid FocusIn and no FocusOut events found, "
+ "falling back");
+#endif
focus_fallback(Fallback_NoFocus);
+ }
}
break;
case EnterNotify:
case LeaveNotify:
/* NotifyUngrab occurs when a mouse button is released and the event is
caused, like when lowering a window */
+ /* NotifyVirtual occurs when ungrabbing the pointer */
if (e->xcrossing.mode == NotifyGrab ||
- e->xcrossing.detail == NotifyInferior)
+ e->xcrossing.detail == NotifyInferior ||
+ (e->xcrossing.mode == NotifyUngrab &&
+ e->xcrossing.detail == NotifyVirtual)) {
+#ifdef DEBUG_FOCUS
+ g_message("%sNotify mode %d detail %d on %lx IGNORED",
+ (e->type == EnterNotify ? "Enter" : "Leave"),
+ e->xcrossing.mode,
+ e->xcrossing.detail, client?client->window:0);
+#endif
return TRUE;
+ }
+#ifdef DEBUG_FOCUS
+ g_message("%sNotify mode %d detail %d on %lx",
+ (e->type == EnterNotify ? "Enter" : "Leave"),
+ e->xcrossing.mode,
+ e->xcrossing.detail, client?client->window:0);
+#endif
break;
}
return FALSE;
return;
/* deal with it in the kernel */
- if (menu)
+ if (menu) {
event_handle_menu(menu, e);
- else if (client)
+ return;
+ } else if (client)
event_handle_client(client, e);
else if (window == ob_root)
event_handle_root(e);
xerror_set_ignore(FALSE);
}
+ if (moveresize_in_progress)
+ if (e->type == MotionNotify || e->type == ButtonRelease ||
+ e->type == ButtonPress ||
+ e->type == KeyPress || e->type == KeyRelease) {
+ moveresize_event(e);
+
+ return; /* no dispatch! */
+
+ }
+
/* user input (action-bound) events */
/*
if (e->type == ButtonPress || e->type == ButtonRelease ||
client_shade(client, FALSE);
client_focus(client);
stacking_raise(client);
- }
+ } else if (msgtype == prop_atoms.net_wm_moveresize) {
+ g_message("net_wm_moveresize for 0x%lx", client->window);
+ if ((Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_size_topleft ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_size_top ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_size_topright ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_size_right ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_size_right ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_size_bottomright ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_size_bottom ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_size_bottomleft ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_size_left ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_move ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_size_keyboard ||
+ (Atom)e->xclient.data.l[2] ==
+ prop_atoms.net_wm_moveresize_move_keyboard) {
+
+ moveresize_start(client, e->xclient.data.l[0],
+ e->xclient.data.l[1], e->xclient.data.l[3],
+ e->xclient.data.l[2]);
+ }
+ } else if (msgtype == prop_atoms.net_moveresize_window) {
+ int oldg = client->gravity;
+ int tmpg, x, y, w, h;
+
+ if (e->xclient.data.l[0] & 0xff)
+ tmpg = e->xclient.data.l[0] & 0xff;
+ else
+ tmpg = oldg;
+
+ if (e->xclient.data.l[0] & 1 << 8)
+ x = e->xclient.data.l[1];
+ else
+ x = client->area.x;
+ if (e->xclient.data.l[0] & 1 << 9)
+ y = e->xclient.data.l[2];
+ else
+ y = client->area.y;
+ if (e->xclient.data.l[0] & 1 << 10)
+ w = e->xclient.data.l[3];
+ else
+ w = client->area.y;
+ if (e->xclient.data.l[0] & 1 << 11)
+ h = e->xclient.data.l[4];
+ else
+ h = client->area.y;
+ client->gravity = tmpg;
+ client_configure(client, Corner_TopLeft, x, y, w, h, TRUE, TRUE);
+ client->gravity = oldg;
+ }
break;
case PropertyNotify:
/* validate cuz we query stuff off the client here */
{
MenuEntry *entry;
+ g_message("EVENT %d", e->type);
switch (e->type) {
+ case ButtonPress:
+ if (e->xbutton.button == 3)
+ menu_hide(menu);
+ break;
+ case ButtonRelease:
+ if (!menu->shown) break;
+
+/* grab_pointer_window(FALSE, None, menu->frame);*/
+
+ entry = menu_find_entry(menu, e->xbutton.window);
+ if (entry) {
+ int junk;
+ Window wjunk;
+ guint ujunk, b, w, h;
+ XGetGeometry(ob_display, e->xbutton.window,
+ &wjunk, &junk, &junk, &w, &h, &b, &ujunk);
+ if (e->xbutton.x >= (signed)-b &&
+ e->xbutton.y >= (signed)-b &&
+ e->xbutton.x < (signed)(w+b) &&
+ e->xbutton.y < (signed)(h+b)) {
+ menu_entry_fire(entry);
+ }
+ }
+ break;
case EnterNotify:
case LeaveNotify:
g_message("enter/leave");