Merge lp:~attente/gtk/gtk-mir into lp:~ubuntu-desktop/gtk/ubuntugtk3

Proposed by William Hua
Status: Merged
Merged at revision: 544
Proposed branch: lp:~attente/gtk/gtk-mir
Merge into: lp:~ubuntu-desktop/gtk/ubuntugtk3
Diff against target: 2085 lines (+1996/-2)
14 files modified
debian/changelog (+20/-0)
debian/control (+2/-1)
debian/control.in (+2/-1)
debian/patches/0001-mir-implement-window-properties.patch (+244/-0)
debian/patches/0002-mir-track-focused-window.patch (+91/-0)
debian/patches/0003-mir-connect-to-content-hub.patch (+108/-0)
debian/patches/0004-mir-copy-clipboard-data-to-content-hub.patch (+292/-0)
debian/patches/0005-mir-paste-clipboard-data-from-content-hub.patch (+415/-0)
debian/patches/0006-mir-properly-handle-empty-clipboard.patch (+37/-0)
debian/patches/0031-mir-fix-compile-time-warnings.patch (+77/-0)
debian/patches/0032-mir-use-modal-window-hint.patch (+76/-0)
debian/patches/0036-mir-use-mir_surface_spec_set_placement-for-menus.patch (+334/-0)
debian/patches/0037-mir-handle-surface-placement-events.patch (+287/-0)
debian/patches/series (+11/-0)
To merge this branch: bzr merge lp:~attente/gtk/gtk-mir
Reviewer Review Type Date Requested Status
Jeremy Bícha Approve
Review via email: mp+316716@code.launchpad.net

Commit message

  * debian/control:
  * debian/control.in:
    - Build depend on libcontent-hub-glib-dev
  * debian/patches/series:
  * debian/patches/0001-mir-implement-window-properties.patch:
  * debian/patches/0002-mir-track-focused-window.patch:
  * debian/patches/0003-mir-connect-to-content-hub.patch:
  * debian/patches/0004-mir-copy-clipboard-data-to-content-hub.patch:
  * debian/patches/0005-mir-paste-clipboard-data-from-content-hub.patch:
  * debian/patches/0006-mir-properly-handle-empty-clipboard.patch:
  * debian/patches/0031-mir-fix-compile-time-warnings.patch:
  * debian/patches/0032-mir-use-modal-window-hint.patch:
  * debian/patches/0036-mir-use-mir_surface_spec_set_placement-for-menus.patch:
  * debian/patches/0037-mir-handle-surface-placement-events.patch:
    - Add upstream patches from gtk-3-22 branch

Description of the change

Apply upstream patches from gtk-3-22 branch:

  * debian/control:
  * debian/control.in:
    - Build depend on libcontent-hub-glib-dev
  * debian/patches/series:
  * debian/patches/0001-mir-implement-window-properties.patch:
  * debian/patches/0002-mir-track-focused-window.patch:
  * debian/patches/0003-mir-connect-to-content-hub.patch:
  * debian/patches/0004-mir-copy-clipboard-data-to-content-hub.patch:
  * debian/patches/0005-mir-paste-clipboard-data-from-content-hub.patch:
  * debian/patches/0006-mir-properly-handle-empty-clipboard.patch:
  * debian/patches/0031-mir-fix-compile-time-warnings.patch:
  * debian/patches/0032-mir-use-modal-window-hint.patch:
  * debian/patches/0036-mir-use-mir_surface_spec_set_placement-for-menus.patch:
  * debian/patches/0037-mir-handle-surface-placement-events.patch:
    - Add upstream patches from gtk-3-22 branch

To post a comment you must log in.
Revision history for this message
Jeremy Bícha (jbicha) wrote :

Thanks!

review: Approve
lp:~attente/gtk/gtk-mir updated
544. By William Hua

* debian/control:
* debian/control.in:
  - Build depend on libcontent-hub-glib-dev
* debian/patches/series:
* debian/patches/0001-mir-implement-window-properties.patch:
* debian/patches/0002-mir-track-focused-window.patch:
* debian/patches/0003-mir-connect-to-content-hub.patch:
* debian/patches/0004-mir-copy-clipboard-data-to-content-hub.patch:
* debian/patches/0005-mir-paste-clipboard-data-from-content-hub.patch:
* debian/patches/0006-mir-properly-handle-empty-clipboard.patch:
* debian/patches/0031-mir-fix-compile-time-warnings.patch:
* debian/patches/0032-mir-use-modal-window-hint.patch:
* debian/patches/0036-mir-use-mir_surface_spec_set_placement-for-menus.patch:
* debian/patches/0037-mir-handle-surface-placement-events.patch:
  - Add upstream patches from gtk-3-22 branch

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/changelog'
--- debian/changelog 2017-01-23 14:44:32 +0000
+++ debian/changelog 2017-02-08 17:37:49 +0000
@@ -1,3 +1,23 @@
1gtk+3.0 (3.22.7-1ubuntu3) zesty; urgency=medium
2
3 * debian/control:
4 * debian/control.in:
5 - Build depend on libcontent-hub-glib-dev
6 * debian/patches/series:
7 * debian/patches/0001-mir-implement-window-properties.patch:
8 * debian/patches/0002-mir-track-focused-window.patch:
9 * debian/patches/0003-mir-connect-to-content-hub.patch:
10 * debian/patches/0004-mir-copy-clipboard-data-to-content-hub.patch:
11 * debian/patches/0005-mir-paste-clipboard-data-from-content-hub.patch:
12 * debian/patches/0006-mir-properly-handle-empty-clipboard.patch:
13 * debian/patches/0031-mir-fix-compile-time-warnings.patch:
14 * debian/patches/0032-mir-use-modal-window-hint.patch:
15 * debian/patches/0036-mir-use-mir_surface_spec_set_placement-for-menus.patch:
16 * debian/patches/0037-mir-handle-surface-placement-events.patch:
17 - Add upstream patches from gtk-3-22 branch
18
19 -- William Hua <william.hua@canonical.com> Wed, 08 Feb 2017 10:27:45 -0500
20
1gtk+3.0 (3.22.7-1ubuntu2) zesty; urgency=medium21gtk+3.0 (3.22.7-1ubuntu2) zesty; urgency=medium
222
3 * Restore gtksocket-unscale-before-sending-configurenotify.patch:23 * Restore gtksocket-unscale-before-sending-configurenotify.patch:
424
=== modified file 'debian/control'
--- debian/control 2016-10-24 16:41:31 +0000
+++ debian/control 2017-02-08 17:37:49 +0000
@@ -52,7 +52,8 @@
52 xsltproc,52 xsltproc,
53 xvfb <!nocheck>,53 xvfb <!nocheck>,
54 libmirclient-dev (>= 0.13.3),54 libmirclient-dev (>= 0.13.3),
55 libmircookie-dev (>= 0.17.0)55 libmircookie-dev (>= 0.17.0),
56 libcontent-hub-glib-dev,
56Build-Depends-Indep: libglib2.0-doc,57Build-Depends-Indep: libglib2.0-doc,
57 libatk1.0-doc,58 libatk1.0-doc,
58 libpango1.0-doc,59 libpango1.0-doc,
5960
=== modified file 'debian/control.in'
--- debian/control.in 2016-10-24 16:41:31 +0000
+++ debian/control.in 2017-02-08 17:37:49 +0000
@@ -52,7 +52,8 @@
52 xsltproc,52 xsltproc,
53 xvfb <!nocheck>,53 xvfb <!nocheck>,
54 libmirclient-dev (>= 0.13.3),54 libmirclient-dev (>= 0.13.3),
55 libmircookie-dev (>= 0.17.0)55 libmircookie-dev (>= 0.17.0),
56 libcontent-hub-glib-dev,
56Build-Depends-Indep: libglib2.0-doc,57Build-Depends-Indep: libglib2.0-doc,
57 libatk1.0-doc,58 libatk1.0-doc,
58 libpango1.0-doc,59 libpango1.0-doc,
5960
=== added file 'debian/patches/0001-mir-implement-window-properties.patch'
--- debian/patches/0001-mir-implement-window-properties.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/0001-mir-implement-window-properties.patch 2017-02-08 17:37:49 +0000
@@ -0,0 +1,244 @@
1From b6baa088dccecb25130d056f33d8078d198dd2d7 Mon Sep 17 00:00:00 2001
2From: William Hua <william.hua@canonical.com>
3Date: Tue, 11 Oct 2016 19:06:12 -0400
4Subject: [PATCH 01/38] mir: implement window properties
5
6https://bugzilla.gnome.org/show_bug.cgi?id=775732
7---
8 gdk/mir/gdkmirwindowimpl.c | 179 +++++++++++++++++++++++++++++++++++++++++----
9 1 file changed, 163 insertions(+), 16 deletions(-)
10
11diff --git a/gdk/mir/gdkmirwindowimpl.c b/gdk/mir/gdkmirwindowimpl.c
12index a7be39c..48e66ca 100644
13--- a/gdk/mir/gdkmirwindowimpl.c
14+++ b/gdk/mir/gdkmirwindowimpl.c
15@@ -36,12 +36,45 @@
16
17 #define MAX_EGL_ATTRS 30
18
19+typedef struct
20+{
21+ GdkAtom type;
22+ GArray *array;
23+} GdkMirProperty;
24+
25+static GdkMirProperty *
26+gdk_mir_property_new (GdkAtom type,
27+ guint format,
28+ guint capacity)
29+{
30+ GdkMirProperty *property = g_slice_new (GdkMirProperty);
31+
32+ property->type = type;
33+ property->array = g_array_sized_new (TRUE, FALSE, format, capacity);
34+
35+ return property;
36+}
37+
38+static void
39+gdk_mir_property_free (gpointer data)
40+{
41+ GdkMirProperty *property = data;
42+
43+ if (!property)
44+ return;
45+
46+ g_array_unref (property->array);
47+ g_slice_free (GdkMirProperty, property);
48+}
49+
50 typedef struct _GdkMirWindowImplClass GdkMirWindowImplClass;
51
52 struct _GdkMirWindowImpl
53 {
54 GdkWindowImpl parent_instance;
55
56+ GHashTable *properties;
57+
58 /* Window we are temporary for */
59 GdkWindow *transient_for;
60 gint transient_x;
61@@ -233,6 +266,7 @@ _gdk_mir_window_impl_get_cursor_state (GdkMirWindowImpl *impl,
62 static void
63 gdk_mir_window_impl_init (GdkMirWindowImpl *impl)
64 {
65+ impl->properties = g_hash_table_new_full (NULL, NULL, NULL, gdk_mir_property_free);
66 impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
67 impl->surface_state = mir_surface_state_unknown;
68 impl->output_scale = 1;
69@@ -687,6 +721,8 @@ gdk_mir_window_impl_finalize (GObject *object)
70 if (impl->cairo_surface)
71 cairo_surface_destroy (impl->cairo_surface);
72
73+ g_clear_pointer (&impl->properties, g_hash_table_unref);
74+
75 G_OBJECT_CLASS (gdk_mir_window_impl_parent_class)->finalize (object);
76 }
77
78@@ -1482,19 +1518,79 @@ gdk_mir_window_impl_simulate_button (GdkWindow *window,
79 }
80
81 static gboolean
82-gdk_mir_window_impl_get_property (GdkWindow *window,
83- GdkAtom property,
84- GdkAtom type,
85- gulong offset,
86- gulong length,
87- gint pdelete,
88- GdkAtom *actual_property_type,
89- gint *actual_format_type,
90- gint *actual_length,
91- guchar **data)
92-{
93- //g_printerr ("gdk_mir_window_impl_get_property window=%p\n", window);
94- return FALSE;
95+gdk_mir_window_impl_get_property (GdkWindow *window,
96+ GdkAtom property,
97+ GdkAtom type,
98+ gulong offset,
99+ gulong length,
100+ gint pdelete,
101+ GdkAtom *actual_type,
102+ gint *actual_format,
103+ gint *actual_length,
104+ guchar **data)
105+{
106+ GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
107+ GdkMirProperty *mir_property;
108+ GdkAtom dummy_actual_type;
109+ gint dummy_actual_format;
110+ gint dummy_actual_length;
111+ guint width;
112+
113+ if (!actual_type)
114+ actual_type = &dummy_actual_type;
115+ if (!actual_format)
116+ actual_format = &dummy_actual_format;
117+ if (!actual_length)
118+ actual_length = &dummy_actual_length;
119+
120+ *actual_type = GDK_NONE;
121+ *actual_format = 0;
122+ *actual_length = 0;
123+
124+ if (data)
125+ *data = NULL;
126+
127+ mir_property = g_hash_table_lookup (impl->properties, property);
128+
129+ if (!mir_property)
130+ return FALSE;
131+
132+ width = g_array_get_element_size (mir_property->array);
133+ *actual_type = mir_property->type;
134+ *actual_format = 8 * width;
135+
136+ /* ICCCM 2.7: GdkAtoms can be 64-bit, but ATOMs and ATOM_PAIRs have format 32 */
137+ if (*actual_type == GDK_SELECTION_TYPE_ATOM || *actual_type == gdk_atom_intern_static_string ("ATOM_PAIR"))
138+ *actual_format = 32;
139+
140+ if (type != GDK_NONE && type != mir_property->type)
141+ return FALSE;
142+
143+ offset *= 4;
144+
145+ /* round up to next nearest multiple of width */
146+ if (length < G_MAXULONG - width + 1)
147+ length = (length - 1 + width) / width * width;
148+ else
149+ length = G_MAXULONG / width * width;
150+
151+ /* we're skipping the first offset bytes */
152+ if (length > mir_property->array->len * width - offset)
153+ length = mir_property->array->len * width - offset;
154+
155+ /* leave room for null terminator */
156+ if (length > G_MAXULONG - width)
157+ length -= width;
158+
159+ *actual_length = length;
160+
161+ if (data)
162+ {
163+ *data = g_memdup (mir_property->array->data + offset, length + width);
164+ memset (*data + length, 0, width);
165+ }
166+
167+ return TRUE;
168 }
169
170 static void
171@@ -1504,16 +1600,67 @@ gdk_mir_window_impl_change_property (GdkWindow *window,
172 gint format,
173 GdkPropMode mode,
174 const guchar *data,
175- gint nelements)
176+ gint n_elements)
177 {
178- //g_printerr ("gdk_mir_window_impl_change_property window=%p\n", window);
179+ GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
180+ GdkMirProperty *mir_property;
181+ GdkEvent *event;
182+
183+ /* ICCCM 2.7: ATOMs and ATOM_PAIRs have format 32, but GdkAtoms can be 64-bit */
184+ if (type == GDK_SELECTION_TYPE_ATOM || type == gdk_atom_intern_static_string ("ATOM_PAIR"))
185+ format = 8 * sizeof (GdkAtom);
186+
187+ if (mode != GDK_PROP_MODE_REPLACE)
188+ mir_property = g_hash_table_lookup (impl->properties, property);
189+ else
190+ mir_property = NULL;
191+
192+ if (!mir_property)
193+ {
194+ /* format is measured in bits, but we need to know this in bytes */
195+ mir_property = gdk_mir_property_new (type, format / 8, n_elements);
196+ g_hash_table_insert (impl->properties, property, mir_property);
197+ }
198+
199+ /* format is measured in bits, but we need to know this in bytes */
200+ if (type != mir_property->type || format / 8 != g_array_get_element_size (mir_property->array))
201+ return;
202+
203+ if (mode == GDK_PROP_MODE_PREPEND)
204+ g_array_prepend_vals (mir_property->array, data, n_elements);
205+ else
206+ g_array_append_vals (mir_property->array, data, n_elements);
207+
208+ event = gdk_event_new (GDK_PROPERTY_NOTIFY);
209+ event->property.window = g_object_ref (window);
210+ event->property.send_event = FALSE;
211+ event->property.atom = property;
212+ event->property.time = GDK_CURRENT_TIME;
213+ event->property.state = GDK_PROPERTY_NEW_VALUE;
214+
215+ gdk_event_put (event);
216+ gdk_event_free (event);
217 }
218
219 static void
220 gdk_mir_window_impl_delete_property (GdkWindow *window,
221 GdkAtom property)
222 {
223- //g_printerr ("gdk_mir_window_impl_delete_property window=%p\n", window);
224+ GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
225+ GdkEvent *event;
226+
227+ if (g_hash_table_remove (impl->properties, property))
228+ {
229+ event = gdk_event_new (GDK_PROPERTY_NOTIFY);
230+ event->property.window = g_object_ref (window);
231+ event->property.send_event = FALSE;
232+ event->property.atom = property;
233+ event->property.time = GDK_CURRENT_TIME;
234+ event->property.state = GDK_PROPERTY_DELETE;
235+
236+ gdk_event_put (event);
237+ gdk_event_free (event);
238+ }
239 }
240
241 static gint
242--
2432.10.2
244
0245
=== added file 'debian/patches/0002-mir-track-focused-window.patch'
--- debian/patches/0002-mir-track-focused-window.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/0002-mir-track-focused-window.patch 2017-02-08 17:37:49 +0000
@@ -0,0 +1,91 @@
1From 0acb58b40fbc158f94486195e35088f610071583 Mon Sep 17 00:00:00 2001
2From: William Hua <william.hua@canonical.com>
3Date: Fri, 14 Oct 2016 17:00:34 -0400
4Subject: [PATCH 02/38] mir: track focused window
5
6https://bugzilla.gnome.org/show_bug.cgi?id=775732
7---
8 gdk/mir/gdkmir-private.h | 4 ++++
9 gdk/mir/gdkmirdisplay.c | 21 +++++++++++++++++++++
10 gdk/mir/gdkmireventsource.c | 10 ++++++++--
11 3 files changed, 33 insertions(+), 2 deletions(-)
12
13diff --git a/gdk/mir/gdkmir-private.h b/gdk/mir/gdkmir-private.h
14index 38f1d7a..7e3893c 100644
15--- a/gdk/mir/gdkmir-private.h
16+++ b/gdk/mir/gdkmir-private.h
17@@ -107,6 +107,10 @@ void _gdk_mir_event_source_queue (GdkMirWindowReference *window_ref, const MirEv
18
19 MirPixelFormat _gdk_mir_display_get_pixel_format (GdkDisplay *display, MirBufferUsage usage);
20
21+void _gdk_mir_display_focus_window (GdkDisplay *display, GdkWindow *window);
22+
23+void _gdk_mir_display_unfocus_window (GdkDisplay *display, GdkWindow *window);
24+
25 gboolean _gdk_mir_display_init_egl_display (GdkDisplay *display);
26
27 EGLDisplay _gdk_mir_display_get_egl_display (GdkDisplay *display);
28diff --git a/gdk/mir/gdkmirdisplay.c b/gdk/mir/gdkmirdisplay.c
29index eea892c..89cfad2 100644
30--- a/gdk/mir/gdkmirdisplay.c
31+++ b/gdk/mir/gdkmirdisplay.c
32@@ -47,6 +47,8 @@ typedef struct GdkMirDisplay
33
34 GdkKeymap *keymap;
35
36+ GdkWindow *focused_window;
37+
38 MirPixelFormat sw_pixel_format;
39 MirPixelFormat hw_pixel_format;
40
41@@ -582,6 +584,25 @@ _gdk_mir_display_get_pixel_format (GdkDisplay *display,
42 return mir_dpy->sw_pixel_format;
43 }
44
45+void
46+_gdk_mir_display_focus_window (GdkDisplay *display,
47+ GdkWindow *window)
48+{
49+ GdkMirDisplay *mir_display = GDK_MIR_DISPLAY (display);
50+
51+ g_set_object (&mir_display->focused_window, window);
52+}
53+
54+void
55+_gdk_mir_display_unfocus_window (GdkDisplay *display,
56+ GdkWindow *window)
57+{
58+ GdkMirDisplay *mir_display = GDK_MIR_DISPLAY (display);
59+
60+ if (window == mir_display->focused_window)
61+ g_clear_object (&mir_display->focused_window);
62+}
63+
64 gboolean
65 _gdk_mir_display_init_egl_display (GdkDisplay *display)
66 {
67diff --git a/gdk/mir/gdkmireventsource.c b/gdk/mir/gdkmireventsource.c
68index 8c7e106..a2a1a12 100644
69--- a/gdk/mir/gdkmireventsource.c
70+++ b/gdk/mir/gdkmireventsource.c
71@@ -240,9 +240,15 @@ generate_focus_event (GdkWindow *window, gboolean focused)
72 GdkEvent *event;
73
74 if (focused)
75- gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FOCUSED);
76+ {
77+ gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FOCUSED);
78+ _gdk_mir_display_focus_window (gdk_window_get_display (window), window);
79+ }
80 else
81- gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FOCUSED, 0);
82+ {
83+ gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FOCUSED, 0);
84+ _gdk_mir_display_unfocus_window (gdk_window_get_display (window), window);
85+ }
86
87 event = gdk_event_new (GDK_FOCUS_CHANGE);
88 event->focus_change.send_event = FALSE;
89--
902.10.2
91
092
=== added file 'debian/patches/0003-mir-connect-to-content-hub.patch'
--- debian/patches/0003-mir-connect-to-content-hub.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/0003-mir-connect-to-content-hub.patch 2017-02-08 17:37:49 +0000
@@ -0,0 +1,108 @@
1From 210d1279e5811ae18b0bad13f16a97c7ec98598e Mon Sep 17 00:00:00 2001
2From: William Hua <william.hua@canonical.com>
3Date: Tue, 11 Oct 2016 16:53:48 -0400
4Subject: [PATCH 03/38] mir: connect to content-hub
5
6https://bugzilla.gnome.org/show_bug.cgi?id=775732
7---
8 configure.ac | 2 +-
9 gdk/mir/gdkmirdisplay.c | 42 ++++++++++++++++++++++++++++++++++++++++++
10 2 files changed, 43 insertions(+), 1 deletion(-)
11
12diff --git a/configure.ac b/configure.ac
13index ea609b3..000e37a 100644
14--- a/configure.ac
15+++ b/configure.ac
16@@ -464,7 +464,7 @@ else
17 AM_CONDITIONAL(USE_WAYLAND, false)
18 fi
19
20-MIR_DEPENDENCIES="mirclient >= mirclient_required_version mircookie >= mircookie_required_version"
21+MIR_DEPENDENCIES="mirclient >= mirclient_required_version mircookie >= mircookie_required_version libcontent-hub-glib"
22 if test "$enable_mir_backend" = "maybe" ; then
23 PKG_CHECK_EXISTS($MIR_DEPENDENCIES, [have_mir_deps=yes], [have_mir_deps=no])
24 AC_MSG_CHECKING([for MIR_DEPENDENCIES])
25diff --git a/gdk/mir/gdkmirdisplay.c b/gdk/mir/gdkmirdisplay.c
26index 89cfad2..718ab60 100644
27--- a/gdk/mir/gdkmirdisplay.c
28+++ b/gdk/mir/gdkmirdisplay.c
29@@ -23,6 +23,8 @@
30 #include "gdkmir.h"
31 #include "gdkmir-private.h"
32
33+#include <com/ubuntu/content/glib/content-hub-glib.h>
34+
35 #define GDK_TYPE_DISPLAY_MIR (gdk_mir_display_get_type ())
36 #define GDK_MIR_DISPLAY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_DISPLAY_MIR, GdkMirDisplay))
37 #define GDK_MIR_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DISPLAY_MIR, GdkMirDisplayClass))
38@@ -57,6 +59,9 @@ typedef struct GdkMirDisplay
39 guint have_egl_buffer_age : 1;
40 guint have_egl_swap_buffers_with_damage : 1;
41 guint have_egl_surfaceless_context : 1;
42+
43+ ContentHubService *content_service;
44+ ContentHubHandler *content_handler;
45 } GdkMirDisplay;
46
47 typedef struct GdkMirDisplayClass
48@@ -108,6 +113,7 @@ _gdk_mir_display_open (const gchar *display_name)
49 MirConnection *connection;
50 MirPixelFormat sw_pixel_format, hw_pixel_format;
51 GdkMirDisplay *display;
52+ GDBusConnection *session;
53
54 //g_printerr ("gdk_mir_display_open\n");
55
56@@ -140,6 +146,39 @@ _gdk_mir_display_open (const gchar *display_name)
57 display->sw_pixel_format = sw_pixel_format;
58 display->hw_pixel_format = hw_pixel_format;
59
60+ session = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
61+
62+ display->content_service = content_hub_service_proxy_new_sync (
63+ session,
64+ G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
65+ "com.ubuntu.content.dbus.Service",
66+ "/",
67+ NULL,
68+ NULL);
69+
70+ display->content_handler = content_hub_handler_skeleton_new ();
71+
72+ g_dbus_interface_skeleton_export (
73+ G_DBUS_INTERFACE_SKELETON (display->content_handler),
74+ session,
75+ "/org/gnome/gtk/content/handler",
76+ NULL);
77+
78+ g_object_unref (session);
79+
80+ content_hub_service_call_register_import_export_handler_sync (
81+ display->content_service,
82+ g_application_get_application_id (g_application_get_default ()),
83+ "/org/gnome/gtk/content/handler",
84+ NULL,
85+ NULL);
86+
87+ content_hub_service_call_handler_active_sync (
88+ display->content_service,
89+ g_application_get_application_id (g_application_get_default ()),
90+ NULL,
91+ NULL);
92+
93 g_signal_emit_by_name (display, "opened");
94
95 return GDK_DISPLAY (display);
96@@ -175,6 +214,9 @@ gdk_mir_display_dispose (GObject *object)
97 {
98 GdkMirDisplay *display = GDK_MIR_DISPLAY (object);
99
100+ g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (display->content_handler));
101+ g_clear_object (&display->content_handler);
102+ g_clear_object (&display->content_service);
103 g_clear_object (&display->screen);
104 g_clear_object (&display->keymap);
105 g_clear_pointer (&display->event_source, g_source_unref);
106--
1072.10.2
108
0109
=== added file 'debian/patches/0004-mir-copy-clipboard-data-to-content-hub.patch'
--- debian/patches/0004-mir-copy-clipboard-data-to-content-hub.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/0004-mir-copy-clipboard-data-to-content-hub.patch 2017-02-08 17:37:49 +0000
@@ -0,0 +1,292 @@
1From 5c4c3f1afd9a56644c1d204df3a9f5f1526ffa38 Mon Sep 17 00:00:00 2001
2From: William Hua <william.hua@canonical.com>
3Date: Wed, 12 Oct 2016 16:56:01 -0400
4Subject: [PATCH 04/38] mir: copy clipboard data to content-hub
5
6https://bugzilla.gnome.org/show_bug.cgi?id=775732
7---
8 gdk/mir/gdkmir-private.h | 5 ++
9 gdk/mir/gdkmirdisplay.c | 60 +++++++++++++++++-
10 gdk/mir/gdkmirwindowimpl.c | 150 ++++++++++++++++++++++++++++++++++++++++++++-
11 3 files changed, 212 insertions(+), 3 deletions(-)
12
13diff --git a/gdk/mir/gdkmir-private.h b/gdk/mir/gdkmir-private.h
14index 7e3893c..a677dec 100644
15--- a/gdk/mir/gdkmir-private.h
16+++ b/gdk/mir/gdkmir-private.h
17@@ -111,6 +111,11 @@ void _gdk_mir_display_focus_window (GdkDisplay *display, GdkWindow *window);
18
19 void _gdk_mir_display_unfocus_window (GdkDisplay *display, GdkWindow *window);
20
21+void _gdk_mir_display_create_paste (GdkDisplay *display,
22+ const gchar * const *paste_formats,
23+ gconstpointer paste_data,
24+ gsize paste_size);
25+
26 gboolean _gdk_mir_display_init_egl_display (GdkDisplay *display);
27
28 EGLDisplay _gdk_mir_display_get_egl_display (GdkDisplay *display);
29diff --git a/gdk/mir/gdkmirdisplay.c b/gdk/mir/gdkmirdisplay.c
30index 718ab60..3dd3798 100644
31--- a/gdk/mir/gdkmirdisplay.c
32+++ b/gdk/mir/gdkmirdisplay.c
33@@ -504,7 +504,28 @@ gdk_mir_display_set_selection_owner (GdkDisplay *display,
34 guint32 time,
35 gboolean send_event)
36 {
37- //g_printerr ("gdk_mir_display_set_selection_owner\n");
38+ GdkEvent *event;
39+
40+ if (selection == GDK_SELECTION_CLIPBOARD)
41+ {
42+ if (owner)
43+ {
44+ event = gdk_event_new (GDK_SELECTION_REQUEST);
45+ event->selection.window = g_object_ref (owner);
46+ event->selection.send_event = FALSE;
47+ event->selection.selection = selection;
48+ event->selection.target = gdk_atom_intern_static_string ("TARGETS");
49+ event->selection.property = gdk_atom_intern_static_string ("AVAILABLE_TARGETS");
50+ event->selection.time = GDK_CURRENT_TIME;
51+ event->selection.requestor = g_object_ref (owner);
52+
53+ gdk_event_put (event);
54+ gdk_event_free (event);
55+
56+ return TRUE;
57+ }
58+ }
59+
60 return FALSE;
61 }
62
63@@ -645,6 +666,43 @@ _gdk_mir_display_unfocus_window (GdkDisplay *display,
64 g_clear_object (&mir_display->focused_window);
65 }
66
67+void
68+_gdk_mir_display_create_paste (GdkDisplay *display,
69+ const gchar * const *paste_formats,
70+ gconstpointer paste_data,
71+ gsize paste_size)
72+{
73+ GdkMirDisplay *mir_display = GDK_MIR_DISPLAY (display);
74+ MirSurface *surface;
75+ MirPersistentId *persistent_id;
76+
77+ if (!mir_display->focused_window)
78+ return;
79+
80+ surface = gdk_mir_window_get_mir_surface (mir_display->focused_window);
81+
82+ if (!surface)
83+ return;
84+
85+ persistent_id = mir_surface_request_persistent_id_sync (surface);
86+
87+ if (!persistent_id)
88+ return;
89+
90+ if (mir_persistent_id_is_valid (persistent_id))
91+ content_hub_service_call_create_paste_sync (
92+ mir_display->content_service,
93+ g_application_get_application_id (g_application_get_default ()),
94+ mir_persistent_id_as_string (persistent_id),
95+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, paste_data, paste_size, sizeof (guchar)),
96+ paste_formats,
97+ NULL,
98+ NULL,
99+ NULL);
100+
101+ mir_persistent_id_release (persistent_id);
102+}
103+
104 gboolean
105 _gdk_mir_display_init_egl_display (GdkDisplay *display)
106 {
107diff --git a/gdk/mir/gdkmirwindowimpl.c b/gdk/mir/gdkmirwindowimpl.c
108index 48e66ca..8a15816 100644
109--- a/gdk/mir/gdkmirwindowimpl.c
110+++ b/gdk/mir/gdkmirwindowimpl.c
111@@ -1594,6 +1594,140 @@ gdk_mir_window_impl_get_property (GdkWindow *window,
112 }
113
114 static void
115+request_targets (GdkWindow *window,
116+ const GdkAtom *available_targets,
117+ gint n_available_targets)
118+{
119+ GArray *requested_targets;
120+ GdkAtom target_pair[2];
121+ gchar *target_location;
122+ GdkEvent *event;
123+ gint i;
124+
125+ requested_targets = g_array_sized_new (TRUE, FALSE, sizeof (GdkAtom), 2 * n_available_targets);
126+
127+ for (i = 0; i < n_available_targets; i++)
128+ {
129+ target_pair[0] = available_targets[i];
130+
131+ if (target_pair[0] == gdk_atom_intern_static_string ("TIMESTAMP") ||
132+ target_pair[0] == gdk_atom_intern_static_string ("TARGETS") ||
133+ target_pair[0] == gdk_atom_intern_static_string ("MULTIPLE") ||
134+ target_pair[0] == gdk_atom_intern_static_string ("SAVE_TARGETS"))
135+ continue;
136+
137+ target_location = g_strdup_printf ("REQUESTED_TARGET_U%u", requested_targets->len / 2);
138+ target_pair[1] = gdk_atom_intern (target_location, FALSE);
139+ g_free (target_location);
140+
141+ g_array_append_vals (requested_targets, target_pair, 2);
142+ }
143+
144+ gdk_property_delete (window, gdk_atom_intern_static_string ("AVAILABLE_TARGETS"));
145+ gdk_property_delete (window, gdk_atom_intern_static_string ("REQUESTED_TARGETS"));
146+
147+ gdk_property_change (window,
148+ gdk_atom_intern_static_string ("REQUESTED_TARGETS"),
149+ GDK_SELECTION_TYPE_ATOM,
150+ 8 * sizeof (GdkAtom),
151+ GDK_PROP_MODE_REPLACE,
152+ (const guchar *) requested_targets->data,
153+ requested_targets->len);
154+
155+ g_array_unref (requested_targets);
156+
157+ event = gdk_event_new (GDK_SELECTION_REQUEST);
158+ event->selection.window = g_object_ref (window);
159+ event->selection.send_event = FALSE;
160+ event->selection.selection = GDK_SELECTION_CLIPBOARD;
161+ event->selection.target = gdk_atom_intern_static_string ("MULTIPLE");
162+ event->selection.property = gdk_atom_intern_static_string ("REQUESTED_TARGETS");
163+ event->selection.time = GDK_CURRENT_TIME;
164+ event->selection.requestor = g_object_ref (window);
165+
166+ gdk_event_put (event);
167+ gdk_event_free (event);
168+}
169+
170+static void
171+create_paste (GdkWindow *window,
172+ const GdkAtom *requested_targets,
173+ gint n_requested_targets)
174+{
175+ GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
176+ GPtrArray *paste_formats;
177+ GArray *paste_header;
178+ GByteArray *paste_data;
179+ gint sizes[4];
180+ GdkMirProperty *mir_property;
181+ const gchar *paste_format;
182+ gint i;
183+
184+ paste_formats = g_ptr_array_new_full (n_requested_targets, g_free);
185+ paste_header = g_array_sized_new (FALSE, FALSE, sizeof (gint), 1 + 4 * n_requested_targets);
186+ paste_data = g_byte_array_new ();
187+
188+ g_array_append_val (paste_header, sizes[0]);
189+
190+ for (i = 0; i < n_requested_targets; i++)
191+ {
192+ if (requested_targets[i] == GDK_NONE)
193+ continue;
194+
195+ mir_property = g_hash_table_lookup (impl->properties, requested_targets[i]);
196+
197+ if (!mir_property)
198+ continue;
199+
200+ paste_format = _gdk_atom_name_const (mir_property->type);
201+
202+ /* skip non-MIME targets */
203+ if (!strchr (paste_format, '/'))
204+ {
205+ g_hash_table_remove (impl->properties, requested_targets[i]);
206+ continue;
207+ }
208+
209+ sizes[0] = paste_data->len;
210+ sizes[1] = strlen (paste_format);
211+ sizes[2] = sizes[0] + sizes[1];
212+ sizes[3] = mir_property->array->len * g_array_get_element_size (mir_property->array);
213+
214+ g_ptr_array_add (paste_formats, g_strdup (paste_format));
215+ g_array_append_vals (paste_header, sizes, 4);
216+ g_byte_array_append (paste_data, (const guint8 *) paste_format, sizes[1]);
217+ g_byte_array_append (paste_data, (const guint8 *) mir_property->array->data, sizes[3]);
218+
219+ g_hash_table_remove (impl->properties, requested_targets[i]);
220+ }
221+
222+ gdk_property_delete (window, gdk_atom_intern_static_string ("REQUESTED_TARGETS"));
223+
224+ g_array_index (paste_header, gint, 0) = paste_formats->len;
225+
226+ for (i = 0; i < paste_formats->len; i++)
227+ {
228+ g_array_index (paste_header, gint, 1 + 4 * i) += paste_header->len * sizeof (gint);
229+ g_array_index (paste_header, gint, 3 + 4 * i) += paste_header->len * sizeof (gint);
230+ }
231+
232+ g_byte_array_prepend (paste_data,
233+ (const guint8 *) paste_header->data,
234+ paste_header->len * g_array_get_element_size (paste_header));
235+
236+ g_ptr_array_add (paste_formats, NULL);
237+
238+ _gdk_mir_display_create_paste (gdk_window_get_display (window),
239+ (const gchar * const *) paste_formats->pdata,
240+ paste_data->data,
241+ paste_data->len);
242+
243+ g_byte_array_unref (paste_data);
244+ g_array_unref (paste_header);
245+ g_ptr_array_unref (paste_formats);
246+}
247+
248+static void
249 gdk_mir_window_impl_change_property (GdkWindow *window,
250 GdkAtom property,
251 GdkAtom type,
252@@ -1604,6 +1738,7 @@ gdk_mir_window_impl_change_property (GdkWindow *window,
253 {
254 GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
255 GdkMirProperty *mir_property;
256+ gboolean existed;
257 GdkEvent *event;
258
259 /* ICCCM 2.7: ATOMs and ATOM_PAIRs have format 32, but GdkAtoms can be 64-bit */
260@@ -1611,9 +1746,15 @@ gdk_mir_window_impl_change_property (GdkWindow *window,
261 format = 8 * sizeof (GdkAtom);
262
263 if (mode != GDK_PROP_MODE_REPLACE)
264- mir_property = g_hash_table_lookup (impl->properties, property);
265+ {
266+ mir_property = g_hash_table_lookup (impl->properties, property);
267+ existed = mir_property != NULL;
268+ }
269 else
270- mir_property = NULL;
271+ {
272+ mir_property = NULL;
273+ existed = g_hash_table_contains (impl->properties, property);
274+ }
275
276 if (!mir_property)
277 {
278@@ -1640,6 +1781,11 @@ gdk_mir_window_impl_change_property (GdkWindow *window,
279
280 gdk_event_put (event);
281 gdk_event_free (event);
282+
283+ if (property == gdk_atom_intern_static_string ("AVAILABLE_TARGETS"))
284+ request_targets (window, (const GdkAtom *) data, n_elements);
285+ else if (property == gdk_atom_intern_static_string ("REQUESTED_TARGETS") && existed)
286+ create_paste (window, (const GdkAtom *) data, n_elements);
287 }
288
289 static void
290--
2912.10.2
292
0293
=== added file 'debian/patches/0005-mir-paste-clipboard-data-from-content-hub.patch'
--- debian/patches/0005-mir-paste-clipboard-data-from-content-hub.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/0005-mir-paste-clipboard-data-from-content-hub.patch 2017-02-08 17:37:49 +0000
@@ -0,0 +1,415 @@
1From 41732391d8b93478d4b63d63f9c3cc5bbf124a2a Mon Sep 17 00:00:00 2001
2From: William Hua <william.hua@canonical.com>
3Date: Sat, 15 Oct 2016 22:19:59 +0200
4Subject: [PATCH 05/38] mir: paste clipboard data from content-hub
5
6https://bugzilla.gnome.org/show_bug.cgi?id=775732
7---
8 gdk/mir/gdkmirdisplay.c | 339 +++++++++++++++++++++++++++++++++++++++++++++++-
9 1 file changed, 335 insertions(+), 4 deletions(-)
10
11diff --git a/gdk/mir/gdkmirdisplay.c b/gdk/mir/gdkmirdisplay.c
12index 3dd3798..21967ac 100644
13--- a/gdk/mir/gdkmirdisplay.c
14+++ b/gdk/mir/gdkmirdisplay.c
15@@ -23,6 +23,8 @@
16 #include "gdkmir.h"
17 #include "gdkmir-private.h"
18
19+#include <string.h>
20+
21 #include <com/ubuntu/content/glib/content-hub-glib.h>
22
23 #define GDK_TYPE_DISPLAY_MIR (gdk_mir_display_get_type ())
24@@ -62,6 +64,7 @@ typedef struct GdkMirDisplay
25
26 ContentHubService *content_service;
27 ContentHubHandler *content_handler;
28+ GVariant *paste_data;
29 } GdkMirDisplay;
30
31 typedef struct GdkMirDisplayClass
32@@ -107,6 +110,13 @@ static void get_pixel_formats (MirConnection *, MirPixelFormat *sw, MirPixelForm
33
34 G_DEFINE_TYPE (GdkMirDisplay, gdk_mir_display, GDK_TYPE_DISPLAY)
35
36+static void
37+pasteboard_changed_cb (GdkMirDisplay *display,
38+ gpointer user_data)
39+{
40+ g_clear_pointer (&display->paste_data, g_variant_unref);
41+}
42+
43 GdkDisplay *
44 _gdk_mir_display_open (const gchar *display_name)
45 {
46@@ -156,6 +166,12 @@ _gdk_mir_display_open (const gchar *display_name)
47 NULL,
48 NULL);
49
50+ g_signal_connect_swapped (
51+ display->content_service,
52+ "pasteboard-changed",
53+ G_CALLBACK (pasteboard_changed_cb),
54+ display);
55+
56 display->content_handler = content_hub_handler_skeleton_new ();
57
58 g_dbus_interface_skeleton_export (
59@@ -214,6 +230,7 @@ gdk_mir_display_dispose (GObject *object)
60 {
61 GdkMirDisplay *display = GDK_MIR_DISPLAY (object);
62
63+ g_clear_pointer (&display->paste_data, g_variant_unref);
64 g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (display->content_handler));
65 g_clear_object (&display->content_handler);
66 g_clear_object (&display->content_service);
67@@ -547,10 +564,255 @@ gdk_mir_display_get_selection_property (GdkDisplay *display,
68 GdkAtom *ret_type,
69 gint *ret_format)
70 {
71- //g_printerr ("gdk_mir_display_get_selection_property\n");
72+ gint length;
73+
74+ gdk_property_get (requestor,
75+ gdk_atom_intern_static_string ("GDK_SELECTION"),
76+ GDK_NONE,
77+ 0,
78+ G_MAXULONG,
79+ FALSE,
80+ ret_type,
81+ ret_format,
82+ &length,
83+ data);
84+
85+ return length;
86+}
87+
88+static gint
89+get_format_score (const gchar *format,
90+ GdkAtom target,
91+ GdkAtom *out_type,
92+ gint *out_size)
93+{
94+ const gchar *target_string;
95+ GdkAtom dummy_type;
96+ gint dummy_size;
97+
98+ target_string = _gdk_atom_name_const (target);
99+
100+ if (!out_type)
101+ out_type = &dummy_type;
102+
103+ if (!out_size)
104+ out_size = &dummy_size;
105+
106+ if (!g_ascii_strcasecmp (format, target_string))
107+ {
108+ *out_type = GDK_SELECTION_TYPE_STRING;
109+ *out_size = sizeof (guchar);
110+
111+ return G_MAXINT;
112+ }
113+
114+ if (target == gdk_atom_intern_static_string ("UTF8_STRING"))
115+ return get_format_score (format, gdk_atom_intern_static_string ("text/plain;charset=utf-8"), out_type, out_size);
116+
117+ /* TODO: use best media type for COMPOUND_TEXT target */
118+ if (target == gdk_atom_intern_static_string ("COMPOUND_TEXT"))
119+ return get_format_score (format, gdk_atom_intern_static_string ("text/plain;charset=utf-8"), out_type, out_size);
120+
121+ if (target == GDK_TARGET_STRING)
122+ return get_format_score (format, gdk_atom_intern_static_string ("text/plain;charset=iso-8859-1"), out_type, out_size);
123+
124+ if (target == gdk_atom_intern_static_string ("GTK_TEXT_BUFFER_CONTENTS"))
125+ return get_format_score (format, gdk_atom_intern_static_string ("text/plain;charset=utf-8"), out_type, out_size);
126+
127+ if (g_content_type_is_a (format, target_string))
128+ {
129+ *out_type = GDK_SELECTION_TYPE_STRING;
130+ *out_size = sizeof (guchar);
131+
132+ return 2;
133+ }
134+
135+ if (g_content_type_is_a (target_string, format))
136+ {
137+ *out_type = GDK_SELECTION_TYPE_STRING;
138+ *out_size = sizeof (guchar);
139+
140+ return 1;
141+ }
142+
143 return 0;
144 }
145
146+static gint
147+get_best_format_index (const gchar * const *formats,
148+ guint n_formats,
149+ GdkAtom target,
150+ GdkAtom *out_type,
151+ gint *out_size)
152+{
153+ gint best_i = -1;
154+ gint best_score = 0;
155+ GdkAtom best_type;
156+ gint best_size;
157+ gint score;
158+ GdkAtom type;
159+ gint size;
160+ gint i;
161+
162+ if (!out_type)
163+ out_type = &best_type;
164+
165+ if (!out_size)
166+ out_size = &best_size;
167+
168+ *out_type = GDK_NONE;
169+ *out_size = 0;
170+
171+ for (i = 0; i < n_formats; i++)
172+ {
173+ score = get_format_score (formats[i], target, &type, &size);
174+
175+ if (score > best_score)
176+ {
177+ best_i = i;
178+ best_score = score;
179+ *out_type = type;
180+ *out_size = size;
181+ }
182+ }
183+
184+ return best_i;
185+}
186+
187+static void
188+gdk_mir_display_real_convert_selection (GdkDisplay *display,
189+ GdkWindow *requestor,
190+ GdkAtom selection,
191+ GdkAtom target,
192+ guint32 time)
193+{
194+ GdkMirDisplay *mir_display = GDK_MIR_DISPLAY (display);
195+ const gchar *paste_data;
196+ gsize paste_size;
197+ const gint *paste_header;
198+ GPtrArray *paste_formats;
199+ GArray *paste_targets;
200+ GdkAtom paste_target;
201+ GdkEvent *event;
202+ gint best_i;
203+ GdkAtom best_type;
204+ gint best_size;
205+ gint i;
206+
207+ g_return_if_fail (mir_display->paste_data);
208+
209+ paste_data = g_variant_get_fixed_array (mir_display->paste_data, &paste_size, sizeof (guchar));
210+ paste_header = (const gint *) paste_data;
211+ paste_formats = g_ptr_array_new_full (paste_header[0], g_free);
212+
213+ for (i = 0; i < paste_header[0]; i++)
214+ g_ptr_array_add (paste_formats, g_strndup (paste_data + paste_header[1 + 4 * i], paste_header[2 + 4 * i]));
215+
216+ if (target == gdk_atom_intern_static_string ("TARGETS"))
217+ {
218+ paste_targets = g_array_sized_new (TRUE, FALSE, sizeof (GdkAtom), paste_formats->len);
219+
220+ for (i = 0; i < paste_formats->len; i++)
221+ {
222+ paste_target = gdk_atom_intern (g_ptr_array_index (paste_formats, i), FALSE);
223+ g_array_append_val (paste_targets, paste_target);
224+ }
225+
226+ gdk_property_change (requestor,
227+ gdk_atom_intern_static_string ("GDK_SELECTION"),
228+ GDK_SELECTION_TYPE_ATOM,
229+ 8 * sizeof (GdkAtom),
230+ GDK_PROP_MODE_REPLACE,
231+ (const guchar *) paste_targets->data,
232+ paste_targets->len);
233+
234+ g_array_unref (paste_targets);
235+
236+ event = gdk_event_new (GDK_SELECTION_NOTIFY);
237+ event->selection.window = g_object_ref (requestor);
238+ event->selection.send_event = FALSE;
239+ event->selection.selection = selection;
240+ event->selection.target = target;
241+ event->selection.property = gdk_atom_intern_static_string ("GDK_SELECTION");
242+ event->selection.time = time;
243+ event->selection.requestor = g_object_ref (requestor);
244+
245+ gdk_event_put (event);
246+ gdk_event_free (event);
247+ }
248+ else
249+ {
250+ best_i = get_best_format_index ((const gchar * const *) paste_formats->pdata,
251+ paste_formats->len,
252+ target,
253+ &best_type,
254+ &best_size);
255+
256+ if (best_i >= 0)
257+ {
258+ gdk_property_change (requestor,
259+ gdk_atom_intern_static_string ("GDK_SELECTION"),
260+ best_type,
261+ 8 * best_size,
262+ GDK_PROP_MODE_REPLACE,
263+ (const guchar *) paste_data + paste_header[3 + 4 * best_i],
264+ paste_header[4 + 4 * best_i] / best_size);
265+
266+ event = gdk_event_new (GDK_SELECTION_NOTIFY);
267+ event->selection.window = g_object_ref (requestor);
268+ event->selection.send_event = FALSE;
269+ event->selection.selection = selection;
270+ event->selection.target = target;
271+ event->selection.property = gdk_atom_intern_static_string ("GDK_SELECTION");
272+ event->selection.time = time;
273+ event->selection.requestor = g_object_ref (requestor);
274+
275+ gdk_event_put (event);
276+ gdk_event_free (event);
277+ }
278+ }
279+
280+ g_ptr_array_unref (paste_formats);
281+}
282+
283+typedef struct
284+{
285+ GdkDisplay *display;
286+ GdkWindow *requestor;
287+ GdkAtom selection;
288+ GdkAtom target;
289+ guint32 time;
290+} ConvertInfo;
291+
292+static void
293+paste_data_ready_cb (GObject *source_object,
294+ GAsyncResult *res,
295+ gpointer user_data)
296+{
297+ ContentHubService *content_service = CONTENT_HUB_SERVICE (source_object);
298+ ConvertInfo *info = user_data;
299+ GdkMirDisplay *mir_display = GDK_MIR_DISPLAY (info->display);
300+ gboolean result;
301+
302+ g_clear_pointer (&mir_display->paste_data, g_variant_unref);
303+
304+ result = content_hub_service_call_get_latest_paste_data_finish (content_service,
305+ &mir_display->paste_data,
306+ res,
307+ NULL);
308+
309+ if (result)
310+ gdk_mir_display_real_convert_selection (info->display,
311+ info->requestor,
312+ info->selection,
313+ info->target,
314+ info->time);
315+
316+ g_object_unref (info->requestor);
317+ g_object_unref (info->display);
318+ g_free (info);
319+}
320+
321 static void
322 gdk_mir_display_convert_selection (GdkDisplay *display,
323 GdkWindow *requestor,
324@@ -558,7 +820,46 @@ gdk_mir_display_convert_selection (GdkDisplay *display,
325 GdkAtom target,
326 guint32 time)
327 {
328- //g_printerr ("gdk_mir_display_convert_selection\n");
329+ GdkMirDisplay *mir_display = GDK_MIR_DISPLAY (display);
330+ MirSurface *surface;
331+ MirPersistentId *persistent_id;
332+ ConvertInfo *info;
333+
334+ if (selection != GDK_SELECTION_CLIPBOARD)
335+ return;
336+ else if (mir_display->paste_data)
337+ gdk_mir_display_real_convert_selection (display, requestor, selection, target, time);
338+ else if (mir_display->focused_window)
339+ {
340+ surface = gdk_mir_window_get_mir_surface (mir_display->focused_window);
341+
342+ if (!surface)
343+ return;
344+
345+ persistent_id = mir_surface_request_persistent_id_sync (surface);
346+
347+ if (!persistent_id)
348+ return;
349+
350+ if (mir_persistent_id_is_valid (persistent_id))
351+ {
352+ info = g_new (ConvertInfo, 1);
353+ info->display = g_object_ref (display);
354+ info->requestor = g_object_ref (requestor);
355+ info->selection = selection;
356+ info->target = target;
357+ info->time = time;
358+
359+ content_hub_service_call_get_latest_paste_data (
360+ mir_display->content_service,
361+ mir_persistent_id_as_string (persistent_id),
362+ NULL,
363+ paste_data_ready_cb,
364+ info);
365+ }
366+
367+ mir_persistent_id_release (persistent_id);
368+ }
369 }
370
371 static gint
372@@ -569,8 +870,38 @@ gdk_mir_display_text_property_to_utf8_list (GdkDisplay *display,
373 gint length,
374 gchar ***list)
375 {
376- //g_printerr ("gdk_mir_display_text_property_to_utf8_list\n");
377- return 0;
378+ GPtrArray *array;
379+ const gchar *ptr;
380+ gsize chunk_len;
381+ gchar *copy;
382+ guint nitems;
383+
384+ ptr = (const gchar *) text;
385+ array = g_ptr_array_new ();
386+
387+ /* split text into utf-8 strings */
388+ while (ptr < (const gchar *) &text[length])
389+ {
390+ chunk_len = strlen (ptr);
391+
392+ if (g_utf8_validate (ptr, chunk_len, NULL))
393+ {
394+ copy = g_strndup (ptr, chunk_len);
395+ g_ptr_array_add (array, copy);
396+ }
397+
398+ ptr = &ptr[chunk_len + 1];
399+ }
400+
401+ nitems = array->len;
402+ g_ptr_array_add (array, NULL);
403+
404+ if (list)
405+ *list = (gchar **) g_ptr_array_free (array, FALSE);
406+ else
407+ g_ptr_array_free (array, TRUE);
408+
409+ return nitems;
410 }
411
412 static gchar *
413--
4142.10.2
415
0416
=== added file 'debian/patches/0006-mir-properly-handle-empty-clipboard.patch'
--- debian/patches/0006-mir-properly-handle-empty-clipboard.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/0006-mir-properly-handle-empty-clipboard.patch 2017-02-08 17:37:49 +0000
@@ -0,0 +1,37 @@
1From 248ef2d6a0f97cbb71d10c0bb37a3183f13ea19f Mon Sep 17 00:00:00 2001
2From: William Hua <william.hua@canonical.com>
3Date: Mon, 9 Jan 2017 12:04:48 -0500
4Subject: [PATCH 06/38] mir: properly handle empty clipboard
5
6https://bugzilla.gnome.org/show_bug.cgi?id=775732
7---
8 gdk/mir/gdkmirdisplay.c | 12 +++++++++---
9 1 file changed, 9 insertions(+), 3 deletions(-)
10
11diff --git a/gdk/mir/gdkmirdisplay.c b/gdk/mir/gdkmirdisplay.c
12index 21967ac..62f36ee 100644
13--- a/gdk/mir/gdkmirdisplay.c
14+++ b/gdk/mir/gdkmirdisplay.c
15@@ -703,10 +703,16 @@ gdk_mir_display_real_convert_selection (GdkDisplay *display,
16
17 paste_data = g_variant_get_fixed_array (mir_display->paste_data, &paste_size, sizeof (guchar));
18 paste_header = (const gint *) paste_data;
19- paste_formats = g_ptr_array_new_full (paste_header[0], g_free);
20
21- for (i = 0; i < paste_header[0]; i++)
22- g_ptr_array_add (paste_formats, g_strndup (paste_data + paste_header[1 + 4 * i], paste_header[2 + 4 * i]));
23+ if (paste_data)
24+ {
25+ paste_formats = g_ptr_array_new_full (paste_header[0], g_free);
26+
27+ for (i = 0; i < paste_header[0]; i++)
28+ g_ptr_array_add (paste_formats, g_strndup (paste_data + paste_header[1 + 4 * i], paste_header[2 + 4 * i]));
29+ }
30+ else
31+ paste_formats = g_ptr_array_new_with_free_func (g_free);
32
33 if (target == gdk_atom_intern_static_string ("TARGETS"))
34 {
35--
362.10.2
37
038
=== added file 'debian/patches/0031-mir-fix-compile-time-warnings.patch'
--- debian/patches/0031-mir-fix-compile-time-warnings.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/0031-mir-fix-compile-time-warnings.patch 2017-02-08 17:37:49 +0000
@@ -0,0 +1,77 @@
1From a95feb498409b42d7b7dd08b2c89c98b70b0a9fe Mon Sep 17 00:00:00 2001
2From: William Hua <william.hua@canonical.com>
3Date: Mon, 9 Jan 2017 17:54:37 -0500
4Subject: [PATCH 31/38] mir: fix compile-time warnings
5
6---
7 gdk/mir/gdkmir-debug.c | 10 ++++++++++
8 gdk/mir/gdkmireventsource.c | 2 ++
9 gdk/mir/gdkmirscreen.c | 4 ++++
10 3 files changed, 16 insertions(+)
11
12diff --git a/gdk/mir/gdkmir-debug.c b/gdk/mir/gdkmir-debug.c
13index 7dd54d5..b0ff929 100644
14--- a/gdk/mir/gdkmir-debug.c
15+++ b/gdk/mir/gdkmir-debug.c
16@@ -127,6 +127,7 @@ _gdk_mir_print_touch_event (const MirInputEvent *event)
17 }
18 switch (mir_touch_event_tooltype (touch_event, i))
19 {
20+ default:
21 case mir_touch_tooltype_unknown:
22 g_printerr (" ? ");
23 break;
24@@ -200,6 +201,12 @@ _gdk_mir_print_motion_event (const MirInputEvent *event)
25 }
26
27 static void
28+_gdk_mir_print_input_event (const MirInputEvent *event)
29+{
30+ g_printerr ("INPUT\n");
31+}
32+
33+static void
34 _gdk_mir_print_surface_event (const MirSurfaceEvent *event)
35 {
36 g_printerr ("SURFACE\n");
37@@ -260,6 +267,9 @@ _gdk_mir_print_event (const MirEvent *event)
38 case mir_input_event_type_pointer:
39 _gdk_mir_print_motion_event (mir_event_get_input_event (event));
40 break;
41+ default:
42+ _gdk_mir_print_input_event (mir_event_get_input_event (event));
43+ break;
44 }
45 break;
46 case mir_event_type_key:
47diff --git a/gdk/mir/gdkmireventsource.c b/gdk/mir/gdkmireventsource.c
48index a2a1a12..d3c85b9 100644
49--- a/gdk/mir/gdkmireventsource.c
50+++ b/gdk/mir/gdkmireventsource.c
51@@ -571,6 +571,8 @@ gdk_mir_event_source_queue_event (GdkDisplay *display,
52 case mir_input_event_type_pointer:
53 handle_motion_event (window, input_event);
54 break;
55+ default:
56+ break;
57 }
58
59 break;
60diff --git a/gdk/mir/gdkmirscreen.c b/gdk/mir/gdkmirscreen.c
61index b369b03..979f2ba 100644
62--- a/gdk/mir/gdkmirscreen.c
63+++ b/gdk/mir/gdkmirscreen.c
64@@ -354,6 +354,10 @@ gdk_mir_screen_get_monitor_plug_name (GdkScreen *screen,
65 return g_strdup_printf ("eDP-%u", output->output_id);
66 case mir_display_output_type_virtual:
67 return g_strdup_printf ("Virtual-%u", output->output_id);
68+ case mir_display_output_type_dsi:
69+ return g_strdup_printf ("DSI-%u", output->output_id);
70+ case mir_display_output_type_dpi:
71+ return g_strdup_printf ("DPI-%u", output->output_id);
72 }
73 }
74
75--
762.10.2
77
078
=== added file 'debian/patches/0032-mir-use-modal-window-hint.patch'
--- debian/patches/0032-mir-use-modal-window-hint.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/0032-mir-use-modal-window-hint.patch 2017-02-08 17:37:49 +0000
@@ -0,0 +1,76 @@
1From 5d7db3246e503016462fa28d34b1b3eafe4754d0 Mon Sep 17 00:00:00 2001
2From: William Hua <william.hua@canonical.com>
3Date: Thu, 12 Jan 2017 17:16:27 -0500
4Subject: [PATCH 32/38] mir: use modal window hint
5
6---
7 gdk/mir/gdkmirwindowimpl.c | 25 +++++++++++++++++++++++--
8 1 file changed, 23 insertions(+), 2 deletions(-)
9
10diff --git a/gdk/mir/gdkmirwindowimpl.c b/gdk/mir/gdkmirwindowimpl.c
11index 8a15816..1f48dfb 100644
12--- a/gdk/mir/gdkmirwindowimpl.c
13+++ b/gdk/mir/gdkmirwindowimpl.c
14@@ -88,6 +88,7 @@ struct _GdkMirWindowImpl
15 /* Desired surface attributes */
16 GdkWindowTypeHint type_hint;
17 MirSurfaceState surface_state;
18+ gboolean modal;
19
20 /* Pattern for background */
21 cairo_pattern_t *background;
22@@ -305,6 +306,7 @@ create_window_type_spec (GdkDisplay *display,
23 gint y,
24 gint width,
25 gint height,
26+ gboolean modal,
27 GdkWindowTypeHint type,
28 const MirRectangle *rect,
29 MirEdgeAttachment edge,
30@@ -358,6 +360,17 @@ create_window_type_spec (GdkDisplay *display,
31 switch (type)
32 {
33 case GDK_WINDOW_TYPE_HINT_DIALOG:
34+ if (modal)
35+ return mir_connection_create_spec_for_modal_dialog (connection,
36+ width,
37+ height,
38+ format,
39+ parent_surface);
40+ else
41+ return mir_connection_create_spec_for_dialog (connection,
42+ width,
43+ height,
44+ format);
45 case GDK_WINDOW_TYPE_HINT_DOCK:
46 return mir_connection_create_spec_for_dialog (connection,
47 width,
48@@ -430,6 +443,7 @@ create_spec (GdkWindow *window, GdkMirWindowImpl *impl)
49 impl->transient_for,
50 impl->transient_x, impl->transient_y,
51 window->width, window->height,
52+ impl->modal,
53 impl->type_hint,
54 impl->has_rect ? &impl->rect : NULL,
55 impl->has_rect ? impl->edge : mir_edge_attachment_any,
56@@ -1133,8 +1147,15 @@ void
57 gdk_mir_window_impl_set_modal_hint (GdkWindow *window,
58 gboolean modal)
59 {
60- //g_printerr ("gdk_mir_window_impl_set_modal_hint window=%p\n", window);
61- /* Mir doesn't support modal windows */
62+ GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
63+
64+ if (modal != impl->modal)
65+ {
66+ impl->modal = modal;
67+
68+ if (impl->surface && !impl->pending_spec_update)
69+ update_surface_spec (window);
70+ }
71 }
72
73 static void
74--
752.10.2
76
077
=== added file 'debian/patches/0036-mir-use-mir_surface_spec_set_placement-for-menus.patch'
--- debian/patches/0036-mir-use-mir_surface_spec_set_placement-for-menus.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/0036-mir-use-mir_surface_spec_set_placement-for-menus.patch 2017-02-08 17:37:49 +0000
@@ -0,0 +1,334 @@
1From 14c8e25cb2063ff3a91b59328b7f45bcbc4cd875 Mon Sep 17 00:00:00 2001
2From: William Hua <william.hua@canonical.com>
3Date: Fri, 27 Jan 2017 14:46:10 -0500
4Subject: [PATCH 36/38] mir: use mir_surface_spec_set_placement for menus
5
6This API was added to Mir for GTK menus, combo boxes, etc.
7---
8 gdk/mir/gdkmirwindowimpl.c | 240 ++++++++++++++++++++++++++++++---------------
9 1 file changed, 159 insertions(+), 81 deletions(-)
10
11diff --git a/gdk/mir/gdkmirwindowimpl.c b/gdk/mir/gdkmirwindowimpl.c
12index 1f48dfb..6fe0b3c 100644
13--- a/gdk/mir/gdkmirwindowimpl.c
14+++ b/gdk/mir/gdkmirwindowimpl.c
15@@ -80,10 +80,15 @@ struct _GdkMirWindowImpl
16 gint transient_x;
17 gint transient_y;
18
19- /* Anchor rectangle */
20- gboolean has_rect;
21- MirRectangle rect;
22- MirEdgeAttachment edge;
23+ /* gdk_window_move_to_rect */
24+ gboolean has_rect;
25+ GdkRectangle rect;
26+ MirRectangle mir_rect;
27+ MirPlacementGravity rect_anchor;
28+ MirPlacementGravity window_anchor;
29+ MirPlacementHints anchor_hints;
30+ gint rect_anchor_dx;
31+ gint rect_anchor_dy;
32
33 /* Desired surface attributes */
34 GdkWindowTypeHint type_hint;
35@@ -308,16 +313,12 @@ create_window_type_spec (GdkDisplay *display,
36 gint height,
37 gboolean modal,
38 GdkWindowTypeHint type,
39- const MirRectangle *rect,
40- MirEdgeAttachment edge,
41 MirBufferUsage buffer_usage)
42 {
43- MirPixelFormat format;
44- MirSurface *parent_surface = NULL;
45 MirConnection *connection = gdk_mir_display_get_mir_connection (display);
46- MirRectangle real_rect;
47-
48- format = _gdk_mir_display_get_pixel_format (display, buffer_usage);
49+ MirSurface *parent_surface = NULL;
50+ MirPixelFormat format;
51+ MirRectangle rect;
52
53 if (parent && parent->impl)
54 {
55@@ -338,24 +339,12 @@ create_window_type_spec (GdkDisplay *display,
56 }
57 }
58
59- if (rect)
60- {
61- real_rect = *rect;
62+ format = _gdk_mir_display_get_pixel_format (display, buffer_usage);
63
64- while (parent && !gdk_window_has_native (parent) && gdk_window_get_effective_parent (parent))
65- {
66- real_rect.left += parent->x;
67- real_rect.top += parent->y;
68- parent = gdk_window_get_effective_parent (parent);
69- }
70- }
71- else
72- {
73- real_rect.left = x;
74- real_rect.top = y;
75- real_rect.width = 1;
76- real_rect.height = 1;
77- }
78+ rect.left = x;
79+ rect.top = y;
80+ rect.width = 1;
81+ rect.height = 1;
82
83 switch (type)
84 {
85@@ -389,9 +378,8 @@ create_window_type_spec (GdkDisplay *display,
86 height,
87 format,
88 parent_surface,
89- &real_rect,
90- edge);
91- break;
92+ &rect,
93+ 0);
94 case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
95 case GDK_WINDOW_TYPE_HINT_UTILITY:
96 return mir_connection_create_spec_for_modal_dialog (connection,
97@@ -438,15 +426,16 @@ static MirSurfaceSpec*
98 create_spec (GdkWindow *window, GdkMirWindowImpl *impl)
99 {
100 MirSurfaceSpec *spec = NULL;
101+ GdkWindow *parent;
102
103 spec = create_window_type_spec (impl->display,
104 impl->transient_for,
105- impl->transient_x, impl->transient_y,
106- window->width, window->height,
107+ impl->transient_x,
108+ impl->transient_y,
109+ window->width,
110+ window->height,
111 impl->modal,
112 impl->type_hint,
113- impl->has_rect ? &impl->rect : NULL,
114- impl->has_rect ? impl->edge : mir_edge_attachment_any,
115 impl->buffer_usage);
116
117 mir_surface_spec_set_name (spec, impl->title);
118@@ -454,6 +443,32 @@ create_spec (GdkWindow *window, GdkMirWindowImpl *impl)
119
120 apply_geometry_hints (spec, impl);
121
122+ if (impl->has_rect)
123+ {
124+ impl->mir_rect.left = impl->rect.x;
125+ impl->mir_rect.top = impl->rect.y;
126+ impl->mir_rect.width = impl->rect.width;
127+ impl->mir_rect.height = impl->rect.height;
128+
129+ parent = impl->transient_for;
130+
131+ while (parent && !gdk_window_has_native (parent))
132+ {
133+ impl->mir_rect.left += parent->x;
134+ impl->mir_rect.top += parent->y;
135+
136+ parent = gdk_window_get_parent (parent);
137+ }
138+
139+ mir_surface_spec_set_placement (spec,
140+ &impl->mir_rect,
141+ impl->rect_anchor,
142+ impl->window_anchor,
143+ impl->anchor_hints,
144+ impl->rect_anchor_dx,
145+ impl->rect_anchor_dy);
146+ }
147+
148 return spec;
149 }
150
151@@ -861,52 +876,117 @@ gdk_mir_window_impl_move_resize (GdkWindow *window,
152 }
153 }
154
155-static MirEdgeAttachment
156-get_edge_for_anchors (GdkGravity rect_anchor,
157- GdkGravity window_anchor,
158- GdkAnchorHints anchor_hints)
159+static MirPlacementGravity
160+get_mir_placement_gravity (GdkGravity gravity)
161 {
162- MirEdgeAttachment edge = 0;
163+ switch (gravity)
164+ {
165+ case GDK_GRAVITY_STATIC:
166+ case GDK_GRAVITY_NORTH_WEST:
167+ return mir_placement_gravity_northwest;
168+ case GDK_GRAVITY_NORTH:
169+ return mir_placement_gravity_north;
170+ case GDK_GRAVITY_NORTH_EAST:
171+ return mir_placement_gravity_northeast;
172+ case GDK_GRAVITY_WEST:
173+ return mir_placement_gravity_west;
174+ case GDK_GRAVITY_CENTER:
175+ return mir_placement_gravity_center;
176+ case GDK_GRAVITY_EAST:
177+ return mir_placement_gravity_east;
178+ case GDK_GRAVITY_SOUTH_WEST:
179+ return mir_placement_gravity_southwest;
180+ case GDK_GRAVITY_SOUTH:
181+ return mir_placement_gravity_south;
182+ case GDK_GRAVITY_SOUTH_EAST:
183+ return mir_placement_gravity_southeast;
184+ }
185
186- if (anchor_hints & GDK_ANCHOR_FLIP_X)
187- edge |= mir_edge_attachment_vertical;
188+ g_warn_if_reached ();
189
190- if (anchor_hints & GDK_ANCHOR_FLIP_Y)
191- edge |= mir_edge_attachment_horizontal;
192+ return mir_placement_gravity_center;
193+}
194+
195+static MirPlacementHints
196+get_mir_placement_hints (GdkAnchorHints hints)
197+{
198+ MirPlacementHints mir_hints = 0;
199+
200+ if (hints & GDK_ANCHOR_FLIP_X)
201+ mir_hints |= mir_placement_hints_flip_x;
202+
203+ if (hints & GDK_ANCHOR_FLIP_Y)
204+ mir_hints |= mir_placement_hints_flip_y;
205+
206+ if (hints & GDK_ANCHOR_SLIDE_X)
207+ mir_hints |= mir_placement_hints_slide_x;
208+
209+ if (hints & GDK_ANCHOR_SLIDE_Y)
210+ mir_hints |= mir_placement_hints_slide_y;
211
212- return edge;
213+ if (hints & GDK_ANCHOR_RESIZE_X)
214+ mir_hints |= mir_placement_hints_resize_x;
215+
216+ if (hints & GDK_ANCHOR_RESIZE_Y)
217+ mir_hints |= mir_placement_hints_resize_y;
218+
219+ return mir_hints;
220 }
221
222-static void
223-get_rect_for_edge (MirRectangle *out_rect,
224- const GdkRectangle *in_rect,
225- MirEdgeAttachment edge,
226- GdkWindow *window)
227+static gint
228+get_window_shadow_dx (GdkWindow *window,
229+ GdkGravity window_anchor)
230 {
231- out_rect->left = in_rect->x;
232- out_rect->top = in_rect->y;
233- out_rect->width = in_rect->width;
234- out_rect->height = in_rect->height;
235+ switch (window_anchor)
236+ {
237+ case GDK_GRAVITY_STATIC:
238+ case GDK_GRAVITY_NORTH_WEST:
239+ case GDK_GRAVITY_WEST:
240+ case GDK_GRAVITY_SOUTH_WEST:
241+ return -window->shadow_left;
242+
243+ case GDK_GRAVITY_NORTH:
244+ case GDK_GRAVITY_CENTER:
245+ case GDK_GRAVITY_SOUTH:
246+ return (window->shadow_right - window->shadow_left) / 2;
247+
248+ case GDK_GRAVITY_NORTH_EAST:
249+ case GDK_GRAVITY_EAST:
250+ case GDK_GRAVITY_SOUTH_EAST:
251+ return window->shadow_right;
252+ }
253
254- switch (edge)
255+ g_warn_if_reached ();
256+
257+ return 0;
258+}
259+
260+static gint
261+get_window_shadow_dy (GdkWindow *window,
262+ GdkGravity window_anchor)
263+{
264+ switch (window_anchor)
265 {
266- case mir_edge_attachment_vertical:
267- out_rect->left += window->shadow_right;
268- out_rect->top -= window->shadow_top;
269- out_rect->width -= window->shadow_left + window->shadow_right;
270- out_rect->height += window->shadow_top + window->shadow_bottom;
271- break;
272-
273- case mir_edge_attachment_horizontal:
274- out_rect->left -= window->shadow_left;
275- out_rect->top += window->shadow_bottom;
276- out_rect->width += window->shadow_left + window->shadow_right;
277- out_rect->height -= window->shadow_top + window->shadow_bottom;
278- break;
279-
280- default:
281- break;
282+ case GDK_GRAVITY_STATIC:
283+ case GDK_GRAVITY_NORTH_WEST:
284+ case GDK_GRAVITY_NORTH:
285+ case GDK_GRAVITY_NORTH_EAST:
286+ return -window->shadow_top;
287+
288+ case GDK_GRAVITY_WEST:
289+ case GDK_GRAVITY_CENTER:
290+ case GDK_GRAVITY_EAST:
291+ return (window->shadow_bottom - window->shadow_top) / 2;
292+
293+ case GDK_GRAVITY_SOUTH_WEST:
294+ case GDK_GRAVITY_SOUTH:
295+ case GDK_GRAVITY_SOUTH_EAST:
296+ return window->shadow_bottom;
297 }
298+
299+ g_warn_if_reached ();
300+
301+ return 0;
302 }
303
304 static void
305@@ -920,18 +1000,16 @@ gdk_mir_window_impl_move_to_rect (GdkWindow *window,
306 {
307 GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
308
309- impl->edge = get_edge_for_anchors (rect_anchor, window_anchor, anchor_hints);
310- get_rect_for_edge (&impl->rect, rect, impl->edge, window);
311 impl->has_rect = TRUE;
312+ impl->rect = *rect;
313+ impl->rect_anchor = get_mir_placement_gravity (rect_anchor);
314+ impl->window_anchor = get_mir_placement_gravity (window_anchor);
315+ impl->anchor_hints = get_mir_placement_hints (anchor_hints);
316+ impl->rect_anchor_dx = rect_anchor_dx + get_window_shadow_dx (window, window_anchor);
317+ impl->rect_anchor_dy = rect_anchor_dy + get_window_shadow_dy (window, window_anchor);
318
319- ensure_no_surface (window);
320-
321- g_signal_emit_by_name (window,
322- "moved-to-rect",
323- NULL,
324- NULL,
325- FALSE,
326- FALSE);
327+ if (impl->surface && !impl->pending_spec_update)
328+ update_surface_spec (window);
329 }
330
331 static void
332--
3332.10.2
334
0335
=== added file 'debian/patches/0037-mir-handle-surface-placement-events.patch'
--- debian/patches/0037-mir-handle-surface-placement-events.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/0037-mir-handle-surface-placement-events.patch 2017-02-08 17:37:49 +0000
@@ -0,0 +1,287 @@
1From d9947b671a2c605ef64cb720d2a9c6c80b39e7af Mon Sep 17 00:00:00 2001
2From: William Hua <william.hua@canonical.com>
3Date: Sun, 29 Jan 2017 11:24:43 -0500
4Subject: [PATCH 37/38] mir: handle surface placement events
5
6This allows the Mir backend to properly emit "moved-to-rect."
7---
8 gdk/mir/gdkmir-private.h | 2 +
9 gdk/mir/gdkmir.h | 1 +
10 gdk/mir/gdkmireventsource.c | 10 +++
11 gdk/mir/gdkmirwindowimpl.c | 207 ++++++++++++++++++++++++++++++++++++++++++++
12 4 files changed, 220 insertions(+)
13
14diff --git a/gdk/mir/gdkmir-private.h b/gdk/mir/gdkmir-private.h
15index a677dec..4595dc5 100644
16--- a/gdk/mir/gdkmir-private.h
17+++ b/gdk/mir/gdkmir-private.h
18@@ -91,6 +91,8 @@ void _gdk_mir_window_impl_set_surface_type (GdkMirWindowImpl *impl, MirSurfaceTy
19
20 void _gdk_mir_window_set_surface_output (GdkWindow *window, gdouble scale);
21
22+void _gdk_mir_window_set_final_rect (GdkWindow *window, MirRectangle rect);
23+
24 void _gdk_mir_window_impl_set_cursor_state (GdkMirWindowImpl *impl, gdouble x, gdouble y, gboolean cursor_inside, guint button_state);
25
26 void _gdk_mir_window_impl_get_cursor_state (GdkMirWindowImpl *impl, gdouble *x, gdouble *y, gboolean *cursor_inside, guint *button_state);
27diff --git a/gdk/mir/gdkmir.h b/gdk/mir/gdkmir.h
28index 38cc80c..6e92fcf 100644
29--- a/gdk/mir/gdkmir.h
30+++ b/gdk/mir/gdkmir.h
31@@ -20,6 +20,7 @@
32
33 #include <gdk/gdk.h>
34 #include <mir_toolkit/mir_client_library.h>
35+#include <mir_toolkit/events/surface_placement.h>
36
37 G_BEGIN_DECLS
38
39diff --git a/gdk/mir/gdkmireventsource.c b/gdk/mir/gdkmireventsource.c
40index d3c85b9..3ebf156 100644
41--- a/gdk/mir/gdkmireventsource.c
42+++ b/gdk/mir/gdkmireventsource.c
43@@ -541,6 +541,13 @@ handle_surface_output_event (GdkWindow *window,
44 _gdk_mir_window_set_surface_output (window, mir_surface_output_event_get_scale (event));
45 }
46
47+static void
48+handle_surface_placement_event (GdkWindow *window,
49+ const MirSurfacePlacementEvent *event)
50+{
51+ _gdk_mir_window_set_final_rect (window, mir_surface_placement_get_relative_position (event));
52+}
53+
54 typedef struct
55 {
56 GdkWindow *window;
57@@ -600,6 +607,9 @@ gdk_mir_event_source_queue_event (GdkDisplay *display,
58 case mir_event_type_surface_output:
59 handle_surface_output_event (window, mir_event_get_surface_output_event (event));
60 break;
61+ case mir_event_type_surface_placement:
62+ handle_surface_placement_event (window, mir_event_get_surface_placement_event (event));
63+ break;
64 default:
65 g_warning ("Ignoring unknown Mir event %d", mir_event_get_type (event));
66 // FIXME?
67diff --git a/gdk/mir/gdkmirwindowimpl.c b/gdk/mir/gdkmirwindowimpl.c
68index 6fe0b3c..1b016ec 100644
69--- a/gdk/mir/gdkmirwindowimpl.c
70+++ b/gdk/mir/gdkmirwindowimpl.c
71@@ -1012,6 +1012,213 @@ gdk_mir_window_impl_move_to_rect (GdkWindow *window,
72 update_surface_spec (window);
73 }
74
75+static gint
76+get_mir_placement_gravity_x (MirPlacementGravity gravity)
77+{
78+ switch (gravity)
79+ {
80+ case mir_placement_gravity_west:
81+ case mir_placement_gravity_northwest:
82+ case mir_placement_gravity_southwest:
83+ return 0;
84+
85+ case mir_placement_gravity_center:
86+ case mir_placement_gravity_north:
87+ case mir_placement_gravity_south:
88+ return 1;
89+
90+ case mir_placement_gravity_east:
91+ case mir_placement_gravity_northeast:
92+ case mir_placement_gravity_southeast:
93+ return 2;
94+ }
95+
96+ g_warn_if_reached ();
97+
98+ return 1;
99+}
100+
101+static gint
102+get_mir_placement_gravity_y (MirPlacementGravity gravity)
103+{
104+ switch (gravity)
105+ {
106+ case mir_placement_gravity_north:
107+ case mir_placement_gravity_northwest:
108+ case mir_placement_gravity_northeast:
109+ return 0;
110+
111+ case mir_placement_gravity_center:
112+ case mir_placement_gravity_west:
113+ case mir_placement_gravity_east:
114+ return 1;
115+
116+ case mir_placement_gravity_south:
117+ case mir_placement_gravity_southwest:
118+ case mir_placement_gravity_southeast:
119+ return 2;
120+ }
121+
122+ g_warn_if_reached ();
123+
124+ return 1;
125+}
126+
127+static GdkRectangle
128+get_unflipped_rect (const GdkRectangle *rect,
129+ gint width,
130+ gint height,
131+ MirPlacementGravity rect_anchor,
132+ MirPlacementGravity window_anchor,
133+ gint rect_anchor_dx,
134+ gint rect_anchor_dy)
135+{
136+ GdkRectangle unflipped_rect;
137+
138+ unflipped_rect.x = rect->x;
139+ unflipped_rect.x += rect->width * get_mir_placement_gravity_x (rect_anchor) / 2;
140+ unflipped_rect.x -= width * get_mir_placement_gravity_x (window_anchor) / 2;
141+ unflipped_rect.x += rect_anchor_dx;
142+ unflipped_rect.y = rect->y;
143+ unflipped_rect.y += rect->height * get_mir_placement_gravity_y (rect_anchor) / 2;
144+ unflipped_rect.y -= height * get_mir_placement_gravity_y (window_anchor) / 2;
145+ unflipped_rect.y += rect_anchor_dy;
146+ unflipped_rect.width = width;
147+ unflipped_rect.height = height;
148+
149+ return unflipped_rect;
150+}
151+
152+static MirPlacementGravity
153+get_opposite_mir_placement_gravity (MirPlacementGravity gravity)
154+{
155+ switch (gravity)
156+ {
157+ case mir_placement_gravity_center:
158+ return mir_placement_gravity_center;
159+ case mir_placement_gravity_west:
160+ return mir_placement_gravity_east;
161+ case mir_placement_gravity_east:
162+ return mir_placement_gravity_west;
163+ case mir_placement_gravity_north:
164+ return mir_placement_gravity_south;
165+ case mir_placement_gravity_south:
166+ return mir_placement_gravity_north;
167+ case mir_placement_gravity_northwest:
168+ return mir_placement_gravity_southeast;
169+ case mir_placement_gravity_northeast:
170+ return mir_placement_gravity_southwest;
171+ case mir_placement_gravity_southwest:
172+ return mir_placement_gravity_northeast;
173+ case mir_placement_gravity_southeast:
174+ return mir_placement_gravity_northwest;
175+ }
176+
177+ g_warn_if_reached ();
178+
179+ return gravity;
180+}
181+
182+static gint
183+get_anchor_x (const GdkRectangle *rect,
184+ MirPlacementGravity anchor)
185+{
186+ return rect->x + rect->width * get_mir_placement_gravity_x (anchor) / 2;
187+}
188+
189+static gint
190+get_anchor_y (const GdkRectangle *rect,
191+ MirPlacementGravity anchor)
192+{
193+ return rect->y + rect->height * get_mir_placement_gravity_y (anchor) / 2;
194+}
195+
196+void
197+_gdk_mir_window_set_final_rect (GdkWindow *window,
198+ MirRectangle rect)
199+{
200+ GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
201+ GdkRectangle best_rect;
202+ GdkRectangle worst_rect;
203+ GdkRectangle flipped_rect;
204+ GdkRectangle final_rect;
205+ gboolean flipped_x = FALSE;
206+ gboolean flipped_y = FALSE;
207+ gint test_position;
208+ gint final_position;
209+ gint unflipped_offset;
210+ gint flipped_offset;
211+
212+ g_return_if_fail (impl->has_rect);
213+
214+ best_rect = get_unflipped_rect (&impl->rect,
215+ window->width,
216+ window->height,
217+ impl->rect_anchor,
218+ impl->window_anchor,
219+ impl->rect_anchor_dx,
220+ impl->rect_anchor_dy);
221+
222+ worst_rect = get_unflipped_rect (&impl->rect,
223+ window->width,
224+ window->height,
225+ get_opposite_mir_placement_gravity (impl->rect_anchor),
226+ get_opposite_mir_placement_gravity (impl->window_anchor),
227+ -impl->rect_anchor_dx,
228+ -impl->rect_anchor_dy);
229+
230+ flipped_rect.x = best_rect.x;
231+ flipped_rect.y = best_rect.y;
232+ flipped_rect.width = window->width;
233+ flipped_rect.height = window->height;
234+
235+ final_rect.x = rect.left - (impl->mir_rect.left - impl->rect.x);
236+ final_rect.y = rect.top - (impl->mir_rect.top - impl->rect.y);
237+ final_rect.width = rect.width;
238+ final_rect.height = rect.height;
239+
240+ if (impl->anchor_hints & mir_placement_hints_flip_x)
241+ {
242+ test_position = get_anchor_x (&best_rect, impl->window_anchor);
243+ final_position = get_anchor_x (&final_rect, impl->window_anchor);
244+ unflipped_offset = final_position - test_position;
245+
246+ test_position = get_anchor_x (&worst_rect, get_opposite_mir_placement_gravity (impl->window_anchor));
247+ final_position = get_anchor_x (&final_rect, get_opposite_mir_placement_gravity (impl->window_anchor));
248+ flipped_offset = final_position - test_position;
249+
250+ if (ABS (flipped_offset) < ABS (unflipped_offset))
251+ {
252+ flipped_rect.x = worst_rect.x;
253+ flipped_x = TRUE;
254+ }
255+ }
256+
257+ if (impl->anchor_hints & mir_placement_hints_flip_y)
258+ {
259+ test_position = get_anchor_y (&best_rect, impl->window_anchor);
260+ final_position = get_anchor_y (&final_rect, impl->window_anchor);
261+ unflipped_offset = final_position - test_position;
262+
263+ test_position = get_anchor_y (&worst_rect, get_opposite_mir_placement_gravity (impl->window_anchor));
264+ final_position = get_anchor_y (&final_rect, get_opposite_mir_placement_gravity (impl->window_anchor));
265+ flipped_offset = final_position - test_position;
266+
267+ if (ABS (flipped_offset) < ABS (unflipped_offset))
268+ {
269+ flipped_rect.y = worst_rect.y;
270+ flipped_y = TRUE;
271+ }
272+ }
273+
274+ g_signal_emit_by_name (window,
275+ "moved-to-rect",
276+ &flipped_rect,
277+ &final_rect,
278+ flipped_x,
279+ flipped_y);
280+}
281+
282 static void
283 gdk_mir_window_impl_set_background (GdkWindow *window,
284 cairo_pattern_t *pattern)
285--
2862.10.2
287
0288
=== modified file 'debian/patches/series'
--- debian/patches/series 2017-01-23 14:44:24 +0000
+++ debian/patches/series 2017-02-08 17:37:49 +0000
@@ -24,3 +24,14 @@
24unity-border-radius.patch24unity-border-radius.patch
25unity-headerbar-maximized-mode.patch25unity-headerbar-maximized-mode.patch
26gtksocket-unscale-before-sending-configurenotify.patch26gtksocket-unscale-before-sending-configurenotify.patch
27
280001-mir-implement-window-properties.patch
290002-mir-track-focused-window.patch
300003-mir-connect-to-content-hub.patch
310004-mir-copy-clipboard-data-to-content-hub.patch
320005-mir-paste-clipboard-data-from-content-hub.patch
330006-mir-properly-handle-empty-clipboard.patch
340031-mir-fix-compile-time-warnings.patch
350032-mir-use-modal-window-hint.patch
360036-mir-use-mir_surface_spec_set_placement-for-menus.patch
370037-mir-handle-surface-placement-events.patch

Subscribers

People subscribed via source and target branches

to all changes: