Compare commits
17 Commits
main
...
wip/waylan
Author | SHA1 | Date | |
---|---|---|---|
531a7b2812 | |||
580669cdea | |||
e50a578ad3 | |||
06b3d36e97 | |||
715fa91599 | |||
997188e914 | |||
c6dd56f9ce | |||
466af03ed3 | |||
9c2d806556 | |||
13a7c8da85 | |||
d69d566087 | |||
b722274886 | |||
164cdabb21 | |||
0b025f0e9c | |||
87354bdac6 | |||
02e163882a | |||
9db02a7379 |
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
2178
src/core/display.c
2178
src/core/display.c
File diff suppressed because it is too large
Load Diff
@ -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
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Reference in New Issue
Block a user