display: Split out input event handling

This helps with git's diff code by moving all the giant indentation
changes, letting us know what's going on better when we move to
Clutter for event handling.
This commit is contained in:
Jasper St. Pierre 2013-10-03 15:23:24 -04:00
parent 9c0cc664d1
commit 58f6ab0a27

View File

@ -178,6 +178,8 @@ static gboolean event_callback (XEvent *event,
gpointer data);
static Window event_get_modified_window (MetaDisplay *display,
XEvent *event);
static Window xievent_get_modified_window (MetaDisplay *display,
XIEvent *input_event);
static guint32 event_get_time (MetaDisplay *display,
XEvent *event);
static void process_request_frame_extents (MetaDisplay *display,
@ -2191,230 +2193,23 @@ handle_window_focus_event (MetaDisplay *display,
}
}
static void
reload_xkb_rules (MetaScreen *screen)
static gboolean
handle_input_xevent (MetaDisplay *display,
XIEvent *input_event,
gulong serial)
{
MetaWaylandCompositor *compositor;
char **names;
int n_names;
gboolean ok;
const char *rules, *model, *layout, *variant, *options;
compositor = meta_wayland_compositor_get_default ();
ok = meta_prop_get_latin1_list (screen->display, screen->xroot,
screen->display->atom__XKB_RULES_NAMES,
&names, &n_names);
if (!ok)
return;
if (n_names != 5)
goto out;
rules = names[0];
model = names[1];
layout = names[2];
variant = names[3];
options = names[4];
meta_wayland_keyboard_set_keymap_names (&compositor->seat->keyboard,
rules, model, layout, variant, options,
META_WAYLAND_KEYBOARD_SKIP_XCLIENTS);
out:
g_strfreev (names);
}
/**
* meta_display_handle_xevent:
* @display: The MetaDisplay that events are coming from
* @event: The event that just happened
*
* This is the most important function in the whole program. It is the heart,
* it is the nexus, it is the Grand Central Station of Mutter's world.
* When we create a #MetaDisplay, we ask GDK to pass *all* events for *all*
* windows to this function. So every time anything happens that we might
* want to know about, this function gets called. You see why it gets a bit
* busy around here. Most of this function is a ginormous switch statement
* dealing with all the kinds of events that might turn up.
*/
gboolean
meta_display_handle_xevent (MetaDisplay *display,
XEvent *event)
{
MetaWindow *window;
MetaWindow *property_for_window;
Window modified;
gboolean frame_was_receiver;
gboolean bypass_compositor = FALSE, bypass_gtk = FALSE;
XIEvent *input_event;
MetaMonitorManager *monitor;
MetaScreen *screen;
#ifdef WITH_VERBOSE_MODE
if (dump_events)
meta_spew_event (display, event);
#endif
#ifdef HAVE_STARTUP_NOTIFICATION
sn_display_process_event (display->sn_display, event);
#endif
/* Intercept XRandR events early and don't attempt any
processing for them. We still let them through to Gdk though,
so it can update its own internal state.
*/
monitor = meta_monitor_manager_get ();
if (meta_monitor_manager_handle_xevent (monitor, event))
{
bypass_compositor = TRUE;
goto out;
}
display->current_time = event_get_time (display, event);
display->monitor_cache_invalidated = TRUE;
if (event->xany.serial > display->focus_serial &&
display->focus_window &&
display->focus_window->xwindow != display->server_focus_window)
{
meta_topic (META_DEBUG_FOCUS, "Earlier attempt to focus %s failed\n",
display->focus_window->desc);
update_focus_window (display,
META_FOCUS_NONE,
meta_display_lookup_x_window (display, display->server_focus_window),
display->server_focus_window,
display->server_focus_serial);
}
screen = meta_display_screen_for_root (display, event->xany.window);
if (screen)
{
if (meta_screen_handle_xevent (screen, event))
{
bypass_gtk = bypass_compositor = TRUE;
goto out;
}
}
modified = event_get_modified_window (display, event);
input_event = get_input_event (display, event);
if (event->type == UnmapNotify)
{
if (meta_ui_window_should_not_cause_focus (display->xdisplay,
modified))
{
meta_display_add_ignored_crossing_serial (display, event->xany.serial);
meta_topic (META_DEBUG_FOCUS,
"Adding EnterNotify serial %lu to ignored focus serials\n",
event->xany.serial);
}
}
else if (input_event &&
input_event->evtype == XI_Leave &&
((XILeaveEvent *)input_event)->mode == XINotifyUngrab &&
modified == display->ungrab_should_not_cause_focus_window)
{
meta_display_add_ignored_crossing_serial (display, event->xany.serial);
meta_topic (META_DEBUG_FOCUS,
"Adding LeaveNotify serial %lu to ignored focus serials\n",
event->xany.serial);
}
if (modified != None)
window = meta_display_lookup_x_window (display, modified);
else
window = NULL;
/* We only want to respond to _NET_WM_USER_TIME property notify
* events on _NET_WM_USER_TIME_WINDOW windows; in particular,
* responding to UnmapNotify events is kind of bad.
*/
property_for_window = NULL;
if (window && modified == window->user_time_window)
{
property_for_window = window;
window = NULL;
}
frame_was_receiver = FALSE;
if (window &&
window->frame &&
modified == window->frame->xwindow)
{
/* Note that if the frame and the client both have an
* XGrabButton (as is normal with our setup), the event
* goes to the frame.
*/
frame_was_receiver = TRUE;
meta_topic (META_DEBUG_EVENTS, "Frame was receiver of event for %s\n",
window->desc);
}
#ifdef HAVE_XSYNC
if (META_DISPLAY_HAS_XSYNC (display) &&
event->type == (display->xsync_event_base + XSyncAlarmNotify))
{
MetaWindow *alarm_window = meta_display_lookup_sync_alarm (display,
((XSyncAlarmNotifyEvent*)event)->alarm);
if (alarm_window != NULL)
{
XSyncValue value = ((XSyncAlarmNotifyEvent*)event)->counter_value;
gint64 new_counter_value;
new_counter_value = XSyncValueLow32 (value) + ((gint64)XSyncValueHigh32 (value) << 32);
meta_window_update_sync_request_counter (alarm_window, new_counter_value);
bypass_gtk = TRUE; /* GTK doesn't want to see this really */
}
else
meta_idle_monitor_handle_xevent_all (event);
goto out;
}
#endif /* HAVE_XSYNC */
#ifdef HAVE_SHAPE
if (META_DISPLAY_HAS_SHAPE (display) &&
event->type == (display->shape_event_base + ShapeNotify))
{
bypass_gtk = TRUE; /* GTK doesn't want to see this really */
if (window && !frame_was_receiver)
{
XShapeEvent *sev = (XShapeEvent*) event;
if (sev->kind == ShapeBounding)
meta_window_update_shape_region_x11 (window);
else if (sev->kind == ShapeInput)
meta_window_update_input_region_x11 (window);
}
else
{
meta_topic (META_DEBUG_SHAPES,
"ShapeNotify not on a client window (window %s frame_was_receiver = %d)\n",
window ? window->desc : "(none)",
frame_was_receiver);
}
goto out;
}
#endif /* HAVE_SHAPE */
#ifdef HAVE_XI23
if (meta_display_process_barrier_event (display, input_event))
{
bypass_gtk = bypass_compositor = TRUE;
goto out;
}
#endif /* HAVE_XI23 */
if (input_event != NULL)
{
XIDeviceEvent *device_event = (XIDeviceEvent *) input_event;
XIEnterEvent *enter_event = (XIEnterEvent *) input_event;
Window modified;
MetaWindow *window;
gboolean frame_was_receiver;
if (input_event == NULL)
return FALSE;
modified = xievent_get_modified_window (display, input_event);
window = modified != None ? meta_display_lookup_x_window (display, modified) : NULL;
frame_was_receiver = (window && window->frame && modified == window->frame->xwindow);
if (window && !window->override_redirect &&
((input_event->type == XI_KeyPress) || (input_event->type == XI_ButtonPress)))
@ -2448,7 +2243,7 @@ meta_display_handle_xevent (MetaDisplay *display,
* want to pass the key event to the compositor or GTK+ at all.
*/
if (meta_display_process_key_event (display, window, (XIDeviceEvent *) input_event))
bypass_gtk = bypass_compositor = TRUE;
return TRUE;
break;
case XI_ButtonPress:
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
@ -2671,7 +2466,7 @@ meta_display_handle_xevent (MetaDisplay *display,
/* Check if we've entered a window; do this even if window->has_focus to
* avoid races.
*/
if (window && !crossing_serial_is_ignored (display, event->xany.serial) &&
if (window && !crossing_serial_is_ignored (display, serial) &&
enter_event->mode != XINotifyGrab &&
enter_event->mode != XINotifyUngrab &&
enter_event->detail != XINotifyInferior &&
@ -2689,7 +2484,7 @@ meta_display_handle_xevent (MetaDisplay *display,
"enter notify with serial %lu at time %lu, "
"and setting display->mouse_mode to TRUE.\n",
window->desc,
event->xany.serial,
serial,
enter_event->time);
if (meta_prefs_get_focus_change_on_pointer_rest())
@ -2727,11 +2522,7 @@ meta_display_handle_xevent (MetaDisplay *display,
break;
case XI_FocusIn:
case XI_FocusOut:
/* libXi does not properly copy the serial to the XIEnterEvent, so pull it
* from the parent XAnyEvent.
* See: https://bugs.freedesktop.org/show_bug.cgi?id=64687
*/
handle_window_focus_event (display, window, enter_event, event->xany.serial);
handle_window_focus_event (display, window, enter_event, serial);
if (!window)
{
/* Check if the window is a root window. */
@ -2768,6 +2559,237 @@ meta_display_handle_xevent (MetaDisplay *display,
}
break;
}
return FALSE;
}
static void
reload_xkb_rules (MetaScreen *screen)
{
MetaWaylandCompositor *compositor;
char **names;
int n_names;
gboolean ok;
const char *rules, *model, *layout, *variant, *options;
compositor = meta_wayland_compositor_get_default ();
ok = meta_prop_get_latin1_list (screen->display, screen->xroot,
screen->display->atom__XKB_RULES_NAMES,
&names, &n_names);
if (!ok)
return;
if (n_names != 5)
goto out;
rules = names[0];
model = names[1];
layout = names[2];
variant = names[3];
options = names[4];
meta_wayland_keyboard_set_keymap_names (&compositor->seat->keyboard,
rules, model, layout, variant, options,
META_WAYLAND_KEYBOARD_SKIP_XCLIENTS);
out:
g_strfreev (names);
}
/**
* meta_display_handle_xevent:
* @display: The MetaDisplay that events are coming from
* @event: The event that just happened
*
* This is the most important function in the whole program. It is the heart,
* it is the nexus, it is the Grand Central Station of Mutter's world.
* When we create a #MetaDisplay, we ask GDK to pass *all* events for *all*
* windows to this function. So every time anything happens that we might
* want to know about, this function gets called. You see why it gets a bit
* busy around here. Most of this function is a ginormous switch statement
* dealing with all the kinds of events that might turn up.
*/
gboolean
meta_display_handle_xevent (MetaDisplay *display,
XEvent *event)
{
MetaWindow *window;
MetaWindow *property_for_window;
Window modified;
gboolean frame_was_receiver;
gboolean bypass_compositor = FALSE, bypass_gtk = FALSE;
XIEvent *input_event;
MetaMonitorManager *monitor;
MetaScreen *screen;
#ifdef WITH_VERBOSE_MODE
if (dump_events)
meta_spew_event (display, event);
#endif
#ifdef HAVE_STARTUP_NOTIFICATION
sn_display_process_event (display->sn_display, event);
#endif
/* Intercept XRandR events early and don't attempt any
processing for them. We still let them through to Gdk though,
so it can update its own internal state.
*/
monitor = meta_monitor_manager_get ();
if (meta_monitor_manager_handle_xevent (monitor, event))
{
bypass_compositor = TRUE;
goto out;
}
display->current_time = event_get_time (display, event);
display->monitor_cache_invalidated = TRUE;
if (event->xany.serial > display->focus_serial &&
display->focus_window &&
display->focus_window->xwindow != display->server_focus_window)
{
meta_topic (META_DEBUG_FOCUS, "Earlier attempt to focus %s failed\n",
display->focus_window->desc);
update_focus_window (display,
META_FOCUS_NONE,
meta_display_lookup_x_window (display, display->server_focus_window),
display->server_focus_window,
display->server_focus_serial);
}
screen = meta_display_screen_for_root (display, event->xany.window);
if (screen)
{
if (meta_screen_handle_xevent (screen, event))
{
bypass_gtk = bypass_compositor = TRUE;
goto out;
}
}
modified = event_get_modified_window (display, event);
input_event = get_input_event (display, event);
if (event->type == UnmapNotify)
{
if (meta_ui_window_should_not_cause_focus (display->xdisplay,
modified))
{
meta_display_add_ignored_crossing_serial (display, event->xany.serial);
meta_topic (META_DEBUG_FOCUS,
"Adding EnterNotify serial %lu to ignored focus serials\n",
event->xany.serial);
}
}
else if (input_event &&
input_event->evtype == XI_Leave &&
((XILeaveEvent *)input_event)->mode == XINotifyUngrab &&
modified == display->ungrab_should_not_cause_focus_window)
{
meta_display_add_ignored_crossing_serial (display, event->xany.serial);
meta_topic (META_DEBUG_FOCUS,
"Adding LeaveNotify serial %lu to ignored focus serials\n",
event->xany.serial);
}
if (modified != None)
window = meta_display_lookup_x_window (display, modified);
else
window = NULL;
/* We only want to respond to _NET_WM_USER_TIME property notify
* events on _NET_WM_USER_TIME_WINDOW windows; in particular,
* responding to UnmapNotify events is kind of bad.
*/
property_for_window = NULL;
if (window && modified == window->user_time_window)
{
property_for_window = window;
window = NULL;
}
frame_was_receiver = FALSE;
if (window &&
window->frame &&
modified == window->frame->xwindow)
{
/* Note that if the frame and the client both have an
* XGrabButton (as is normal with our setup), the event
* goes to the frame.
*/
frame_was_receiver = TRUE;
meta_topic (META_DEBUG_EVENTS, "Frame was receiver of event for %s\n",
window->desc);
}
#ifdef HAVE_XSYNC
if (META_DISPLAY_HAS_XSYNC (display) &&
event->type == (display->xsync_event_base + XSyncAlarmNotify))
{
MetaWindow *alarm_window = meta_display_lookup_sync_alarm (display,
((XSyncAlarmNotifyEvent*)event)->alarm);
if (alarm_window != NULL)
{
XSyncValue value = ((XSyncAlarmNotifyEvent*)event)->counter_value;
gint64 new_counter_value;
new_counter_value = XSyncValueLow32 (value) + ((gint64)XSyncValueHigh32 (value) << 32);
meta_window_update_sync_request_counter (alarm_window, new_counter_value);
bypass_gtk = TRUE; /* GTK doesn't want to see this really */
}
else
meta_idle_monitor_handle_xevent_all (event);
goto out;
}
#endif /* HAVE_XSYNC */
#ifdef HAVE_SHAPE
if (META_DISPLAY_HAS_SHAPE (display) &&
event->type == (display->shape_event_base + ShapeNotify))
{
bypass_gtk = TRUE; /* GTK doesn't want to see this really */
if (window && !frame_was_receiver)
{
XShapeEvent *sev = (XShapeEvent*) event;
if (sev->kind == ShapeBounding)
meta_window_update_shape_region_x11 (window);
else if (sev->kind == ShapeInput)
meta_window_update_input_region_x11 (window);
}
else
{
meta_topic (META_DEBUG_SHAPES,
"ShapeNotify not on a client window (window %s frame_was_receiver = %d)\n",
window ? window->desc : "(none)",
frame_was_receiver);
}
goto out;
}
#endif /* HAVE_SHAPE */
#ifdef HAVE_XI23
if (meta_display_process_barrier_event (display, input_event))
{
bypass_gtk = bypass_compositor = TRUE;
goto out;
}
#endif /* HAVE_XI23 */
/* libXi does not properly copy the serial to XI2 events, so pull it
* from the parent XAnyEvent and pass it to handle_input_xevent.
* See: https://bugs.freedesktop.org/show_bug.cgi?id=64687
*/
if (handle_input_xevent (display, input_event, event->xany.serial))
{
bypass_gtk = bypass_compositor = TRUE;
goto out;
}
else
{
@ -3252,18 +3274,10 @@ event_callback (XEvent *event,
return meta_display_handle_xevent (display, event);
}
/* Return the window this has to do with, if any, rather
* than the frame or root window that was selecting
* for substructure
*/
static Window
event_get_modified_window (MetaDisplay *display,
XEvent *event)
xievent_get_modified_window (MetaDisplay *display,
XIEvent *input_event)
{
XIEvent *input_event = get_input_event (display, event);
if (input_event)
{
switch (input_event->evtype)
{
case XI_Motion:
@ -3283,7 +3297,22 @@ event_get_modified_window (MetaDisplay *display,
return ((XIBarrierEvent *) input_event)->event;
#endif /* HAVE_XI23 */
}
}
return None;
}
/* Return the window this has to do with, if any, rather
* than the frame or root window that was selecting
* for substructure
*/
static Window
event_get_modified_window (MetaDisplay *display,
XEvent *event)
{
XIEvent *input_event = get_input_event (display, event);
if (input_event)
return xievent_get_modified_window (display, input_event);
switch (event->type)
{