mirror of
https://gitlab.gnome.org/GNOME/libmks.git
synced 2024-09-28 18:15:47 +00:00
lib: set cursor from guest provided texture data
This commit is contained in:
parent
8dd08014b1
commit
5c52047800
@ -26,6 +26,7 @@
|
|||||||
#include "mks-display.h"
|
#include "mks-display.h"
|
||||||
#include "mks-keyboard.h"
|
#include "mks-keyboard.h"
|
||||||
#include "mks-mouse.h"
|
#include "mks-mouse.h"
|
||||||
|
#include "mks-paintable-private.h"
|
||||||
#include "mks-screen.h"
|
#include "mks-screen.h"
|
||||||
#include "mks-util-private.h"
|
#include "mks-util-private.h"
|
||||||
|
|
||||||
@ -42,6 +43,7 @@ typedef struct
|
|||||||
GdkPaintable *paintable;
|
GdkPaintable *paintable;
|
||||||
gulong invalidate_contents_handler;
|
gulong invalidate_contents_handler;
|
||||||
gulong invalidate_size_handler;
|
gulong invalidate_size_handler;
|
||||||
|
gulong notify_cursor_handler;
|
||||||
|
|
||||||
/* Tracking the last known positions of mouse events so that we may
|
/* Tracking the last known positions of mouse events so that we may
|
||||||
* do something "reasonable" if the pointer is not absolute.
|
* do something "reasonable" if the pointer is not absolute.
|
||||||
@ -98,24 +100,39 @@ mks_display_get_paintable_area (MksDisplay *self,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
mks_display_invalidate_contents_cb (MksDisplay *self,
|
mks_display_invalidate_contents_cb (MksDisplay *self,
|
||||||
GdkPaintable *paintable)
|
MksPaintable *paintable)
|
||||||
{
|
{
|
||||||
g_assert (MKS_IS_DISPLAY (self));
|
g_assert (MKS_IS_DISPLAY (self));
|
||||||
g_assert (GDK_IS_PAINTABLE (paintable));
|
g_assert (MKS_IS_PAINTABLE (paintable));
|
||||||
|
|
||||||
gtk_widget_queue_draw (GTK_WIDGET (self));
|
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mks_display_invalidate_size_cb (MksDisplay *self,
|
mks_display_invalidate_size_cb (MksDisplay *self,
|
||||||
GdkPaintable *paintable)
|
MksPaintable *paintable)
|
||||||
{
|
{
|
||||||
g_assert (MKS_IS_DISPLAY (self));
|
g_assert (MKS_IS_DISPLAY (self));
|
||||||
g_assert (GDK_IS_PAINTABLE (paintable));
|
g_assert (MKS_IS_PAINTABLE (paintable));
|
||||||
|
|
||||||
gtk_widget_queue_resize (GTK_WIDGET (self));
|
gtk_widget_queue_resize (GTK_WIDGET (self));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mks_display_notify_cursor_cb (MksDisplay *self,
|
||||||
|
GParamSpec *pspec,
|
||||||
|
MksPaintable *paintable)
|
||||||
|
{
|
||||||
|
GdkCursor *cursor;
|
||||||
|
|
||||||
|
g_assert (MKS_IS_DISPLAY (self));
|
||||||
|
g_assert (MKS_IS_PAINTABLE (paintable));
|
||||||
|
|
||||||
|
cursor = _mks_paintable_get_cursor (paintable);
|
||||||
|
|
||||||
|
gtk_widget_set_cursor (GTK_WIDGET (self), cursor);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mks_display_set_paintable (MksDisplay *self,
|
mks_display_set_paintable (MksDisplay *self,
|
||||||
GdkPaintable *paintable)
|
GdkPaintable *paintable)
|
||||||
@ -132,6 +149,7 @@ mks_display_set_paintable (MksDisplay *self,
|
|||||||
{
|
{
|
||||||
g_clear_signal_handler (&priv->invalidate_contents_handler, priv->paintable);
|
g_clear_signal_handler (&priv->invalidate_contents_handler, priv->paintable);
|
||||||
g_clear_signal_handler (&priv->invalidate_size_handler, priv->paintable);
|
g_clear_signal_handler (&priv->invalidate_size_handler, priv->paintable);
|
||||||
|
g_clear_signal_handler (&priv->notify_cursor_handler, priv->paintable);
|
||||||
g_clear_object (&priv->paintable);
|
g_clear_object (&priv->paintable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,6 +168,12 @@ mks_display_set_paintable (MksDisplay *self,
|
|||||||
G_CALLBACK (mks_display_invalidate_size_cb),
|
G_CALLBACK (mks_display_invalidate_size_cb),
|
||||||
self,
|
self,
|
||||||
G_CONNECT_SWAPPED);
|
G_CONNECT_SWAPPED);
|
||||||
|
priv->notify_cursor_handler =
|
||||||
|
g_signal_connect_object (paintable,
|
||||||
|
"notify::cursor",
|
||||||
|
G_CALLBACK (mks_display_notify_cursor_cb),
|
||||||
|
self,
|
||||||
|
G_CONNECT_SWAPPED);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_PAINTABLE]);
|
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_PAINTABLE]);
|
||||||
|
@ -32,5 +32,6 @@ G_DECLARE_FINAL_TYPE (MksPaintable, mks_paintable, MKS, PAINTABLE, GObject)
|
|||||||
GdkPaintable *_mks_paintable_new (GCancellable *cancellable,
|
GdkPaintable *_mks_paintable_new (GCancellable *cancellable,
|
||||||
int *peer_fd,
|
int *peer_fd,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
GdkCursor *_mks_paintable_get_cursor (MksPaintable *self);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
@ -39,10 +39,12 @@ struct _MksPaintable
|
|||||||
MksQemuListener *listener;
|
MksQemuListener *listener;
|
||||||
GDBusConnection *connection;
|
GDBusConnection *connection;
|
||||||
GdkPaintable *child;
|
GdkPaintable *child;
|
||||||
|
GdkCursor *cursor;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
|
PROP_CURSOR,
|
||||||
PROP_PAINTABLE,
|
PROP_PAINTABLE,
|
||||||
N_PROPS
|
N_PROPS
|
||||||
};
|
};
|
||||||
@ -149,6 +151,7 @@ mks_paintable_dispose (GObject *object)
|
|||||||
g_clear_object (&self->listener);
|
g_clear_object (&self->listener);
|
||||||
g_clear_object (&self->child);
|
g_clear_object (&self->child);
|
||||||
g_clear_object (&self->gl_context);
|
g_clear_object (&self->gl_context);
|
||||||
|
g_clear_object (&self->cursor);
|
||||||
|
|
||||||
G_OBJECT_CLASS (mks_paintable_parent_class)->dispose (object);
|
G_OBJECT_CLASS (mks_paintable_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
@ -163,6 +166,10 @@ mks_paintable_get_property (GObject *object,
|
|||||||
|
|
||||||
switch (prop_id)
|
switch (prop_id)
|
||||||
{
|
{
|
||||||
|
case PROP_CURSOR:
|
||||||
|
g_value_set_object (value, _mks_paintable_get_cursor (self));
|
||||||
|
break;
|
||||||
|
|
||||||
case PROP_PAINTABLE:
|
case PROP_PAINTABLE:
|
||||||
g_value_set_object (value, self->child);
|
g_value_set_object (value, self->child);
|
||||||
break;
|
break;
|
||||||
@ -180,6 +187,11 @@ mks_paintable_class_init (MksPaintableClass *klass)
|
|||||||
object_class->dispose = mks_paintable_dispose;
|
object_class->dispose = mks_paintable_dispose;
|
||||||
object_class->get_property = mks_paintable_get_property;
|
object_class->get_property = mks_paintable_get_property;
|
||||||
|
|
||||||
|
properties [PROP_CURSOR] =
|
||||||
|
g_param_spec_object ("cursor", NULL, NULL,
|
||||||
|
GDK_TYPE_CURSOR,
|
||||||
|
(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
properties [PROP_PAINTABLE] =
|
properties [PROP_PAINTABLE] =
|
||||||
g_param_spec_object ("paintable", NULL, NULL,
|
g_param_spec_object ("paintable", NULL, NULL,
|
||||||
GDK_TYPE_PAINTABLE,
|
GDK_TYPE_PAINTABLE,
|
||||||
@ -497,13 +509,43 @@ mks_paintable_listener_cursor_define (MksPaintable *self,
|
|||||||
int height,
|
int height,
|
||||||
int hot_x,
|
int hot_x,
|
||||||
int hot_y,
|
int hot_y,
|
||||||
GVariant *bytes,
|
GVariant *bytestring,
|
||||||
MksQemuListener *listener)
|
MksQemuListener *listener)
|
||||||
{
|
{
|
||||||
|
g_autoptr(GBytes) bytes = NULL;
|
||||||
|
g_autoptr(GdkTexture) texture = NULL;
|
||||||
|
g_autoptr(GdkCursor) cursor = NULL;
|
||||||
|
gsize data_len;
|
||||||
|
|
||||||
g_assert (MKS_IS_PAINTABLE (self));
|
g_assert (MKS_IS_PAINTABLE (self));
|
||||||
g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
|
g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
|
||||||
g_assert (MKS_QEMU_IS_LISTENER (listener));
|
g_assert (MKS_QEMU_IS_LISTENER (listener));
|
||||||
|
|
||||||
|
if (width < 1 || width > 512 ||
|
||||||
|
height < 1 || height > 512 ||
|
||||||
|
!(bytes = g_variant_get_data_as_bytes (bytestring)))
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
data_len = g_bytes_get_size (bytes);
|
||||||
|
if (data_len != (4 * width * height))
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
texture = gdk_memory_texture_new (width,
|
||||||
|
height,
|
||||||
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||||
|
GDK_MEMORY_B8G8R8A8_PREMULTIPLIED,
|
||||||
|
#else
|
||||||
|
GDK_MEMORY_A8R8G8B8_PREMULTIPLIED,
|
||||||
|
#endif
|
||||||
|
bytes,
|
||||||
|
width * 4);
|
||||||
|
|
||||||
|
cursor = gdk_cursor_new_from_texture (texture, hot_x, hot_y, NULL);
|
||||||
|
|
||||||
|
if (g_set_object (&self->cursor, cursor))
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CURSOR]);
|
||||||
|
|
||||||
|
failure:
|
||||||
mks_qemu_listener_complete_cursor_define (listener, invocation);
|
mks_qemu_listener_complete_cursor_define (listener, invocation);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -693,3 +735,19 @@ _mks_paintable_new (GCancellable *cancellable,
|
|||||||
|
|
||||||
return GDK_PAINTABLE (g_steal_pointer (&self));
|
return GDK_PAINTABLE (g_steal_pointer (&self));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _mks_paintable_get_cursor:
|
||||||
|
* @self: a #MksPaintable
|
||||||
|
*
|
||||||
|
* Gets the cursor as defined by the Qemu instance.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none) (nullable): a #GdkCursor or %NULL
|
||||||
|
*/
|
||||||
|
GdkCursor *
|
||||||
|
_mks_paintable_get_cursor (MksPaintable *self)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (MKS_IS_PAINTABLE (self), NULL);
|
||||||
|
|
||||||
|
return self->cursor;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user