Compare commits

...

17 Commits

Author SHA1 Message Date
531a7b2812 wayland: Support alternative focus modes like focus-follows-mouse
Use the existing code for MetaWindow focus-follows-mouse to support this.
2013-11-02 12:53:32 -04:00
580669cdea display: Use MetaWindow for auto-raise callbacks
This allows us to autoraise Wayland windows... well, except for the
XQueryPointer, but we'll replace that soon.
2013-11-02 12:53:31 -04:00
e50a578ad3 display: Invoke Wayland from the Grand Central Station callback 2013-11-02 12:53:31 -04:00
06b3d36e97 wayland: Move cursor tracker handling code to meta_wayland_seat_handle_event 2013-11-02 12:53:31 -04:00
715fa91599 wayland: Drop raise on click too
We'll handle this through GCD as well.
2013-11-02 12:53:31 -04:00
997188e914 wayland: Drop focus on click
The native raise-on-click works with Wayland clients through the standard
Grand Central Station event handling, with MetaWindow.
2013-11-02 12:53:31 -04:00
c6dd56f9ce wayland: Drop old hack to synthesize motion events
mutter now uses Clutter events for the source of its drag support, so
we don't need to synthesize X11 events anymore.
2013-11-02 12:53:31 -04:00
466af03ed3 keybindings: Port to Clutter 2013-11-02 12:53:31 -04:00
9c2d806556 wayland: Use an event filter instead of the captured event signal
In order to see all Clutter events, Mutter was previously installing a
signal handler on the ‘captured-event’ signal on the stage and
additionally using a signal emission hook to cope with grabs. This
changes it to use the new clutter_event_add_filter API so that we can
avoid the signal emission hook hack.
2013-11-02 12:53:31 -04:00
13a7c8da85 display: Move the pointer event handling code to work in terms of Clutter events
There is now a meta_display_handle_event alongside the
meta_display_handle_xevent function which handles events in terms of
Clutter events instead of X events. A Clutter event filter is
registered so that all Clutter events will pass through this function.
The pointer event handling code from the X event version has been moved
into this new function and has been modified to use the details from
the Clutter event instead of the X event. This is a step towards
moving all of the event handling code over to use Clutter events.

Based-heavily-on-a-patch-by: Neil Roberts <neil@linux.intel.com>
2013-11-02 12:53:30 -04:00
d69d566087 display: Split out other event handling as well
This vastly simplifies the code in event_callback and allows us to potentially
take more of this logic and punt it to Wayland-specific backends.
2013-11-02 12:35:59 -04:00
b722274886 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.
2013-11-02 12:35:59 -04:00
164cdabb21 display: Rename filter_out_event to bypass_gtk
This clarifies the intent of the variable and makes it match bypass_compositor
2013-11-02 12:35:59 -04:00
0b025f0e9c display: Move barrier event processing to barrier.c
This puts all the code that's easily ported to Clutter events in one giant
switch statement, as Clutter doesn't translate barrier events.
2013-11-02 12:35:58 -04:00
87354bdac6 display: Add a quick out path to handle_xevent
This makes the code flow more like the scheme we usually use, and allows
us to flatten out the method somewhat.
2013-11-02 12:35:58 -04:00
02e163882a display: Rename meta_display_handle_event to meta_display_handle_xevent
The plan is to make a new version of meta_display_handle_event that
will accept Clutter events instead of X events and then gradually move
over the events to the new function and finally remove the X version.
2013-11-02 12:35:58 -04:00
9db02a7379 wayland: sync the keymap from X to wayland
When X clients change the keyboard map, the also update a property
on the root window. We can notice that and rebuild our data structures
with the new values, as well as inform the wayland clients.

This is a terrible hack, and it's not how we want to implement things
in 3.12, but it's enough to have the same keyboard layout in the
shell, in X clients and in wayland clients in 3.10, until we decide
on the fate of the keyboard g-s-d plugin.

https://bugzilla.gnome.org/show_bug.cgi?id=707446
2013-11-02 12:35:58 -04:00
20 changed files with 1967 additions and 2119 deletions

View File

@ -366,11 +366,25 @@ meta_barrier_fire_event (MetaBarrier *barrier,
}
gboolean
meta_display_process_barrier_event (MetaDisplay *display,
XIBarrierEvent *xev)
meta_display_process_barrier_event (MetaDisplay *display,
XIEvent *event)
{
MetaBarrier *barrier;
XIBarrierEvent *xev;
if (event == NULL)
return FALSE;
switch (event->evtype)
{
case XI_BarrierHit:
case XI_BarrierLeave:
break;
default:
return FALSE;
}
xev = (XIBarrierEvent *) event;
barrier = g_hash_table_lookup (display->xids, &xev->barrier);
if (barrier != NULL)
{

View File

@ -39,6 +39,7 @@
#include "keybindings-private.h"
#include <meta/prefs.h>
#include <meta/barrier.h>
#include <clutter/clutter.h>
#ifdef HAVE_STARTUP_NOTIFICATION
#include <libsn/sn.h>
@ -189,7 +190,7 @@ struct _MetaDisplay
MetaWindow* autoraise_window;
/* Alt+click button grabs */
unsigned int window_grab_modifiers;
ClutterModifierType window_grab_modifiers;
/* current window operation */
MetaGrabOp grab_op;
@ -473,21 +474,23 @@ void meta_display_queue_autoraise_callback (MetaDisplay *display,
void meta_display_remove_autoraise_callback (MetaDisplay *display);
void meta_display_overlay_key_activate (MetaDisplay *display);
void meta_display_accelerator_activate (MetaDisplay *display,
guint action,
guint deviceid,
guint timestamp);
void meta_display_accelerator_activate (MetaDisplay *display,
guint action,
ClutterKeyEvent *event);
gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
/* In above-tab-keycode.c */
guint meta_display_get_above_tab_keycode (MetaDisplay *display);
gboolean meta_display_handle_event (MetaDisplay *display,
XEvent *event);
gboolean meta_display_handle_xevent (MetaDisplay *display,
XEvent *event);
gboolean meta_display_handle_event (MetaDisplay *display,
const ClutterEvent *event);
#ifdef HAVE_XI23
gboolean meta_display_process_barrier_event (MetaDisplay *display,
XIBarrierEvent *event);
gboolean meta_display_process_barrier_event (MetaDisplay *display,
XIEvent *event);
#endif /* HAVE_XI23 */
void meta_display_set_input_focus_xwindow (MetaDisplay *display,

File diff suppressed because it is too large Load Diff

View File

@ -66,9 +66,9 @@ gboolean meta_window_grab_all_keys (MetaWindow *window,
guint32 timestamp);
void meta_window_ungrab_all_keys (MetaWindow *window,
guint32 timestamp);
gboolean meta_display_process_key_event (MetaDisplay *display,
MetaWindow *window,
XIDeviceEvent *event);
gboolean meta_display_process_key_event (MetaDisplay *display,
MetaWindow *window,
ClutterKeyEvent *event);
void meta_display_process_mapping_event (MetaDisplay *display,
XEvent *event);
@ -81,7 +81,3 @@ gboolean meta_prefs_remove_keybinding (const char *name);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -44,6 +44,7 @@
#include <X11/Xutil.h>
#include <cairo.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <clutter/clutter.h>
#include "meta-wayland-types.h"
typedef struct _MetaWindowQueue MetaWindowQueue;
@ -642,8 +643,8 @@ void meta_window_update_sync_request_counter (MetaWindow *window,
gint64 new_counter_value);
#endif /* HAVE_XSYNC */
void meta_window_handle_mouse_grab_op_event (MetaWindow *window,
XIDeviceEvent *xev);
void meta_window_handle_mouse_grab_op_event (MetaWindow *window,
const ClutterEvent *event);
GList* meta_window_get_workspaces (MetaWindow *window);
@ -733,4 +734,9 @@ void meta_window_set_gtk_dbus_properties (MetaWindow *window,
void meta_window_set_transient_for (MetaWindow *window,
MetaWindow *parent);
void meta_window_handle_enter (MetaWindow *window,
guint32 timestamp,
guint root_x,
guint root_y);
#endif

View File

@ -63,6 +63,7 @@
#include <X11/extensions/Xcomposite.h>
#include "meta-wayland-private.h"
#include "meta/compositor-mutter.h"
/* Windows that unmaximize to a size bigger than that fraction of the workarea
* will be scaled down to that size (while maintaining aspect ratio).
@ -2001,6 +2002,8 @@ meta_window_unmanage (MetaWindow *window,
meta_window_ungrab_keys (window);
meta_display_ungrab_window_buttons (window->display, window->xwindow);
meta_display_ungrab_focus_window_button (window->display, window);
if (window->display->autoraise_window == window)
meta_display_remove_autoraise_callback (window->display);
if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
{
@ -9901,96 +9904,20 @@ update_resize (MetaWindow *window,
g_get_current_time (&window->display->grab_last_moveresize_time);
}
typedef struct
{
Window window;
int count;
guint32 last_time;
} EventScannerData;
static Bool
find_last_time_predicate (Display *display,
XEvent *ev,
XPointer arg)
{
EventScannerData *esd = (void*) arg;
XIEvent *xev;
if (ev->type != GenericEvent)
return False;
/* We are peeking into events not yet handled by GDK,
* Allocate cookie events here so we can handle XI2.
*
* GDK will handle later these events, and eventually
* free the cookie data itself.
*/
XGetEventData (display, &ev->xcookie);
xev = (XIEvent *) ev->xcookie.data;
if (xev->evtype != XI_Motion)
return False;
if (esd->window != ((XIDeviceEvent *) xev)->event)
return False;
esd->count += 1;
esd->last_time = xev->time;
return False;
}
static gboolean
check_use_this_motion_notify (MetaWindow *window,
XIDeviceEvent *xev)
check_use_this_motion_notify (MetaWindow *window,
const ClutterEvent *event)
{
EventScannerData esd;
XEvent useless;
/* This code is copied from Owen's GDK code. */
if (window->display->grab_motion_notify_time != 0)
{
/* == is really the right test, but I'm all for paranoia */
if (window->display->grab_motion_notify_time <=
xev->time)
{
meta_topic (META_DEBUG_RESIZING,
"Arrived at event with time %u (waiting for %u), using it\n",
(unsigned int)xev->time,
window->display->grab_motion_notify_time);
window->display->grab_motion_notify_time = 0;
return TRUE;
}
else
return FALSE; /* haven't reached the saved timestamp yet */
}
esd.window = xev->event;
esd.count = 0;
esd.last_time = 0;
/* "useless" isn't filled in because the predicate never returns True */
XCheckIfEvent (window->display->xdisplay,
&useless,
find_last_time_predicate,
(XPointer) &esd);
if (esd.count > 0)
meta_topic (META_DEBUG_RESIZING,
"Will skip %d motion events and use the event with time %u\n",
esd.count, (unsigned int) esd.last_time);
if (esd.last_time == 0)
return TRUE;
else
{
/* Save this timestamp, and ignore all motion notify
* until we get to the one with this stamp.
*/
window->display->grab_motion_notify_time = esd.last_time;
return FALSE;
}
/* XXX: Previously this code would walk through the X event queue
and filter out motion events that are followed by a later motion
event. There currently isn't any API to do the equivalent
procedure with the Clutter event queue so this function does
nothing. Clutter does its own motion event squashing so it may be
the case that this function isn't necessary. If it turns out that
we do need additional motion event squashing we could add some
extra API to the Clutter event queue and implement this function
properly. */
return TRUE;
}
static void
@ -10064,17 +9991,23 @@ meta_window_update_sync_request_counter (MetaWindow *window,
#endif /* HAVE_XSYNC */
void
meta_window_handle_mouse_grab_op_event (MetaWindow *window,
XIDeviceEvent *xev)
meta_window_handle_mouse_grab_op_event (MetaWindow *window,
const ClutterEvent *event)
{
switch (xev->evtype)
gboolean is_window_root = (event->any.stage != NULL &&
window &&
window->screen &&
CLUTTER_ACTOR (event->any.stage) ==
meta_get_stage_for_screen (window->screen));
switch (event->type)
{
case XI_ButtonRelease:
if (xev->detail == 1)
case CLUTTER_BUTTON_RELEASE:
if (event->button.button == 1)
{
meta_display_check_threshold_reached (window->display,
xev->root_x,
xev->root_y);
event->button.x,
event->button.y);
/* If the user was snap moving then ignore the button
* release because they may have let go of shift before
* releasing the mouse button and they almost certainly do
@ -10087,19 +10020,19 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window,
{
if (window->tile_mode != META_TILE_NONE)
meta_window_tile (window);
else if (xev->root == window->screen->xroot)
else if (is_window_root)
update_move (window,
xev->mods.effective & ShiftMask,
xev->root_x,
xev->root_y);
event->button.modifier_state & CLUTTER_SHIFT_MASK,
event->button.x,
event->button.y);
}
else if (meta_grab_op_is_resizing (window->display->grab_op))
{
if (xev->root == window->screen->xroot)
if (is_window_root)
update_resize (window,
xev->mods.effective & ShiftMask,
xev->root_x,
xev->root_y,
event->button.modifier_state & CLUTTER_SHIFT_MASK,
event->button.x,
event->button.y,
TRUE);
/* If a tiled window has been dragged free with a
@ -10111,37 +10044,36 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window,
*/
update_tile_mode (window);
}
meta_display_end_grab_op (window->display, event->any.time);
}
meta_display_end_grab_op (window->display, xev->time);
}
break;
case XI_Motion:
case CLUTTER_MOTION:
meta_display_check_threshold_reached (window->display,
xev->root_x,
xev->root_y);
event->motion.x,
event->motion.y);
if (meta_grab_op_is_moving (window->display->grab_op))
{
if (xev->root == window->screen->xroot)
if (is_window_root)
{
if (check_use_this_motion_notify (window,
xev))
if (check_use_this_motion_notify (window, event))
update_move (window,
xev->mods.effective & ShiftMask,
xev->root_x,
xev->root_y);
event->button.modifier_state & CLUTTER_SHIFT_MASK,
event->motion.x,
event->motion.y);
}
}
else if (meta_grab_op_is_resizing (window->display->grab_op))
{
if (xev->root == window->screen->xroot)
if (is_window_root)
{
if (check_use_this_motion_notify (window,
xev))
if (check_use_this_motion_notify (window, event))
update_resize (window,
xev->mods.effective & ShiftMask,
xev->root_x,
xev->root_y,
event->button.modifier_state & CLUTTER_SHIFT_MASK,
event->motion.x,
event->motion.y,
FALSE);
}
}
@ -11737,3 +11669,185 @@ meta_window_set_transient_for (MetaWindow *window,
if (meta_window_appears_focused (window) && window->transient_for != None)
meta_window_propagate_focus_appearance (window, TRUE);
}
static void
reset_ignored_crossing_serials (MetaDisplay *display)
{
int i;
i = 0;
while (i < N_IGNORED_CROSSING_SERIALS)
{
display->ignored_crossing_serials[i] = 0;
++i;
}
display->ungrab_should_not_cause_focus_window = None;
}
typedef struct
{
MetaWindow *window;
int pointer_x;
int pointer_y;
} MetaFocusData;
static void
mouse_mode_focus (MetaWindow *window,
guint32 timestamp)
{
MetaDisplay *display = window->display;
if (window->type != META_WINDOW_DESKTOP)
{
meta_topic (META_DEBUG_FOCUS,
"Focusing %s at time %u.\n", window->desc, timestamp);
meta_window_focus (window, timestamp);
if (meta_prefs_get_auto_raise ())
meta_display_queue_autoraise_callback (display, window);
else
meta_topic (META_DEBUG_FOCUS, "Auto raise is disabled\n");
}
else
{
/* In mouse focus mode, we defocus when the mouse *enters*
* the DESKTOP window, instead of defocusing on LeaveNotify.
* This is because having the mouse enter override-redirect
* child windows unfortunately causes LeaveNotify events that
* we can't distinguish from the mouse actually leaving the
* toplevel window as we expect. But, since we filter out
* EnterNotify events on override-redirect windows, this
* alternative mechanism works great.
*/
if (meta_prefs_get_focus_mode() == G_DESKTOP_FOCUS_MODE_MOUSE &&
display->focus_window != NULL)
{
meta_topic (META_DEBUG_FOCUS,
"Unsetting focus from %s due to mouse entering "
"the DESKTOP window\n",
display->focus_window->desc);
meta_display_focus_the_no_focus_window (display,
window->screen,
timestamp);
}
}
}
static gboolean
window_focus_on_pointer_rest_callback (gpointer data)
{
MetaFocusData *focus_data = data;
MetaWindow *window = focus_data->window;
MetaDisplay *display = window->display;
MetaScreen *screen = window->screen;
Window root, child;
double root_x, root_y, x, y;
guint32 timestamp;
XIButtonState buttons;
XIModifierState mods;
XIGroupState group;
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK)
goto out;
meta_error_trap_push (display);
XIQueryPointer (display->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
screen->xroot,
&root, &child,
&root_x, &root_y, &x, &y,
&buttons, &mods, &group);
meta_error_trap_pop (display);
free (buttons.mask);
if (root_x != focus_data->pointer_x ||
root_y != focus_data->pointer_y)
{
focus_data->pointer_x = root_x;
focus_data->pointer_y = root_y;
return TRUE;
}
/* Explicitly check for the overlay window, as get_focus_window_at_point()
* may return windows that extend underneath the chrome (like
* override-redirect or DESKTOP windows)
*/
if (child == meta_get_overlay_window (screen))
goto out;
window =
meta_stack_get_default_focus_window_at_point (screen->stack,
screen->active_workspace,
None, root_x, root_y);
if (window == NULL)
goto out;
timestamp = meta_display_get_current_time_roundtrip (display);
mouse_mode_focus (window, timestamp);
out:
display->focus_timeout_id = 0;
return FALSE;
}
/* The interval, in milliseconds, we use in focus-follows-mouse
* mode to check whether the pointer has stopped moving after a
* crossing event.
*/
#define FOCUS_TIMEOUT_DELAY 25
static void
queue_focus_callback (MetaDisplay *display,
MetaWindow *window,
int pointer_x,
int pointer_y)
{
MetaFocusData *focus_data;
focus_data = g_new (MetaFocusData, 1);
focus_data->window = window;
focus_data->pointer_x = pointer_x;
focus_data->pointer_y = pointer_y;
if (display->focus_timeout_id != 0)
g_source_remove (display->focus_timeout_id);
display->focus_timeout_id =
g_timeout_add_full (G_PRIORITY_DEFAULT,
FOCUS_TIMEOUT_DELAY,
window_focus_on_pointer_rest_callback,
focus_data,
g_free);
}
void
meta_window_handle_enter (MetaWindow *window,
guint32 timestamp,
guint root_x,
guint root_y)
{
MetaDisplay *display = window->display;
switch (meta_prefs_get_focus_mode ())
{
case G_DESKTOP_FOCUS_MODE_SLOPPY:
case G_DESKTOP_FOCUS_MODE_MOUSE:
display->mouse_mode = TRUE;
if (window->type != META_WINDOW_DOCK)
{
if (meta_prefs_get_focus_change_on_pointer_rest())
queue_focus_callback (display, window, root_x, root_y);
else
mouse_mode_focus (window, timestamp);
/* stop ignoring stuff */
reset_ignored_crossing_serials (display);
}
break;
case G_DESKTOP_FOCUS_MODE_CLICK:
break;
}
}

View File

@ -536,6 +536,81 @@ meta_prop_get_utf8_list (MetaDisplay *display,
return utf8_list_from_results (&results, str_p, n_str_p);
}
/* this one freakishly returns g_malloc memory */
static gboolean
latin1_list_from_results (GetPropertyResults *results,
char ***str_p,
int *n_str_p)
{
int i;
int n_strings;
char **retval;
const char *p;
*str_p = NULL;
*n_str_p = 0;
if (!validate_or_free_results (results, 8, XA_STRING, FALSE))
return FALSE;
/* I'm not sure this is right, but I'm guessing the
* property is nul-separated
*/
i = 0;
n_strings = 0;
while (i < (int) results->n_items)
{
if (results->prop[i] == '\0')
++n_strings;
++i;
}
if (results->prop[results->n_items - 1] != '\0')
++n_strings;
/* we're guaranteed that results->prop has a nul on the end
* by XGetWindowProperty
*/
retval = g_new0 (char*, n_strings + 1);
p = (char *)results->prop;
i = 0;
while (i < n_strings)
{
retval[i] = g_strdup (p);
p = p + strlen (p) + 1;
++i;
}
*str_p = retval;
*n_str_p = i;
meta_XFree (results->prop);
results->prop = NULL;
return TRUE;
}
gboolean
meta_prop_get_latin1_list (MetaDisplay *display,
Window xwindow,
Atom xatom,
char ***str_p,
int *n_str_p)
{
GetPropertyResults results;
*str_p = NULL;
if (!get_property (display, xwindow, xatom,
XA_STRING, &results))
return FALSE;
return latin1_list_from_results (&results, str_p, n_str_p);
}
void
meta_prop_set_utf8_string_hint (MetaDisplay *display,
Window xwindow,

View File

@ -102,6 +102,11 @@ gboolean meta_prop_get_utf8_list (MetaDisplay *display,
Atom xatom,
char ***str_p,
int *n_str_p);
gboolean meta_prop_get_latin1_list (MetaDisplay *display,
Window xwindow,
Atom xatom,
char ***str_p,
int *n_str_p);
void meta_prop_set_utf8_string_hint
(MetaDisplay *display,
Window xwindow,

View File

@ -81,6 +81,7 @@ item(TIMESTAMP)
item(VERSION)
item(ATOM_PAIR)
item(BACKLIGHT)
item(_XKB_RULES_NAMES)
/* Oddities: These are used, and we need atoms for them,
* but when we need all _NET_WM hints (i.e. when we're making

View File

@ -31,6 +31,7 @@
#include <X11/Xlib.h>
#include <X11/extensions/XInput.h>
#include <X11/extensions/XInput2.h>
#include <clutter/clutter.h>
#include <glib.h>
#include <gtk/gtk.h>

View File

@ -391,17 +391,17 @@ struct _MetaKeyCombo
* @display: a #MetaDisplay
* @screen: a #MetaScreen
* @window: a #MetaWindow
* @event: (type gpointer): a #XIDeviceEvent
* @event: a #ClutterKeyEvent
* @binding: a #MetaKeyBinding
* @user_data: data passed to the function
*
*/
typedef void (* MetaKeyHandlerFunc) (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
XIDeviceEvent *event,
MetaKeyBinding *binding,
gpointer user_data);
typedef void (* MetaKeyHandlerFunc) (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
ClutterKeyEvent *event,
MetaKeyBinding *binding,
gpointer user_data);
typedef struct _MetaKeyHandler MetaKeyHandler;

View File

@ -106,11 +106,49 @@ create_anonymous_file (off_t size,
return -1;
}
static gboolean
meta_wayland_xkb_info_new_keymap (MetaWaylandXkbInfo *xkb_info)
static void
inform_clients_of_new_keymap (MetaWaylandKeyboard *keyboard,
int flags)
{
MetaWaylandCompositor *compositor;
struct wl_client *xclient;
struct wl_resource *keyboard_resource;
compositor = meta_wayland_compositor_get_default ();
xclient = compositor->xwayland_client;
wl_resource_for_each (keyboard_resource, &keyboard->resource_list)
{
if ((flags & META_WAYLAND_KEYBOARD_SKIP_XCLIENTS) &&
wl_resource_get_client (keyboard_resource) == xclient)
continue;
wl_keyboard_send_keymap (keyboard_resource,
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
keyboard->xkb_info.keymap_fd,
keyboard->xkb_info.keymap_size);
}
}
static void
meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard,
struct xkb_keymap *keymap,
int flags)
{
MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info;
GError *error = NULL;
char *keymap_str;
size_t previous_size;
if (keymap == NULL)
{
g_warning ("Attempting to set null keymap (compilation probably failed)");
return;
}
if (xkb_info->keymap)
xkb_keymap_unref (xkb_info->keymap);
xkb_info->keymap = keymap;
xkb_info->shift_mod =
xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_SHIFT);
@ -129,21 +167,28 @@ meta_wayland_xkb_info_new_keymap (MetaWaylandXkbInfo *xkb_info)
keymap_str = xkb_map_get_as_string (xkb_info->keymap);
if (keymap_str == NULL)
{
g_warning ("failed to get string version of keymap\n");
return FALSE;
g_warning ("failed to get string version of keymap");
return;
}
previous_size = xkb_info->keymap_size;
xkb_info->keymap_size = strlen (keymap_str) + 1;
if (xkb_info->keymap_fd >= 0)
close (xkb_info->keymap_fd);
xkb_info->keymap_fd = create_anonymous_file (xkb_info->keymap_size, &error);
if (xkb_info->keymap_fd < 0)
{
g_warning ("creating a keymap file for %lu bytes failed: %s\n",
g_warning ("creating a keymap file for %lu bytes failed: %s",
(unsigned long) xkb_info->keymap_size,
error->message);
g_clear_error (&error);
goto err_keymap_str;
}
if (xkb_info->keymap_area)
munmap (xkb_info->keymap_area, previous_size);
xkb_info->keymap_area = mmap (NULL, xkb_info->keymap_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, xkb_info->keymap_fd, 0);
@ -156,41 +201,24 @@ meta_wayland_xkb_info_new_keymap (MetaWaylandXkbInfo *xkb_info)
strcpy (xkb_info->keymap_area, keymap_str);
free (keymap_str);
return TRUE;
if (keyboard->is_evdev)
{
ClutterDeviceManager *manager;
manager = clutter_device_manager_get_default ();
clutter_evdev_set_keyboard_map (manager, xkb_info->keymap);
}
inform_clients_of_new_keymap (keyboard, flags);
return;
err_dev_zero:
close (xkb_info->keymap_fd);
xkb_info->keymap_fd = -1;
err_keymap_str:
free (keymap_str);
return FALSE;
}
static gboolean
meta_wayland_keyboard_build_global_keymap (struct xkb_context *xkb_context,
struct xkb_rule_names *xkb_names,
MetaWaylandXkbInfo *xkb_info)
{
xkb_info->keymap = xkb_map_new_from_names (xkb_context,
xkb_names,
0 /* flags */);
if (xkb_info->keymap == NULL)
{
g_warning ("failed to compile global XKB keymap\n"
" tried rules %s, model %s, layout %s, variant %s, "
"options %s\n",
xkb_names->rules,
xkb_names->model,
xkb_names->layout,
xkb_names->variant,
xkb_names->options);
return FALSE;
}
if (!meta_wayland_xkb_info_new_keymap (xkb_info))
return FALSE;
return TRUE;
return;
}
static void
@ -306,9 +334,8 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
struct wl_display *display,
gboolean is_evdev)
{
ClutterDeviceManager *manager;
memset (keyboard, 0, sizeof *keyboard);
keyboard->xkb_info.keymap_fd = -1;
wl_list_init (&keyboard->resource_list);
wl_array_init (&keyboard->keys);
@ -320,18 +347,15 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
keyboard->display = display;
keyboard->xkb_context = xkb_context_new (0 /* flags */);
meta_wayland_keyboard_build_global_keymap (keyboard->xkb_context,
&keyboard->xkb_names,
&keyboard->xkb_info);
keyboard->is_evdev = is_evdev;
if (is_evdev)
{
manager = clutter_device_manager_get_default ();
clutter_evdev_set_keyboard_map (manager, keyboard->xkb_info.keymap);
}
/* Compute a default until gnome-settings-daemon starts and sets
the appropriate values
*/
meta_wayland_keyboard_set_keymap_names (keyboard,
"evdev",
"pc105",
"us", "", "", 0);
return TRUE;
}
@ -559,12 +583,6 @@ meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard)
void
meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard)
{
g_free ((char *) keyboard->xkb_names.rules);
g_free ((char *) keyboard->xkb_names.model);
g_free ((char *) keyboard->xkb_names.layout);
g_free ((char *) keyboard->xkb_names.variant);
g_free ((char *) keyboard->xkb_names.options);
meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
xkb_context_unref (keyboard->xkb_context);
@ -652,3 +670,28 @@ meta_wayland_keyboard_end_modal (MetaWaylandKeyboard *keyboard,
meta_verbose ("Released modal keyboard grab, timestamp %d\n", timestamp);
}
void
meta_wayland_keyboard_set_keymap_names (MetaWaylandKeyboard *keyboard,
const char *rules,
const char *model,
const char *layout,
const char *variant,
const char *options,
int flags)
{
struct xkb_rule_names xkb_names;
xkb_names.rules = rules;
xkb_names.model = model;
xkb_names.layout = layout;
xkb_names.variant = variant;
xkb_names.options = options;
meta_wayland_keyboard_take_keymap (keyboard,
xkb_keymap_new_from_names (keyboard->xkb_context,
&xkb_names,
0 /* flags */),
flags);
}

View File

@ -112,7 +112,6 @@ struct _MetaWaylandKeyboard
struct xkb_context *xkb_context;
gboolean is_evdev;
MetaWaylandXkbInfo xkb_info;
struct xkb_rule_names xkb_names;
MetaWaylandKeyboardGrab input_method_grab;
struct wl_resource *input_method_resource;
@ -123,6 +122,18 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
struct wl_display *display,
gboolean is_evdev);
typedef enum {
META_WAYLAND_KEYBOARD_SKIP_XCLIENTS = 1,
} MetaWaylandKeyboardSetKeymapFlags;
void
meta_wayland_keyboard_set_keymap_names (MetaWaylandKeyboard *keyboard,
const char *rules,
const char *model,
const char *layout,
const char *variant,
const char *options,
int flags);
gboolean
meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
const ClutterKeyEvent *event);

View File

@ -352,6 +352,11 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
}
meta_wayland_pointer_get_relative_coordinates (pointer, surface, &sx, &sy);
meta_window_handle_enter (surface->window,
/* XXX -- can we reliably get a timestamp for setting focus? */
clutter_get_current_event_time (),
wl_fixed_to_int (pointer->x),
wl_fixed_to_int (pointer->y));
wl_pointer_send_enter (resource, serial, surface->resource, sx, sy);
wl_resource_add_destroy_listener (resource, &pointer->focus_listener);
pointer->focus_serial = serial;

View File

@ -62,7 +62,6 @@ struct _MetaWaylandPointer
wl_fixed_t x, y; /* TODO: remove, use ClutterInputDevice instead */
MetaWaylandSurface *current;
wl_fixed_t current_x, current_y;
guint32 button_count;
};

View File

@ -83,14 +83,6 @@ struct _MetaWaylandCompositor
int drm_fd;
MetaWaylandSeat *seat;
/* This surface is only used to keep drag of the implicit grab when
synthesizing XEvents for Mutter */
MetaWaylandSurface *implicit_grab_surface;
/* Button that was pressed to initiate an implicit grab. The
implicit grab will only be released when this button is
released */
guint32 implicit_grab_button;
};
void meta_wayland_init (void);
@ -104,6 +96,8 @@ void meta_wayland_compositor_repick (MetaWaylandComp
void meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
MetaWindow *window);
gboolean meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor,
const ClutterEvent *event);
MetaLauncher *meta_wayland_compositor_get_launcher (MetaWaylandCompositor *compositor);
gboolean meta_wayland_compositor_is_native (MetaWaylandCompositor *compositor);

View File

@ -280,31 +280,9 @@ handle_button_event (MetaWaylandSeat *seat,
const ClutterEvent *event)
{
MetaWaylandPointer *pointer = &seat->pointer;
gboolean state = event->type == CLUTTER_BUTTON_PRESS;
uint32_t button;
MetaWaylandSurface *surface;
notify_motion (seat, event);
if (state && pointer->button_count == 1)
{
button = clutter_event_get_button (event);
pointer->grab_button = button;
pointer->grab_time = clutter_event_get_time (event);
pointer->grab_x = pointer->x;
pointer->grab_y = pointer->y;
/* FIXME: synth a XI2 event and handle in display.c */
surface = pointer->current;
if (button == CLUTTER_BUTTON_PRIMARY &&
surface &&
surface->window &&
surface->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
{
meta_window_raise (surface->window);
}
}
pointer->grab->interface->button (pointer->grab, event);
if (pointer->button_count == 1)
@ -381,6 +359,19 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
{
seat->pointer.button_count = count_buttons (event);
if (seat->cursor_tracker)
{
meta_cursor_tracker_update_position (seat->cursor_tracker,
wl_fixed_to_int (seat->pointer.x),
wl_fixed_to_int (seat->pointer.y));
if (seat->pointer.current == NULL)
meta_cursor_tracker_revert_root (seat->cursor_tracker);
meta_cursor_tracker_queue_redraw (seat->cursor_tracker,
CLUTTER_ACTOR (event->any.stage));
}
switch (event->type)
{
case CLUTTER_MOTION:
@ -408,20 +399,6 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
return FALSE;
}
static void
update_pointer_position_for_actor (MetaWaylandPointer *pointer,
ClutterActor *actor)
{
float ax, ay;
clutter_actor_transform_stage_point (actor,
wl_fixed_to_double (pointer->x),
wl_fixed_to_double (pointer->y),
&ax, &ay);
pointer->current_x = wl_fixed_from_double (ax);
pointer->current_y = wl_fixed_from_double (ay);
}
/* The actor argument can be NULL in which case a Clutter pick will be
performed to determine the right actor. An actor should only be
passed if the repick is being performed due to an event in which
@ -458,16 +435,12 @@ meta_wayland_seat_repick (MetaWaylandSeat *seat,
MetaWindow *window =
meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor));
update_pointer_position_for_actor (pointer, actor);
surface = window->surface;
}
else if (META_IS_SHAPED_TEXTURE (actor))
{
MetaShapedTexture *shaped_texture = META_SHAPED_TEXTURE (actor);
update_pointer_position_for_actor (pointer, actor);
surface = meta_shaped_texture_get_wayland_surface (shaped_texture);
}

View File

@ -409,9 +409,6 @@ meta_wayland_surface_free (MetaWaylandSurface *surface)
g_assert (surface != compositor->seat->pointer.focus);
}
if (compositor->implicit_grab_surface == surface)
compositor->implicit_grab_surface = compositor->seat->pointer.current;
if (surface->resource)
wl_resource_set_user_data (surface->resource, NULL);
g_slice_free (MetaWaylandSurface, surface);

View File

@ -533,119 +533,6 @@ stage_destroy_cb (void)
meta_quit (META_EXIT_SUCCESS);
}
#define N_BUTTONS 5
static void
synthesize_motion_event (MetaWaylandCompositor *compositor,
const ClutterEvent *event)
{
/* We want to synthesize X events for mouse motion events so that we
don't have to rely on the X server's window position being
synched with the surface position. See the comment in
event_callback() in display.c */
MetaWaylandSeat *seat = compositor->seat;
MetaWaylandPointer *pointer = &seat->pointer;
MetaWaylandSurface *surface;
XGenericEventCookie generic_event;
XIDeviceEvent device_event;
unsigned char button_mask[(N_BUTTONS + 7) / 8] = { 0 };
MetaDisplay *display = meta_get_display ();
ClutterModifierType button_state;
int i;
generic_event.type = GenericEvent;
generic_event.serial = 0;
generic_event.send_event = False;
generic_event.display = display->xdisplay;
generic_event.extension = display->xinput_opcode;
generic_event.evtype = XI_Motion;
/* Mutter assumes the data for the event is already retrieved by GDK
* so we don't need the cookie */
generic_event.cookie = 0;
generic_event.data = &device_event;
memcpy (&device_event, &generic_event, sizeof (XGenericEvent));
device_event.time = clutter_event_get_time (event);
device_event.deviceid = clutter_event_get_device_id (event);
device_event.sourceid = 0; /* not used, not sure what this should be */
device_event.detail = 0;
device_event.root = DefaultRootWindow (display->xdisplay);
device_event.flags = 0 /* not used for motion events */;
if (compositor->implicit_grab_surface)
surface = compositor->implicit_grab_surface;
else
surface = pointer->current;
if (surface == pointer->current)
{
device_event.event_x = wl_fixed_to_int (pointer->current_x);
device_event.event_y = wl_fixed_to_int (pointer->current_y);
}
else if (surface && surface->window)
{
ClutterActor *window_actor =
CLUTTER_ACTOR (meta_window_get_compositor_private (surface->window));
if (window_actor)
{
float ax, ay;
clutter_actor_transform_stage_point (window_actor,
wl_fixed_to_double (pointer->x),
wl_fixed_to_double (pointer->y),
&ax, &ay);
device_event.event_x = ax;
device_event.event_y = ay;
}
else
{
device_event.event_x = wl_fixed_to_double (pointer->x);
device_event.event_y = wl_fixed_to_double (pointer->y);
}
}
else
{
device_event.event_x = wl_fixed_to_double (pointer->x);
device_event.event_y = wl_fixed_to_double (pointer->y);
}
if (surface && surface->window != NULL)
device_event.event = surface->window->xwindow;
else
device_event.event = device_event.root;
/* Mutter doesn't really know about the sub-windows. This assumes it
doesn't care either */
device_event.child = device_event.event;
device_event.root_x = wl_fixed_to_double (pointer->x);
device_event.root_y = wl_fixed_to_double (pointer->y);
clutter_event_get_state_full (event,
&button_state,
(ClutterModifierType*)&device_event.mods.base,
(ClutterModifierType*)&device_event.mods.latched,
(ClutterModifierType*)&device_event.mods.locked,
(ClutterModifierType*)&device_event.mods.effective);
device_event.mods.effective &= ~button_state;
memset (&device_event.group, 0, sizeof (device_event.group));
device_event.group.effective = (device_event.mods.effective >> 13) & 0x3;
for (i = 0; i < N_BUTTONS; i++)
if ((button_state & (CLUTTER_BUTTON1_MASK << i)))
XISetMask (button_mask, i + 1);
device_event.buttons.mask_len = N_BUTTONS + 1;
device_event.buttons.mask = button_mask;
device_event.valuators.mask_len = 0;
device_event.valuators.mask = NULL;
device_event.valuators.values = NULL;
meta_display_handle_event (display, (XEvent *) &generic_event);
}
static void
reset_idletimes (const ClutterEvent *event)
{
@ -671,132 +558,13 @@ reset_idletimes (const ClutterEvent *event)
}
}
static gboolean
event_cb (ClutterActor *stage,
const ClutterEvent *event,
MetaWaylandCompositor *compositor)
gboolean
meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor,
const ClutterEvent *event)
{
MetaWaylandSeat *seat = compositor->seat;
MetaWaylandPointer *pointer = &seat->pointer;
MetaWaylandSurface *surface;
MetaDisplay *display;
reset_idletimes (event);
if (meta_wayland_seat_handle_event (compositor->seat, event))
return TRUE;
/* HACK: for now, the surfaces from Wayland clients aren't
integrated into Mutter's event handling and Mutter won't give them
focus on mouse clicks. As a hack to work around this we can just
give them input focus on mouse clicks so we can at least test the
keyboard support */
if (event->type == CLUTTER_BUTTON_PRESS)
{
surface = pointer->current;
if (surface && surface->window &&
surface->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
{
MetaDisplay *display = meta_get_display ();
guint32 timestamp = meta_display_get_current_time_roundtrip (display);
meta_window_focus (surface->window, timestamp);
}
}
if (seat->cursor_tracker)
{
meta_cursor_tracker_update_position (seat->cursor_tracker,
wl_fixed_to_int (pointer->x),
wl_fixed_to_int (pointer->y));
if (pointer->current == NULL)
meta_cursor_tracker_revert_root (seat->cursor_tracker);
meta_cursor_tracker_queue_redraw (seat->cursor_tracker, stage);
}
display = meta_get_display ();
if (!display)
return FALSE;
switch (event->type)
{
case CLUTTER_BUTTON_PRESS:
if (compositor->implicit_grab_surface == NULL)
{
compositor->implicit_grab_button = event->button.button;
compositor->implicit_grab_surface = pointer->current;
}
return FALSE;
case CLUTTER_BUTTON_RELEASE:
if (event->type == CLUTTER_BUTTON_RELEASE &&
compositor->implicit_grab_surface &&
event->button.button == compositor->implicit_grab_button)
compositor->implicit_grab_surface = NULL;
return FALSE;
case CLUTTER_MOTION:
synthesize_motion_event (compositor, event);
return FALSE;
default:
return FALSE;
}
}
static gboolean
event_emission_hook_cb (GSignalInvocationHint *ihint,
guint n_param_values,
const GValue *param_values,
gpointer data)
{
MetaWaylandCompositor *compositor = data;
ClutterActor *actor;
ClutterEvent *event;
g_return_val_if_fail (n_param_values == 2, FALSE);
actor = g_value_get_object (param_values + 0);
event = g_value_get_boxed (param_values + 1);
if (actor == NULL)
return TRUE /* stay connected */;
/* If this event belongs to the corresponding grab for this event
* type then the captured-event signal won't be emitted so we have
* to manually forward it on */
switch (event->type)
{
/* Pointer events */
case CLUTTER_MOTION:
case CLUTTER_ENTER:
case CLUTTER_LEAVE:
case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE:
case CLUTTER_SCROLL:
if (actor == clutter_get_pointer_grab ())
event_cb (clutter_actor_get_stage (actor),
event,
compositor);
break;
/* Keyboard events */
case CLUTTER_KEY_PRESS:
case CLUTTER_KEY_RELEASE:
if (actor == clutter_get_keyboard_grab ())
event_cb (clutter_actor_get_stage (actor),
event,
compositor);
default:
break;
}
return TRUE /* stay connected */;
return meta_wayland_seat_handle_event (compositor->seat, event);
}
static void
@ -839,7 +607,6 @@ void
meta_wayland_init (void)
{
MetaWaylandCompositor *compositor = &_meta_wayland_compositor;
guint event_signal;
MetaMonitorManager *monitors;
ClutterBackend *backend;
CoglContext *cogl_context;
@ -928,21 +695,6 @@ meta_wayland_init (void)
compositor->seat = meta_wayland_seat_new (compositor->wayland_display,
compositor->drm_fd >= 0);
g_signal_connect (compositor->stage,
"captured-event",
G_CALLBACK (event_cb),
compositor);
/* If something sets a grab on an actor then the captured event
* signal won't get emitted but we still want to see these events so
* we can update the cursor position. To make sure we see all events
* we also install an emission hook on the event signal */
event_signal = g_signal_lookup ("event", CLUTTER_TYPE_STAGE);
g_signal_add_emission_hook (event_signal,
0 /* detail */,
event_emission_hook_cb,
compositor, /* hook_data */
NULL /* data_destroy */);
meta_wayland_init_shell (compositor);
clutter_actor_show (compositor->stage);