[gtk+] mir: implement window properties



commit ed0bd0bba29114a893b1355f799f6568dddf5d9a
Author: William Hua <william hua canonical com>
Date:   Tue Oct 11 19:06:12 2016 -0400

    mir: implement window properties
    
    https://bugzilla.gnome.org/show_bug.cgi?id=775732

 gdk/mir/gdkmirwindowimpl.c |  179 ++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 163 insertions(+), 16 deletions(-)
---
diff --git a/gdk/mir/gdkmirwindowimpl.c b/gdk/mir/gdkmirwindowimpl.c
index aae3886..862fd15 100644
--- a/gdk/mir/gdkmirwindowimpl.c
+++ b/gdk/mir/gdkmirwindowimpl.c
@@ -36,12 +36,45 @@
 
 #define MAX_EGL_ATTRS 30
 
+typedef struct
+{
+  GdkAtom type;
+  GArray *array;
+} GdkMirProperty;
+
+static GdkMirProperty *
+gdk_mir_property_new (GdkAtom type,
+                      guint   format,
+                      guint   capacity)
+{
+  GdkMirProperty *property = g_slice_new (GdkMirProperty);
+
+  property->type = type;
+  property->array = g_array_sized_new (TRUE, FALSE, format, capacity);
+
+  return property;
+}
+
+static void
+gdk_mir_property_free (gpointer data)
+{
+  GdkMirProperty *property = data;
+
+  if (!property)
+    return;
+
+  g_array_unref (property->array);
+  g_slice_free (GdkMirProperty, property);
+}
+
 typedef struct _GdkMirWindowImplClass GdkMirWindowImplClass;
 
 struct _GdkMirWindowImpl
 {
   GdkWindowImpl parent_instance;
 
+  GHashTable *properties;
+
   /* Window we are temporary for */
   GdkWindow *transient_for;
   gint transient_x;
@@ -224,6 +257,7 @@ _gdk_mir_window_impl_get_cursor_state (GdkMirWindowImpl *impl,
 static void
 gdk_mir_window_impl_init (GdkMirWindowImpl *impl)
 {
+  impl->properties = g_hash_table_new_full (NULL, NULL, NULL, gdk_mir_property_free);
   impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
   impl->surface_state = mir_surface_state_unknown;
   impl->output_scale = 1;
@@ -666,6 +700,8 @@ gdk_mir_window_impl_finalize (GObject *object)
   if (impl->cairo_surface)
     cairo_surface_destroy (impl->cairo_surface);
 
+  g_clear_pointer (&impl->properties, g_hash_table_unref);
+
   G_OBJECT_CLASS (gdk_mir_window_impl_parent_class)->finalize (object);
 }
 
@@ -1396,19 +1432,79 @@ gdk_mir_window_impl_simulate_button (GdkWindow       *window,
 }
 
 static gboolean
-gdk_mir_window_impl_get_property (GdkWindow   *window,
-                                  GdkAtom      property,
-                                  GdkAtom      type,
-                                  gulong       offset,
-                                  gulong       length,
-                                  gint         pdelete,
-                                  GdkAtom     *actual_property_type,
-                                  gint        *actual_format_type,
-                                  gint        *actual_length,
-                                  guchar     **data)
-{
-  //g_printerr ("gdk_mir_window_impl_get_property window=%p\n", window);
-  return FALSE;
+gdk_mir_window_impl_get_property (GdkWindow  *window,
+                                  GdkAtom     property,
+                                  GdkAtom     type,
+                                  gulong      offset,
+                                  gulong      length,
+                                  gint        pdelete,
+                                  GdkAtom    *actual_type,
+                                  gint       *actual_format,
+                                  gint       *actual_length,
+                                  guchar    **data)
+{
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
+  GdkMirProperty *mir_property;
+  GdkAtom dummy_actual_type;
+  gint dummy_actual_format;
+  gint dummy_actual_length;
+  guint width;
+
+  if (!actual_type)
+    actual_type = &dummy_actual_type;
+  if (!actual_format)
+    actual_format = &dummy_actual_format;
+  if (!actual_length)
+    actual_length = &dummy_actual_length;
+
+  *actual_type = GDK_NONE;
+  *actual_format = 0;
+  *actual_length = 0;
+
+  if (data)
+    *data = NULL;
+
+  mir_property = g_hash_table_lookup (impl->properties, property);
+
+  if (!mir_property)
+    return FALSE;
+
+  width = g_array_get_element_size (mir_property->array);
+  *actual_type = mir_property->type;
+  *actual_format = 8 * width;
+
+  /* ICCCM 2.7: GdkAtoms can be 64-bit, but ATOMs and ATOM_PAIRs have format 32  */
+  if (*actual_type == GDK_SELECTION_TYPE_ATOM || *actual_type == gdk_atom_intern_static_string ("ATOM_PAIR"))
+    *actual_format = 32;
+
+  if (type != GDK_NONE && type != mir_property->type)
+    return FALSE;
+
+  offset *= 4;
+
+  /* round up to next nearest multiple of width */
+  if (length < G_MAXULONG - width + 1)
+    length = (length - 1 + width) / width * width;
+  else
+    length = G_MAXULONG / width * width;
+
+  /* we're skipping the first offset bytes */
+  if (length > mir_property->array->len * width - offset)
+    length = mir_property->array->len * width - offset;
+
+  /* leave room for null terminator */
+  if (length > G_MAXULONG - width)
+    length -= width;
+
+  *actual_length = length;
+
+  if (data)
+    {
+      *data = g_memdup (mir_property->array->data + offset, length + width);
+      memset (*data + length, 0, width);
+    }
+
+  return TRUE;
 }
 
 static void
@@ -1418,16 +1514,67 @@ gdk_mir_window_impl_change_property (GdkWindow    *window,
                                      gint          format,
                                      GdkPropMode   mode,
                                      const guchar *data,
-                                     gint          nelements)
+                                     gint          n_elements)
 {
-  //g_printerr ("gdk_mir_window_impl_change_property window=%p\n", window);
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
+  GdkMirProperty *mir_property;
+  GdkEvent *event;
+
+  /* ICCCM 2.7: ATOMs and ATOM_PAIRs have format 32, but GdkAtoms can be 64-bit */
+  if (type == GDK_SELECTION_TYPE_ATOM || type == gdk_atom_intern_static_string ("ATOM_PAIR"))
+    format = 8 * sizeof (GdkAtom);
+
+  if (mode != GDK_PROP_MODE_REPLACE)
+    mir_property = g_hash_table_lookup (impl->properties, property);
+  else
+    mir_property = NULL;
+
+  if (!mir_property)
+    {
+      /* format is measured in bits, but we need to know this in bytes */
+      mir_property = gdk_mir_property_new (type, format / 8, n_elements);
+      g_hash_table_insert (impl->properties, property, mir_property);
+    }
+
+  /* format is measured in bits, but we need to know this in bytes */
+  if (type != mir_property->type || format / 8 != g_array_get_element_size (mir_property->array))
+    return;
+
+  if (mode == GDK_PROP_MODE_PREPEND)
+    g_array_prepend_vals (mir_property->array, data, n_elements);
+  else
+    g_array_append_vals (mir_property->array, data, n_elements);
+
+  event = gdk_event_new (GDK_PROPERTY_NOTIFY);
+  event->property.window = g_object_ref (window);
+  event->property.send_event = FALSE;
+  event->property.atom = property;
+  event->property.time = GDK_CURRENT_TIME;
+  event->property.state = GDK_PROPERTY_NEW_VALUE;
+
+  gdk_event_put (event);
+  gdk_event_free (event);
 }
 
 static void
 gdk_mir_window_impl_delete_property (GdkWindow *window,
                                      GdkAtom    property)
 {
-  //g_printerr ("gdk_mir_window_impl_delete_property window=%p\n", window);
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
+  GdkEvent *event;
+
+  if (g_hash_table_remove (impl->properties, property))
+    {
+      event = gdk_event_new (GDK_PROPERTY_NOTIFY);
+      event->property.window = g_object_ref (window);
+      event->property.send_event = FALSE;
+      event->property.atom = property;
+      event->property.time = GDK_CURRENT_TIME;
+      event->property.state = GDK_PROPERTY_DELETE;
+
+      gdk_event_put (event);
+      gdk_event_free (event);
+    }
 }
 
 static gint


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]