~attente/gtk/mir-copy-paste

« back to all changes in this revision

Viewing changes to debian/patches/0001-Update-the-GDK-Mir-backend-to-fix-a-few-problems.patch

  • Committer: Iain Lane
  • Date: 2016-08-15 14:20:34 UTC
  • mfrom: (519.1.1 trunk)
  • Revision ID: iain.lane@canonical.com-20160815142034-6yhwmxrl2js60w0l
* Add 0001-Update-the-GDK-Mir-backend-to-fix-a-few-problems.patch
  - See https://bugzilla.gnome.org/show_bug.cgi?id=768138, thanks to
    Andreas Pokorny

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
From 52b9d12764e90efe21806a54c4191ae999ed7751 Mon Sep 17 00:00:00 2001
 
2
From: Andreas Pokorny <andreas.pokorny@canonical.com>
 
3
Date: Tue, 19 Jul 2016 14:56:34 +0200
 
4
Subject: [PATCH] Update the GDK-Mir backend to fix a few problems
 
5
 
 
6
See https://bugzilla.gnome.org/show_bug.cgi?id=768138
 
7
---
 
8
 configure.ac                |   2 +-
 
9
 gdk/mir/gdkmir-private.h    |   4 +-
 
10
 gdk/mir/gdkmirdisplay.c     |   2 +-
 
11
 gdk/mir/gdkmireventsource.c |  62 +++----
 
12
 gdk/mir/gdkmirscreen.c      |   4 +-
 
13
 gdk/mir/gdkmirwindowimpl.c  | 425 ++++++++++++++++++++++++++++++++++++--------
 
14
 6 files changed, 382 insertions(+), 117 deletions(-)
 
15
 
 
16
diff --git a/configure.ac b/configure.ac
 
17
index 89722cd..66a5fc6 100644
 
18
--- a/configure.ac
 
19
+++ b/configure.ac
 
20
@@ -61,7 +61,7 @@ m4_define([gdk_pixbuf_required_version], [2.30.0])
 
21
 m4_define([introspection_required_version], [1.39.0])
 
22
 m4_define([wayland_required_version], [1.9.91])
 
23
 m4_define([wayland_protocols_required_version], [1.0])
 
24
-m4_define([mirclient_required_version], [0.11.0])
 
25
+m4_define([mirclient_required_version], [0.22.0])
 
26
 m4_define([mircookie_required_version], [0.17.0])
 
27
 m4_define([epoxy_required_version], [1.0])
 
28
 GLIB_REQUIRED_VERSION=glib_required_version
 
29
diff --git a/gdk/mir/gdkmir-private.h b/gdk/mir/gdkmir-private.h
 
30
index 84051a7..38f1d7a 100644
 
31
--- a/gdk/mir/gdkmir-private.h
 
32
+++ b/gdk/mir/gdkmir-private.h
 
33
@@ -83,12 +83,14 @@ GdkCursor *_gdk_mir_cursor_new_for_name (GdkDisplay *display, const gchar *name)
 
34
 
 
35
 const gchar *_gdk_mir_cursor_get_name (GdkCursor *cursor);
 
36
 
 
37
-GdkWindowImpl *_gdk_mir_window_impl_new (void);
 
38
+GdkWindowImpl *_gdk_mir_window_impl_new (GdkDisplay *display, GdkWindow *window, GdkWindowAttr *attributes, gint attributes_mask);
 
39
 
 
40
 void _gdk_mir_window_impl_set_surface_state (GdkMirWindowImpl *impl, MirSurfaceState state);
 
41
 
 
42
 void _gdk_mir_window_impl_set_surface_type (GdkMirWindowImpl *impl, MirSurfaceType type);
 
43
 
 
44
+void _gdk_mir_window_set_surface_output (GdkWindow *window, gdouble scale);
 
45
+
 
46
 void _gdk_mir_window_impl_set_cursor_state (GdkMirWindowImpl *impl, gdouble x, gdouble y, gboolean cursor_inside, guint button_state);
 
47
 
 
48
 void _gdk_mir_window_impl_get_cursor_state (GdkMirWindowImpl *impl, gdouble *x, gdouble *y, gboolean *cursor_inside, guint *button_state);
 
49
diff --git a/gdk/mir/gdkmirdisplay.c b/gdk/mir/gdkmirdisplay.c
 
50
index ffcee8a..eea892c 100644
 
51
--- a/gdk/mir/gdkmirdisplay.c
 
52
+++ b/gdk/mir/gdkmirdisplay.c
 
53
@@ -411,7 +411,7 @@ gdk_mir_display_create_window_impl (GdkDisplay    *display,
 
54
 
 
55
   if (attributes->wclass == GDK_INPUT_OUTPUT)
 
56
     {
 
57
-      window->impl = _gdk_mir_window_impl_new ();
 
58
+      window->impl = _gdk_mir_window_impl_new (display, window, attributes, attributes_mask);
 
59
       window->impl_window = window;
 
60
     }
 
61
   else /* attributes->wclass == GDK_INPUT_ONLY */
 
62
diff --git a/gdk/mir/gdkmireventsource.c b/gdk/mir/gdkmireventsource.c
 
63
index a288cb7..865b6f6 100644
 
64
--- a/gdk/mir/gdkmireventsource.c
 
65
+++ b/gdk/mir/gdkmireventsource.c
 
66
@@ -289,28 +289,17 @@ handle_key_event (GdkWindow *window, const MirInputEvent *event)
 
67
   if (!keyboard_event)
 
68
     return;
 
69
 
 
70
-  switch (mir_keyboard_event_action (keyboard_event))
 
71
-    {
 
72
-    case mir_keyboard_action_up:
 
73
-    case mir_keyboard_action_down:
 
74
-      // FIXME: Convert keycode
 
75
-      _gdk_mir_window_impl_get_cursor_state (impl, NULL, NULL, NULL, &button_state);
 
76
-      modifier_state = get_modifier_state (mir_keyboard_event_modifiers (keyboard_event), button_state);
 
77
-      keymap = gdk_keymap_get_for_display (gdk_window_get_display (window));
 
78
-
 
79
-      generate_key_event (window,
 
80
-                          mir_keyboard_event_action (keyboard_event) == mir_keyboard_action_down ? GDK_KEY_PRESS : GDK_KEY_RELEASE,
 
81
-                          modifier_state,
 
82
-                          mir_keyboard_event_key_code (keyboard_event),
 
83
-                          mir_keyboard_event_scan_code (keyboard_event),
 
84
-                          _gdk_mir_keymap_key_is_modifier (keymap, mir_keyboard_event_key_code (keyboard_event)),
 
85
-                          NANO_TO_MILLI (mir_input_event_get_event_time (event)));
 
86
-      break;
 
87
-    default:
 
88
-    //case mir_key_action_multiple:
 
89
-      // FIXME
 
90
-      break;
 
91
-    }
 
92
+  _gdk_mir_window_impl_get_cursor_state (impl, NULL, NULL, NULL, &button_state);
 
93
+  modifier_state = get_modifier_state (mir_keyboard_event_modifiers (keyboard_event), button_state);
 
94
+  keymap = gdk_keymap_get_for_display (gdk_window_get_display (window));
 
95
+
 
96
+  generate_key_event (window,
 
97
+                      mir_keyboard_event_action (keyboard_event) == mir_keyboard_action_up ? GDK_KEY_RELEASE : GDK_KEY_PRESS,
 
98
+                      modifier_state,
 
99
+                      mir_keyboard_event_key_code (keyboard_event),
 
100
+                      mir_keyboard_event_scan_code (keyboard_event),
 
101
+                      _gdk_mir_keymap_key_is_modifier (keymap, mir_keyboard_event_key_code (keyboard_event)),
 
102
+                      NANO_TO_MILLI (mir_input_event_get_event_time (event)));
 
103
 }
 
104
 
 
105
 static void
 
106
@@ -324,18 +313,13 @@ handle_touch_event (GdkWindow           *window,
 
107
 
 
108
   for (i = 0; i < n; i++)
 
109
     {
 
110
-      switch (mir_touch_event_action (mir_touch_event, i))
 
111
-        {
 
112
-        case mir_touch_action_up:
 
113
-          gdk_event = gdk_event_new (GDK_TOUCH_END);
 
114
-          break;
 
115
-        case mir_touch_action_down:
 
116
-          gdk_event = gdk_event_new (GDK_TOUCH_BEGIN);
 
117
-          break;
 
118
-        case mir_touch_action_change:
 
119
-          gdk_event = gdk_event_new (GDK_TOUCH_UPDATE);
 
120
-          break;
 
121
-        }
 
122
+      MirTouchAction action = mir_touch_event_action (mir_touch_event, i);
 
123
+      if (action == mir_touch_action_up)
 
124
+        gdk_event = gdk_event_new (GDK_TOUCH_END);
 
125
+      else if (action == mir_touch_action_down)
 
126
+        gdk_event = gdk_event_new (GDK_TOUCH_BEGIN);
 
127
+      else
 
128
+        gdk_event = gdk_event_new (GDK_TOUCH_UPDATE);
 
129
 
 
130
       gdk_event->touch.window = window;
 
131
       gdk_event->touch.sequence = GINT_TO_POINTER (mir_touch_event_id (mir_touch_event, i));
 
132
@@ -543,6 +527,13 @@ handle_close_event (GdkWindow *window)
 
133
   gdk_window_destroy_notify (window);
 
134
 }
 
135
 
 
136
+static void
 
137
+handle_surface_output_event (GdkWindow                  *window,
 
138
+                             const MirSurfaceOutputEvent *event)
 
139
+{
 
140
+  _gdk_mir_window_set_surface_output (window, mir_surface_output_event_get_scale (event));
 
141
+}
 
142
+
 
143
 typedef struct
 
144
 {
 
145
   GdkWindow *window;
 
146
@@ -597,6 +588,9 @@ gdk_mir_event_source_queue_event (GdkDisplay     *display,
 
147
     case mir_event_type_close_surface:
 
148
       handle_close_event (window);
 
149
       break;
 
150
+    case mir_event_type_surface_output:
 
151
+      handle_surface_output_event (window, mir_event_get_surface_output_event (event));
 
152
+      break;
 
153
     default:
 
154
       g_warning ("Ignoring unknown Mir event %d", mir_event_get_type (event));
 
155
       // FIXME?
 
156
diff --git a/gdk/mir/gdkmirscreen.c b/gdk/mir/gdkmirscreen.c
 
157
index 7aa0aa6..b369b03 100644
 
158
--- a/gdk/mir/gdkmirscreen.c
 
159
+++ b/gdk/mir/gdkmirscreen.c
 
160
@@ -257,7 +257,6 @@ gdk_mir_screen_get_root_window (GdkScreen *screen)
 
161
   get_screen_size (GDK_MIR_SCREEN (screen)->display_config, &width, &height);
 
162
 
 
163
   s->root_window = _gdk_display_create_window (s->display);
 
164
-  s->root_window->impl = _gdk_mir_window_impl_new ();
 
165
   s->root_window->impl_window = s->root_window;
 
166
   s->root_window->visual = s->visual;
 
167
   s->root_window->window_type = GDK_WINDOW_ROOT;
 
168
@@ -269,6 +268,7 @@ gdk_mir_screen_get_root_window (GdkScreen *screen)
 
169
   s->root_window->width = width;
 
170
   s->root_window->height = height;
 
171
   s->root_window->viewable = TRUE;
 
172
+  s->root_window->impl = _gdk_mir_window_impl_new (s->display, s->root_window, NULL, 0);
 
173
 
 
174
   return s->root_window;
 
175
 }
 
176
@@ -352,6 +352,8 @@ gdk_mir_screen_get_monitor_plug_name (GdkScreen *screen,
 
177
             return g_strdup_printf ("TV-%u", output->output_id);
 
178
           case mir_display_output_type_edp:
 
179
             return g_strdup_printf ("eDP-%u", output->output_id);
 
180
+          case mir_display_output_type_virtual:
 
181
+            return g_strdup_printf ("Virtual-%u", output->output_id);
 
182
         }
 
183
     }
 
184
 
 
185
diff --git a/gdk/mir/gdkmirwindowimpl.c b/gdk/mir/gdkmirwindowimpl.c
 
186
index 5ca9d89..fc37c7e 100644
 
187
--- a/gdk/mir/gdkmirwindowimpl.c
 
188
+++ b/gdk/mir/gdkmirwindowimpl.c
 
189
@@ -16,6 +16,7 @@
 
190
  */
 
191
 
 
192
 #include <inttypes.h>
 
193
+#include <math.h>
 
194
 
 
195
 #include "config.h"
 
196
 
 
197
@@ -28,6 +29,7 @@
 
198
 #include "gdkintl.h"
 
199
 #include "gdkdisplayprivate.h"
 
200
 #include "gdkdeviceprivate.h"
 
201
+#include "gdkframeclockprivate.h"
 
202
 
 
203
 #define GDK_MIR_WINDOW_IMPL_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WINDOW_IMPL_MIR, GdkMirWindowImplClass))
 
204
 #define GDK_IS_WINDOW_IMPL_MIR_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WINDOW_IMPL_MIR))
 
205
@@ -58,12 +60,21 @@ struct _GdkMirWindowImpl
 
206
   gdouble y;
 
207
   guint button_state;
 
208
 
 
209
+  GdkDisplay *display;
 
210
+
 
211
   /* Surface being rendered to (only exists when window visible) */
 
212
   MirSurface *surface;
 
213
+  MirBufferStream *buffer_stream;
 
214
+  MirBufferUsage buffer_usage;
 
215
 
 
216
   /* Cairo context for current frame */
 
217
   cairo_surface_t *cairo_surface;
 
218
 
 
219
+  gchar *title;
 
220
+
 
221
+  GdkGeometry geometry_hints;
 
222
+  GdkWindowHints geometry_mask;
 
223
+
 
224
   /* Egl surface for the current mir surface */
 
225
   EGLSurface egl_surface;
 
226
 
 
227
@@ -75,6 +86,12 @@ struct _GdkMirWindowImpl
 
228
 
 
229
   /* TRUE if cursor is inside this window */
 
230
   gboolean cursor_inside;
 
231
+
 
232
+  gboolean pending_redraw;
 
233
+  gboolean pending_commit;
 
234
+  gboolean pending_swap;
 
235
+  gboolean pending_spec_update;
 
236
+  gint output_scale;
 
237
 };
 
238
 
 
239
 struct _GdkMirWindowImplClass
 
240
@@ -85,11 +102,97 @@ struct _GdkMirWindowImplClass
 
241
 G_DEFINE_TYPE (GdkMirWindowImpl, gdk_mir_window_impl, GDK_TYPE_WINDOW_IMPL)
 
242
 
 
243
 static cairo_surface_t *gdk_mir_window_impl_ref_cairo_surface (GdkWindow *window);
 
244
+static void on_frame_clock_after_paint (GdkFrameClock *clock, GdkWindow *window);
 
245
+static void ensure_surface (GdkWindow *window);
 
246
+static void apply_geometry_hints (MirSurfaceSpec *spec, GdkMirWindowImpl *impl);
 
247
+
 
248
+static gboolean
 
249
+type_hint_differs (GdkWindowTypeHint lhs, GdkWindowTypeHint rhs)
 
250
+{
 
251
+    if (lhs == rhs)
 
252
+      return FALSE;
 
253
+
 
254
+    switch (lhs)
 
255
+    {
 
256
+      case GDK_WINDOW_TYPE_HINT_DIALOG:
 
257
+      case GDK_WINDOW_TYPE_HINT_DOCK:
 
258
+        return rhs != GDK_WINDOW_TYPE_HINT_DIALOG &&
 
259
+            rhs != GDK_WINDOW_TYPE_HINT_DOCK;
 
260
+      case GDK_WINDOW_TYPE_HINT_MENU:
 
261
+      case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU:
 
262
+      case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
 
263
+      case GDK_WINDOW_TYPE_HINT_TOOLBAR:
 
264
+      case GDK_WINDOW_TYPE_HINT_COMBO:
 
265
+        return rhs != GDK_WINDOW_TYPE_HINT_MENU &&
 
266
+            rhs != GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU &&
 
267
+            rhs != GDK_WINDOW_TYPE_HINT_POPUP_MENU &&
 
268
+            rhs != GDK_WINDOW_TYPE_HINT_TOOLBAR &&
 
269
+            rhs != GDK_WINDOW_TYPE_HINT_COMBO;
 
270
+      case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
 
271
+      case GDK_WINDOW_TYPE_HINT_UTILITY:
 
272
+        return rhs != GDK_WINDOW_TYPE_HINT_SPLASHSCREEN &&
 
273
+            rhs != GDK_WINDOW_TYPE_HINT_UTILITY;
 
274
+      case GDK_WINDOW_TYPE_HINT_DND:
 
275
+      case GDK_WINDOW_TYPE_HINT_TOOLTIP:
 
276
+      case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
 
277
+        return rhs != GDK_WINDOW_TYPE_HINT_DND &&
 
278
+            rhs != GDK_WINDOW_TYPE_HINT_TOOLTIP &&
 
279
+            rhs != GDK_WINDOW_TYPE_HINT_NOTIFICATION;
 
280
+      case GDK_WINDOW_TYPE_HINT_NORMAL:
 
281
+      case GDK_WINDOW_TYPE_HINT_DESKTOP:
 
282
+      default:
 
283
+        return rhs != GDK_WINDOW_TYPE_HINT_NORMAL &&
 
284
+            rhs != GDK_WINDOW_TYPE_HINT_DESKTOP;
 
285
+    }
 
286
+}
 
287
+
 
288
+static void
 
289
+drop_cairo_surface (GdkWindow *window)
 
290
+{
 
291
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
 
292
+
 
293
+  g_clear_pointer (&impl->cairo_surface, cairo_surface_destroy);
 
294
+}
 
295
+
 
296
+static const gchar *
 
297
+get_default_title (void)
 
298
+{
 
299
+  const char *title;
 
300
+
 
301
+  title = g_get_application_name ();
 
302
+  if (!title)
 
303
+    title = g_get_prgname ();
 
304
+  if (!title)
 
305
+    title = "";
 
306
+
 
307
+  return title;
 
308
+}
 
309
 
 
310
 GdkWindowImpl *
 
311
-_gdk_mir_window_impl_new (void)
 
312
+_gdk_mir_window_impl_new (GdkDisplay *display, GdkWindow *window, GdkWindowAttr *attributes, gint attributes_mask)
 
313
 {
 
314
-  return g_object_new (GDK_TYPE_MIR_WINDOW_IMPL, NULL);
 
315
+  GdkFrameClock *frame_clock = gdk_window_get_frame_clock (window);
 
316
+  GdkMirWindowImpl *impl = g_object_new (GDK_TYPE_MIR_WINDOW_IMPL, NULL);
 
317
+
 
318
+  impl->display = display;
 
319
+
 
320
+  if (attributes && attributes_mask & GDK_WA_TITLE)
 
321
+    impl->title = g_strdup (attributes->title);
 
322
+  else
 
323
+    impl->title = g_strdup (get_default_title ());
 
324
+
 
325
+  if (attributes && attributes_mask & GDK_WA_TYPE_HINT)
 
326
+    impl->type_hint = attributes->type_hint;
 
327
+
 
328
+  impl->pending_spec_update = TRUE;
 
329
+
 
330
+  if (window->window_type != GDK_WINDOW_ROOT)
 
331
+    {
 
332
+      g_signal_connect (frame_clock, "after-paint",
 
333
+                        G_CALLBACK (on_frame_clock_after_paint), window);
 
334
+    }
 
335
+
 
336
+  return (GdkWindowImpl *) impl;
 
337
 }
 
338
 
 
339
 void
 
340
@@ -139,18 +242,25 @@ gdk_mir_window_impl_init (GdkMirWindowImpl *impl)
 
341
 {
 
342
   impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
 
343
   impl->surface_state = mir_surface_state_unknown;
 
344
+  impl->output_scale = 1;
 
345
 }
 
346
 
 
347
 static void
 
348
 set_surface_state (GdkMirWindowImpl *impl,
 
349
                    MirSurfaceState state)
 
350
 {
 
351
+  MirConnection *connection = gdk_mir_display_get_mir_connection (impl->display);
 
352
   if (impl->surface_state == state)
 
353
     return;
 
354
 
 
355
   impl->surface_state = state;
 
356
-  if (impl->surface)
 
357
-    mir_surface_set_state (impl->surface, state);
 
358
+  if (impl->surface && !impl->pending_spec_update)
 
359
+    {
 
360
+      MirSurfaceSpec *spec = mir_connection_create_spec_for_changes (connection);
 
361
+      mir_surface_spec_set_state (spec, state);
 
362
+      mir_surface_apply_spec (impl->surface, spec);
 
363
+      mir_surface_spec_release (spec);
 
364
+    }
 
365
 }
 
366
 
 
367
 static void
 
368
@@ -161,26 +271,21 @@ event_cb (MirSurface     *surface,
 
369
   _gdk_mir_event_source_queue (context, event);
 
370
 }
 
371
 
 
372
-static void ensure_surface (GdkWindow *window);
 
373
-
 
374
-static MirSurface *
 
375
-create_mir_surface (GdkDisplay *display,
 
376
-                    GdkWindow *parent,
 
377
-                    gint x,
 
378
-                    gint y,
 
379
-                    gint width,
 
380
-                    gint height,
 
381
-                    GdkWindowTypeHint type,
 
382
-                    MirBufferUsage buffer_usage)
 
383
+static MirSurfaceSpec *
 
384
+create_window_type_spec (GdkDisplay *display,
 
385
+                         GdkWindow *parent,
 
386
+                         gint x,
 
387
+                         gint y,
 
388
+                         gint width,
 
389
+                         gint height,
 
390
+                         GdkWindowTypeHint type,
 
391
+                         MirBufferUsage buffer_usage)
 
392
 {
 
393
-  MirSurface *parent_surface = NULL;
 
394
-  MirSurfaceSpec *spec;
 
395
-  MirConnection *connection;
 
396
-  MirPixelFormat format;
 
397
-  MirSurface *surface;
 
398
   MirRectangle rect;
 
399
+  MirPixelFormat format;
 
400
+  MirSurface *parent_surface = NULL;
 
401
+  MirConnection *connection = gdk_mir_display_get_mir_connection (display);
 
402
 
 
403
-  connection = gdk_mir_display_get_mir_connection (display);
 
404
   format = _gdk_mir_display_get_pixel_format (display, buffer_usage);
 
405
 
 
406
   if (parent && parent->impl)
 
407
@@ -206,11 +311,10 @@ create_mir_surface (GdkDisplay *display,
 
408
     {
 
409
       case GDK_WINDOW_TYPE_HINT_DIALOG:
 
410
       case GDK_WINDOW_TYPE_HINT_DOCK:
 
411
-        spec = mir_connection_create_spec_for_dialog (connection,
 
412
+        return mir_connection_create_spec_for_dialog (connection,
 
413
                                                       width,
 
414
                                                       height,
 
415
                                                       format);
 
416
-        break;
 
417
       case GDK_WINDOW_TYPE_HINT_MENU:
 
418
       case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU:
 
419
       case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
 
420
@@ -220,22 +324,20 @@ create_mir_surface (GdkDisplay *display,
 
421
         rect.top = y;
 
422
         rect.width = 1;
 
423
         rect.height = 1;
 
424
-        spec = mir_connection_create_spec_for_menu (connection,
 
425
+        return mir_connection_create_spec_for_menu (connection,
 
426
                                                     width,
 
427
                                                     height,
 
428
                                                     format,
 
429
                                                     parent_surface,
 
430
                                                     &rect,
 
431
                                                     mir_edge_attachment_any);
 
432
-        break;
 
433
       case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
 
434
       case GDK_WINDOW_TYPE_HINT_UTILITY:
 
435
-        spec = mir_connection_create_spec_for_modal_dialog (connection,
 
436
+        return mir_connection_create_spec_for_modal_dialog (connection,
 
437
                                                             width,
 
438
                                                             height,
 
439
                                                             format,
 
440
                                                             parent_surface);
 
441
-        break;
 
442
       case GDK_WINDOW_TYPE_HINT_DND:
 
443
       case GDK_WINDOW_TYPE_HINT_TOOLTIP:
 
444
       case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
 
445
@@ -243,7 +345,7 @@ create_mir_surface (GdkDisplay *display,
 
446
         rect.top = y;
 
447
         rect.width = 1;
 
448
         rect.height = 1;
 
449
-        spec = mir_connection_create_spec_for_tooltip (connection,
 
450
+        return mir_connection_create_spec_for_tooltip (connection,
 
451
                                                        width,
 
452
                                                        height,
 
453
                                                        format,
 
454
@@ -253,19 +355,73 @@ create_mir_surface (GdkDisplay *display,
 
455
       case GDK_WINDOW_TYPE_HINT_NORMAL:
 
456
       case GDK_WINDOW_TYPE_HINT_DESKTOP:
 
457
       default:
 
458
-        spec = mir_connection_create_spec_for_normal_surface (connection,
 
459
+        return mir_connection_create_spec_for_normal_surface (connection,
 
460
                                                               width,
 
461
                                                               height,
 
462
                                                               format);
 
463
-        break;
 
464
     }
 
465
+}
 
466
 
 
467
-  mir_surface_spec_set_name (spec, g_get_prgname ());
 
468
-  mir_surface_spec_set_buffer_usage (spec, buffer_usage);
 
469
-  surface = mir_surface_create_sync (spec);
 
470
-  mir_surface_spec_release (spec);
 
471
+static void
 
472
+apply_geometry_hints (MirSurfaceSpec *spec, GdkMirWindowImpl *impl)
 
473
+{
 
474
+  if (impl->geometry_mask & GDK_HINT_RESIZE_INC)
 
475
+    {
 
476
+      mir_surface_spec_set_width_increment (spec, impl->geometry_hints.width_inc);
 
477
+      mir_surface_spec_set_height_increment (spec, impl->geometry_hints.height_inc);
 
478
+    }
 
479
+  if (impl->geometry_mask & GDK_HINT_MIN_SIZE)
 
480
+    {
 
481
+      mir_surface_spec_set_min_width (spec, impl->geometry_hints.min_width);
 
482
+      mir_surface_spec_set_min_height (spec, impl->geometry_hints.min_height);
 
483
+    }
 
484
+  if (impl->geometry_mask & GDK_HINT_MAX_SIZE)
 
485
+    {
 
486
+      mir_surface_spec_set_max_width (spec, impl->geometry_hints.max_width);
 
487
+      mir_surface_spec_set_max_height (spec, impl->geometry_hints.max_height);
 
488
+    }
 
489
+  if (impl->geometry_mask & GDK_HINT_ASPECT)
 
490
+    {
 
491
+      mir_surface_spec_set_min_aspect_ratio (spec, 1000, (unsigned)(1000.0/impl->geometry_hints.min_aspect));
 
492
+      mir_surface_spec_set_max_aspect_ratio (spec, 1000, (unsigned)(1000.0/impl->geometry_hints.max_aspect));
 
493
+    }
 
494
+}
 
495
+
 
496
+static MirSurfaceSpec*
 
497
+create_spec (GdkWindow *window, GdkMirWindowImpl *impl)
 
498
+{
 
499
+  MirSurfaceSpec *spec = NULL;
 
500
+
 
501
+  spec = create_window_type_spec (impl->display,
 
502
+                                  impl->transient_for,
 
503
+                                  impl->transient_x, impl->transient_y,
 
504
+                                  window->width, window->height,
 
505
+                                  impl->type_hint,
 
506
+                                  impl->buffer_usage);
 
507
+
 
508
+  mir_surface_spec_set_name (spec, impl->title);
 
509
+  mir_surface_spec_set_buffer_usage (spec, impl->buffer_usage);
 
510
+
 
511
+  apply_geometry_hints (spec, impl);
 
512
+
 
513
+  return spec;
 
514
+}
 
515
+
 
516
+static void
 
517
+update_surface_spec (GdkWindow *window)
 
518
+{
 
519
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
 
520
+  MirSurfaceSpec *spec;
 
521
+
 
522
+  if (!impl->surface)
 
523
+    return;
 
524
+
 
525
+  spec = create_spec (window, impl);
 
526
 
 
527
-  return surface;
 
528
+  mir_surface_apply_spec (impl->surface, spec);
 
529
+  mir_surface_spec_release (spec);
 
530
+  impl->pending_spec_update = FALSE;
 
531
+  impl->buffer_stream = mir_surface_get_buffer_stream (impl->surface);
 
532
 }
 
533
 
 
534
 static GdkDevice *
 
535
@@ -319,20 +475,29 @@ ensure_surface_full (GdkWindow *window,
 
536
 {
 
537
   GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
 
538
   GdkMirWindowReference *window_ref;
 
539
+  MirSurfaceSpec *spec;
 
540
 
 
541
   if (impl->surface)
 
542
-    return;
 
543
+    {
 
544
+      if (impl->pending_spec_update)
 
545
+        update_surface_spec(window);
 
546
+      return;
 
547
+    }
 
548
 
 
549
   /* no destroy notify -- we must leak for now
 
550
    * https://bugs.launchpad.net/mir/+bug/1324100
 
551
    */
 
552
   window_ref = _gdk_mir_event_source_get_window_reference (window);
 
553
+  impl->buffer_usage = buffer_usage;
 
554
+
 
555
+  spec = create_spec (window, impl);
 
556
+
 
557
+  impl->surface = mir_surface_create_sync (spec);
 
558
 
 
559
-  impl->surface = create_mir_surface (gdk_window_get_display (window), impl->transient_for,
 
560
-                                      impl->transient_x, impl->transient_y,
 
561
-                                      window->width, window->height,
 
562
-                                      impl->type_hint,
 
563
-                                      buffer_usage);
 
564
+  mir_surface_spec_release(spec);
 
565
+
 
566
+  impl->pending_spec_update = FALSE;
 
567
+  impl->buffer_stream = mir_surface_get_buffer_stream (impl->surface);
 
568
 
 
569
   /* FIXME: can't make an initial resize event */
 
570
   // MirEvent *resize_event;
 
571
@@ -356,9 +521,10 @@ ensure_surface_full (GdkWindow *window,
 
572
 static void
 
573
 ensure_surface (GdkWindow *window)
 
574
 {
 
575
-  ensure_surface_full (window, window->gl_paint_context ?
 
576
-                                 mir_buffer_usage_hardware :
 
577
-                                 mir_buffer_usage_software);
 
578
+  ensure_surface_full (window,
 
579
+                       window->gl_paint_context ?
 
580
+                         mir_buffer_usage_hardware :
 
581
+                         mir_buffer_usage_software);
 
582
 }
 
583
 
 
584
 static void
 
585
@@ -390,19 +556,63 @@ ensure_no_surface (GdkWindow *window)
 
586
         }
 
587
     }
 
588
 
 
589
+  impl->pending_commit = FALSE;
 
590
+  impl->pending_swap = FALSE;
 
591
   g_clear_pointer(&impl->surface, mir_surface_release_sync);
 
592
 }
 
593
 
 
594
 static void
 
595
-send_buffer (GdkWindow *window)
 
596
+on_swap_buffer_completed (MirBufferStream *stream, void *data)
 
597
 {
 
598
+  GdkWindow *window = data;
 
599
   GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
 
600
 
 
601
-  /* Send the completed buffer to Mir */
 
602
-  mir_buffer_stream_swap_buffers_sync (mir_surface_get_buffer_stream (impl->surface));
 
603
-
 
604
   /* The Cairo context is no longer valid */
 
605
   g_clear_pointer (&impl->cairo_surface, cairo_surface_destroy);
 
606
+  impl->pending_swap = FALSE;
 
607
+
 
608
+  _gdk_frame_clock_thaw (gdk_window_get_frame_clock (window));
 
609
+}
 
610
+
 
611
+static void
 
612
+on_frame_clock_after_paint (GdkFrameClock *clock,
 
613
+                            GdkWindow     *window)
 
614
+{
 
615
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
 
616
+
 
617
+  if (!impl->pending_commit)
 
618
+    return;
 
619
+
 
620
+  impl->pending_commit = FALSE;
 
621
+  _gdk_frame_clock_freeze (clock);
 
622
+
 
623
+  if (impl->pending_spec_update)
 
624
+    update_surface_spec (window);
 
625
+
 
626
+  impl->pending_spec_update = FALSE;
 
627
+
 
628
+  /* Send the completed buffer to Mir */
 
629
+  impl->pending_swap = TRUE;
 
630
+  mir_buffer_stream_swap_buffers (impl->buffer_stream, on_swap_buffer_completed, window);
 
631
+}
 
632
+
 
633
+static void
 
634
+send_buffer_delayed (GdkWindow *window)
 
635
+{
 
636
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
 
637
+
 
638
+  if (impl->pending_swap || impl->pending_commit)
 
639
+    return;
 
640
+
 
641
+  impl->pending_commit = TRUE;
 
642
+}
 
643
+
 
644
+static void
 
645
+send_buffer (GdkWindow *window)
 
646
+{
 
647
+  send_buffer_delayed (window);
 
648
+  gdk_frame_clock_request_phase (gdk_window_get_frame_clock (window),
 
649
+                                 GDK_FRAME_CLOCK_PHASE_AFTER_PAINT);
 
650
 }
 
651
 
 
652
 static cairo_surface_t *
 
653
@@ -421,15 +631,16 @@ gdk_mir_window_impl_ref_cairo_surface (GdkWindow *window)
 
654
       return impl->cairo_surface;
 
655
     }
 
656
 
 
657
+  ensure_surface (window);
 
658
+
 
659
   /* Transient windows get rendered into a buffer and copied onto their parent */
 
660
   if (window->gl_paint_context)
 
661
     {
 
662
       cairo_surface = cairo_image_surface_create (pixel_format, window->width, window->height);
 
663
+      cairo_surface_set_device_scale (cairo_surface, (double) impl->output_scale, (double) impl->output_scale);
 
664
     }
 
665
   else if (impl->visible)
 
666
     {
 
667
-      ensure_surface (window);
 
668
-
 
669
       mir_buffer_stream_get_graphics_region (mir_surface_get_buffer_stream (impl->surface), &region);
 
670
 
 
671
       switch (region.pixel_format)
 
672
@@ -473,6 +684,7 @@ gdk_mir_window_impl_ref_cairo_surface (GdkWindow *window)
 
673
                                                            region.width,
 
674
                                                            region.height,
 
675
                                                            region.stride);
 
676
+      cairo_surface_set_device_scale (cairo_surface, (double) impl->output_scale, (double) impl->output_scale);
 
677
     }
 
678
   else
 
679
     cairo_surface = cairo_image_surface_create (pixel_format, 0, 0);
 
680
@@ -506,6 +718,7 @@ gdk_mir_window_impl_finalize (GObject *object)
 
681
 {
 
682
   GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (object);
 
683
 
 
684
+  g_free (impl->title);
 
685
   if (impl->background)
 
686
     cairo_pattern_destroy (impl->background);
 
687
   if (impl->surface)
 
688
@@ -526,6 +739,7 @@ gdk_mir_window_impl_show (GdkWindow *window,
 
689
   //g_printerr ("gdk_mir_window_impl_show window=%p\n", window);
 
690
 
 
691
   impl->visible = TRUE;
 
692
+  set_surface_state (impl, mir_surface_state_restored);
 
693
 
 
694
   /* Make sure there's a surface to see */
 
695
   ensure_surface (window);
 
696
@@ -547,7 +761,8 @@ gdk_mir_window_impl_hide (GdkWindow *window)
 
697
 
 
698
   impl->cursor_inside = FALSE;
 
699
   impl->visible = FALSE;
 
700
-  ensure_no_surface (window);
 
701
+
 
702
+  set_surface_state (impl, mir_surface_state_hidden);
 
703
 }
 
704
 
 
705
 static void
 
706
@@ -558,7 +773,8 @@ gdk_mir_window_impl_withdraw (GdkWindow *window)
 
707
 
 
708
   impl->cursor_inside = FALSE;
 
709
   impl->visible = FALSE;
 
710
-  ensure_no_surface (window);
 
711
+
 
712
+  set_surface_state (impl, mir_surface_state_hidden);
 
713
 }
 
714
 
 
715
 static void
 
716
@@ -610,32 +826,28 @@ gdk_mir_window_impl_move_resize (GdkWindow *window,
 
717
   g_printerr ("\n");
 
718
   */
 
719
   GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
 
720
-  gboolean recreate_surface = FALSE;
 
721
-
 
722
-  /* Transient windows can move wherever they want */
 
723
-  if (with_move)
 
724
-    {
 
725
-      if (x != impl->transient_x || y != impl->transient_y)
 
726
-        {
 
727
-          impl->transient_x = x;
 
728
-          impl->transient_y = y;
 
729
-          recreate_surface = TRUE;
 
730
-        }
 
731
-    }
 
732
+  //g_printerr ("gdk_mir_window_impl_move_resize window=%p, impl=%p\n", window, impl);
 
733
 
 
734
   /* If resize requested then rebuild surface */
 
735
-  if (width >= 0)
 
736
+  if (width >= 0 && (window->width != width || window->height != height))
 
737
   {
 
738
     /* We accept any resize */
 
739
     window->width = width;
 
740
     window->height = height;
 
741
-    recreate_surface = TRUE;
 
742
+    impl->pending_redraw = TRUE;
 
743
+    impl->pending_spec_update = TRUE;
 
744
   }
 
745
 
 
746
-  if (recreate_surface && impl->surface)
 
747
+  /* Transient windows can move wherever they want */
 
748
+  if (with_move)
 
749
     {
 
750
-      ensure_no_surface (window);
 
751
-      ensure_surface (window);
 
752
+      if (x != impl->transient_x || y != impl->transient_y)
 
753
+        {
 
754
+          impl->transient_x = x;
 
755
+          impl->transient_y = y;
 
756
+          if (!impl->pending_spec_update && impl->surface)
 
757
+            update_surface_spec (window);
 
758
+        }
 
759
     }
 
760
 }
 
761
 
 
762
@@ -754,9 +966,12 @@ gdk_mir_window_impl_get_device_state (GdkWindow       *window,
 
763
 static gboolean
 
764
 gdk_mir_window_impl_begin_paint (GdkWindow *window)
 
765
 {
 
766
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
 
767
+
 
768
+  ensure_surface (window);
 
769
   //g_printerr ("gdk_mir_window_impl_begin_paint window=%p\n", window);
 
770
   /* Indicate we are ready to be drawn onto directly? */
 
771
-  return FALSE;
 
772
+  return impl->pending_swap;
 
773
 }
 
774
 
 
775
 static void
 
776
@@ -832,10 +1047,11 @@ gdk_mir_window_impl_set_type_hint (GdkWindow         *window,
 
777
 {
 
778
   GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
 
779
 
 
780
-  if (hint != impl->type_hint)
 
781
+  if (type_hint_differs (hint, impl->type_hint))
 
782
     {
 
783
       impl->type_hint = hint;
 
784
-      ensure_no_surface (window);
 
785
+      if (impl->surface && !impl->pending_spec_update)
 
786
+        update_surface_spec (window);
 
787
     }
 
788
 }
 
789
 
 
790
@@ -881,15 +1097,39 @@ gdk_mir_window_impl_set_geometry_hints (GdkWindow         *window,
 
791
                                         const GdkGeometry *geometry,
 
792
                                         GdkWindowHints     geom_mask)
 
793
 {
 
794
-  //g_printerr ("gdk_mir_window_impl_set_geometry_hints window=%p\n", window);
 
795
-  //FIXME: ?
 
796
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
 
797
+  MirConnection *connection = gdk_mir_display_get_mir_connection (impl->display);
 
798
+  //g_printerr ("gdk_mir_window_impl_set_geometry_hints window=%p impl=%p\n", window, impl);
 
799
+
 
800
+  impl->geometry_hints = *geometry;
 
801
+  impl->geometry_mask = geom_mask;
 
802
+
 
803
+  if (impl->surface && !impl->pending_spec_update)
 
804
+    {
 
805
+       MirSurfaceSpec* spec = mir_connection_create_spec_for_changes (connection);
 
806
+       apply_geometry_hints (spec, impl);
 
807
+       mir_surface_apply_spec (impl->surface, spec);
 
808
+       mir_surface_spec_release (spec);
 
809
+    }
 
810
 }
 
811
 
 
812
 static void
 
813
 gdk_mir_window_impl_set_title (GdkWindow   *window,
 
814
                                const gchar *title)
 
815
 {
 
816
-  // g_printerr ("gdk_mir_window_impl_set_title window=%p\n", window);
 
817
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
 
818
+  MirConnection *connection = gdk_mir_display_get_mir_connection (impl->display);
 
819
+  //g_printerr ("gdk_mir_window_impl_set_title window=%p\n", window);
 
820
+
 
821
+  g_free (impl->title);
 
822
+  impl->title = g_strdup (title);
 
823
+  if (impl->surface && !impl->pending_spec_update)
 
824
+    {
 
825
+       MirSurfaceSpec* spec = mir_connection_create_spec_for_changes (connection);
 
826
+       mir_surface_spec_set_name (spec, impl->title);
 
827
+       mir_surface_apply_spec (impl->surface, spec);
 
828
+       mir_surface_spec_release (spec);
 
829
+    }
 
830
 }
 
831
 
 
832
 static void
 
833
@@ -918,6 +1158,9 @@ gdk_mir_window_impl_set_transient_for (GdkWindow *window,
 
834
 
 
835
   /* Link this window to the parent */
 
836
   impl->transient_for = parent;
 
837
+
 
838
+  if (impl->surface && !impl->pending_spec_update)
 
839
+    update_surface_spec (window);
 
840
 }
 
841
 
 
842
 static void
 
843
@@ -1247,8 +1490,8 @@ static gint
 
844
 gdk_mir_window_impl_get_scale_factor (GdkWindow *window)
 
845
 {
 
846
   //g_printerr ("gdk_mir_window_impl_get_scale_factor window=%p\n", window);
 
847
-  /* Don't support monitor scaling */
 
848
-  return 1;
 
849
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
 
850
+  return impl->output_scale;
 
851
 }
 
852
 
 
853
 static void
 
854
@@ -1460,7 +1703,7 @@ _gdk_mir_window_get_egl_surface (GdkWindow *window,
 
855
       ensure_surface_full (window, mir_buffer_usage_hardware);
 
856
 
 
857
       egl_display = _gdk_mir_display_get_egl_display (gdk_window_get_display (window));
 
858
-      egl_window = (EGLNativeWindowType) mir_buffer_stream_get_egl_native_window (mir_surface_get_buffer_stream (impl->surface));
 
859
+      egl_window = (EGLNativeWindowType) mir_buffer_stream_get_egl_native_window (impl->buffer_stream);
 
860
 
 
861
       impl->egl_surface =
 
862
         eglCreateWindowSurface (egl_display, config, egl_window, NULL);
 
863
@@ -1485,7 +1728,7 @@ _gdk_mir_window_get_dummy_egl_surface (GdkWindow *window,
 
864
 
 
865
       display = gdk_window_get_display (window);
 
866
       egl_display = _gdk_mir_display_get_egl_display (display);
 
867
-      egl_window = (EGLNativeWindowType) mir_buffer_stream_get_egl_native_window (mir_surface_get_buffer_stream (impl->surface));
 
868
+      egl_window = (EGLNativeWindowType) mir_buffer_stream_get_egl_native_window (impl->buffer_stream);
 
869
 
 
870
       impl->dummy_egl_surface =
 
871
         eglCreateWindowSurface (egl_display, config, egl_window, NULL);
 
872
@@ -1506,6 +1749,30 @@ gdk_mir_window_get_mir_surface (GdkWindow *window)
 
873
   return impl->surface;
 
874
 }
 
875
 
 
876
+void
 
877
+_gdk_mir_window_set_surface_output (GdkWindow *window, gdouble scale)
 
878
+{
 
879
+  // g_printerr ("_gdk_mir_window_impl_set_surface_output impl=%p\n", impl);
 
880
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
 
881
+  GdkRectangle area = {0, 0, window->width, window->height};
 
882
+  cairo_region_t *region;
 
883
+  gint new_scale = (gint) round (scale);
 
884
+
 
885
+  if (impl->output_scale != new_scale)
 
886
+    {
 
887
+      impl->output_scale = new_scale;
 
888
+
 
889
+      drop_cairo_surface (window);
 
890
+
 
891
+      if (impl->buffer_stream)
 
892
+        mir_buffer_stream_set_scale (impl->buffer_stream, (float) new_scale);
 
893
+
 
894
+      region = cairo_region_create_rectangle (&area);
 
895
+      _gdk_window_invalidate_for_expose (window, region);
 
896
+      cairo_region_destroy (region);
 
897
+    }
 
898
+}
 
899
+
 
900
 static void
 
901
 gdk_mir_window_impl_class_init (GdkMirWindowImplClass *klass)
 
902
 {
 
903
-- 
 
904
2.8.1
 
905