/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
event.c for the Openbox window manager
+ Copyright (c) 2004 Mikael Magnusson
Copyright (c) 2003 Ben Jansens
This program is free software; you can redistribute it and/or modify
#ifdef HAVE_SIGNAL_H
# include <signal.h>
#endif
+#ifdef XKB
+# include <X11/XKBlib.h>
+#endif
#ifdef USE_SM
#include <X11/ICE/ICElib.h>
} ObEventData;
static void event_process(const XEvent *e, gpointer data);
+static void event_client_dest(ObClient *client, gpointer data);
static void event_handle_root(XEvent *e);
static void event_handle_menu(XEvent *e);
static void event_handle_dock(ObDock *s, XEvent *e);
static void event_handle_group(ObGroup *g, XEvent *e);
static gboolean focus_delay_func(gpointer data);
-static void focus_delay_client_dest(gpointer data);
+static void focus_delay_client_dest(ObClient *client, gpointer data);
static gboolean menu_hide_delay_func(gpointer data);
Time event_lasttime = 0;
/*! The value of the mask for the NumLock modifier */
-unsigned int NumLockMask;
+guint NumLockMask;
/*! The value of the mask for the ScrollLock modifier */
-unsigned int ScrollLockMask;
+guint ScrollLockMask;
/*! The key codes for the modifier keys */
static XModifierKeymap *modmap;
/*! Table of the constant modifier masks */
-static const int mask_table[] = {
+static const gint mask_table[] = {
ShiftMask, LockMask, ControlMask, Mod1Mask,
Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
};
-static int mask_table_size;
+static gint mask_table_size;
static guint ignore_enter_focus = 0;
static gboolean menu_can_hide;
#ifdef USE_SM
-static void ice_handler(int fd, gpointer conn)
+static void ice_handler(gint fd, gpointer conn)
{
Bool b;
IceProcessMessages(conn, NULL, &b);
modmap = XGetModifierMapping(ob_display);
g_assert(modmap);
if (modmap && modmap->max_keypermod > 0) {
- size_t cnt;
- const size_t size = mask_table_size * modmap->max_keypermod;
- /* get the values of the keyboard lock modifiers
- Note: Caps lock is not retrieved the same way as Scroll and Num
- lock since it doesn't need to be. */
- const KeyCode num_lock = XKeysymToKeycode(ob_display, XK_Num_Lock);
- const KeyCode scroll_lock = XKeysymToKeycode(ob_display,
- XK_Scroll_Lock);
-
- for (cnt = 0; cnt < size; ++cnt) {
- if (! modmap->modifiermap[cnt]) continue;
-
- if (num_lock == modmap->modifiermap[cnt])
- NumLockMask = mask_table[cnt / modmap->max_keypermod];
- if (scroll_lock == modmap->modifiermap[cnt])
- ScrollLockMask = mask_table[cnt / modmap->max_keypermod];
- }
+ size_t cnt;
+ const size_t size = mask_table_size * modmap->max_keypermod;
+ /* get the values of the keyboard lock modifiers
+ Note: Caps lock is not retrieved the same way as Scroll and Num
+ lock since it doesn't need to be. */
+ const KeyCode num_lock = XKeysymToKeycode(ob_display, XK_Num_Lock);
+ const KeyCode scroll_lock = XKeysymToKeycode(ob_display,
+ XK_Scroll_Lock);
+
+ for (cnt = 0; cnt < size; ++cnt) {
+ if (! modmap->modifiermap[cnt]) continue;
+
+ if (num_lock == modmap->modifiermap[cnt])
+ NumLockMask = mask_table[cnt / modmap->max_keypermod];
+ if (scroll_lock == modmap->modifiermap[cnt])
+ ScrollLockMask = mask_table[cnt / modmap->max_keypermod];
+ }
}
ob_main_loop_x_add(ob_main_loop, event_process, NULL, NULL);
IceAddConnectionWatch(ice_watch, NULL);
#endif
- client_add_destructor(focus_delay_client_dest);
+ client_add_destructor(focus_delay_client_dest, NULL);
+ client_add_destructor(event_client_dest, NULL);
}
void event_shutdown(gboolean reconfig)
window = RootWindow(ob_display, ob_screen);
break;
case MapRequest:
- window = e->xmap.window;
- break;
+ window = e->xmap.window;
+ break;
case UnmapNotify:
- window = e->xunmap.window;
- break;
+ window = e->xunmap.window;
+ break;
case DestroyNotify:
- window = e->xdestroywindow.window;
- break;
+ window = e->xdestroywindow.window;
+ break;
case ConfigureRequest:
- window = e->xconfigurerequest.window;
- break;
+ window = e->xconfigurerequest.window;
+ break;
case ConfigureNotify:
window = e->xconfigure.window;
break;
default:
#ifdef XKB
- if (extensions_xkb && e->type == extensions_xkb_event_basep) {
- switch (((XkbAnyEvent*)e)->xkb_type) {
- case XkbBellNotify:
- window = ((XkbBellNotifyEvent*)e)->window;
- default:
- window = None;
- }
+ if (extensions_xkb && e->type == extensions_xkb_event_basep) {
+ switch (((XkbAnyEvent*)e)->xkb_type) {
+ case XkbBellNotify:
+ window = ((XkbBellNotifyEvent*)e)->window;
+ default:
+ window = None;
+ }
} else
#endif
window = e->xany.window;
switch (e->type) {
case ButtonPress:
case ButtonRelease:
- t = e->xbutton.time;
- break;
+ t = e->xbutton.time;
+ break;
case KeyPress:
- t = e->xkey.time;
- break;
+ t = e->xkey.time;
+ break;
case KeyRelease:
- t = e->xkey.time;
- break;
+ t = e->xkey.time;
+ break;
case MotionNotify:
- t = e->xmotion.time;
- break;
+ t = e->xmotion.time;
+ break;
case PropertyNotify:
- t = e->xproperty.time;
- break;
+ t = e->xproperty.time;
+ break;
case EnterNotify:
case LeaveNotify:
- t = e->xcrossing.time;
- break;
+ t = e->xcrossing.time;
+ break;
default:
/* if more event types are anticipated, get their timestamp
explicitly */
}
#define STRIP_MODS(s) \
- s &= ~(LockMask | NumLockMask | ScrollLockMask), \
- /* kill off the Button1Mask etc, only want the modifiers */ \
- s &= (ControlMask | ShiftMask | Mod1Mask | \
+ s &= ~(LockMask | NumLockMask | ScrollLockMask), \
+ /* kill off the Button1Mask etc, only want the modifiers */ \
+ s &= (ControlMask | ShiftMask | Mod1Mask | \
Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask) \
static void event_hack_mods(XEvent *e)
{
+#ifdef XKB
+ XkbStateRec xkb_state;
+#endif
KeyCode *kp;
- int i, k;
+ gint i, k;
switch (e->type) {
case ButtonPress:
case ButtonRelease:
STRIP_MODS(e->xbutton.state);
- break;
+ break;
case KeyPress:
STRIP_MODS(e->xkey.state);
- break;
+ break;
case KeyRelease:
STRIP_MODS(e->xkey.state);
- /* remove from the state the mask of the modifier being released, if
- it is a modifier key being released (this is a little ugly..) */
- kp = modmap->modifiermap;
- for (i = 0; i < mask_table_size; ++i) {
- for (k = 0; k < modmap->max_keypermod; ++k) {
- if (*kp == e->xkey.keycode) { /* found the keycode */
- /* remove the mask for it */
- e->xkey.state &= ~mask_table[i];
- /* cause the first loop to break; */
- i = mask_table_size;
- break; /* get outta here! */
- }
- ++kp;
- }
- }
- break;
+ /* remove from the state the mask of the modifier being released, if
+ it is a modifier key being released (this is a little ugly..) */
+#ifdef XKB
+ if (XkbGetState(ob_display, XkbUseCoreKbd, &xkb_state) == Success) {
+ e->xkey.state = xkb_state.compat_state;
+ break;
+ }
+#endif
+ kp = modmap->modifiermap;
+ for (i = 0; i < mask_table_size; ++i) {
+ for (k = 0; k < modmap->max_keypermod; ++k) {
+ if (*kp == e->xkey.keycode) { /* found the keycode */
+ /* remove the mask for it */
+ e->xkey.state &= ~mask_table[i];
+ /* cause the first loop to break; */
+ i = mask_table_size;
+ break; /* get outta here! */
+ }
+ ++kp;
+ }
+ }
+ break;
case MotionNotify:
STRIP_MODS(e->xmotion.state);
- /* compress events */
+ /* compress events */
{
XEvent ce;
while (XCheckTypedWindowEvent(ob_display, e->xmotion.window,
e->xmotion.x_root = ce.xmotion.x_root;
e->xmotion.y_root = ce.xmotion.y_root;
}
- }
- break;
+ }
+ break;
}
}
want will be of type NotifyAncestor. This situation does not occur
for FocusOut, so it is safely ignored there.
*/
- if (INVALID_FOCUSIN(e) ||
+ if (INVALID_FOCUSIN(e) ||
client == NULL) {
#ifdef DEBUG_FOCUS
ob_debug("FocusIn on %lx mode %d detail %d IGNORED\n",
#endif
break;
case FocusOut:
- if (INVALID_FOCUSOUT(e)) {
+ if (INVALID_FOCUSOUT(e)) {
#ifdef DEBUG_FOCUS
ob_debug("FocusOut on %lx mode %d detail %d IGNORED\n",
e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
ob_debug("FocusOut on %lx mode %d detail %d\n",
e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
#endif
-
{
XEvent fe;
gboolean fallback = TRUE;
/* deal with it in the kernel */
if (group)
- event_handle_group(group, e);
+ event_handle_group(group, e);
else if (client)
- event_handle_client(client, e);
+ event_handle_client(client, e);
else if (dockapp)
- event_handle_dockapp(dockapp, e);
+ event_handle_dockapp(dockapp, e);
else if (dock)
- event_handle_dock(dock, e);
+ event_handle_dock(dock, e);
else if (window == RootWindow(ob_display, ob_screen))
- event_handle_root(e);
+ event_handle_root(e);
else if (e->type == MapRequest)
- client_manage(window);
+ client_manage(window);
else if (e->type == ConfigureRequest) {
- /* unhandled configure requests must be used to configure the
- window directly */
- XWindowChanges xwc;
-
- xwc.x = e->xconfigurerequest.x;
- xwc.y = e->xconfigurerequest.y;
- xwc.width = e->xconfigurerequest.width;
- xwc.height = e->xconfigurerequest.height;
- xwc.border_width = e->xconfigurerequest.border_width;
- xwc.sibling = e->xconfigurerequest.above;
- xwc.stack_mode = e->xconfigurerequest.detail;
+ /* unhandled configure requests must be used to configure the
+ window directly */
+ XWindowChanges xwc;
+
+ xwc.x = e->xconfigurerequest.x;
+ xwc.y = e->xconfigurerequest.y;
+ xwc.width = e->xconfigurerequest.width;
+ xwc.height = e->xconfigurerequest.height;
+ xwc.border_width = e->xconfigurerequest.border_width;
+ xwc.sibling = e->xconfigurerequest.above;
+ xwc.stack_mode = e->xconfigurerequest.detail;
- /* we are not to be held responsible if someone sends us an
- invalid request! */
- xerror_set_ignore(TRUE);
- XConfigureWindow(ob_display, window,
- e->xconfigurerequest.value_mask, &xwc);
- xerror_set_ignore(FALSE);
+ /* we are not to be held responsible if someone sends us an
+ invalid request! */
+ xerror_set_ignore(TRUE);
+ XConfigureWindow(ob_display, window,
+ e->xconfigurerequest.value_mask, &xwc);
+ xerror_set_ignore(FALSE);
}
/* user input (action-bound) events */
menu_can_hide = FALSE;
ob_main_loop_timeout_add(ob_main_loop,
- G_USEC_PER_SEC / 4,
+ config_menu_hide_delay * 1000,
menu_hide_delay_func,
NULL, NULL);
e->type == MotionNotify)
mouse_event(client, e);
else if (e->type == KeyPress)
- /* when in the middle of a focus cycling action, this
- causes the window which appears to be focused to be
- the one on which the actions will be executed */
- keyboard_event((focus_cycle_target ?
- focus_cycle_target : client), e);
+ keyboard_event((focus_cycle_target ? focus_cycle_target :
+ (focus_hilite ? focus_hilite : client)),
+ e);
}
}
}
break;
case ClientMessage:
- if (e->xclient.format != 32) break;
-
- msgtype = e->xclient.message_type;
- if (msgtype == prop_atoms.net_current_desktop) {
- unsigned int d = e->xclient.data.l[0];
- if (d < screen_num_desktops)
- screen_set_desktop(d);
- } else if (msgtype == prop_atoms.net_number_of_desktops) {
- unsigned int d = e->xclient.data.l[0];
- if (d > 0)
- screen_set_num_desktops(d);
- } else if (msgtype == prop_atoms.net_showing_desktop) {
- screen_show_desktop(e->xclient.data.l[0] != 0);
- }
- break;
+ if (e->xclient.format != 32) break;
+
+ msgtype = e->xclient.message_type;
+ if (msgtype == prop_atoms.net_current_desktop) {
+ guint d = e->xclient.data.l[0];
+ if (d < screen_num_desktops)
+ screen_set_desktop(d);
+ } else if (msgtype == prop_atoms.net_number_of_desktops) {
+ guint d = e->xclient.data.l[0];
+ if (d > 0)
+ screen_set_num_desktops(d);
+ } else if (msgtype == prop_atoms.net_showing_desktop) {
+ screen_show_desktop(e->xclient.data.l[0] != 0);
+ }
+ break;
case PropertyNotify:
- if (e->xproperty.atom == prop_atoms.net_desktop_names)
- screen_update_desktop_names();
- else if (e->xproperty.atom == prop_atoms.net_desktop_layout)
- screen_update_layout();
- break;
+ if (e->xproperty.atom == prop_atoms.net_desktop_names)
+ screen_update_desktop_names();
+ else if (e->xproperty.atom == prop_atoms.net_desktop_layout)
+ screen_update_layout();
+ break;
case ConfigureNotify:
#ifdef XRANDR
XRRUpdateConfiguration(e);
{
XEvent ce;
Atom msgtype;
- int i=0;
+ gint i=0;
ObFrameContext con;
switch (e->type) {
break;
case FocusIn:
#ifdef DEBUG_FOCUS
- ob_debug("FocusIn on client for %lx\n", client->window);
+ ob_debug("FocusIn on client for %lx (client %lx) mode %d detail %d\n",
+ e->xfocus.window, client->window,
+ e->xfocus.mode, e->xfocus.detail);
#endif
if (client != focus_client) {
focus_set_client(client);
break;
case FocusOut:
#ifdef DEBUG_FOCUS
- ob_debug("FocusOut on client for %lx\n", client->window);
+ ob_debug("FocusOut on client for %lx (client %lx) mode %d detail %d\n",
+ e->xfocus.window, client->window,
+ e->xfocus.mode, e->xfocus.detail);
#endif
+ focus_hilite = NULL;
frame_adjust_focus(client->frame, FALSE);
client_calc_layer(client);
break;
frame_adjust_state(client->frame);
break;
case OB_FRAME_CONTEXT_FRAME:
- /*
if (config_focus_follow && config_focus_delay)
ob_main_loop_timeout_remove_data(ob_main_loop,
focus_delay_func,
client);
- */
break;
default:
break;
} else {
#ifdef DEBUG_FOCUS
ob_debug("%sNotify mode %d detail %d on %lx, "
- "focusing window\n",
+ "focusing window: %d\n",
(e->type == EnterNotify ? "Enter" : "Leave"),
e->xcrossing.mode,
- e->xcrossing.detail, client?client->window:0);
+ e->xcrossing.detail, (client?client->window:0),
+ !nofocus);
#endif
if (!nofocus && config_focus_follow)
event_enter_client(client);
break;
}
case ConfigureRequest:
- /* compress these */
- while (XCheckTypedWindowEvent(ob_display, client->window,
- ConfigureRequest, &ce)) {
+ /* compress these */
+ while (XCheckTypedWindowEvent(ob_display, client->window,
+ ConfigureRequest, &ce)) {
++i;
- /* XXX if this causes bad things.. we can compress config req's
- with the same mask. */
- e->xconfigurerequest.value_mask |=
- ce.xconfigurerequest.value_mask;
- if (ce.xconfigurerequest.value_mask & CWX)
- e->xconfigurerequest.x = ce.xconfigurerequest.x;
- if (ce.xconfigurerequest.value_mask & CWY)
- e->xconfigurerequest.y = ce.xconfigurerequest.y;
- if (ce.xconfigurerequest.value_mask & CWWidth)
- e->xconfigurerequest.width = ce.xconfigurerequest.width;
- if (ce.xconfigurerequest.value_mask & CWHeight)
- e->xconfigurerequest.height = ce.xconfigurerequest.height;
- if (ce.xconfigurerequest.value_mask & CWBorderWidth)
- e->xconfigurerequest.border_width =
- ce.xconfigurerequest.border_width;
- if (ce.xconfigurerequest.value_mask & CWStackMode)
- e->xconfigurerequest.detail = ce.xconfigurerequest.detail;
- }
-
- /* if we are iconic (or shaded (fvwm does this)) ignore the event */
- if (client->iconic || client->shaded) return;
-
- /* resize, then move, as specified in the EWMH section 7.7 */
- if (e->xconfigurerequest.value_mask & (CWWidth | CWHeight |
- CWX | CWY |
+ /* XXX if this causes bad things.. we can compress config req's
+ with the same mask. */
+ e->xconfigurerequest.value_mask |=
+ ce.xconfigurerequest.value_mask;
+ if (ce.xconfigurerequest.value_mask & CWX)
+ e->xconfigurerequest.x = ce.xconfigurerequest.x;
+ if (ce.xconfigurerequest.value_mask & CWY)
+ e->xconfigurerequest.y = ce.xconfigurerequest.y;
+ if (ce.xconfigurerequest.value_mask & CWWidth)
+ e->xconfigurerequest.width = ce.xconfigurerequest.width;
+ if (ce.xconfigurerequest.value_mask & CWHeight)
+ e->xconfigurerequest.height = ce.xconfigurerequest.height;
+ if (ce.xconfigurerequest.value_mask & CWBorderWidth)
+ e->xconfigurerequest.border_width =
+ ce.xconfigurerequest.border_width;
+ if (ce.xconfigurerequest.value_mask & CWStackMode)
+ e->xconfigurerequest.detail = ce.xconfigurerequest.detail;
+ }
+
+ /* if we are iconic (or shaded (fvwm does this)) ignore the event */
+ if (client->iconic || client->shaded) return;
+
+ /* resize, then move, as specified in the EWMH section 7.7 */
+ if (e->xconfigurerequest.value_mask & (CWWidth | CWHeight |
+ CWX | CWY |
CWBorderWidth)) {
- int x, y, w, h;
- ObCorner corner;
+ gint x, y, w, h;
+ ObCorner corner;
if (e->xconfigurerequest.value_mask & CWBorderWidth)
client->border_width = e->xconfigurerequest.border_width;
- x = (e->xconfigurerequest.value_mask & CWX) ?
- e->xconfigurerequest.x : client->area.x;
- y = (e->xconfigurerequest.value_mask & CWY) ?
- e->xconfigurerequest.y : client->area.y;
- w = (e->xconfigurerequest.value_mask & CWWidth) ?
- e->xconfigurerequest.width : client->area.width;
- h = (e->xconfigurerequest.value_mask & CWHeight) ?
- e->xconfigurerequest.height : client->area.height;
+ x = (e->xconfigurerequest.value_mask & CWX) ?
+ e->xconfigurerequest.x : client->area.x;
+ y = (e->xconfigurerequest.value_mask & CWY) ?
+ e->xconfigurerequest.y : client->area.y;
+ w = (e->xconfigurerequest.value_mask & CWWidth) ?
+ e->xconfigurerequest.width : client->area.width;
+ h = (e->xconfigurerequest.value_mask & CWHeight) ?
+ e->xconfigurerequest.height : client->area.height;
{
- int newx = x;
- int newy = y;
- int fw = w +
- client->frame->size.left + client->frame->size.right;
- int fh = h +
- client->frame->size.top + client->frame->size.bottom;
+ gint newx = x;
+ gint newy = y;
+ gint fw = w +
+ client->frame->size.left + client->frame->size.right;
+ gint fh = h +
+ client->frame->size.top + client->frame->size.bottom;
client_find_onscreen(client, &newx, &newy, fw, fh,
client_normal(client));
if (e->xconfigurerequest.value_mask & CWX)
if (e->xconfigurerequest.value_mask & CWY)
y = newy;
}
-
- switch (client->gravity) {
- case NorthEastGravity:
- case EastGravity:
- corner = OB_CORNER_TOPRIGHT;
- break;
- case SouthWestGravity:
- case SouthGravity:
- corner = OB_CORNER_BOTTOMLEFT;
- break;
- case SouthEastGravity:
- corner = OB_CORNER_BOTTOMRIGHT;
- break;
- default: /* NorthWest, Static, etc */
- corner = OB_CORNER_TOPLEFT;
- }
-
- client_configure_full(client, corner, x, y, w, h, FALSE, TRUE,
+
+ switch (client->gravity) {
+ case NorthEastGravity:
+ case EastGravity:
+ corner = OB_CORNER_TOPRIGHT;
+ break;
+ case SouthWestGravity:
+ case SouthGravity:
+ corner = OB_CORNER_BOTTOMLEFT;
+ break;
+ case SouthEastGravity:
+ corner = OB_CORNER_BOTTOMRIGHT;
+ break;
+ default: /* NorthWest, Static, etc */
+ corner = OB_CORNER_TOPLEFT;
+ }
+
+ client_configure_full(client, corner, x, y, w, h, FALSE, TRUE,
TRUE);
- }
-
- if (e->xconfigurerequest.value_mask & CWStackMode) {
- switch (e->xconfigurerequest.detail) {
- case Below:
- case BottomIf:
- stacking_lower(CLIENT_AS_WINDOW(client));
- break;
-
- case Above:
- case TopIf:
- default:
- stacking_raise(CLIENT_AS_WINDOW(client));
- break;
- }
- }
- break;
+ }
+
+ if (e->xconfigurerequest.value_mask & CWStackMode) {
+ switch (e->xconfigurerequest.detail) {
+ case Below:
+ case BottomIf:
+ client_lower(client);
+ break;
+
+ case Above:
+ case TopIf:
+ default:
+ client_raise(client);
+ break;
+ }
+ }
+ break;
case UnmapNotify:
- if (client->ignore_unmaps) {
- client->ignore_unmaps--;
- break;
- }
- client_unmanage(client);
- break;
+ if (client->ignore_unmaps) {
+ client->ignore_unmaps--;
+ break;
+ }
+ client_unmanage(client);
+ break;
case DestroyNotify:
- client_unmanage(client);
- break;
+ client_unmanage(client);
+ break;
case ReparentNotify:
- /* this is when the client is first taken captive in the frame */
- if (e->xreparent.parent == client->frame->plate) break;
-
- /*
- This event is quite rare and is usually handled in unmapHandler.
- However, if the window is unmapped when the reparent event occurs,
- the window manager never sees it because an unmap event is not sent
- to an already unmapped window.
- */
-
- /* we don't want the reparent event, put it back on the stack for the
- X server to deal with after we unmanage the window */
- XPutBackEvent(ob_display, e);
+ /* this is when the client is first taken captive in the frame */
+ if (e->xreparent.parent == client->frame->plate) break;
+
+ /*
+ This event is quite rare and is usually handled in unmapHandler.
+ However, if the window is unmapped when the reparent event occurs,
+ the window manager never sees it because an unmap event is not sent
+ to an already unmapped window.
+ */
+
+ /* we don't want the reparent event, put it back on the stack for the
+ X server to deal with after we unmanage the window */
+ XPutBackEvent(ob_display, e);
- client_unmanage(client);
- break;
+ client_unmanage(client);
+ break;
case MapRequest:
ob_debug("MapRequest for 0x%lx\n", client->window);
if (!client->iconic) break; /* this normally doesn't happen, but if it
- does, we don't want it! */
- if (screen_showing_desktop)
- screen_show_desktop(FALSE);
- client_iconify(client, FALSE, TRUE);
- if (!client->frame->visible)
- /* if its not visible still, then don't mess with it */
- break;
- if (client->shaded)
- client_shade(client, FALSE);
- client_focus(client);
- stacking_raise(CLIENT_AS_WINDOW(client));
- break;
+ does, we don't want it!
+ it can happen now when the window is on
+ another desktop, but we still don't
+ want it! */
+ client_activate(client, FALSE);
+ break;
case ClientMessage:
- /* validate cuz we query stuff off the client here */
- if (!client_validate(client)) break;
-
- if (e->xclient.format != 32) return;
-
- msgtype = e->xclient.message_type;
- if (msgtype == prop_atoms.wm_change_state) {
- /* compress changes into a single change */
- while (XCheckTypedWindowEvent(ob_display, client->window,
- e->type, &ce)) {
- /* XXX: it would be nice to compress ALL messages of a
- type, not just messages in a row without other
- message types between. */
- if (ce.xclient.message_type != msgtype) {
- XPutBackEvent(ob_display, &ce);
- break;
- }
- e->xclient = ce.xclient;
- }
- client_set_wm_state(client, e->xclient.data.l[0]);
- } else if (msgtype == prop_atoms.net_wm_desktop) {
- /* compress changes into a single change */
- while (XCheckTypedWindowEvent(ob_display, client->window,
- e->type, &ce)) {
- /* XXX: it would be nice to compress ALL messages of a
- type, not just messages in a row without other
- message types between. */
- if (ce.xclient.message_type != msgtype) {
- XPutBackEvent(ob_display, &ce);
- break;
- }
- e->xclient = ce.xclient;
- }
+ /* validate cuz we query stuff off the client here */
+ if (!client_validate(client)) break;
+
+ if (e->xclient.format != 32) return;
+
+ msgtype = e->xclient.message_type;
+ if (msgtype == prop_atoms.wm_change_state) {
+ /* compress changes into a single change */
+ while (XCheckTypedWindowEvent(ob_display, client->window,
+ e->type, &ce)) {
+ /* XXX: it would be nice to compress ALL messages of a
+ type, not just messages in a row without other
+ message types between. */
+ if (ce.xclient.message_type != msgtype) {
+ XPutBackEvent(ob_display, &ce);
+ break;
+ }
+ e->xclient = ce.xclient;
+ }
+ client_set_wm_state(client, e->xclient.data.l[0]);
+ } else if (msgtype == prop_atoms.net_wm_desktop) {
+ /* compress changes into a single change */
+ while (XCheckTypedWindowEvent(ob_display, client->window,
+ e->type, &ce)) {
+ /* XXX: it would be nice to compress ALL messages of a
+ type, not just messages in a row without other
+ message types between. */
+ if (ce.xclient.message_type != msgtype) {
+ XPutBackEvent(ob_display, &ce);
+ break;
+ }
+ e->xclient = ce.xclient;
+ }
if ((unsigned)e->xclient.data.l[0] < screen_num_desktops ||
(unsigned)e->xclient.data.l[0] == DESKTOP_ALL)
client_set_desktop(client, (unsigned)e->xclient.data.l[0],
FALSE);
- } else if (msgtype == prop_atoms.net_wm_state) {
- /* can't compress these */
- ob_debug("net_wm_state %s %ld %ld for 0x%lx\n",
+ } else if (msgtype == prop_atoms.net_wm_state) {
+ /* can't compress these */
+ ob_debug("net_wm_state %s %ld %ld for 0x%lx\n",
(e->xclient.data.l[0] == 0 ? "Remove" :
e->xclient.data.l[0] == 1 ? "Add" :
e->xclient.data.l[0] == 2 ? "Toggle" : "INVALID"),
e->xclient.data.l[1], e->xclient.data.l[2],
client->window);
- client_set_state(client, e->xclient.data.l[0],
- e->xclient.data.l[1], e->xclient.data.l[2]);
- } else if (msgtype == prop_atoms.net_close_window) {
- ob_debug("net_close_window for 0x%lx\n", client->window);
- client_close(client);
- } else if (msgtype == prop_atoms.net_active_window) {
- ob_debug("net_active_window for 0x%lx\n", client->window);
+ client_set_state(client, e->xclient.data.l[0],
+ e->xclient.data.l[1], e->xclient.data.l[2]);
+ } else if (msgtype == prop_atoms.net_close_window) {
+ ob_debug("net_close_window for 0x%lx\n", client->window);
+ client_close(client);
+ } else if (msgtype == prop_atoms.net_active_window) {
+ ob_debug("net_active_window for 0x%lx\n", client->window);
client_activate(client, FALSE);
- } else if (msgtype == prop_atoms.net_wm_moveresize) {
- ob_debug("net_wm_moveresize for 0x%lx\n", client->window);
+ } else if (msgtype == prop_atoms.net_wm_moveresize) {
+ ob_debug("net_wm_moveresize for 0x%lx\n", client->window);
if ((Atom)e->xclient.data.l[2] ==
prop_atoms.net_wm_moveresize_size_topleft ||
(Atom)e->xclient.data.l[2] ==
e->xclient.data.l[2]);
}
} else if (msgtype == prop_atoms.net_moveresize_window) {
- int oldg = client->gravity;
- int tmpg, x, y, w, h;
+ gint oldg = client->gravity;
+ gint tmpg, x, y, w, h;
if (e->xclient.data.l[0] & 0xff)
tmpg = e->xclient.data.l[0] & 0xff;
client->gravity = tmpg;
{
- int newx = x;
- int newy = y;
- int fw = w +
- client->frame->size.left + client->frame->size.right;
- int fh = h +
- client->frame->size.top + client->frame->size.bottom;
+ gint newx = x;
+ gint newy = y;
+ gint fw = w +
+ client->frame->size.left + client->frame->size.right;
+ gint fh = h +
+ client->frame->size.top + client->frame->size.bottom;
client_find_onscreen(client, &newx, &newy, fw, fh,
client_normal(client));
if (e->xclient.data.l[0] & 1 << 8)
if (e->xclient.data.l[0] & 1 << 9)
y = newy;
}
-
+
client_configure(client, OB_CORNER_TOPLEFT,
x, y, w, h, FALSE, TRUE);
client->gravity = oldg;
}
- break;
+ break;
case PropertyNotify:
- /* validate cuz we query stuff off the client here */
- if (!client_validate(client)) break;
+ /* validate cuz we query stuff off the client here */
+ if (!client_validate(client)) break;
- /* compress changes to a single property into a single change */
- while (XCheckTypedWindowEvent(ob_display, client->window,
- e->type, &ce)) {
+ /* compress changes to a single property into a single change */
+ while (XCheckTypedWindowEvent(ob_display, client->window,
+ e->type, &ce)) {
Atom a, b;
/* XXX: it would be nice to compress ALL changes to a property,
- not just changes in a row without other props between. */
+ not just changes in a row without other props between. */
a = ce.xproperty.atom;
b = e->xproperty.atom;
XPutBackEvent(ob_display, &ce);
break;
- }
-
- msgtype = e->xproperty.atom;
- if (msgtype == XA_WM_NORMAL_HINTS) {
- client_update_normal_hints(client);
- /* normal hints can make a window non-resizable */
- client_setup_decor_and_functions(client);
- } else if (msgtype == XA_WM_HINTS) {
- client_update_wmhints(client);
- } else if (msgtype == XA_WM_TRANSIENT_FOR) {
- client_update_transient_for(client);
- client_get_type(client);
- /* type may have changed, so update the layer */
- client_calc_layer(client);
- client_setup_decor_and_functions(client);
- } else if (msgtype == prop_atoms.net_wm_name ||
+ }
+
+ msgtype = e->xproperty.atom;
+ if (msgtype == XA_WM_NORMAL_HINTS) {
+ client_update_normal_hints(client);
+ /* normal hints can make a window non-resizable */
+ client_setup_decor_and_functions(client);
+ } else if (msgtype == XA_WM_HINTS) {
+ client_update_wmhints(client);
+ } else if (msgtype == XA_WM_TRANSIENT_FOR) {
+ client_update_transient_for(client);
+ client_get_type(client);
+ /* type may have changed, so update the layer */
+ client_calc_layer(client);
+ client_setup_decor_and_functions(client);
+ } else if (msgtype == prop_atoms.net_wm_name ||
msgtype == prop_atoms.wm_name ||
msgtype == prop_atoms.net_wm_icon_name ||
msgtype == prop_atoms.wm_icon_name) {
- client_update_title(client);
- } else if (msgtype == prop_atoms.wm_class) {
- client_update_class(client);
+ client_update_title(client);
+ } else if (msgtype == prop_atoms.wm_class) {
+ client_update_class(client);
} else if (msgtype == prop_atoms.wm_protocols) {
- client_update_protocols(client);
- client_setup_decor_and_functions(client);
- }
- else if (msgtype == prop_atoms.net_wm_strut) {
- client_update_strut(client);
+ client_update_protocols(client);
+ client_setup_decor_and_functions(client);
}
- else if (msgtype == prop_atoms.net_wm_icon ||
+ else if (msgtype == prop_atoms.net_wm_strut) {
+ client_update_strut(client);
+ }
+ else if (msgtype == prop_atoms.net_wm_icon ||
msgtype == prop_atoms.kwm_win_icon) {
- client_update_icons(client);
+ client_update_icons(client);
}
else if (msgtype == prop_atoms.sm_client_id) {
client_update_sm_client_id(client);
{
switch (e->type) {
case ButtonPress:
- stacking_raise(DOCK_AS_WINDOW(s));
+ if (e->xbutton.button == 1)
+ stacking_raise(DOCK_AS_WINDOW(s), FALSE);
+ else if (e->xbutton.button == 2)
+ stacking_lower(DOCK_AS_WINDOW(s), FALSE);
break;
case EnterNotify:
dock_hide(FALSE);
dock_app_drag(app, &e->xmotion);
break;
case UnmapNotify:
- if (app->ignore_unmaps) {
- app->ignore_unmaps--;
- break;
- }
- dock_remove(app, TRUE);
- break;
+ if (app->ignore_unmaps) {
+ app->ignore_unmaps--;
+ break;
+ }
+ dock_remove(app, TRUE);
+ break;
case DestroyNotify:
- dock_remove(app, FALSE);
- break;
+ dock_remove(app, FALSE);
+ break;
case ReparentNotify:
- dock_remove(app, FALSE);
- break;
+ dock_remove(app, FALSE);
+ break;
case ConfigureNotify:
dock_app_configure(app, e->xconfigure.width, e->xconfigure.height);
break;
ObMenuFrame* find_active_menu()
{
GList *it;
- ObMenuFrame *f;
+ ObMenuFrame *ret = NULL;
for (it = menu_frame_visible; it; it = g_list_next(it)) {
- f = it->data;
- if (f->selected)
+ ret = it->data;
+ if (ret->selected)
break;
+ ret = NULL;
}
- return it ? it->data : NULL;
+ return ret;
+}
+
+ObMenuFrame* find_active_or_last_menu()
+{
+ ObMenuFrame *ret = NULL;
+
+ ret = find_active_menu();
+ if (!ret && menu_frame_visible)
+ ret = menu_frame_visible->data;
+ return ret;
}
static void event_handle_menu(XEvent *ev)
switch (ev->type) {
case ButtonRelease:
- if ((e = menu_entry_frame_under(ev->xbutton.x_root,
- ev->xbutton.y_root)))
- menu_entry_frame_execute(e, ev->xbutton.state);
- else if (menu_can_hide)
- menu_frame_hide_all();
+ if (menu_can_hide) {
+ if ((e = menu_entry_frame_under(ev->xbutton.x_root,
+ ev->xbutton.y_root)))
+ menu_entry_frame_execute(e, ev->xbutton.state);
+ else
+ menu_frame_hide_all();
+ }
break;
case MotionNotify:
if ((f = menu_frame_under(ev->xmotion.x_root,
menu_entry_frame_execute(f->selected, ev->xkey.state);
} else if (ev->xkey.keycode == ob_keycode(OB_KEY_LEFT)) {
ObMenuFrame *f;
- if ((f = find_active_menu()) && f->parent)
+ if ((f = find_active_or_last_menu()) && f->parent)
menu_frame_select(f, NULL);
} else if (ev->xkey.keycode == ob_keycode(OB_KEY_RIGHT)) {
ObMenuFrame *f;
- if ((f = find_active_menu()) && f->child)
+ if ((f = find_active_or_last_menu()) && f->child)
menu_frame_select_next(f->child);
} else if (ev->xkey.keycode == ob_keycode(OB_KEY_UP)) {
ObMenuFrame *f;
- if ((f = find_active_menu()))
+ if ((f = find_active_or_last_menu()))
menu_frame_select_previous(f);
} else if (ev->xkey.keycode == ob_keycode(OB_KEY_DOWN)) {
ObMenuFrame *f;
- if ((f = find_active_menu()))
+ if ((f = find_active_or_last_menu()))
menu_frame_select_next(f);
}
break;
{
ObClient *c = data;
- client_focus(c);
- if (config_focus_raise)
- stacking_raise(CLIENT_AS_WINDOW(c));
+ if (focus_client != c) {
+ client_focus(c);
+ if (config_focus_raise)
+ client_raise(c);
+ }
return FALSE; /* no repeat */
}
-static void focus_delay_client_dest(gpointer data)
+static void focus_delay_client_dest(ObClient *client, gpointer data)
{
- ObClient *c = data;
+ ob_main_loop_timeout_remove_data(ob_main_loop, focus_delay_func, client);
+}
+
+static void event_client_dest(ObClient *client, gpointer data)
+{
+ if (client == focus_hilite)
+ focus_hilite = NULL;
+}
- ob_main_loop_timeout_remove_data(ob_main_loop, focus_delay_func, c);
+void event_halt_focus_delay()
+{
+ ob_main_loop_timeout_remove(ob_main_loop, focus_delay_func);
}
void event_ignore_queued_enters()
while (TRUE) {
e = g_new(XEvent, 1);
if (XCheckTypedEvent(ob_display, EnterNotify, e)) {
+ ObWindow *win;
+
+ win = g_hash_table_lookup(window_map, &e->xany.window);
+ if (win && WINDOW_IS_CLIENT(win))
+ ++ignore_enter_focus;
+
saved = g_slist_append(saved, e);
- ++ignore_enter_focus;
} else {
g_free(e);
break;