summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Hua <william.hua@canonical.com>2016-10-11 19:06:12 -0400
committerWilliam Hua <william.hua@canonical.com>2017-01-05 17:57:36 -0500
commited0bd0bba29114a893b1355f799f6568dddf5d9a (patch)
treec575ffe2612df3789daf834ed682132f4bf81c3b
parentf3779b42c57b1bf628f83853f5ca532aa061bb12 (diff)
downloadgtk+-ed0bd0bba29114a893b1355f799f6568dddf5d9a.tar.gz
mir: implement window properties
https://bugzilla.gnome.org/show_bug.cgi?id=775732
-rw-r--r--gdk/mir/gdkmirwindowimpl.c179
1 files changed, 163 insertions, 16 deletions
diff --git a/gdk/mir/gdkmirwindowimpl.c b/gdk/mir/gdkmirwindowimpl.c
index aae3886d6a..862fd15f70 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