Compare commits

..

9 Commits

Author SHA1 Message Date
Florian Müllner
7abc2762e1 Bump version to 3.10.4
Update NEWS.
2014-02-19 19:52:25 +01:00
Ryan Lortie
d59472bb6b idle-monitor: avoid XSyncBadAlarm X error
If we fail to find the IDLETIME counter, then the alarm variable will be
uninitialised.  Most code paths are careful to check this before
submitting XSync calls, but there is one check missing.

https://bugzilla.gnome.org/show_bug.cgi?id=724364
2014-02-15 13:14:54 +01:00
Giovanni Campagna
28d2f36b72 window: don't set _NET_WM_FULLSCREEN_MONITORS to bogus values
Prior to the DisplayConfig merge, we would set _NET_WM_FULLSCREEN_MONITORS
to (unsigned)-1 when unset. After that, we would have invalid
reads inside meta_screen_monitor_index_to_xinerama_index() (called
with -1).
The way I read the specification, the proper way to indicate
that the window is back to fullscreen on all monitors is to
remove the property, so do that.

Also, add an assertion that meta_screne_monitor_index_to_xinerama_index()
is doing the right thing.

https://bugzilla.gnome.org/show_bug.cgi?id=724258
2014-02-13 13:20:35 +01:00
Giovanni Campagna
766181eeae window: fix invalid read in computing the input shape
If we are reported only one rectangle in the input shape, we should
not try to read more.

https://bugzilla.gnome.org/show_bug.cgi?id=724257
2014-02-13 13:20:33 +01:00
Adel Gadllah
5dd2e4bc72 monitorManager: Fix logic bug in make_logical_config
The code that prevents the creation of multiple MonitorInfos for clones
wasn't working due to using the wrong index when getting the already
created info so fix that to use the correct one.

https://bugzilla.gnome.org/show_bug.cgi?id=710610
2014-02-02 15:17:08 +01:00
Adel Gadllah
93ee413df2 window_actor: Remove the frame_messages timeout in destroy
Otherwise it might fire off later and cause a crash.

https://bugzilla.gnome.org/show_bug.cgi?id=723468
2014-02-02 15:17:05 +01:00
Adel Gadllah
06186639fc window-actor: Fix unobscured_region handling when computing paint volume
We currently ignore the unobscured region when we have mapped clones in
meta_window_actor_process_damage and meta_window_actor_damage_all but
use it unconditionally when computing the paint volume.

This is wrong. We should ignore it there as well or we will end up with
empty clones if the cloned window is completly obscured
(like the tray icons in gnome-shell).

https://bugzilla.gnome.org/show_bug.cgi?id=721596
2014-01-31 15:28:42 +01:00
Jasper St. Pierre
5d4138b933 window-actor: Fix optimization in get_paint_volume
We need to clip the paint volume to the unobscured region, not the
other way around...

https://bugzilla.gnome.org/show_bug.cgi?id=720630
2014-01-31 15:28:38 +01:00
Florian Müllner
bafbbc62e2 window: Add "skip-taskbar" property
We currently only have a method to query the skip-taskbar hint.
Add a corresponding property to allow listening for change
notifications.

https://bugzilla.gnome.org/show_bug.cgi?id=723307
2014-01-31 10:11:58 +01:00
36 changed files with 2317 additions and 2048 deletions

View File

@@ -6,5 +6,3 @@ EXTRA_DIST = HACKING MAINTAINERS rationales.txt
DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}

16
NEWS
View File

@@ -1,14 +1,14 @@
3.11.1
3.10.4
======
* Fix tile previews getting stuck on right click during drags [Lionel; #704759]
* Use new UPower API [Bastien]
* Set hot spot when cursor set from wl_buffer [Jonas; #709593]
* Expose min-backlight-step [Asad; #710380]
* Misc. bug fixes and cleanups [Jasper, Olav, Magdalen; #709776]
* Expose MetaWindow:skip-taskbar property [Florian; #723307]
* Fix legacy tray icons showing up blank [Adel; #721596]
* Fix configuration of cloned monitors [Adel; #710610]
* Misc. bug fixes [Jasper, Adel, Giovanni; #720630, #723468, #724257, #724258,
#724364]
Contributors:
Magdalen Berns, Lionel Landwerlin, Asad Mehmood, Bastien Nocera,
Jasper St. Pierre, Olav Vitters, Jonas Ådahl
Giovanni Campagna, Adel Gadllah, Ryan Lortie, Florian Müllner,
Jasper St. Pierre
3.10.1
======

View File

@@ -1,9 +1,8 @@
AC_PREREQ(2.50)
AC_CONFIG_MACRO_DIR([m4])
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [11])
m4_define([mutter_micro_version], [1])
m4_define([mutter_minor_version], [10])
m4_define([mutter_micro_version], [4])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@@ -80,7 +79,7 @@ MUTTER_PC_MODULES="
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
$CLUTTER_PACKAGE >= 1.15.94
cogl-1.0 >= 1.13.3
upower-glib >= 0.99.0
upower-glib > 0.9.11
gnome-desktop-3.0
"

View File

@@ -207,6 +207,7 @@ meta_key_binding_get_modifiers
meta_key_binding_get_mask
meta_key_binding_is_builtin
meta_keybindings_set_custom_handler
meta_keybindings_switch_window
meta_screen_ungrab_all_keys
meta_screen_grab_all_keys
</SECTION>

View File

@@ -21,7 +21,6 @@ environment.</description>
-->
<mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gnome-shell-list" />
<download-page rdf:resource="http://download.gnome.org/sources/mutter/" />
<download-page rdf:resource="http://download.gnome.org/sources/mutter-wayland/" />
<bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=mutter" />
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />

View File

@@ -395,6 +395,7 @@ $(dbus_xrandr_built_sources) : Makefile.am xrandr.xml
--generate-c-code meta-dbus-xrandr \
$(srcdir)/xrandr.xml
dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
$(dbus_idle_built_sources) : Makefile.am idle-monitor.xml
$(AM_V_GEN)gdbus-codegen \

View File

@@ -767,8 +767,12 @@ meta_window_actor_get_paint_volume (ClutterActor *actor,
gdk_rectangle_union (&bounds, &shadow_bounds, &bounds);
}
if (priv->unobscured_region)
cairo_region_intersect_rectangle (priv->unobscured_region, &bounds);
if (priv->unobscured_region && !clutter_actor_has_mapped_clones (actor))
{
cairo_rectangle_int_t unobscured_bounds;
cairo_region_get_extents (priv->unobscured_region, &unobscured_bounds);
gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds);
}
origin.x = bounds.x;
origin.y = bounds.y;
@@ -1438,6 +1442,12 @@ meta_window_actor_destroy (MetaWindowActor *self)
window_type = meta_window_get_window_type (window);
meta_window_set_compositor_private (window, NULL);
if (priv->send_frame_messages_timer != 0)
{
g_source_remove (priv->send_frame_messages_timer);
priv->send_frame_messages_timer = 0;
}
/*
* We remove the window from internal lookup hashes and thus any other
* unmap events etc fail

View File

@@ -366,25 +366,11 @@ meta_barrier_fire_event (MetaBarrier *barrier,
}
gboolean
meta_display_process_barrier_event (MetaDisplay *display,
XIEvent *event)
meta_display_process_barrier_event (MetaDisplay *display,
XIBarrierEvent *xev)
{
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

@@ -476,6 +476,26 @@ meta_core_change_workspace (Display *xdisplay,
new_workspace));
}
int
meta_core_get_num_workspaces (Screen *xscreen)
{
MetaScreen *screen;
screen = meta_screen_for_x_screen (xscreen);
return meta_screen_get_n_workspaces (screen);
}
int
meta_core_get_active_workspace (Screen *xscreen)
{
MetaScreen *screen;
screen = meta_screen_for_x_screen (xscreen);
return meta_workspace_index (screen->active_workspace);
}
void
meta_core_show_window_menu (Display *xdisplay,
Window frame_xwindow,

View File

@@ -153,6 +153,8 @@ void meta_core_change_workspace (Display *xdisplay,
Window frame_xwindow,
int new_workspace);
int meta_core_get_num_workspaces (Screen *xscreen);
int meta_core_get_active_workspace (Screen *xscreen);
int meta_core_get_frame_workspace (Display *xdisplay,
Window frame_xwindow);
const char* meta_core_get_workspace_name_with_index (Display *xdisplay,

View File

@@ -39,7 +39,6 @@
#include "keybindings-private.h"
#include <meta/prefs.h>
#include <meta/barrier.h>
#include <clutter/clutter.h>
#ifdef HAVE_STARTUP_NOTIFICATION
#include <libsn/sn.h>
@@ -190,7 +189,7 @@ struct _MetaDisplay
MetaWindow* autoraise_window;
/* Alt+click button grabs */
ClutterModifierType window_grab_modifiers;
unsigned int window_grab_modifiers;
/* current window operation */
MetaGrabOp grab_op;
@@ -474,23 +473,21 @@ 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,
ClutterKeyEvent *event);
void meta_display_accelerator_activate (MetaDisplay *display,
guint action,
guint deviceid,
guint timestamp);
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_xevent (MetaDisplay *display,
XEvent *event);
gboolean meta_display_handle_event (MetaDisplay *display,
const ClutterEvent *event);
gboolean meta_display_handle_event (MetaDisplay *display,
XEvent *event);
#ifdef HAVE_XI23
gboolean meta_display_process_barrier_event (MetaDisplay *display,
XIEvent *event);
gboolean meta_display_process_barrier_event (MetaDisplay *display,
XIBarrierEvent *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,
ClutterKeyEvent *event);
gboolean meta_display_process_key_event (MetaDisplay *display,
MetaWindow *window,
XIDeviceEvent *event);
void meta_display_process_mapping_event (MetaDisplay *display,
XEvent *event);
@@ -81,3 +81,7 @@ gboolean meta_prefs_remove_keybinding (const char *name);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -352,8 +352,6 @@ meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
self = g_slice_new0 (MetaCursorReference);
self->ref_count = 1;
self->hot_x = hot_x;
self->hot_y = hot_y;
backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (backend);

View File

@@ -537,7 +537,7 @@ make_watch (MetaIdleMonitor *monitor,
watch->timeout_source = source;
}
}
else
else if (monitor->user_active_alarm != None)
{
if (timeout_msec != 0)
{

View File

@@ -99,9 +99,8 @@ static gboolean meta_monitor_config_assign_crtcs (MetaConfiguration *config,
GPtrArray *crtcs,
GPtrArray *outputs);
static void power_client_changed_cb (UpClient *client,
GParamSpec *pspec,
gpointer user_data);
static void power_client_changed_cb (UpClient *client,
gpointer user_data);
static void
free_output_key (MetaOutputKey *key)
@@ -233,7 +232,7 @@ meta_monitor_config_init (MetaMonitorConfig *self)
self->up_client = up_client_new ();
self->lid_is_closed = up_client_get_lid_is_closed (self->up_client);
g_signal_connect_object (self->up_client, "notify::lid-is-closed",
g_signal_connect_object (self->up_client, "changed",
G_CALLBACK (power_client_changed_cb), self, 0);
}
@@ -1336,9 +1335,8 @@ turn_off_laptop_display (MetaMonitorConfig *self,
}
static void
power_client_changed_cb (UpClient *client,
GParamSpec *pspec,
gpointer user_data)
power_client_changed_cb (UpClient *client,
gpointer user_data)
{
MetaMonitorManager *manager = meta_monitor_manager_get ();
MetaMonitorConfig *self = user_data;

View File

@@ -290,7 +290,7 @@ make_logical_config (MetaMonitorManager *manager)
for (j = 0; j < monitor_infos->len; j++)
{
MetaMonitorInfo *info = &g_array_index (monitor_infos, MetaMonitorInfo, i);
MetaMonitorInfo *info = &g_array_index (monitor_infos, MetaMonitorInfo, j);
if (meta_rectangle_equal (&crtc->rect,
&info->rect))
{
@@ -729,9 +729,6 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_new_take_string (make_display_name (manager, output)));
g_variant_builder_add (&properties, "{sv}", "backlight",
g_variant_new_int32 (output->backlight));
g_variant_builder_add (&properties, "{sv}", "min-backlight-step",
g_variant_new_int32 ((output->backlight_max - output->backlight_min) ?
100 / (output->backlight_max - output->backlight_min) : -1));
g_variant_builder_add (&properties, "{sv}", "primary",
g_variant_new_boolean (output->is_primary));
g_variant_builder_add (&properties, "{sv}", "presentation",

View File

@@ -391,6 +391,8 @@ int
meta_screen_monitor_index_to_xinerama_index (MetaScreen *screen,
int index)
{
g_return_val_if_fail (index >= 0 && index < screen->n_monitor_infos, -1);
meta_screen_ensure_xinerama_indices (screen);
return screen->monitor_infos[index].xinerama_index;

View File

@@ -44,7 +44,6 @@
#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;
@@ -643,8 +642,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,
const ClutterEvent *event);
void meta_window_handle_mouse_grab_op_event (MetaWindow *window,
XIDeviceEvent *xev);
GList* meta_window_get_workspaces (MetaWindow *window);
@@ -734,9 +733,4 @@ 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,7 +63,6 @@
#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).
@@ -178,6 +177,7 @@ enum {
PROP_USER_TIME,
PROP_DEMANDS_ATTENTION,
PROP_URGENT,
PROP_SKIP_TASKBAR,
PROP_MUTTER_HINTS,
PROP_APPEARS_FOCUSED,
PROP_RESIZEABLE,
@@ -314,6 +314,9 @@ meta_window_get_property(GObject *object,
case PROP_URGENT:
g_value_set_boolean (value, win->wm_hints_urgent);
break;
case PROP_SKIP_TASKBAR:
g_value_set_boolean (value, win->skip_taskbar);
break;
case PROP_MUTTER_HINTS:
g_value_set_string (value, win->mutter_hints);
break;
@@ -474,6 +477,14 @@ meta_window_class_init (MetaWindowClass *klass)
FALSE,
G_PARAM_READABLE));
g_object_class_install_property (object_class,
PROP_SKIP_TASKBAR,
g_param_spec_boolean ("skip-taskbar",
"Skip taskbar",
"Whether the skip-taskbar flag of WM_HINTS is set",
FALSE,
G_PARAM_READABLE));
g_object_class_install_property (object_class,
PROP_MUTTER_HINTS,
g_param_spec_string ("mutter-hints",
@@ -2002,8 +2013,6 @@ 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)
{
@@ -2232,23 +2241,35 @@ set_net_wm_state (MetaWindow *window)
if (window->fullscreen)
{
data[0] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[0]);
data[1] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[1]);
data[2] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[2]);
data[3] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[3]);
if (window->fullscreen_monitors[0] >= 0)
{
data[0] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[0]);
data[1] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[1]);
data[2] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[2]);
data[3] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[3]);
meta_verbose ("Setting _NET_WM_FULLSCREEN_MONITORS\n");
meta_error_trap_push (window->display);
XChangeProperty (window->display->xdisplay,
window->xwindow,
window->display->atom__NET_WM_FULLSCREEN_MONITORS,
XA_CARDINAL, 32, PropModeReplace,
(guchar*) data, 4);
meta_error_trap_pop (window->display);
meta_verbose ("Setting _NET_WM_FULLSCREEN_MONITORS\n");
meta_error_trap_push (window->display);
XChangeProperty (window->display->xdisplay,
window->xwindow,
window->display->atom__NET_WM_FULLSCREEN_MONITORS,
XA_CARDINAL, 32, PropModeReplace,
(guchar*) data, 4);
meta_error_trap_pop (window->display);
}
else
{
meta_verbose ("Clearing _NET_WM_FULLSCREEN_MONITORS\n");
meta_error_trap_push (window->display);
XDeleteProperty (window->display->xdisplay,
window->xwindow,
window->display->atom__NET_WM_FULLSCREEN_MONITORS);
meta_error_trap_pop (window->display);
}
}
}
@@ -6839,7 +6860,8 @@ meta_window_property_notify (MetaWindow *window,
void
meta_window_change_workspace_by_index (MetaWindow *window,
gint space_index,
gboolean append)
gboolean append,
guint32 timestamp)
{
MetaWorkspace *workspace;
MetaScreen *screen;
@@ -6858,7 +6880,11 @@ meta_window_change_workspace_by_index (MetaWindow *window,
meta_screen_get_workspace_by_index (screen, space_index);
if (!workspace && append)
workspace = meta_screen_append_new_workspace (screen, FALSE, CurrentTime);
{
if (timestamp == CurrentTime)
timestamp = meta_display_get_current_time_roundtrip (window->display);
workspace = meta_screen_append_new_workspace (screen, FALSE, timestamp);
}
if (workspace)
{
@@ -8027,9 +8053,9 @@ meta_window_update_input_region_x11 (MetaWindow *window)
if (n_rects > 1 ||
(n_rects == 1 &&
(rects[0].x != x_bounding ||
rects[1].y != y_bounding ||
rects[2].width != w_bounding ||
rects[3].height != h_bounding)))
rects[0].y != y_bounding ||
rects[0].width != w_bounding ||
rects[0].height != h_bounding)))
region = region_create_from_x_rectangles (rects, n_rects);
XFree (rects);
@@ -8670,6 +8696,7 @@ recalc_window_features (MetaWindow *window)
gboolean old_has_resize_func;
gboolean old_has_shade_func;
gboolean old_always_sticky;
gboolean old_skip_taskbar;
old_has_close_func = window->has_close_func;
old_has_minimize_func = window->has_minimize_func;
@@ -8677,6 +8704,7 @@ recalc_window_features (MetaWindow *window)
old_has_resize_func = window->has_resize_func;
old_has_shade_func = window->has_shade_func;
old_always_sticky = window->always_sticky;
old_skip_taskbar = window->skip_taskbar;
/* Use MWM hints initially */
if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
@@ -8871,6 +8899,9 @@ recalc_window_features (MetaWindow *window)
window->skip_taskbar,
window->skip_pager);
if (old_skip_taskbar != window->skip_taskbar)
g_object_notify (G_OBJECT (window), "skip-taskbar");
/* FIXME:
* Lame workaround for recalc_window_features
* being used overzealously. The fix is to
@@ -9904,20 +9935,96 @@ update_resize (MetaWindow *window,
g_get_current_time (&window->display->grab_last_moveresize_time);
}
static gboolean
check_use_this_motion_notify (MetaWindow *window,
const ClutterEvent *event)
typedef struct
{
/* 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;
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)
{
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;
}
}
static void
@@ -9991,89 +10098,81 @@ meta_window_update_sync_request_counter (MetaWindow *window,
#endif /* HAVE_XSYNC */
void
meta_window_handle_mouse_grab_op_event (MetaWindow *window,
const ClutterEvent *event)
meta_window_handle_mouse_grab_op_event (MetaWindow *window,
XIDeviceEvent *xev)
{
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)
switch (xev->evtype)
{
case CLUTTER_BUTTON_RELEASE:
if (event->button.button == 1)
case XI_ButtonRelease:
meta_display_check_threshold_reached (window->display,
xev->root_x,
xev->root_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 not want a
* non-snapped movement to occur from the button release.
*/
if (!window->display->grab_last_user_action_was_snap)
{
meta_display_check_threshold_reached (window->display,
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
* not want a non-snapped movement to occur from the button
* release.
*/
if (!window->display->grab_last_user_action_was_snap)
if (meta_grab_op_is_moving (window->display->grab_op))
{
if (meta_grab_op_is_moving (window->display->grab_op))
{
if (window->tile_mode != META_TILE_NONE)
meta_window_tile (window);
else if (is_window_root)
update_move (window,
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 (is_window_root)
update_resize (window,
event->button.modifier_state & CLUTTER_SHIFT_MASK,
event->button.x,
event->button.y,
TRUE);
if (window->tile_mode != META_TILE_NONE)
meta_window_tile (window);
else if (xev->root == window->screen->xroot)
update_move (window,
xev->mods.effective & ShiftMask,
xev->root_x,
xev->root_y);
}
else if (meta_grab_op_is_resizing (window->display->grab_op))
{
if (xev->root == window->screen->xroot)
update_resize (window,
xev->mods.effective & ShiftMask,
xev->root_x,
xev->root_y,
TRUE);
/* If a tiled window has been dragged free with a
* mouse resize without snapping back to the tiled
* state, it will end up with an inconsistent tile
* mode on mouse release; cleaning the mode earlier
* would break the ability to snap back to the tiled
* state, so we wait until mouse release.
*/
update_tile_mode (window);
}
meta_display_end_grab_op (window->display, event->any.time);
/* If a tiled window has been dragged free with a
* mouse resize without snapping back to the tiled
* state, it will end up with an inconsistent tile
* mode on mouse release; cleaning the mode earlier
* would break the ability to snap back to the tiled
* state, so we wait until mouse release.
*/
update_tile_mode (window);
}
}
meta_display_end_grab_op (window->display, xev->time);
break;
case CLUTTER_MOTION:
case XI_Motion:
meta_display_check_threshold_reached (window->display,
event->motion.x,
event->motion.y);
xev->root_x,
xev->root_y);
if (meta_grab_op_is_moving (window->display->grab_op))
{
if (is_window_root)
if (xev->root == window->screen->xroot)
{
if (check_use_this_motion_notify (window, event))
if (check_use_this_motion_notify (window,
xev))
update_move (window,
event->button.modifier_state & CLUTTER_SHIFT_MASK,
event->motion.x,
event->motion.y);
xev->mods.effective & ShiftMask,
xev->root_x,
xev->root_y);
}
}
else if (meta_grab_op_is_resizing (window->display->grab_op))
{
if (is_window_root)
if (xev->root == window->screen->xroot)
{
if (check_use_this_motion_notify (window, event))
if (check_use_this_motion_notify (window,
xev))
update_resize (window,
event->button.modifier_state & CLUTTER_SHIFT_MASK,
event->motion.x,
event->motion.y,
xev->mods.effective & ShiftMask,
xev->root_x,
xev->root_y,
FALSE);
}
}
@@ -11669,185 +11768,3 @@ 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,81 +536,6 @@ 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,11 +102,6 @@ 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,7 +81,6 @@ 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,7 +31,6 @@
#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

@@ -35,6 +35,13 @@ gboolean meta_keybindings_set_custom_handler (const gchar *name,
gpointer user_data,
GDestroyNotify free_data);
void meta_keybindings_switch_window (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *event_window,
XIDeviceEvent *event,
MetaKeyBinding *binding);
void meta_screen_ungrab_all_keys (MetaScreen *screen, guint32 timestamp);
gboolean meta_screen_grab_all_keys (MetaScreen *screen, guint32 timestamp);
#endif

View File

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

View File

@@ -150,7 +150,8 @@ void meta_window_unset_demands_attention (MetaWindow *window);
const char* meta_window_get_startup_id (MetaWindow *window);
void meta_window_change_workspace_by_index (MetaWindow *window,
gint space_index,
gboolean append);
gboolean append,
guint32 timestamp);
void meta_window_change_workspace (MetaWindow *window,
MetaWorkspace *workspace);
GObject *meta_window_get_compositor_private (MetaWindow *window);

View File

@@ -106,49 +106,11 @@ create_anonymous_file (off_t size,
return -1;
}
static void
inform_clients_of_new_keymap (MetaWaylandKeyboard *keyboard,
int flags)
static gboolean
meta_wayland_xkb_info_new_keymap (MetaWaylandXkbInfo *xkb_info)
{
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);
@@ -167,28 +129,21 @@ meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard,
keymap_str = xkb_map_get_as_string (xkb_info->keymap);
if (keymap_str == NULL)
{
g_warning ("failed to get string version of keymap");
return;
g_warning ("failed to get string version of keymap\n");
return FALSE;
}
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",
g_warning ("creating a keymap file for %lu bytes failed: %s\n",
(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);
@@ -201,24 +156,41 @@ meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard,
strcpy (xkb_info->keymap_area, keymap_str);
free (keymap_str);
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;
return TRUE;
err_dev_zero:
close (xkb_info->keymap_fd);
xkb_info->keymap_fd = -1;
err_keymap_str:
free (keymap_str);
return;
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;
}
static void
@@ -334,8 +306,9 @@ 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);
@@ -347,15 +320,18 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
keyboard->display = display;
keyboard->xkb_context = xkb_context_new (0 /* flags */);
keyboard->is_evdev = is_evdev;
/* Compute a default until gnome-settings-daemon starts and sets
the appropriate values
*/
meta_wayland_keyboard_set_keymap_names (keyboard,
"evdev",
"pc105",
"us", "", "", 0);
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);
}
return TRUE;
}
@@ -583,6 +559,12 @@ 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);
@@ -670,28 +652,3 @@ 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,6 +112,7 @@ 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;
@@ -122,18 +123,6 @@ 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,11 +352,6 @@ 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;
@@ -390,6 +385,32 @@ meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer)
interface->focus (pointer->grab, pointer->current, NULL);
}
static void
current_surface_destroy (struct wl_listener *listener, void *data)
{
MetaWaylandPointer *pointer =
wl_container_of (listener, pointer, current_listener);
pointer->current = NULL;
}
void
meta_wayland_pointer_set_current (MetaWaylandPointer *pointer,
MetaWaylandSurface *surface)
{
if (pointer->current)
wl_list_remove (&pointer->current_listener.link);
pointer->current = surface;
if (!surface)
return;
wl_resource_add_destroy_listener (surface->resource,
&pointer->current_listener);
pointer->current_listener.notify = current_surface_destroy;
}
static void
modal_focus (MetaWaylandPointerGrab *grab,
MetaWaylandSurface *surface,

View File

@@ -62,6 +62,8 @@ struct _MetaWaylandPointer
wl_fixed_t x, y; /* TODO: remove, use ClutterInputDevice instead */
MetaWaylandSurface *current;
struct wl_listener current_listener;
wl_fixed_t current_x, current_y;
guint32 button_count;
};
@@ -95,6 +97,10 @@ gboolean
meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
MetaWaylandSurface *popup);
void
meta_wayland_pointer_set_current (MetaWaylandPointer *pointer,
MetaWaylandSurface *surface);
void
meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer,
MetaWaylandSurface *surface,

View File

@@ -83,6 +83,14 @@ 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);
@@ -96,8 +104,6 @@ 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,9 +280,31 @@ 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)
@@ -359,19 +381,6 @@ 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:
@@ -399,6 +408,20 @@ 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
@@ -435,12 +458,16 @@ 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,6 +409,9 @@ 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,6 +533,119 @@ 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)
{
@@ -558,13 +671,132 @@ reset_idletimes (const ClutterEvent *event)
}
}
gboolean
meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor,
const ClutterEvent *event)
static gboolean
event_cb (ClutterActor *stage,
const ClutterEvent *event,
MetaWaylandCompositor *compositor)
{
MetaWaylandSeat *seat = compositor->seat;
MetaWaylandPointer *pointer = &seat->pointer;
MetaWaylandSurface *surface;
MetaDisplay *display;
reset_idletimes (event);
return meta_wayland_seat_handle_event (compositor->seat, 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 */;
}
static void
@@ -607,6 +839,7 @@ void
meta_wayland_init (void)
{
MetaWaylandCompositor *compositor = &_meta_wayland_compositor;
guint event_signal;
MetaMonitorManager *monitors;
ClutterBackend *backend;
CoglContext *cogl_context;
@@ -695,6 +928,21 @@ 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);