Compare commits

...

6 Commits

Author SHA1 Message Date
Giovanni Campagna
30898007f3 Make ShellXFixesCursor work under wayland
Replace ClutterX11 with GdkX11 + Mutter, so that it works when
Clutter is not using the X11 backend.

FIXME: doesn't work...
2013-07-15 13:22:10 +02:00
Giovanni Campagna
2754a5e3a1 Don't ignore crossing event
We were sometimes ignoring crossing events to avoid unfocusing
the tray after the user interacted with a legacy icon.
This can't happen any more, as the tray is modal and all events
are synthetized, so remove this code, which crashes the shell
under wayland.
2013-07-15 12:51:30 +02:00
Neil Roberts
da1b7f4f83 Don't pass on X events to Clutter
The Mutter plugin manager has now been changed so that it itself will
pass on the events through Clutter so there is no need to do this in
Gnome Shell anymore.
2013-06-19 14:31:25 +01:00
Neil Roberts
206f036cef wayland: Don't set properties on the overlay window on Wayland
When Mutter is running as a display server it won't create an overlay
window. Therefore we shouldn't need to set the DND proxy on the
window. This was previously causing X errors when it tried to set a
property on an invalid window.
2013-06-19 14:31:18 +01:00
Neil Roberts
e3be2237b8 wayland: Create a dummy stage window when running as a display server
When Mutter is running as a display server then Clutter won't be using
the X11 backend so there won't be a window for the stage. The shell
global keeps track of this stage window to be used in various places.
This patch adds a dummy window that is never mapped to use instead of
the stage window so that the various places that are using it might be
able to continue working without generating X errors.
2013-06-19 13:49:31 +01:00
Neil Roberts
d663beab97 wayland: Add a --display-server option
This makes Gnome Shell run as its own display server.
2013-06-17 12:30:08 +01:00
6 changed files with 99 additions and 196 deletions

View File

@ -53,7 +53,7 @@ const Magnifier = new Lang.Class({
this._zoomRegions = []; this._zoomRegions = [];
// Create small clutter tree for the magnified mouse. // Create small clutter tree for the magnified mouse.
let xfixesCursor = Shell.XFixesCursor.get_for_stage(global.stage); let xfixesCursor = Shell.XFixesCursor.get_for_screen(global.screen);
this._mouseSprite = new Clutter.Texture(); this._mouseSprite = new Clutter.Texture();
xfixesCursor.update_texture_image(this._mouseSprite); xfixesCursor.update_texture_image(this._mouseSprite);
this._cursorRoot = new Clutter.Actor(); this._cursorRoot = new Clutter.Actor();
@ -83,7 +83,7 @@ const Magnifier = new Lang.Class({
* Show the system mouse pointer. * Show the system mouse pointer.
*/ */
showSystemCursor: function() { showSystemCursor: function() {
this._xfixesCursor.show(); global.stage.show_cursor();
}, },
/** /**
@ -91,7 +91,7 @@ const Magnifier = new Lang.Class({
* Hide the system mouse pointer. * Hide the system mouse pointer.
*/ */
hideSystemCursor: function() { hideSystemCursor: function() {
this._xfixesCursor.hide(); global.stage.hide_cursor();
}, },
/** /**
@ -112,7 +112,7 @@ const Magnifier = new Lang.Class({
// Make sure system mouse pointer is shown when all zoom regions are // Make sure system mouse pointer is shown when all zoom regions are
// invisible. // invisible.
if (!activate) if (!activate)
this._xfixesCursor.show(); global.stage.show_cursor();
// Notify interested parties of this change // Notify interested parties of this change
this.emit('active-changed', activate); this.emit('active-changed', activate);

View File

@ -314,38 +314,6 @@ gnome_shell_plugin_kill_switch_workspace (MetaPlugin *plugin)
_shell_wm_kill_switch_workspace (get_shell_wm()); _shell_wm_kill_switch_workspace (get_shell_wm());
} }
static gboolean
ignore_crossing_event (MetaPlugin *plugin,
XIEnterEvent *enter_event)
{
MetaScreen *screen = meta_plugin_get_screen (plugin);
ClutterStage *stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
if (enter_event->event == clutter_x11_get_stage_window (stage))
{
/* If the pointer enters a child of the stage window (eg, a
* trayicon), we want to consider it to still be in the stage,
* so don't let Clutter see the event.
*/
if (enter_event->detail == XINotifyInferior)
return TRUE;
/* If the pointer is grabbed by a window it is not currently in,
* filter that out as well. In particular, if a trayicon grabs
* the pointer after a click on its label, we don't want to hide
* the message tray. Filtering out this event will leave Clutter
* out of sync, but that happens fairly often with grabs, and we
* can work around it. (Eg, shell_global_sync_pointer().)
*/
if (enter_event->mode == XINotifyGrab &&
(enter_event->detail == XINotifyNonlinear ||
enter_event->detail == XINotifyNonlinearVirtual))
return TRUE;
}
return FALSE;
}
static gboolean static gboolean
gnome_shell_plugin_xevent_filter (MetaPlugin *plugin, gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
XEvent *xev) XEvent *xev)
@ -371,25 +339,10 @@ gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
} }
#endif #endif
/* Make sure that Clutter doesn't see certain focus change events,
* so that when we're moving into something like a tray icon, we
* don't unfocus the container. */
if (xev->type == GenericEvent &&
xev->xcookie.extension == meta_display_get_xinput_opcode (display))
{
XIEvent *input_event = (XIEvent *) xev->xcookie.data;
if ((input_event->evtype == XI_Enter || input_event->evtype == XI_Leave) &&
ignore_crossing_event (plugin, (XIEnterEvent *) input_event))
return TRUE;
}
/* /*
* Pass the event to shell-global * Pass the event to shell-global
*/ */
if (_shell_global_check_xdnd_event (shell_plugin->global, xev)) return _shell_global_check_xdnd_event (shell_plugin->global, xev);
return TRUE;
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
} }
static gboolean static gboolean

View File

@ -22,6 +22,7 @@
#include <atk-bridge.h> #include <atk-bridge.h>
#include <telepathy-glib/debug.h> #include <telepathy-glib/debug.h>
#include <telepathy-glib/debug-sender.h> #include <telepathy-glib/debug-sender.h>
#include <meta/util.h>
#include "shell-global.h" #include "shell-global.h"
#include "shell-global-private.h" #include "shell-global-private.h"
@ -41,6 +42,7 @@ extern GType gnome_shell_plugin_get_type (void);
static gboolean is_gdm_mode = FALSE; static gboolean is_gdm_mode = FALSE;
static char *session_mode = NULL; static char *session_mode = NULL;
static gboolean is_display_server = FALSE;
#define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 1 #define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 1
#define DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER 4 #define DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER 4
@ -347,6 +349,12 @@ print_version (const gchar *option_name,
} }
GOptionEntry gnome_shell_options[] = { GOptionEntry gnome_shell_options[] = {
{
"display-server", 0, 0, G_OPTION_ARG_NONE,
&is_display_server,
N_("Run as a display server"),
NULL,
},
{ {
"version", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, "version", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
print_version, print_version,
@ -396,6 +404,8 @@ main (int argc, char **argv)
g_option_context_free (ctx); g_option_context_free (ctx);
meta_set_is_display_server (is_display_server);
meta_plugin_manager_set_plugin_type (gnome_shell_plugin_get_type ()); meta_plugin_manager_set_plugin_type (gnome_shell_plugin_get_type ());
meta_set_wm_name (WM_NAME); meta_set_wm_name (WM_NAME);

View File

@ -930,9 +930,34 @@ _shell_global_set_plugin (ShellGlobal *global,
meta_screen_get_screen_number (global->meta_screen)); meta_screen_get_screen_number (global->meta_screen));
global->stage = CLUTTER_STAGE (meta_get_stage_for_screen (global->meta_screen)); global->stage = CLUTTER_STAGE (meta_get_stage_for_screen (global->meta_screen));
global->stage_xwindow = clutter_x11_get_stage_window (global->stage); if (meta_is_display_server ())
global->stage_gdk_window = gdk_x11_window_foreign_new_for_display (global->gdk_display, {
global->stage_xwindow); /* When Mutter is acting as its own display server then the
stage does not have a window. Instead we'll just create a
dummy window that might make some things blunder along but
will probably just leave most things broken. It might be
possible to fix this to make the fake window be the same size
as the stage window would be and make it more useful. */
GdkWindowAttr attributes;
attributes.wclass = GDK_INPUT_OUTPUT;
attributes.width = 100;
attributes.height = 100;
attributes.window_type = GDK_WINDOW_TOPLEVEL;
global->stage_gdk_window = gdk_window_new (NULL,
&attributes,
0 /* attributes_mask */);
global->stage_xwindow = gdk_x11_window_get_xid (global->stage_gdk_window);
}
else
{
global->stage_xwindow = clutter_x11_get_stage_window (global->stage);
global->stage_gdk_window =
gdk_x11_window_foreign_new_for_display (global->gdk_display,
global->stage_xwindow);
}
g_signal_connect (global->stage, "notify::width", g_signal_connect (global->stage, "notify::width",
G_CALLBACK (global_stage_notify_width), global); G_CALLBACK (global_stage_notify_width), global);
@ -1240,9 +1265,12 @@ void shell_global_init_xdnd (ShellGlobal *global)
gdk_x11_get_xatom_by_name ("XdndAware"), XA_ATOM, gdk_x11_get_xatom_by_name ("XdndAware"), XA_ATOM,
32, PropModeReplace, (const unsigned char *)&xdnd_version, 1); 32, PropModeReplace, (const unsigned char *)&xdnd_version, 1);
XChangeProperty (global->xdisplay, output_window, /* There is no overlay window when running as a display server */
gdk_x11_get_xatom_by_name ("XdndProxy"), XA_WINDOW, if (output_window)
32, PropModeReplace, (const unsigned char *)&global->stage_xwindow, 1); XChangeProperty (global->xdisplay, output_window,
gdk_x11_get_xatom_by_name ("XdndProxy"), XA_WINDOW,
32, PropModeReplace,
(const unsigned char *)&global->stage_xwindow, 1);
/* /*
* XdndProxy is additionally set on the proxy window as verification that the * XdndProxy is additionally set on the proxy window as verification that the

View File

@ -4,8 +4,11 @@
#include "shell-xfixes-cursor.h" #include "shell-xfixes-cursor.h"
#include <clutter/x11/clutter-x11.h> #include <gdk/gdkx.h>
#include <X11/extensions/Xfixes.h> #include <X11/extensions/Xfixes.h>
#include <meta/display.h>
#include <meta/screen.h>
#include <meta/util.h>
/** /**
* SECTION:shell-xfixes-cursor * SECTION:shell-xfixes-cursor
@ -24,7 +27,7 @@ struct _ShellXFixesCursorClass
struct _ShellXFixesCursor { struct _ShellXFixesCursor {
GObject parent; GObject parent;
ClutterStage *stage; MetaScreen *screen;
gboolean have_xfixes; gboolean have_xfixes;
int xfixes_event_base; int xfixes_event_base;
@ -36,17 +39,14 @@ struct _ShellXFixesCursor {
int cursor_hot_y; int cursor_hot_y;
}; };
static void xfixes_cursor_show (ShellXFixesCursor *xfixes_cursor); static void xfixes_cursor_set_screen (ShellXFixesCursor *xfixes_cursor,
static void xfixes_cursor_hide (ShellXFixesCursor *xfixes_cursor); MetaScreen *screen);
static void xfixes_cursor_set_stage (ShellXFixesCursor *xfixes_cursor,
ClutterStage *stage);
static void xfixes_cursor_reset_image (ShellXFixesCursor *xfixes_cursor); static void xfixes_cursor_reset_image (ShellXFixesCursor *xfixes_cursor);
enum { enum {
PROP_0, PROP_0,
PROP_STAGE, PROP_SCREEN,
}; };
G_DEFINE_TYPE(ShellXFixesCursor, shell_xfixes_cursor, G_TYPE_OBJECT); G_DEFINE_TYPE(ShellXFixesCursor, shell_xfixes_cursor, G_TYPE_OBJECT);
@ -71,31 +71,22 @@ shell_xfixes_cursor_finalize (GObject *object)
{ {
ShellXFixesCursor *xfixes_cursor = SHELL_XFIXES_CURSOR (object); ShellXFixesCursor *xfixes_cursor = SHELL_XFIXES_CURSOR (object);
// Make sure the system cursor is showing before leaving the stage. xfixes_cursor_set_screen (xfixes_cursor, NULL);
xfixes_cursor_show (xfixes_cursor);
xfixes_cursor_set_stage (xfixes_cursor, NULL);
if (xfixes_cursor->cursor_sprite != NULL) if (xfixes_cursor->cursor_sprite != NULL)
cogl_handle_unref (xfixes_cursor->cursor_sprite); cogl_handle_unref (xfixes_cursor->cursor_sprite);
G_OBJECT_CLASS (shell_xfixes_cursor_parent_class)->finalize (object); G_OBJECT_CLASS (shell_xfixes_cursor_parent_class)->finalize (object);
} }
static void static GdkFilterReturn
xfixes_cursor_on_stage_destroy (ClutterActor *actor, xfixes_cursor_event_filter (XEvent *xev,
ShellXFixesCursor *xfixes_cursor) GdkEvent *ev,
{ gpointer data)
xfixes_cursor_set_stage (xfixes_cursor, NULL);
}
static ClutterX11FilterReturn
xfixes_cursor_event_filter (XEvent *xev,
ClutterEvent *cev,
gpointer data)
{ {
ShellXFixesCursor *xfixes_cursor = data; ShellXFixesCursor *xfixes_cursor = data;
if (xev->xany.window != clutter_x11_get_stage_window (xfixes_cursor->stage)) if (xev->xany.window != meta_get_overlay_window (xfixes_cursor->screen))
return CLUTTER_X11_FILTER_CONTINUE; return GDK_FILTER_CONTINUE;
if (xev->xany.type == xfixes_cursor->xfixes_event_base + XFixesCursorNotify) if (xev->xany.type == xfixes_cursor->xfixes_event_base + XFixesCursorNotify)
{ {
@ -103,93 +94,43 @@ xfixes_cursor_event_filter (XEvent *xev,
if (notify_event->subtype == XFixesDisplayCursorNotify) if (notify_event->subtype == XFixesDisplayCursorNotify)
xfixes_cursor_reset_image (xfixes_cursor); xfixes_cursor_reset_image (xfixes_cursor);
} }
return CLUTTER_X11_FILTER_CONTINUE;
return GDK_FILTER_CONTINUE;
} }
static void static void
xfixes_cursor_set_stage (ShellXFixesCursor *xfixes_cursor, xfixes_cursor_set_screen (ShellXFixesCursor *xfixes_cursor,
ClutterStage *stage) MetaScreen *screen)
{ {
if (xfixes_cursor->stage == stage) if (xfixes_cursor->screen == screen)
return; return;
if (xfixes_cursor->stage) if (xfixes_cursor->screen)
{ {
g_signal_handlers_disconnect_by_func (xfixes_cursor->stage, gdk_window_remove_filter (NULL, (GdkFilterFunc)xfixes_cursor_event_filter, xfixes_cursor);
(void *)xfixes_cursor_on_stage_destroy,
xfixes_cursor);
clutter_x11_remove_filter (xfixes_cursor_event_filter, xfixes_cursor);
} }
xfixes_cursor->stage = stage;
if (xfixes_cursor->stage) xfixes_cursor->screen = screen;
if (xfixes_cursor->screen)
{ {
int error_base; int error_base;
xfixes_cursor->stage = stage; gdk_window_add_filter (NULL, (GdkFilterFunc)xfixes_cursor_event_filter, xfixes_cursor);
g_signal_connect (xfixes_cursor->stage, "destroy",
G_CALLBACK (xfixes_cursor_on_stage_destroy), xfixes_cursor);
clutter_x11_add_filter (xfixes_cursor_event_filter, xfixes_cursor); xfixes_cursor->have_xfixes = XFixesQueryExtension (gdk_x11_get_default_xdisplay (),
xfixes_cursor->have_xfixes = XFixesQueryExtension (clutter_x11_get_default_display (),
&xfixes_cursor->xfixes_event_base, &xfixes_cursor->xfixes_event_base,
&error_base); &error_base);
if (xfixes_cursor->have_xfixes)
XFixesSelectCursorInput (clutter_x11_get_default_display (), /* FIXME: this needs to be moved down to mutter as a whole */
clutter_x11_get_stage_window (stage), if (xfixes_cursor->have_xfixes && !meta_is_display_server())
XFixesSelectCursorInput (gdk_x11_get_default_xdisplay (),
meta_get_overlay_window (screen),
XFixesDisplayCursorNotifyMask); XFixesDisplayCursorNotifyMask);
xfixes_cursor_reset_image (xfixes_cursor); xfixes_cursor_reset_image (xfixes_cursor);
} }
} }
static void
xfixes_cursor_show (ShellXFixesCursor *xfixes_cursor)
{
int minor, major;
Display *xdisplay;
Window xwindow;
if (xfixes_cursor->is_showing == TRUE)
return;
if (!xfixes_cursor->have_xfixes || !xfixes_cursor->stage)
return;
xdisplay = clutter_x11_get_default_display ();
xwindow = clutter_x11_get_stage_window (xfixes_cursor->stage);
XFixesQueryVersion (xdisplay, &major, &minor);
if (major >= 4)
{
XFixesShowCursor (xdisplay, xwindow);
xfixes_cursor->is_showing = TRUE;
}
}
static void
xfixes_cursor_hide (ShellXFixesCursor *xfixes_cursor)
{
int minor, major;
Display *xdisplay;
Window xwindow;
if (xfixes_cursor->is_showing == FALSE)
return;
if (!xfixes_cursor->have_xfixes || !xfixes_cursor->stage)
return;
xdisplay = clutter_x11_get_default_display ();
xwindow = clutter_x11_get_stage_window (xfixes_cursor->stage);
XFixesQueryVersion (xdisplay, &major, &minor);
if (major >= 4)
{
XFixesHideCursor (xdisplay, xwindow);
xfixes_cursor->is_showing = FALSE;
}
}
static void static void
xfixes_cursor_reset_image (ShellXFixesCursor *xfixes_cursor) xfixes_cursor_reset_image (ShellXFixesCursor *xfixes_cursor)
{ {
@ -201,7 +142,7 @@ xfixes_cursor_reset_image (ShellXFixesCursor *xfixes_cursor)
if (!xfixes_cursor->have_xfixes) if (!xfixes_cursor->have_xfixes)
return; return;
cursor_image = XFixesGetCursorImage (clutter_x11_get_default_display ()); cursor_image = XFixesGetCursorImage (gdk_x11_get_default_xdisplay ());
if (!cursor_image) if (!cursor_image)
return; return;
@ -265,8 +206,8 @@ shell_xfixes_cursor_set_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_STAGE: case PROP_SCREEN:
xfixes_cursor_set_stage (xfixes_cursor, g_value_get_object (value)); xfixes_cursor_set_screen (xfixes_cursor, g_value_get_object (value));
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -284,8 +225,8 @@ shell_xfixes_cursor_get_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_STAGE: case PROP_SCREEN:
g_value_set_object (value, G_OBJECT (xfixes_cursor->stage)); g_value_set_object (value, G_OBJECT (xfixes_cursor->screen));
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -311,22 +252,22 @@ shell_xfixes_cursor_class_init (ShellXFixesCursorClass *klass)
gobject_class->set_property = shell_xfixes_cursor_set_property; gobject_class->set_property = shell_xfixes_cursor_set_property;
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_STAGE, PROP_SCREEN,
g_param_spec_object ("stage", g_param_spec_object ("screen",
"Stage", "Screen",
"Stage for mouse cursor", "Screen for mouse cursor",
CLUTTER_TYPE_STAGE, META_TYPE_SCREEN,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
} }
/** /**
* shell_xfixes_cursor_get_for_stage: * shell_xfixes_cursor_get_for_screen:
* @stage: (transfer none): The #ClutterStage to get the cursor for * @screen: (transfer none): The #MetaScreen to get the cursor for
* *
* Return value: (transfer none): A #ShellXFixesCursor instance * Return value: (transfer none): A #ShellXFixesCursor instance
*/ */
ShellXFixesCursor * ShellXFixesCursor *
shell_xfixes_cursor_get_for_stage (ClutterStage *stage) shell_xfixes_cursor_get_for_screen (MetaScreen *screen)
{ {
ShellXFixesCursor *instance; ShellXFixesCursor *instance;
static GQuark xfixes_cursor_quark; static GQuark xfixes_cursor_quark;
@ -334,47 +275,19 @@ shell_xfixes_cursor_get_for_stage (ClutterStage *stage)
if (G_UNLIKELY (xfixes_cursor_quark == 0)) if (G_UNLIKELY (xfixes_cursor_quark == 0))
xfixes_cursor_quark = g_quark_from_static_string ("gnome-shell-xfixes-cursor"); xfixes_cursor_quark = g_quark_from_static_string ("gnome-shell-xfixes-cursor");
instance = g_object_get_qdata (G_OBJECT (stage), xfixes_cursor_quark); instance = g_object_get_qdata (G_OBJECT (screen), xfixes_cursor_quark);
if (instance == NULL) if (instance == NULL)
{ {
instance = g_object_new (SHELL_TYPE_XFIXES_CURSOR, instance = g_object_new (SHELL_TYPE_XFIXES_CURSOR,
"stage", stage, "screen", screen,
NULL); NULL);
g_object_set_qdata (G_OBJECT (stage), xfixes_cursor_quark, instance); g_object_set_qdata (G_OBJECT (screen), xfixes_cursor_quark, instance);
} }
return instance; return instance;
} }
/**
* shell_xfixes_cursor_hide:
* @xfixes_cursor: the #ShellXFixesCursor
*
* Hide the system mouse cursor.
*/
void
shell_xfixes_cursor_hide (ShellXFixesCursor *xfixes_cursor)
{
g_return_if_fail (SHELL_IS_XFIXES_CURSOR (xfixes_cursor));
xfixes_cursor_hide (xfixes_cursor);
}
/**
* shell_xfixes_cursor_show:
* @xfixes_cursor: the #ShellXFixesCursor
*
* Show the system mouse cursor to show
*/
void
shell_xfixes_cursor_show (ShellXFixesCursor *xfixes_cursor)
{
g_return_if_fail (SHELL_IS_XFIXES_CURSOR (xfixes_cursor));
xfixes_cursor_show (xfixes_cursor);
}
/** /**
* shell_xfixes_cursor_update_texture_image: * shell_xfixes_cursor_update_texture_image:
* @xfixes_cursor: the #ShellXFixesCursor * @xfixes_cursor: the #ShellXFixesCursor

View File

@ -4,6 +4,7 @@
#include <clutter/clutter.h> #include <clutter/clutter.h>
#include <gdk-pixbuf/gdk-pixbuf.h> #include <gdk-pixbuf/gdk-pixbuf.h>
#include <meta/screen.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@ -19,10 +20,8 @@ typedef struct _ShellXFixesCursorClass ShellXFixesCursorClass;
GType shell_xfixes_cursor_get_type (void) G_GNUC_CONST; GType shell_xfixes_cursor_get_type (void) G_GNUC_CONST;
ShellXFixesCursor *shell_xfixes_cursor_get_for_stage (ClutterStage *stage); ShellXFixesCursor *shell_xfixes_cursor_get_for_screen (MetaScreen *screen);
void shell_xfixes_cursor_show (ShellXFixesCursor *xfixes_cursor);
void shell_xfixes_cursor_hide (ShellXFixesCursor *xfixes_cursor);
int shell_xfixes_cursor_get_hot_x (ShellXFixesCursor *xfixes_cursor); int shell_xfixes_cursor_get_hot_x (ShellXFixesCursor *xfixes_cursor);
int shell_xfixes_cursor_get_hot_y (ShellXFixesCursor *xfixes_cursor); int shell_xfixes_cursor_get_hot_y (ShellXFixesCursor *xfixes_cursor);
void shell_xfixes_cursor_update_texture_image (ShellXFixesCursor *xfixes_cursor, void shell_xfixes_cursor_update_texture_image (ShellXFixesCursor *xfixes_cursor,