[Spice-devel,spice-gtk,v2,1/3] cursor: Add cursor shape property

Submitted by Pavel Grunt on May 23, 2017, 2:56 p.m.

Details

Message ID 20170523145626.16741-1-pgrunt@redhat.com
State Accepted
Commit d24db22d3c41684d51ea9c80bc47f83d6ba3ba79
Headers show
Series "Series without cover letter" ( rev: 2 1 ) in Spice

Not browsing as part of any series.

Commit Message

Pavel Grunt May 23, 2017, 2:56 p.m.
It provides information about the remote cursor similar to the signal
"cursor-set". The benefit over the signal is that the property can be
queried at any time.

Users of the "cursor-set" signal should migrate to "notify::cursor".

Related:
https://bugzilla.redhat.com/show_bug.cgi?id=1411380
---
v2: split deprecation of the cursor-set signal
---
 doc/reference/spice-gtk-sections.txt |  3 ++
 src/channel-cursor.c                 | 99 +++++++++++++++++++++++++++++++++++-
 src/channel-cursor.h                 | 25 +++++++++
 src/map-file                         |  1 +
 src/spice-glib-sym-file              |  1 +
 5 files changed, 127 insertions(+), 2 deletions(-)

Patch hide | download patch | download mbox

diff --git a/doc/reference/spice-gtk-sections.txt b/doc/reference/spice-gtk-sections.txt
index 99baddf..ebc2845 100644
--- a/doc/reference/spice-gtk-sections.txt
+++ b/doc/reference/spice-gtk-sections.txt
@@ -180,6 +180,8 @@  SPICE_IS_DISPLAY_CHANNEL_CLASS
 SPICE_DISPLAY_CHANNEL_GET_CLASS
 SPICE_TYPE_GL_SCANOUT
 spice_gl_scanout_get_type
+SPICE_TYPE_CURSOR_SHAPE
+spice_cursor_shape_get_type
 <SUBSECTION Private>
 SpiceDisplayChannelPrivate
 </SECTION>
@@ -189,6 +191,7 @@  SpiceDisplayChannelPrivate
 <TITLE>SpiceCursorChannel</TITLE>
 SpiceCursorChannel
 SpiceCursorChannelClass
+SpiceCursorShape
 <SUBSECTION Standard>
 SPICE_CURSOR_CHANNEL
 SPICE_IS_CURSOR_CHANNEL
diff --git a/src/channel-cursor.c b/src/channel-cursor.c
index 609243b..53b1ecf 100644
--- a/src/channel-cursor.c
+++ b/src/channel-cursor.c
@@ -36,8 +36,9 @@ 
  * The Spice protocol defines a set of messages for controlling cursor
  * shape and position on the remote display area. The cursor changes
  * that should be reflected on the display are notified by
- * signals. See for example #SpiceCursorChannel::cursor-set
- * #SpiceCursorChannel::cursor-move signals.
+ * signals. See for example #SpiceCursorChannel::cursor-set and
+ * #SpiceCursorChannel::cursor-move signals and the #SpiceCursorChannel:cursor
+ * property.
  */
 
 #define SPICE_CURSOR_CHANNEL_GET_PRIVATE(obj)                                  \
@@ -55,6 +56,13 @@  struct display_cursor {
 struct _SpiceCursorChannelPrivate {
     display_cache               *cursors;
     gboolean                    init_done;
+    SpiceCursorShape            last_cursor;
+};
+
+/* Properties */
+enum {
+    PROP_0,
+    PROP_CURSOR,
 };
 
 enum {
@@ -74,7 +82,34 @@  static void channel_set_handlers(SpiceChannelClass *klass);
 
 G_DEFINE_TYPE(SpiceCursorChannel, spice_cursor_channel, SPICE_TYPE_CHANNEL)
 
+static SpiceCursorShape *spice_cursor_shape_copy(const SpiceCursorShape *cursor);
+static void spice_cursor_shape_free(SpiceCursorShape *cursor);
+
+G_DEFINE_BOXED_TYPE(SpiceCursorShape, spice_cursor_shape,
+                    (GBoxedCopyFunc)spice_cursor_shape_copy,
+                    (GBoxedFreeFunc)spice_cursor_shape_free)
+
 /* ------------------------------------------------------------------ */
+static SpiceCursorShape *spice_cursor_shape_copy(const SpiceCursorShape *cursor)
+{
+    SpiceCursorShape *new_cursor;
+
+    g_return_val_if_fail(cursor != NULL, NULL);
+
+    new_cursor = g_new(SpiceCursorShape, 1);
+    *new_cursor = *cursor;
+    new_cursor->data = g_memdup(cursor->data, cursor->width * cursor->height * 4);
+
+    return new_cursor;
+}
+
+static void spice_cursor_shape_free(SpiceCursorShape *cursor)
+{
+    g_return_if_fail(cursor != NULL);
+
+    g_free(cursor->data);
+    g_free(cursor);
+}
 
 static void spice_cursor_channel_init(SpiceCursorChannel *channel)
 {
@@ -107,15 +142,60 @@  static void spice_cursor_channel_reset(SpiceChannel *channel, gboolean migrating
     SPICE_CHANNEL_CLASS(spice_cursor_channel_parent_class)->channel_reset(channel, migrating);
 }
 
+static void spice_cursor_channel_dispose(GObject *object)
+{
+    SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(object)->priv;
+
+    g_clear_pointer(&c->last_cursor.data, g_free);
+
+    if (G_OBJECT_CLASS(spice_cursor_channel_parent_class)->dispose)
+        G_OBJECT_CLASS(spice_cursor_channel_parent_class)->dispose(object);
+}
+
+static void spice_cursor_channel_get_property(GObject    *object,
+                                              guint       prop_id,
+                                              GValue     *value,
+                                              GParamSpec *pspec)
+{
+    SpiceCursorChannel *channel = SPICE_CURSOR_CHANNEL(object);
+    SpiceCursorChannelPrivate *c = channel->priv;
+
+    switch (prop_id) {
+    case PROP_CURSOR:
+        g_value_set_static_boxed(value, c->last_cursor.data ? &c->last_cursor : NULL);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
 static void spice_cursor_channel_class_init(SpiceCursorChannelClass *klass)
 {
     GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
     SpiceChannelClass *channel_class = SPICE_CHANNEL_CLASS(klass);
 
+    gobject_class->dispose      = spice_cursor_channel_dispose;
     gobject_class->finalize     = spice_cursor_channel_finalize;
+    gobject_class->get_property = spice_cursor_channel_get_property;
     channel_class->channel_reset = spice_cursor_channel_reset;
 
     /**
+     * SpiceCursorChannel:cursor:
+     *
+     * The last #SpiceCursorShape received.
+     *
+     * Since: 0.34
+     */
+    g_object_class_install_property
+        (gobject_class, PROP_CURSOR,
+         g_param_spec_boxed("cursor",
+                            "Last cursor shape",
+                            "Last cursor shape received from the server",
+                            SPICE_TYPE_CURSOR_SHAPE,
+                            G_PARAM_READABLE |
+                            G_PARAM_STATIC_STRINGS));
+    /**
      * SpiceCursorChannel::cursor-set:
      * @cursor: the #SpiceCursorChannel that emitted the signal
      * @width: width of the shape
@@ -399,7 +479,22 @@  cache_add:
 /* coroutine context */
 static void emit_cursor_set(SpiceChannel *channel, display_cursor *cursor)
 {
+    SpiceCursorChannelPrivate *c;
+
     g_return_if_fail(cursor != NULL);
+
+    c = SPICE_CURSOR_CHANNEL(channel)->priv;
+
+    c->last_cursor.type = cursor->hdr.type;
+    c->last_cursor.width = cursor->hdr.width;
+    c->last_cursor.height = cursor->hdr.height;
+    c->last_cursor.hot_spot_x = cursor->hdr.hot_spot_x;
+    c->last_cursor.hot_spot_y = cursor->hdr.hot_spot_y;
+    g_free(c->last_cursor.data);
+    c->last_cursor.data = g_memdup(cursor->data,
+                                   cursor->hdr.width * cursor->hdr.height * 4);
+
+    g_coroutine_object_notify(G_OBJECT(channel), "cursor");
     g_coroutine_signal_emit(channel, signals[SPICE_CURSOR_SET], 0,
                             cursor->hdr.width, cursor->hdr.height,
                             cursor->hdr.hot_spot_x, cursor->hdr.hot_spot_y,
diff --git a/src/channel-cursor.h b/src/channel-cursor.h
index 20f0380..7ba48a9 100644
--- a/src/channel-cursor.h
+++ b/src/channel-cursor.h
@@ -37,6 +37,29 @@  typedef struct _SpiceCursorChannel SpiceCursorChannel;
 typedef struct _SpiceCursorChannelClass SpiceCursorChannelClass;
 typedef struct _SpiceCursorChannelPrivate SpiceCursorChannelPrivate;
 
+#define SPICE_TYPE_CURSOR_SHAPE (spice_cursor_shape_get_type())
+/**
+ * SpiceCursorShape:
+ * @type: a #SpiceCursorType of @data
+ * @width: a width of the remote cursor
+ * @height: a height of the remote cursor
+ * @hot_spot_x: a 'x' coordinate of the remote cursor
+ * @hot_spot_y: a 'y' coordinate of the remote cursor
+ * @data: image data of the remote cursor
+ *
+ * The #SpiceCursorShape structure defines the remote cursor's shape.
+ *
+ */
+typedef struct _SpiceCursorShape SpiceCursorShape;
+struct _SpiceCursorShape {
+    SpiceCursorType type;
+    guint16 width;
+    guint16 height;
+    guint16 hot_spot_x;
+    guint16 hot_spot_y;
+    gpointer data;
+};
+
 /**
  * SpiceCursorChannel:
  *
@@ -76,6 +99,8 @@  struct _SpiceCursorChannelClass {
 
 GType spice_cursor_channel_get_type(void);
 
+GType spice_cursor_shape_get_type(void) G_GNUC_CONST;
+
 G_END_DECLS
 
 #endif /* __SPICE_CLIENT_CURSOR_CHANNEL_H__ */
diff --git a/src/map-file b/src/map-file
index 31cafc2..668ff41 100644
--- a/src/map-file
+++ b/src/map-file
@@ -20,6 +20,7 @@  spice_channel_test_common_capability;
 spice_channel_type_to_string;
 spice_client_error_quark;
 spice_cursor_channel_get_type;
+spice_cursor_shape_get_type;
 spice_display_change_preferred_compression;
 spice_display_change_preferred_video_codec_type;
 spice_display_channel_get_type;
diff --git a/src/spice-glib-sym-file b/src/spice-glib-sym-file
index d73f799..e061744 100644
--- a/src/spice-glib-sym-file
+++ b/src/spice-glib-sym-file
@@ -18,6 +18,7 @@  spice_channel_test_common_capability
 spice_channel_type_to_string
 spice_client_error_quark
 spice_cursor_channel_get_type
+spice_cursor_shape_get_type
 spice_display_change_preferred_compression
 spice_display_change_preferred_video_codec_type
 spice_display_channel_get_type

Comments

On Tue, May 23, 2017 at 04:56:24PM +0200, Pavel Grunt wrote:
> It provides information about the remote cursor similar to the signal
> "cursor-set". The benefit over the signal is that the property can be
> queried at any time.
>
> Users of the "cursor-set" signal should migrate to "notify::cursor".
>
> Related:
> https://bugzilla.redhat.com/show_bug.cgi?id=1411380

Acked-by: Victor Toso <victortoso@redhat.com>

> ---
> v2: split deprecation of the cursor-set signal
> ---
>  doc/reference/spice-gtk-sections.txt |  3 ++
>  src/channel-cursor.c                 | 99 +++++++++++++++++++++++++++++++++++-
>  src/channel-cursor.h                 | 25 +++++++++
>  src/map-file                         |  1 +
>  src/spice-glib-sym-file              |  1 +
>  5 files changed, 127 insertions(+), 2 deletions(-)
> 
> diff --git a/doc/reference/spice-gtk-sections.txt b/doc/reference/spice-gtk-sections.txt
> index 99baddf..ebc2845 100644
> --- a/doc/reference/spice-gtk-sections.txt
> +++ b/doc/reference/spice-gtk-sections.txt
> @@ -180,6 +180,8 @@ SPICE_IS_DISPLAY_CHANNEL_CLASS
>  SPICE_DISPLAY_CHANNEL_GET_CLASS
>  SPICE_TYPE_GL_SCANOUT
>  spice_gl_scanout_get_type
> +SPICE_TYPE_CURSOR_SHAPE
> +spice_cursor_shape_get_type
>  <SUBSECTION Private>
>  SpiceDisplayChannelPrivate
>  </SECTION>
> @@ -189,6 +191,7 @@ SpiceDisplayChannelPrivate
>  <TITLE>SpiceCursorChannel</TITLE>
>  SpiceCursorChannel
>  SpiceCursorChannelClass
> +SpiceCursorShape
>  <SUBSECTION Standard>
>  SPICE_CURSOR_CHANNEL
>  SPICE_IS_CURSOR_CHANNEL
> diff --git a/src/channel-cursor.c b/src/channel-cursor.c
> index 609243b..53b1ecf 100644
> --- a/src/channel-cursor.c
> +++ b/src/channel-cursor.c
> @@ -36,8 +36,9 @@
>   * The Spice protocol defines a set of messages for controlling cursor
>   * shape and position on the remote display area. The cursor changes
>   * that should be reflected on the display are notified by
> - * signals. See for example #SpiceCursorChannel::cursor-set
> - * #SpiceCursorChannel::cursor-move signals.
> + * signals. See for example #SpiceCursorChannel::cursor-set and
> + * #SpiceCursorChannel::cursor-move signals and the #SpiceCursorChannel:cursor
> + * property.
>   */
>  
>  #define SPICE_CURSOR_CHANNEL_GET_PRIVATE(obj)                                  \
> @@ -55,6 +56,13 @@ struct display_cursor {
>  struct _SpiceCursorChannelPrivate {
>      display_cache               *cursors;
>      gboolean                    init_done;
> +    SpiceCursorShape            last_cursor;
> +};
> +
> +/* Properties */
> +enum {
> +    PROP_0,
> +    PROP_CURSOR,
>  };
>  
>  enum {
> @@ -74,7 +82,34 @@ static void channel_set_handlers(SpiceChannelClass *klass);
>  
>  G_DEFINE_TYPE(SpiceCursorChannel, spice_cursor_channel, SPICE_TYPE_CHANNEL)
>  
> +static SpiceCursorShape *spice_cursor_shape_copy(const SpiceCursorShape *cursor);
> +static void spice_cursor_shape_free(SpiceCursorShape *cursor);
> +
> +G_DEFINE_BOXED_TYPE(SpiceCursorShape, spice_cursor_shape,
> +                    (GBoxedCopyFunc)spice_cursor_shape_copy,
> +                    (GBoxedFreeFunc)spice_cursor_shape_free)
> +
>  /* ------------------------------------------------------------------ */
> +static SpiceCursorShape *spice_cursor_shape_copy(const SpiceCursorShape *cursor)
> +{
> +    SpiceCursorShape *new_cursor;
> +
> +    g_return_val_if_fail(cursor != NULL, NULL);
> +
> +    new_cursor = g_new(SpiceCursorShape, 1);
> +    *new_cursor = *cursor;
> +    new_cursor->data = g_memdup(cursor->data, cursor->width * cursor->height * 4);
> +
> +    return new_cursor;
> +}
> +
> +static void spice_cursor_shape_free(SpiceCursorShape *cursor)
> +{
> +    g_return_if_fail(cursor != NULL);
> +
> +    g_free(cursor->data);
> +    g_free(cursor);
> +}
>  
>  static void spice_cursor_channel_init(SpiceCursorChannel *channel)
>  {
> @@ -107,15 +142,60 @@ static void spice_cursor_channel_reset(SpiceChannel *channel, gboolean migrating
>      SPICE_CHANNEL_CLASS(spice_cursor_channel_parent_class)->channel_reset(channel, migrating);
>  }
>  
> +static void spice_cursor_channel_dispose(GObject *object)
> +{
> +    SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(object)->priv;
> +
> +    g_clear_pointer(&c->last_cursor.data, g_free);
> +
> +    if (G_OBJECT_CLASS(spice_cursor_channel_parent_class)->dispose)
> +        G_OBJECT_CLASS(spice_cursor_channel_parent_class)->dispose(object);
> +}
> +
> +static void spice_cursor_channel_get_property(GObject    *object,
> +                                              guint       prop_id,
> +                                              GValue     *value,
> +                                              GParamSpec *pspec)
> +{
> +    SpiceCursorChannel *channel = SPICE_CURSOR_CHANNEL(object);
> +    SpiceCursorChannelPrivate *c = channel->priv;
> +
> +    switch (prop_id) {
> +    case PROP_CURSOR:
> +        g_value_set_static_boxed(value, c->last_cursor.data ? &c->last_cursor : NULL);
> +        break;
> +    default:
> +        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
> +        break;
> +    }
> +}
> +
>  static void spice_cursor_channel_class_init(SpiceCursorChannelClass *klass)
>  {
>      GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
>      SpiceChannelClass *channel_class = SPICE_CHANNEL_CLASS(klass);
>  
> +    gobject_class->dispose      = spice_cursor_channel_dispose;
>      gobject_class->finalize     = spice_cursor_channel_finalize;
> +    gobject_class->get_property = spice_cursor_channel_get_property;
>      channel_class->channel_reset = spice_cursor_channel_reset;
>  
>      /**
> +     * SpiceCursorChannel:cursor:
> +     *
> +     * The last #SpiceCursorShape received.
> +     *
> +     * Since: 0.34
> +     */
> +    g_object_class_install_property
> +        (gobject_class, PROP_CURSOR,
> +         g_param_spec_boxed("cursor",
> +                            "Last cursor shape",
> +                            "Last cursor shape received from the server",
> +                            SPICE_TYPE_CURSOR_SHAPE,
> +                            G_PARAM_READABLE |
> +                            G_PARAM_STATIC_STRINGS));
> +    /**
>       * SpiceCursorChannel::cursor-set:
>       * @cursor: the #SpiceCursorChannel that emitted the signal
>       * @width: width of the shape
> @@ -399,7 +479,22 @@ cache_add:
>  /* coroutine context */
>  static void emit_cursor_set(SpiceChannel *channel, display_cursor *cursor)
>  {
> +    SpiceCursorChannelPrivate *c;
> +
>      g_return_if_fail(cursor != NULL);
> +
> +    c = SPICE_CURSOR_CHANNEL(channel)->priv;
> +
> +    c->last_cursor.type = cursor->hdr.type;
> +    c->last_cursor.width = cursor->hdr.width;
> +    c->last_cursor.height = cursor->hdr.height;
> +    c->last_cursor.hot_spot_x = cursor->hdr.hot_spot_x;
> +    c->last_cursor.hot_spot_y = cursor->hdr.hot_spot_y;
> +    g_free(c->last_cursor.data);
> +    c->last_cursor.data = g_memdup(cursor->data,
> +                                   cursor->hdr.width * cursor->hdr.height * 4);
> +
> +    g_coroutine_object_notify(G_OBJECT(channel), "cursor");
>      g_coroutine_signal_emit(channel, signals[SPICE_CURSOR_SET], 0,
>                              cursor->hdr.width, cursor->hdr.height,
>                              cursor->hdr.hot_spot_x, cursor->hdr.hot_spot_y,
> diff --git a/src/channel-cursor.h b/src/channel-cursor.h
> index 20f0380..7ba48a9 100644
> --- a/src/channel-cursor.h
> +++ b/src/channel-cursor.h
> @@ -37,6 +37,29 @@ typedef struct _SpiceCursorChannel SpiceCursorChannel;
>  typedef struct _SpiceCursorChannelClass SpiceCursorChannelClass;
>  typedef struct _SpiceCursorChannelPrivate SpiceCursorChannelPrivate;
>  
> +#define SPICE_TYPE_CURSOR_SHAPE (spice_cursor_shape_get_type())
> +/**
> + * SpiceCursorShape:
> + * @type: a #SpiceCursorType of @data
> + * @width: a width of the remote cursor
> + * @height: a height of the remote cursor
> + * @hot_spot_x: a 'x' coordinate of the remote cursor
> + * @hot_spot_y: a 'y' coordinate of the remote cursor
> + * @data: image data of the remote cursor
> + *
> + * The #SpiceCursorShape structure defines the remote cursor's shape.
> + *
> + */
> +typedef struct _SpiceCursorShape SpiceCursorShape;
> +struct _SpiceCursorShape {
> +    SpiceCursorType type;
> +    guint16 width;
> +    guint16 height;
> +    guint16 hot_spot_x;
> +    guint16 hot_spot_y;
> +    gpointer data;
> +};
> +
>  /**
>   * SpiceCursorChannel:
>   *
> @@ -76,6 +99,8 @@ struct _SpiceCursorChannelClass {
>  
>  GType spice_cursor_channel_get_type(void);
>  
> +GType spice_cursor_shape_get_type(void) G_GNUC_CONST;
> +
>  G_END_DECLS
>  
>  #endif /* __SPICE_CLIENT_CURSOR_CHANNEL_H__ */
> diff --git a/src/map-file b/src/map-file
> index 31cafc2..668ff41 100644
> --- a/src/map-file
> +++ b/src/map-file
> @@ -20,6 +20,7 @@ spice_channel_test_common_capability;
>  spice_channel_type_to_string;
>  spice_client_error_quark;
>  spice_cursor_channel_get_type;
> +spice_cursor_shape_get_type;
>  spice_display_change_preferred_compression;
>  spice_display_change_preferred_video_codec_type;
>  spice_display_channel_get_type;
> diff --git a/src/spice-glib-sym-file b/src/spice-glib-sym-file
> index d73f799..e061744 100644
> --- a/src/spice-glib-sym-file
> +++ b/src/spice-glib-sym-file
> @@ -18,6 +18,7 @@ spice_channel_test_common_capability
>  spice_channel_type_to_string
>  spice_client_error_quark
>  spice_cursor_channel_get_type
> +spice_cursor_shape_get_type
>  spice_display_change_preferred_compression
>  spice_display_change_preferred_video_codec_type
>  spice_display_channel_get_type
> -- 
> 2.13.0
> 
> _______________________________________________
> Spice-devel mailing list
> Spice-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/spice-devel