static void event_handle_dockapp(ObDockApp *app, XEvent *e);
static void event_handle_client(ObClient *c, XEvent *e);
static void event_handle_group(ObGroup *g, XEvent *e);
+static void event_handle_user_input(ObClient *client, XEvent *e);
static void focus_delay_dest(gpointer data);
static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2);
/* This means focus moved from one client to another */
if (detail == NotifyNonlinearVirtual)
return TRUE;
+ /* This means focus moved to the frame window */
+ if (detail == NotifyInferior)
+ return TRUE;
/* Otherwise.. */
return FALSE;
}
#endif
- /* user input (action-bound) events */
if (e->type == ButtonPress || e->type == ButtonRelease ||
e->type == MotionNotify || e->type == KeyPress ||
e->type == KeyRelease)
{
- gboolean useevent = TRUE;
-
- if (menu_frame_visible) {
- if (event_handle_menu(e))
- /* don't use the event if the menu used it, but if the menu
- didn't use it and it's a keypress that is bound, it will
- close the menu and be used */
- useevent = FALSE;
- }
-
- if (useevent) {
- /* if the keyboard interactive action uses the event then dont
- use it for bindings. likewise is moveresize uses the event. */
- if (!keyboard_process_interactive_grab(e, &client) &&
- !(moveresize_in_progress && moveresize_event(e)))
- {
- if (moveresize_in_progress)
- /* make further actions work on the client being
- moved/resized */
- client = moveresize_client;
-
-
- menu_can_hide = FALSE;
- ob_main_loop_timeout_add(ob_main_loop,
- config_menu_hide_delay * 1000,
- menu_hide_delay_func,
- NULL, g_direct_equal, NULL);
-
- if (e->type == ButtonPress || e->type == ButtonRelease ||
- e->type == MotionNotify) {
- mouse_event(client, e);
- } else if (e->type == KeyPress) {
- keyboard_event((focus_cycle_target ? focus_cycle_target :
- (client ? client : focus_client)), e);
- }
- }
- }
+ event_handle_user_input(client, e);
}
+
/* if something happens and it's not from an XEvent, then we don't know
the time */
event_curtime = CurrentTime;
guint d = e->xclient.data.l[0];
if (d < screen_num_desktops) {
event_curtime = e->xclient.data.l[1];
- ob_debug("SWITCH DESKTOP TIME: %d\n", event_curtime);
+ if (event_curtime == 0)
+ ob_debug_type(OB_DEBUG_APP_BUGS,
+ "_NET_CURRENT_DESKTOP message is missing "
+ "a timestamp\n");
screen_set_desktop(d);
}
} else if (msgtype == prop_atoms.net_number_of_desktops) {
screen_set_num_desktops(d);
} else if (msgtype == prop_atoms.net_showing_desktop) {
screen_show_desktop(e->xclient.data.l[0] != 0, TRUE);
- } else if (msgtype == prop_atoms.ob_control) {
+ } else if (msgtype == prop_atoms.openbox_control) {
if (e->xclient.data.l[0] == 1)
ob_reconfigure();
else if (e->xclient.data.l[0] == 2)
{
XEvent ce;
Atom msgtype;
- gint i=0;
ObFrameContext con;
switch (e->type) {
frame_adjust_state(client->frame);
break;
case OB_FRAME_CONTEXT_FRAME:
+ /* When the mouse leaves an animating window, don't use the
+ corresponding enter events. Pretend like the animating window
+ doesn't even exist..! */
+ if (frame_iconify_animating(client->frame))
+ event_ignore_queued_enters();
+
ob_debug_type(OB_DEBUG_FOCUS,
"%sNotify mode %d detail %d on %lx\n",
(e->type == EnterNotify ? "Enter" : "Leave"),
break;
}
case ConfigureRequest:
- /* 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;
- }
+ /* dont compress these unless you're going to watch for property
+ notifies in between (these can change what the configure would
+ do to the window).
+ also you can't compress stacking events
+ */
- /* if we are iconic (or shaded (fvwm does this)) ignore the event */
- if (client->iconic || client->shaded) return;
+ ob_debug("ConfigureRequest desktop %d wmstate %d vis %d\n",
+ screen_desktop, client->wmstate, client->frame->visible);
+
+ /* don't allow clients to move shaded windows (fvwm does this) */
+ if (client->shaded) {
+ e->xconfigurerequest.value_mask &= ~CWX;
+ e->xconfigurerequest.value_mask &= ~CWY;
+ }
/* resize, then move, as specified in the EWMH section 7.7 */
if (e->xconfigurerequest.value_mask & (CWWidth | CWHeight |
e->xconfigurerequest.value_mask & CWX, x,
e->xconfigurerequest.value_mask & CWY, y);
+ /* check for broken apps moving to their root position
+
+ XXX remove this some day...that would be nice. right now all
+ kde apps do this when they try activate themselves on another
+ desktop. eg. open amarok window on desktop 1, switch to desktop
+ 2, click amarok tray icon. it will move by its decoration size.
+ */
+ if (x != client->area.x &&
+ x == (client->frame->area.x + client->frame->size.left -
+ (gint)client->border_width) &&
+ y != client->area.y &&
+ y == (client->frame->area.y + client->frame->size.top -
+ (gint)client->border_width))
+ {
+ ob_debug_type(OB_DEBUG_APP_BUGS,
+ "Application %s is trying to move via "
+ "ConfigureRequest to it's root window position "
+ "but it is not using StaticGravity\n",
+ client->title);
+ /* don't move it */
+ x = client->area.x;
+ y = client->area.y;
+ }
+
client_find_onscreen(client, &x, &y, w, h, FALSE);
client_configure_full(client, x, y, w, h, FALSE, TRUE, TRUE);
}
(e->xclient.data.l[0] == 0 ? "unknown" :
(e->xclient.data.l[0] == 1 ? "application" :
(e->xclient.data.l[0] == 2 ? "user" : "INVALID"))));
- /* XXX make use of data.l[2] ! */
+ /* XXX make use of data.l[2] !? */
event_curtime = e->xclient.data.l[1];
+ ob_debug_type(OB_DEBUG_APP_BUGS,
+ "_NET_ACTIVE_WINDOW message for window %s is "
+ "missing a timestamp\n", client->title);
client_activate(client, FALSE,
(e->xclient.data.l[0] == 0 ||
e->xclient.data.l[0] == 2));
else if (msgtype == prop_atoms.net_wm_icon) {
client_update_icons(client);
}
+ else if (msgtype == prop_atoms.net_wm_icon_geometry) {
+ client_update_icon_geometry(client);
+ }
else if (msgtype == prop_atoms.net_wm_user_time) {
client_update_user_time(client);
}
ObMenuEntryFrame *e = it->data;
gunichar entrykey = 0;
- if (e->entry->type == OB_MENU_ENTRY_TYPE_NORMAL &&
- e->entry->data.normal.enabled)
+ if (e->entry->type == OB_MENU_ENTRY_TYPE_NORMAL)
entrykey = e->entry->data.normal.shortcut;
else if (e->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU)
entrykey = e->entry->data.submenu.submenu->shortcut;
num_found == 1)
{
menu_frame_select(frame, found, TRUE);
- usleep(50000);
+ usleep(50000); /* highlight the item for a short bit so the
+ user can see what happened */
menu_entry_frame_execute(found, state, ev->xkey.time);
} else {
menu_frame_select(frame, found, TRUE);
return ret;
}
+static void event_handle_user_input(ObClient *client, XEvent *e)
+{
+ g_assert(e->type == ButtonPress || e->type == ButtonRelease ||
+ e->type == MotionNotify || e->type == KeyPress ||
+ e->type == KeyRelease);
+
+ if (menu_frame_visible) {
+ if (event_handle_menu(e))
+ /* don't use the event if the menu used it, but if the menu
+ didn't use it and it's a keypress that is bound, it will
+ close the menu and be used */
+ return;
+ }
+
+ /* if the keyboard interactive action uses the event then dont
+ use it for bindings. likewise is moveresize uses the event. */
+ if (!keyboard_process_interactive_grab(e, &client) &&
+ !(moveresize_in_progress && moveresize_event(e)))
+ {
+ if (moveresize_in_progress)
+ /* make further actions work on the client being
+ moved/resized */
+ client = moveresize_client;
+
+ menu_can_hide = FALSE;
+ ob_main_loop_timeout_add(ob_main_loop,
+ config_menu_hide_delay * 1000,
+ menu_hide_delay_func,
+ NULL, g_direct_equal, NULL);
+
+ if (e->type == ButtonPress ||
+ e->type == ButtonRelease ||
+ e->type == MotionNotify)
+ {
+ /* the frame may not be "visible" but they can still click on it
+ in the case where it is animating before disappearing */
+ if (!client || !frame_iconify_animating(client->frame))
+ mouse_event(client, e);
+ } else if (e->type == KeyPress) {
+ keyboard_event((focus_cycle_target ? focus_cycle_target :
+ (client ? client : focus_client)), e);
+ }
+ }
+}
+
static gboolean menu_hide_delay_func(gpointer data)
{
menu_can_hide = TRUE;