1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
3 * Josh MacDonald, Ryan Lortie
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /*
20 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
21 * file for a list of people on the GTK+ Team. See the ChangeLog
22 * files for a list of changes. These files are distributed with
23 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
24 */
25
26 #include "config.h"
27
28 #include "gdksurface-broadway.h"
29
30 #include "gdkbroadwaydisplay.h"
31 #include "gdkdeviceprivate.h"
32 #include "gdkdisplay-broadway.h"
33 #include "gdkdevice-broadway.h"
34 #include "gdkdisplay.h"
35 #include "gdkdragsurfaceprivate.h"
36 #include "gdkeventsource.h"
37 #include "gdkframeclockidleprivate.h"
38 #include "gdkinternals.h"
39 #include "gdkpopupprivate.h"
40 #include "gdkprivate-broadway.h"
41 #include "gdksurfaceprivate.h"
42 #include "gdktextureprivate.h"
43 #include "gdktoplevelprivate.h"
44 #include "gdk-private.h"
45
46 #include <graphene.h>
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <string.h>
50
51 /* Forward declarations */
52 static void gdk_broadway_surface_finalize (GObject *object);
53
54 G_DEFINE_TYPE (GdkBroadwaySurface, gdk_broadway_surface, GDK_TYPE_SURFACE)
55
56 GType gdk_broadway_toplevel_get_type (void) G_GNUC_CONST;
57 GType gdk_broadway_popup_get_type (void) G_GNUC_CONST;
58 GType gdk_broadway_drag_surface_get_type (void) G_GNUC_CONST;
59
60 #define GDK_TYPE_BROADWAY_TOPLEVEL (gdk_broadway_toplevel_get_type ())
61 #define GDK_TYPE_BROADWAY_POPUP (gdk_broadway_popup_get_type ())
62 #define GDK_TYPE_BROADWAY_DRAG_SURFACE (gdk_broadway_drag_surface_get_type ())
63
64 /* We need to flush in an idle rather than AFTER_PAINT, as the clock
65 is frozen during e.g. surface resizes so the paint will not happen
66 and the surface resize request is never flushed. */
67 static void
queue_flush(GdkSurface * surface)68 queue_flush (GdkSurface *surface)
69 {
70 gdk_broadway_display_flush_in_idle (gdk_surface_get_display (surface));
71 }
72
73 static void
gdk_broadway_surface_init(GdkBroadwaySurface * impl)74 gdk_broadway_surface_init (GdkBroadwaySurface *impl)
75 {
76 }
77
78 static void
gdk_broadway_surface_finalize(GObject * object)79 gdk_broadway_surface_finalize (GObject *object)
80 {
81 GdkBroadwaySurface *impl;
82 GdkBroadwayDisplay *broadway_display;
83
84 g_return_if_fail (GDK_IS_BROADWAY_SURFACE (object));
85
86 impl = GDK_BROADWAY_SURFACE (object);
87
88 _gdk_broadway_surface_grab_check_destroy (GDK_SURFACE (impl));
89
90 broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (GDK_SURFACE (impl)));
91
92 g_hash_table_remove (broadway_display->id_ht, GINT_TO_POINTER (impl->id));
93
94 if (impl->cursor)
95 g_object_unref (impl->cursor);
96
97 broadway_display->toplevels = g_list_remove (broadway_display->toplevels, impl);
98
99 G_OBJECT_CLASS (gdk_broadway_surface_parent_class)->finalize (object);
100 }
101
102 static gboolean
thaw_updates_cb(GdkSurface * surface)103 thaw_updates_cb (GdkSurface *surface)
104 {
105 if (!GDK_SURFACE_DESTROYED (surface))
106 gdk_surface_thaw_updates (surface);
107 g_object_unref (surface);
108 return G_SOURCE_REMOVE;
109 }
110
111 void
_gdk_broadway_roundtrip_notify(GdkSurface * surface,guint32 tag,gboolean local_reply)112 _gdk_broadway_roundtrip_notify (GdkSurface *surface,
113 guint32 tag,
114 gboolean local_reply)
115 {
116 GdkBroadwaySurface *impl = GDK_BROADWAY_SURFACE (surface);
117 GdkFrameClock *clock = gdk_surface_get_frame_clock (surface);
118 GdkFrameTimings *timings;
119
120 timings = gdk_frame_clock_get_timings (clock, impl->pending_frame_counter);
121 impl->pending_frame_counter = 0;
122
123 /* If there is no remote web client, rate limit update to once a second */
124 if (local_reply)
125 g_timeout_add_seconds (1, (GSourceFunc)thaw_updates_cb, g_object_ref (surface));
126 else
127 gdk_surface_thaw_updates (surface);
128
129 if (timings)
130 {
131 timings->refresh_interval = 33333; /* default to 1/30th of a second */
132 // This isn't quite right, since we've done a roundtrip back too, can we do better?
133 timings->presentation_time = g_get_monotonic_time ();
134 timings->complete = TRUE;
135
136
137 #ifdef G_ENABLE_DEBUG
138 if ((_gdk_debug_flags & GDK_DEBUG_FRAMES) != 0)
139 _gdk_frame_clock_debug_print_timings (clock, timings);
140
141 if (GDK_PROFILER_IS_RUNNING)
142 _gdk_frame_clock_add_timings_to_profiler (clock, timings);
143 #endif
144 }
145 }
146
147 static void
on_frame_clock_after_paint(GdkFrameClock * clock,GdkSurface * surface)148 on_frame_clock_after_paint (GdkFrameClock *clock,
149 GdkSurface *surface)
150 {
151 GdkDisplay *display = gdk_surface_get_display (surface);
152 GdkBroadwaySurface *impl = GDK_BROADWAY_SURFACE (surface);
153 GdkBroadwayDisplay *broadway_display;
154
155 impl->pending_frame_counter = gdk_frame_clock_get_frame_counter (clock);
156 gdk_surface_freeze_updates (surface);
157
158 broadway_display = GDK_BROADWAY_DISPLAY (display);
159
160 _gdk_broadway_server_roundtrip (broadway_display->server, impl->id, _gdk_display_get_next_serial (display));
161
162 gdk_display_flush (display);
163 }
164
165 static void
on_frame_clock_before_paint(GdkFrameClock * clock,GdkSurface * surface)166 on_frame_clock_before_paint (GdkFrameClock *clock,
167 GdkSurface *surface)
168 {
169 GdkFrameTimings *timings = gdk_frame_clock_get_current_timings (clock);
170 gint64 presentation_time;
171 gint64 refresh_interval;
172
173 if (surface->update_freeze_count > 0)
174 return;
175
176 gdk_frame_clock_get_refresh_info (clock,
177 timings->frame_time,
178 &refresh_interval, &presentation_time);
179 if (presentation_time != 0)
180 {
181 timings->predicted_presentation_time = presentation_time + refresh_interval;
182 }
183 else
184 {
185 timings->predicted_presentation_time = timings->frame_time + refresh_interval / 2 + refresh_interval;
186 }
187 }
188
189 static void
connect_frame_clock(GdkSurface * surface)190 connect_frame_clock (GdkSurface *surface)
191 {
192 GdkFrameClock *frame_clock = gdk_surface_get_frame_clock (surface);
193
194 g_signal_connect (frame_clock, "before-paint",
195 G_CALLBACK (on_frame_clock_before_paint), surface);
196 g_signal_connect (frame_clock, "after-paint",
197 G_CALLBACK (on_frame_clock_after_paint), surface);
198 }
199
200 static void
disconnect_frame_clock(GdkSurface * surface)201 disconnect_frame_clock (GdkSurface *surface)
202 {
203 GdkFrameClock *frame_clock = gdk_surface_get_frame_clock (surface);
204
205 g_signal_handlers_disconnect_by_func (frame_clock,
206 on_frame_clock_before_paint, surface);
207 g_signal_handlers_disconnect_by_func (frame_clock,
208 on_frame_clock_after_paint, surface);
209 }
210
211 GdkSurface *
_gdk_broadway_display_create_surface(GdkDisplay * display,GdkSurfaceType surface_type,GdkSurface * parent,int x,int y,int width,int height)212 _gdk_broadway_display_create_surface (GdkDisplay *display,
213 GdkSurfaceType surface_type,
214 GdkSurface *parent,
215 int x,
216 int y,
217 int width,
218 int height)
219 {
220 GdkBroadwayDisplay *broadway_display;
221 GdkFrameClock *frame_clock;
222 GdkSurface *surface;
223 GdkBroadwaySurface *impl;
224 GType type;
225
226 if (parent)
227 frame_clock = g_object_ref (gdk_surface_get_frame_clock (parent));
228 else
229 frame_clock = _gdk_frame_clock_idle_new ();
230
231 switch (surface_type)
232 {
233 case GDK_SURFACE_TOPLEVEL:
234 type = GDK_TYPE_BROADWAY_TOPLEVEL;
235 break;
236 case GDK_SURFACE_POPUP:
237 type = GDK_TYPE_BROADWAY_POPUP;
238 break;
239 case GDK_SURFACE_TEMP:
240 type = GDK_TYPE_BROADWAY_DRAG_SURFACE;
241 break;
242 default:
243 g_assert_not_reached ();
244 break;
245 }
246
247 surface = g_object_new (type,
248 "display", display,
249 "frame-clock", frame_clock,
250 NULL);
251
252 g_object_unref (frame_clock);
253
254 surface->parent = parent;
255 surface->x = x;
256 surface->y = y;
257 surface->width = width;
258 surface->height = height;
259
260 broadway_display = GDK_BROADWAY_DISPLAY (display);
261
262 impl = GDK_BROADWAY_SURFACE (surface);
263 impl->root_x = x;
264 impl->root_y = y;
265 if (parent)
266 {
267 impl->root_x += GDK_BROADWAY_SURFACE (parent)->root_x;
268 impl->root_y += GDK_BROADWAY_SURFACE (parent)->root_y;
269 }
270
271 impl->id = _gdk_broadway_server_new_surface (broadway_display->server,
272 impl->root_x,
273 impl->root_y,
274 surface->width,
275 surface->height);
276 g_hash_table_insert (broadway_display->id_ht, GINT_TO_POINTER(impl->id), surface);
277
278 g_object_ref (surface);
279
280 if (!surface->parent)
281 broadway_display->toplevels = g_list_prepend (broadway_display->toplevels, impl);
282
283 connect_frame_clock (surface);
284
285 /* We treat the real parent as a default transient for to get stacking right */
286 if (parent)
287 {
288 impl->transient_for = GDK_BROADWAY_SURFACE (parent)->id;
289 _gdk_broadway_server_surface_set_transient_for (broadway_display->server, impl->id, impl->transient_for);
290 }
291
292 return surface;
293 }
294
295 static cairo_surface_t *
gdk_broadway_surface_ref_cairo_surface(GdkSurface * surface)296 gdk_broadway_surface_ref_cairo_surface (GdkSurface *surface)
297 {
298 if (GDK_IS_BROADWAY_SURFACE (surface) &&
299 GDK_SURFACE_DESTROYED (surface))
300 return NULL;
301
302 return cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
303 }
304
305 static void
_gdk_broadway_surface_destroy(GdkSurface * surface,gboolean foreign_destroy)306 _gdk_broadway_surface_destroy (GdkSurface *surface,
307 gboolean foreign_destroy)
308 {
309 GdkBroadwaySurface *impl;
310 GdkBroadwayDisplay *broadway_display;
311
312 g_return_if_fail (GDK_IS_SURFACE (surface));
313
314 impl = GDK_BROADWAY_SURFACE (surface);
315
316 disconnect_frame_clock (surface);
317
318 if (impl->node_data)
319 g_array_unref (impl->node_data);
320 if (impl->node_data_textures)
321 g_ptr_array_unref (impl->node_data_textures);
322
323 _gdk_broadway_surface_grab_check_destroy (surface);
324
325 broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (surface));
326 g_hash_table_remove (broadway_display->id_ht, GINT_TO_POINTER (impl->id));
327
328 _gdk_broadway_server_destroy_surface (broadway_display->server, impl->id);
329 }
330
331 void
gdk_broadway_surface_set_nodes(GdkSurface * surface,GArray * nodes,GPtrArray * node_textures)332 gdk_broadway_surface_set_nodes (GdkSurface *surface,
333 GArray *nodes,
334 GPtrArray *node_textures)
335 {
336 GdkBroadwaySurface *impl;
337 GdkBroadwayDisplay *broadway_display;
338
339 g_return_if_fail (GDK_IS_SURFACE (surface));
340
341 impl = GDK_BROADWAY_SURFACE (surface);
342
343 broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (surface));
344
345 if (nodes)
346 g_array_ref (nodes);
347 if (impl->node_data)
348 g_array_unref (impl->node_data);
349 impl->node_data = nodes;
350
351 if (node_textures)
352 g_ptr_array_ref (node_textures);
353 if (impl->node_data_textures)
354 g_ptr_array_unref (impl->node_data_textures);
355 impl->node_data_textures = node_textures;
356
357 gdk_broadway_server_surface_set_nodes (broadway_display->server, impl->id, impl->node_data);
358 }
359
360 /* This function is called when the XSurface is really gone.
361 */
362 static void
gdk_broadway_surface_destroy_notify(GdkSurface * surface)363 gdk_broadway_surface_destroy_notify (GdkSurface *surface)
364 {
365 if (!GDK_SURFACE_DESTROYED (surface))
366 _gdk_surface_destroy (surface, TRUE);
367
368 g_object_unref (surface);
369 }
370
371 static void
gdk_broadway_surface_show(GdkSurface * surface,gboolean already_mapped)372 gdk_broadway_surface_show (GdkSurface *surface,
373 gboolean already_mapped)
374 {
375 GdkBroadwaySurface *impl;
376 GdkBroadwayDisplay *broadway_display;
377
378 impl = GDK_BROADWAY_SURFACE (surface);
379 impl->visible = TRUE;
380
381 /* FIXME: update state ? */
382
383 broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (surface));
384 if (_gdk_broadway_server_surface_show (broadway_display->server, impl->id))
385 queue_flush (surface);
386
387 }
388
389 static void
gdk_broadway_surface_hide(GdkSurface * surface)390 gdk_broadway_surface_hide (GdkSurface *surface)
391 {
392 GdkBroadwaySurface *impl;
393 GdkBroadwayDisplay *broadway_display;
394
395 impl = GDK_BROADWAY_SURFACE (surface);
396 impl->visible = FALSE;
397
398 /* FIXME: update state ? */
399
400 broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (surface));
401
402 _gdk_broadway_surface_grab_check_unmap (surface,
403 _gdk_broadway_server_get_next_serial (broadway_display->server));
404
405 if (_gdk_broadway_server_surface_hide (broadway_display->server, impl->id))
406 queue_flush (surface);
407
408 _gdk_surface_clear_update_area (surface);
409 }
410
411 static int
gdk_broadway_surface_get_scale_factor(GdkSurface * surface)412 gdk_broadway_surface_get_scale_factor (GdkSurface *surface)
413 {
414 GdkBroadwayDisplay *broadway_display;
415
416 if (GDK_SURFACE_DESTROYED (surface))
417 return 1;
418
419 broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (surface));
420
421 return broadway_display->scale_factor;
422 }
423
424 static void
sync_child_root_pos(GdkSurface * parent)425 sync_child_root_pos (GdkSurface *parent)
426 {
427 GdkBroadwaySurface *parent_impl = GDK_BROADWAY_SURFACE (parent);
428 GdkBroadwayDisplay *broadway_display;
429 GList *l;
430
431 broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (parent));
432
433 for (l = parent->children; l; l = l->next)
434 {
435 GdkBroadwaySurface *child_impl = l->data;
436 GdkSurface *child = GDK_SURFACE (child_impl);
437 int root_x, root_y;
438
439 root_x = child->x + parent_impl->root_x;
440 root_y = child->y + parent_impl->root_y;
441
442 if (root_x != child_impl->root_x ||
443 root_y != child_impl->root_y)
444 {
445 child_impl->root_x = root_x;
446 child_impl->root_y = root_y;
447
448 _gdk_broadway_server_surface_move_resize (broadway_display->server,
449 child_impl->id,
450 TRUE,
451 child_impl->root_x, child_impl->root_y,
452 child->width, child->height);
453 sync_child_root_pos (child);
454 }
455 }
456 }
457
458 /* x, y is relative to parent */
459 static void
gdk_broadway_surface_move_resize_internal(GdkSurface * surface,gboolean with_move,int x,int y,int width,int height)460 gdk_broadway_surface_move_resize_internal (GdkSurface *surface,
461 gboolean with_move,
462 int x,
463 int y,
464 int width,
465 int height)
466 {
467 GdkBroadwaySurface *impl = GDK_BROADWAY_SURFACE (surface);
468 GdkBroadwayDisplay *broadway_display;
469 gboolean size_changed;
470
471 if (with_move)
472 {
473 surface->x = x;
474 surface->y = y;
475 impl->root_x = x;
476 impl->root_y = y;
477 if (surface->parent)
478 {
479 GdkBroadwaySurface *parent_impl = GDK_BROADWAY_SURFACE (surface->parent);
480 impl->root_x += parent_impl->root_x;
481 impl->root_y += parent_impl->root_y;
482 }
483 }
484
485 size_changed = FALSE;
486
487 broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (surface));
488
489 if (width > 0 || height > 0)
490 {
491 if (width < 1)
492 width = 1;
493
494 if (height < 1)
495 height = 1;
496
497 if (width != surface->width ||
498 height != surface->height)
499 {
500 size_changed = TRUE;
501
502 /* Resize clears the content */
503 impl->dirty = TRUE;
504 impl->last_synced = FALSE;
505
506 surface->width = width;
507 surface->height = height;
508 }
509 }
510
511 _gdk_broadway_server_surface_move_resize (broadway_display->server,
512 impl->id,
513 with_move,
514 impl->root_x, impl->root_y,
515 surface->width, surface->height);
516 sync_child_root_pos (surface);
517
518 queue_flush (surface);
519 if (size_changed)
520 {
521 surface->resize_count++;
522 _gdk_surface_update_size (surface);
523 }
524 }
525
526 void
gdk_broadway_surface_move_resize(GdkSurface * surface,int x,int y,int width,int height)527 gdk_broadway_surface_move_resize (GdkSurface *surface,
528 int x,
529 int y,
530 int width,
531 int height)
532 {
533 gdk_broadway_surface_move_resize_internal (surface, TRUE,
534 x, y,
535 width, height);
536 }
537
538 static void
gdk_broadway_surface_toplevel_resize(GdkSurface * surface,int width,int height)539 gdk_broadway_surface_toplevel_resize (GdkSurface *surface,
540 int width,
541 int height)
542 {
543 gdk_broadway_surface_move_resize_internal (surface, FALSE,
544 0, 0,
545 width, height);
546 }
547
548 static void
gdk_broadway_surface_move(GdkSurface * surface,int x,int y)549 gdk_broadway_surface_move (GdkSurface *surface,
550 int x,
551 int y)
552 {
553 gdk_broadway_surface_move_resize_internal (surface, TRUE, x, y, -1, -1);
554 }
555
556 static void
gdk_broadway_surface_layout_popup(GdkSurface * surface,int width,int height,GdkPopupLayout * layout)557 gdk_broadway_surface_layout_popup (GdkSurface *surface,
558 int width,
559 int height,
560 GdkPopupLayout *layout)
561 {
562 GdkBroadwaySurface *impl = GDK_BROADWAY_SURFACE (surface);
563 GdkMonitor *monitor;
564 GdkRectangle bounds;
565 GdkRectangle final_rect;
566 int x, y;
567
568 monitor = gdk_surface_get_layout_monitor (surface, layout,
569 gdk_monitor_get_geometry);
570 gdk_monitor_get_geometry (monitor, &bounds);
571
572 gdk_surface_layout_popup_helper (surface,
573 width,
574 height,
575 impl->shadow_left,
576 impl->shadow_right,
577 impl->shadow_top,
578 impl->shadow_bottom,
579 monitor,
580 &bounds,
581 layout,
582 &final_rect);
583
584 x = final_rect.x;
585 y = final_rect.y;
586
587 if (final_rect.width != surface->width ||
588 final_rect.height != surface->height)
589 {
590 gdk_broadway_surface_move_resize (surface,
591 x,
592 y,
593 final_rect.width,
594 final_rect.height);
595 }
596 else
597 {
598 gdk_broadway_surface_move (surface, x, y);
599 }
600 }
601
602 static void
show_popup(GdkSurface * surface)603 show_popup (GdkSurface *surface)
604 {
605 gdk_surface_set_is_mapped (surface, TRUE);
606 gdk_broadway_surface_show (surface, FALSE);
607 gdk_surface_invalidate_rect (surface, NULL);
608 }
609
610 static void
show_grabbing_popup(GdkSeat * seat,GdkSurface * surface,gpointer user_data)611 show_grabbing_popup (GdkSeat *seat,
612 GdkSurface *surface,
613 gpointer user_data)
614 {
615 show_popup (surface);
616 }
617
618 static gboolean
gdk_broadway_surface_present_popup(GdkSurface * surface,int width,int height,GdkPopupLayout * layout)619 gdk_broadway_surface_present_popup (GdkSurface *surface,
620 int width,
621 int height,
622 GdkPopupLayout *layout)
623 {
624 gdk_broadway_surface_layout_popup (surface, width, height, layout);
625
626 if (GDK_SURFACE_IS_MAPPED (surface))
627 return TRUE;
628
629 if (surface->autohide)
630 {
631 gdk_seat_grab (gdk_display_get_default_seat (surface->display),
632 surface,
633 GDK_SEAT_CAPABILITY_ALL,
634 TRUE,
635 NULL, NULL,
636 show_grabbing_popup, NULL);
637 }
638 else
639 {
640 show_popup (surface);
641 }
642
643 return GDK_SURFACE_IS_MAPPED (surface);
644 }
645
646 static void
gdk_broadway_surface_focus(GdkSurface * surface,guint32 timestamp)647 gdk_broadway_surface_focus (GdkSurface *surface,
648 guint32 timestamp)
649 {
650 GdkBroadwaySurface *impl;
651 GdkBroadwayDisplay *broadway_display;
652
653 g_return_if_fail (GDK_IS_SURFACE (surface));
654
655 if (GDK_SURFACE_DESTROYED (surface))
656 return;
657
658 impl = GDK_BROADWAY_SURFACE (surface);
659 broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (surface));
660 _gdk_broadway_server_surface_focus (broadway_display->server,
661 impl->id);
662 }
663
664 static void
gdk_broadway_surface_set_geometry_hints(GdkSurface * surface,const GdkGeometry * geometry,GdkSurfaceHints geom_mask)665 gdk_broadway_surface_set_geometry_hints (GdkSurface *surface,
666 const GdkGeometry *geometry,
667 GdkSurfaceHints geom_mask)
668 {
669 GdkBroadwaySurface *impl;
670
671 impl = GDK_BROADWAY_SURFACE (surface);
672
673 impl->geometry_hints = *geometry;
674 impl->geometry_hints_mask = geom_mask;
675 }
676
677 static void
gdk_broadway_surface_set_title(GdkSurface * surface,const char * title)678 gdk_broadway_surface_set_title (GdkSurface *surface,
679 const char *title)
680 {
681 }
682
683 static void
gdk_broadway_surface_set_startup_id(GdkSurface * surface,const char * startup_id)684 gdk_broadway_surface_set_startup_id (GdkSurface *surface,
685 const char *startup_id)
686 {
687 }
688
689 static void
gdk_broadway_surface_set_transient_for(GdkSurface * surface,GdkSurface * parent)690 gdk_broadway_surface_set_transient_for (GdkSurface *surface,
691 GdkSurface *parent)
692 {
693 GdkBroadwayDisplay *display;
694 GdkBroadwaySurface *impl;
695 int parent_id;
696
697 impl = GDK_BROADWAY_SURFACE (surface);
698
699 /* We treat the real parent as a default transient for to get stacking right */
700 if (parent == NULL)
701 parent = surface->parent;
702
703 parent_id = 0;
704 if (parent)
705 parent_id = GDK_BROADWAY_SURFACE (parent)->id;
706
707 impl->transient_for = parent_id;
708
709 display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (surface));
710 _gdk_broadway_server_surface_set_transient_for (display->server, impl->id, impl->transient_for);
711 }
712
713 static void
gdk_broadway_surface_get_geometry(GdkSurface * surface,int * x,int * y,int * width,int * height)714 gdk_broadway_surface_get_geometry (GdkSurface *surface,
715 int *x,
716 int *y,
717 int *width,
718 int *height)
719 {
720 g_return_if_fail (GDK_IS_SURFACE (surface));
721
722 /* TODO: These should really roundtrip to the client to get the current data */
723
724 if (x)
725 *x = surface->x;
726 if (y)
727 *y = surface->y;
728 if (width)
729 *width = surface->width;
730 if (height)
731 *height = surface->height;
732
733 }
734
735 static void
gdk_broadway_surface_get_root_coords(GdkSurface * surface,int x,int y,int * root_x,int * root_y)736 gdk_broadway_surface_get_root_coords (GdkSurface *surface,
737 int x,
738 int y,
739 int *root_x,
740 int *root_y)
741 {
742 GdkBroadwaySurface *impl;
743
744 impl = GDK_BROADWAY_SURFACE (surface);
745
746 if (root_x)
747 *root_x = x + impl->root_x;
748 if (root_y)
749 *root_y = y + impl->root_y;
750 }
751
752 static gboolean
gdk_broadway_surface_get_device_state(GdkSurface * surface,GdkDevice * device,double * x,double * y,GdkModifierType * mask)753 gdk_broadway_surface_get_device_state (GdkSurface *surface,
754 GdkDevice *device,
755 double *x,
756 double *y,
757 GdkModifierType *mask)
758 {
759 g_return_val_if_fail (surface == NULL || GDK_IS_SURFACE (surface), FALSE);
760
761 if (GDK_SURFACE_DESTROYED (surface))
762 return FALSE;
763
764 gdk_broadway_device_query_state (device, surface, x, y, mask);
765
766 return *x >= 0 && *y >= 0 && *x < surface->width && *y < surface->height;
767 }
768
769 static void
gdk_broadway_surface_set_input_region(GdkSurface * surface,cairo_region_t * shape_region)770 gdk_broadway_surface_set_input_region (GdkSurface *surface,
771 cairo_region_t *shape_region)
772 {
773 }
774
775 static void
gdk_broadway_surface_minimize(GdkSurface * surface)776 gdk_broadway_surface_minimize (GdkSurface *surface)
777 {
778 if (GDK_SURFACE_DESTROYED (surface))
779 return;
780 }
781
782 static void
gdk_broadway_surface_unminimize(GdkSurface * surface)783 gdk_broadway_surface_unminimize (GdkSurface *surface)
784 {
785 if (GDK_SURFACE_DESTROYED (surface))
786 return;
787 }
788
789 static void
gdk_broadway_surface_maximize(GdkSurface * surface)790 gdk_broadway_surface_maximize (GdkSurface *surface)
791 {
792 GdkBroadwaySurface *impl;
793 GdkDisplay *display;
794 GdkRectangle geom;
795
796 if (GDK_SURFACE_DESTROYED (surface))
797 return;
798
799 impl = GDK_BROADWAY_SURFACE (surface);
800
801 if (impl->maximized)
802 return;
803
804 impl->maximized = TRUE;
805
806 gdk_synthesize_surface_state (surface, 0, GDK_TOPLEVEL_STATE_MAXIMIZED);
807
808 impl->pre_maximize_x = surface->x;
809 impl->pre_maximize_y = surface->y;
810 impl->pre_maximize_width = surface->width;
811 impl->pre_maximize_height = surface->height;
812
813 display = gdk_surface_get_display (surface);
814 gdk_monitor_get_geometry (GDK_BROADWAY_DISPLAY (display)->monitor, &geom);
815
816 gdk_broadway_surface_move_resize (surface,
817 geom.x, geom.y,
818 geom.width, geom.height);
819 }
820
821 static void
gdk_broadway_surface_unmaximize(GdkSurface * surface)822 gdk_broadway_surface_unmaximize (GdkSurface *surface)
823 {
824 GdkBroadwaySurface *impl;
825
826 if (GDK_SURFACE_DESTROYED (surface))
827 return;
828
829 impl = GDK_BROADWAY_SURFACE (surface);
830
831 if (!impl->maximized)
832 return;
833
834 impl->maximized = FALSE;
835
836 gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_MAXIMIZED, 0);
837
838 gdk_broadway_surface_move_resize (surface,
839 impl->pre_maximize_x,
840 impl->pre_maximize_y,
841 impl->pre_maximize_width,
842 impl->pre_maximize_height);
843 }
844
845 typedef struct _MoveResizeData MoveResizeData;
846
847 struct _MoveResizeData
848 {
849 GdkDisplay *display;
850
851 GdkSurface *moveresize_surface;
852 GdkSurface *moveresize_emulation_surface;
853 gboolean is_resize;
854 GdkSurfaceEdge resize_edge;
855 int moveresize_button;
856 int moveresize_x;
857 int moveresize_y;
858 int moveresize_orig_x;
859 int moveresize_orig_y;
860 int moveresize_orig_width;
861 int moveresize_orig_height;
862 long moveresize_process_time;
863 GdkSurfaceHints moveresize_geom_mask;
864 GdkGeometry moveresize_geometry;
865 BroadwayInputMsg *moveresize_pending_event;
866 };
867
868 static MoveResizeData *
get_move_resize_data(GdkDisplay * display,gboolean create)869 get_move_resize_data (GdkDisplay *display,
870 gboolean create)
871 {
872 GdkBroadwayDisplay *broadway_display;
873 MoveResizeData *mv_resize;
874
875 broadway_display = GDK_BROADWAY_DISPLAY (display);
876
877 mv_resize = broadway_display->move_resize_data;
878
879 if (!mv_resize && create)
880 {
881 mv_resize = g_new0 (MoveResizeData, 1);
882 mv_resize->display = display;
883
884 broadway_display->move_resize_data = mv_resize;
885 }
886
887 return mv_resize;
888 }
889
890 static void
update_pos(MoveResizeData * mv_resize,int new_root_x,int new_root_y)891 update_pos (MoveResizeData *mv_resize,
892 int new_root_x,
893 int new_root_y)
894 {
895 int dx, dy;
896
897 dx = new_root_x - mv_resize->moveresize_x;
898 dy = new_root_y - mv_resize->moveresize_y;
899
900 if (mv_resize->is_resize)
901 {
902 int x, y, w, h;
903
904 x = mv_resize->moveresize_orig_x;
905 y = mv_resize->moveresize_orig_y;
906
907 w = mv_resize->moveresize_orig_width;
908 h = mv_resize->moveresize_orig_height;
909
910 switch (mv_resize->resize_edge)
911 {
912 case GDK_SURFACE_EDGE_NORTH_WEST:
913 x += dx;
914 y += dy;
915 w -= dx;
916 h -= dy;
917 break;
918 case GDK_SURFACE_EDGE_NORTH:
919 y += dy;
920 h -= dy;
921 break;
922 case GDK_SURFACE_EDGE_NORTH_EAST:
923 y += dy;
924 h -= dy;
925 w += dx;
926 break;
927 case GDK_SURFACE_EDGE_SOUTH_WEST:
928 h += dy;
929 x += dx;
930 w -= dx;
931 break;
932 case GDK_SURFACE_EDGE_SOUTH_EAST:
933 w += dx;
934 h += dy;
935 break;
936 case GDK_SURFACE_EDGE_SOUTH:
937 h += dy;
938 break;
939 case GDK_SURFACE_EDGE_EAST:
940 w += dx;
941 break;
942 case GDK_SURFACE_EDGE_WEST:
943 x += dx;
944 w -= dx;
945 break;
946 default:
947 break;
948 }
949
950 x = MAX (x, 0);
951 y = MAX (y, 0);
952 w = MAX (w, 1);
953 h = MAX (h, 1);
954
955 if (mv_resize->moveresize_geom_mask)
956 {
957 gdk_surface_constrain_size (&mv_resize->moveresize_geometry,
958 mv_resize->moveresize_geom_mask,
959 w, h, &w, &h);
960 }
961
962 gdk_broadway_surface_move_resize (mv_resize->moveresize_surface,
963 x, y, w, h);
964 }
965 else
966 {
967 int x, y;
968
969 x = mv_resize->moveresize_orig_x + dx;
970 y = mv_resize->moveresize_orig_y + dy;
971
972 gdk_broadway_surface_move (mv_resize->moveresize_surface, x, y);
973 }
974 }
975
976 static void
finish_drag(MoveResizeData * mv_resize)977 finish_drag (MoveResizeData *mv_resize)
978 {
979 gdk_surface_destroy (mv_resize->moveresize_emulation_surface);
980 mv_resize->moveresize_emulation_surface = NULL;
981 g_object_unref (mv_resize->moveresize_surface);
982 mv_resize->moveresize_surface = NULL;
983 g_clear_pointer (&mv_resize->moveresize_pending_event, g_free);
984 }
985
986 static gboolean
moveresize_lookahead(GdkDisplay * display,MoveResizeData * mv_resize,BroadwayInputMsg * event)987 moveresize_lookahead (GdkDisplay *display,
988 MoveResizeData *mv_resize,
989 BroadwayInputMsg *event)
990 {
991 GdkBroadwayDisplay *broadway_display;
992
993 broadway_display = GDK_BROADWAY_DISPLAY (display);
994
995 return !_gdk_broadway_server_lookahead_event (broadway_display->server, "mb");
996 }
997
998 gboolean
_gdk_broadway_moveresize_handle_event(GdkDisplay * display,BroadwayInputMsg * event)999 _gdk_broadway_moveresize_handle_event (GdkDisplay *display,
1000 BroadwayInputMsg *event)
1001 {
1002 guint button_mask = 0;
1003 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
1004
1005 if (!mv_resize || !mv_resize->moveresize_surface)
1006 return FALSE;
1007
1008 button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
1009
1010 switch (event->base.type)
1011 {
1012 case BROADWAY_EVENT_TOUCH:
1013 if (event->touch.touch_type == 2) /* END */
1014 {
1015 update_pos (mv_resize,
1016 event->touch.root_x,
1017 event->touch.root_y);
1018
1019 finish_drag (mv_resize);
1020 }
1021 else if (event->touch.touch_type == 1) /* UPDATE */
1022 {
1023 if (mv_resize->moveresize_surface->resize_count > 0)
1024 {
1025 if (mv_resize->moveresize_pending_event)
1026 *mv_resize->moveresize_pending_event = *event;
1027 else
1028 mv_resize->moveresize_pending_event =
1029 g_memdup2 (event, sizeof (BroadwayInputMsg));
1030
1031 break;
1032 }
1033 update_pos (mv_resize,
1034 event->touch.root_x,
1035 event->touch.root_y);
1036 }
1037
1038 break;
1039
1040 case BROADWAY_EVENT_POINTER_MOVE:
1041 if (mv_resize->moveresize_surface->resize_count > 0)
1042 {
1043 if (mv_resize->moveresize_pending_event)
1044 *mv_resize->moveresize_pending_event = *event;
1045 else
1046 mv_resize->moveresize_pending_event =
1047 g_memdup2 (event, sizeof (BroadwayInputMsg));
1048
1049 break;
1050 }
1051 if (!moveresize_lookahead (display, mv_resize, event))
1052 break;
1053
1054 update_pos (mv_resize,
1055 event->pointer.root_x,
1056 event->pointer.root_y);
1057
1058 /* This should never be triggered in normal cases, but in the
1059 * case where the drag started without an implicit grab being
1060 * in effect, we could miss the release if it occurs before
1061 * we grab the pointer; this ensures that we will never
1062 * get a permanently stuck grab.
1063 */
1064 if ((event->pointer.state & button_mask) == 0)
1065 finish_drag (mv_resize);
1066 break;
1067
1068 case BROADWAY_EVENT_BUTTON_RELEASE:
1069 update_pos (mv_resize,
1070 event->pointer.root_x,
1071 event->pointer.root_y);
1072
1073 if (event->button.button == mv_resize->moveresize_button)
1074 finish_drag (mv_resize);
1075 break;
1076 default:
1077 break;
1078 }
1079 return TRUE;
1080 }
1081
1082 gboolean
_gdk_broadway_moveresize_configure_done(GdkDisplay * display,GdkSurface * surface)1083 _gdk_broadway_moveresize_configure_done (GdkDisplay *display,
1084 GdkSurface *surface)
1085 {
1086 BroadwayInputMsg *tmp_event;
1087 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
1088
1089 if (!mv_resize || surface != mv_resize->moveresize_surface)
1090 return FALSE;
1091
1092 if (mv_resize->moveresize_pending_event)
1093 {
1094 tmp_event = mv_resize->moveresize_pending_event;
1095 mv_resize->moveresize_pending_event = NULL;
1096 _gdk_broadway_moveresize_handle_event (display, tmp_event);
1097 g_free (tmp_event);
1098 }
1099
1100 return TRUE;
1101 }
1102
1103 static void
create_moveresize_surface(MoveResizeData * mv_resize,guint32 timestamp)1104 create_moveresize_surface (MoveResizeData *mv_resize,
1105 guint32 timestamp)
1106 {
1107 GdkGrabStatus status;
1108 GdkSeat *seat;
1109 GdkDevice *pointer;
1110
1111 g_assert (mv_resize->moveresize_emulation_surface == NULL);
1112
1113 mv_resize->moveresize_emulation_surface =
1114 _gdk_broadway_display_create_surface (mv_resize->display,
1115 GDK_SURFACE_TEMP,
1116 NULL,
1117 -100, -100, 1, 1);
1118
1119 gdk_broadway_surface_show (mv_resize->moveresize_emulation_surface, FALSE);
1120
1121 seat = gdk_display_get_default_seat (mv_resize->display);
1122 pointer = gdk_seat_get_pointer (seat);
1123
1124 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1125 status = gdk_device_grab (pointer,
1126 mv_resize->moveresize_emulation_surface,
1127 FALSE,
1128 GDK_BUTTON_RELEASE_MASK |
1129 GDK_POINTER_MOTION_MASK,
1130 NULL,
1131 timestamp);
1132 G_GNUC_END_IGNORE_DEPRECATIONS;
1133
1134 if (status != GDK_GRAB_SUCCESS)
1135 {
1136 /* If this fails, some other client has grabbed the surface
1137 * already.
1138 */
1139 finish_drag (mv_resize);
1140 }
1141
1142 mv_resize->moveresize_process_time = 0;
1143 }
1144
1145 static void
calculate_unmoving_origin(MoveResizeData * mv_resize)1146 calculate_unmoving_origin (MoveResizeData *mv_resize)
1147 {
1148 gdk_surface_get_geometry (mv_resize->moveresize_surface,
1149 &mv_resize->moveresize_orig_x,
1150 &mv_resize->moveresize_orig_y,
1151 NULL, NULL);
1152 }
1153
1154 static void
gdk_broadway_toplevel_begin_resize(GdkToplevel * toplevel,GdkSurfaceEdge edge,GdkDevice * device,int button,double x,double y,guint32 timestamp)1155 gdk_broadway_toplevel_begin_resize (GdkToplevel *toplevel,
1156 GdkSurfaceEdge edge,
1157 GdkDevice *device,
1158 int button,
1159 double x,
1160 double y,
1161 guint32 timestamp)
1162 {
1163 GdkSurface *surface = GDK_SURFACE (toplevel);
1164 GdkBroadwaySurface *impl = GDK_BROADWAY_SURFACE (surface);
1165 MoveResizeData *mv_resize;
1166
1167 if (GDK_SURFACE_DESTROYED (surface))
1168 return;
1169
1170 if (impl->maximized)
1171 return;
1172
1173 mv_resize = get_move_resize_data (gdk_surface_get_display (surface), TRUE);
1174
1175 if (mv_resize->moveresize_surface != NULL)
1176 return; /* already a drag operation in progress */
1177
1178 mv_resize->is_resize = TRUE;
1179 mv_resize->moveresize_button = button;
1180 mv_resize->resize_edge = edge;
1181 mv_resize->moveresize_x = x + surface->x;
1182 mv_resize->moveresize_y = y + surface->y;
1183 mv_resize->moveresize_surface = g_object_ref (surface);
1184
1185 mv_resize->moveresize_orig_width = gdk_surface_get_width (surface);
1186 mv_resize->moveresize_orig_height = gdk_surface_get_height (surface);
1187
1188 mv_resize->moveresize_geom_mask = impl->geometry_hints_mask;
1189 mv_resize->moveresize_geometry = impl->geometry_hints;
1190
1191 calculate_unmoving_origin (mv_resize);
1192
1193 create_moveresize_surface (mv_resize, timestamp);
1194 }
1195
1196 static void
gdk_broadway_toplevel_begin_move(GdkToplevel * toplevel,GdkDevice * device,int button,double x,double y,guint32 timestamp)1197 gdk_broadway_toplevel_begin_move (GdkToplevel *toplevel,
1198 GdkDevice *device,
1199 int button,
1200 double x,
1201 double y,
1202 guint32 timestamp)
1203 {
1204 GdkSurface *surface = GDK_SURFACE (toplevel);
1205 GdkBroadwaySurface *impl = GDK_BROADWAY_SURFACE (surface);
1206 MoveResizeData *mv_resize;
1207
1208 if (GDK_SURFACE_DESTROYED (surface))
1209 return;
1210
1211 if (impl->maximized)
1212 return;
1213
1214 mv_resize = get_move_resize_data (gdk_surface_get_display (surface), TRUE);
1215
1216 if (mv_resize->moveresize_surface != NULL)
1217 return; /* already a drag operation in progress */
1218
1219 mv_resize->is_resize = FALSE;
1220 mv_resize->moveresize_button = button;
1221 mv_resize->moveresize_x = x + surface->x;
1222 mv_resize->moveresize_y = y + surface->y;
1223 mv_resize->moveresize_surface = g_object_ref (surface);
1224
1225 mv_resize->moveresize_orig_width = gdk_surface_get_width (surface);
1226 mv_resize->moveresize_orig_height = gdk_surface_get_height (surface);
1227
1228 mv_resize->moveresize_geom_mask = impl->geometry_hints_mask;
1229 mv_resize->moveresize_geometry = impl->geometry_hints;
1230
1231 calculate_unmoving_origin (mv_resize);
1232
1233 create_moveresize_surface (mv_resize, timestamp);
1234 }
1235
1236 static gboolean
gdk_broadway_surface_beep(GdkSurface * surface)1237 gdk_broadway_surface_beep (GdkSurface *surface)
1238 {
1239 return FALSE;
1240 }
1241
1242 static void
gdk_broadway_surface_class_init(GdkBroadwaySurfaceClass * klass)1243 gdk_broadway_surface_class_init (GdkBroadwaySurfaceClass *klass)
1244 {
1245 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1246 GdkSurfaceClass *impl_class = GDK_SURFACE_CLASS (klass);
1247
1248 object_class->finalize = gdk_broadway_surface_finalize;
1249
1250 impl_class->ref_cairo_surface = gdk_broadway_surface_ref_cairo_surface;
1251 impl_class->hide = gdk_broadway_surface_hide;
1252 impl_class->get_geometry = gdk_broadway_surface_get_geometry;
1253 impl_class->get_root_coords = gdk_broadway_surface_get_root_coords;
1254 impl_class->get_device_state = gdk_broadway_surface_get_device_state;
1255 impl_class->set_input_region = gdk_broadway_surface_set_input_region;
1256 impl_class->destroy = _gdk_broadway_surface_destroy;
1257 impl_class->beep = gdk_broadway_surface_beep;
1258 impl_class->destroy_notify = gdk_broadway_surface_destroy_notify;
1259 impl_class->drag_begin = _gdk_broadway_surface_drag_begin;
1260 impl_class->get_scale_factor = gdk_broadway_surface_get_scale_factor;
1261 }
1262
1263 #define LAST_PROP 1
1264
1265 typedef struct
1266 {
1267 GdkBroadwaySurface parent_instance;
1268 } GdkBroadwayPopup;
1269
1270 typedef struct
1271 {
1272 GdkBroadwaySurfaceClass parent_class;
1273 } GdkBroadwayPopupClass;
1274
1275 static void gdk_broadway_popup_iface_init (GdkPopupInterface *iface);
1276
G_DEFINE_TYPE_WITH_CODE(GdkBroadwayPopup,gdk_broadway_popup,GDK_TYPE_BROADWAY_SURFACE,G_IMPLEMENT_INTERFACE (GDK_TYPE_POPUP,gdk_broadway_popup_iface_init))1277 G_DEFINE_TYPE_WITH_CODE (GdkBroadwayPopup, gdk_broadway_popup, GDK_TYPE_BROADWAY_SURFACE,
1278 G_IMPLEMENT_INTERFACE (GDK_TYPE_POPUP,
1279 gdk_broadway_popup_iface_init))
1280
1281 static void
1282 gdk_broadway_popup_init (GdkBroadwayPopup *popup)
1283 {
1284 }
1285
1286 static void
gdk_broadway_popup_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1287 gdk_broadway_popup_get_property (GObject *object,
1288 guint prop_id,
1289 GValue *value,
1290 GParamSpec *pspec)
1291 {
1292 GdkSurface *surface = GDK_SURFACE (object);
1293
1294 switch (prop_id)
1295 {
1296 case LAST_PROP + GDK_POPUP_PROP_PARENT:
1297 g_value_set_object (value, surface->parent);
1298 break;
1299
1300 case LAST_PROP + GDK_POPUP_PROP_AUTOHIDE:
1301 g_value_set_boolean (value, surface->autohide);
1302 break;
1303
1304 default:
1305 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1306 break;
1307 }
1308 }
1309
1310 static void
gdk_broadway_popup_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1311 gdk_broadway_popup_set_property (GObject *object,
1312 guint prop_id,
1313 const GValue *value,
1314 GParamSpec *pspec)
1315 {
1316 GdkSurface *surface = GDK_SURFACE (object);
1317
1318 switch (prop_id)
1319 {
1320 case LAST_PROP + GDK_POPUP_PROP_PARENT:
1321 surface->parent = g_value_dup_object (value);
1322 if (surface->parent != NULL)
1323 surface->parent->children = g_list_prepend (surface->parent->children, surface);
1324 break;
1325
1326 case LAST_PROP + GDK_POPUP_PROP_AUTOHIDE:
1327 surface->autohide = g_value_get_boolean (value);
1328 break;
1329
1330 default:
1331 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1332 break;
1333 }
1334 }
1335
1336 static void
gdk_broadway_popup_class_init(GdkBroadwayPopupClass * class)1337 gdk_broadway_popup_class_init (GdkBroadwayPopupClass *class)
1338 {
1339 GObjectClass *object_class = G_OBJECT_CLASS (class);
1340
1341 object_class->get_property = gdk_broadway_popup_get_property;
1342 object_class->set_property = gdk_broadway_popup_set_property;
1343
1344 gdk_popup_install_properties (object_class, 1);
1345 }
1346
1347 static gboolean
gdk_broadway_popup_present(GdkPopup * popup,int width,int height,GdkPopupLayout * layout)1348 gdk_broadway_popup_present (GdkPopup *popup,
1349 int width,
1350 int height,
1351 GdkPopupLayout *layout)
1352 {
1353 return gdk_broadway_surface_present_popup (GDK_SURFACE (popup), width, height, layout);
1354 }
1355
1356 static GdkGravity
gdk_broadway_popup_get_surface_anchor(GdkPopup * popup)1357 gdk_broadway_popup_get_surface_anchor (GdkPopup *popup)
1358 {
1359 return GDK_SURFACE (popup)->popup.surface_anchor;
1360 }
1361
1362 static GdkGravity
gdk_broadway_popup_get_rect_anchor(GdkPopup * popup)1363 gdk_broadway_popup_get_rect_anchor (GdkPopup *popup)
1364 {
1365 return GDK_SURFACE (popup)->popup.rect_anchor;
1366 }
1367
1368 static int
gdk_broadway_popup_get_position_x(GdkPopup * popup)1369 gdk_broadway_popup_get_position_x (GdkPopup *popup)
1370 {
1371 return GDK_SURFACE (popup)->x;
1372 }
1373
1374 static int
gdk_broadway_popup_get_position_y(GdkPopup * popup)1375 gdk_broadway_popup_get_position_y (GdkPopup *popup)
1376 {
1377 return GDK_SURFACE (popup)->y;
1378 }
1379
1380 static void
gdk_broadway_popup_iface_init(GdkPopupInterface * iface)1381 gdk_broadway_popup_iface_init (GdkPopupInterface *iface)
1382 {
1383 iface->present = gdk_broadway_popup_present;
1384 iface->get_surface_anchor = gdk_broadway_popup_get_surface_anchor;
1385 iface->get_rect_anchor = gdk_broadway_popup_get_rect_anchor;
1386 iface->get_position_x = gdk_broadway_popup_get_position_x;
1387 iface->get_position_y = gdk_broadway_popup_get_position_y;
1388 }
1389
1390 typedef struct
1391 {
1392 GdkBroadwaySurface parent_instance;
1393 } GdkBroadwayToplevel;
1394
1395 typedef struct
1396 {
1397 GdkBroadwaySurfaceClass parent_class;
1398 } GdkBroadwayToplevelClass;
1399
1400 static void gdk_broadway_toplevel_iface_init (GdkToplevelInterface *iface);
1401
G_DEFINE_TYPE_WITH_CODE(GdkBroadwayToplevel,gdk_broadway_toplevel,GDK_TYPE_BROADWAY_SURFACE,G_IMPLEMENT_INTERFACE (GDK_TYPE_TOPLEVEL,gdk_broadway_toplevel_iface_init))1402 G_DEFINE_TYPE_WITH_CODE (GdkBroadwayToplevel, gdk_broadway_toplevel, GDK_TYPE_BROADWAY_SURFACE,
1403 G_IMPLEMENT_INTERFACE (GDK_TYPE_TOPLEVEL,
1404 gdk_broadway_toplevel_iface_init))
1405
1406 static void
1407 gdk_broadway_toplevel_init (GdkBroadwayToplevel *toplevel)
1408 {
1409 }
1410
1411 static void
gdk_broadway_toplevel_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1412 gdk_broadway_toplevel_set_property (GObject *object,
1413 guint prop_id,
1414 const GValue *value,
1415 GParamSpec *pspec)
1416 {
1417 GdkSurface *surface = GDK_SURFACE (object);
1418
1419 switch (prop_id)
1420 {
1421 case LAST_PROP + GDK_TOPLEVEL_PROP_TITLE:
1422 gdk_broadway_surface_set_title (surface, g_value_get_string (value));
1423 g_object_notify_by_pspec (G_OBJECT (surface), pspec);
1424 break;
1425
1426 case LAST_PROP + GDK_TOPLEVEL_PROP_STARTUP_ID:
1427 gdk_broadway_surface_set_startup_id (surface, g_value_get_string (value));
1428 g_object_notify_by_pspec (G_OBJECT (surface), pspec);
1429 break;
1430
1431 case LAST_PROP + GDK_TOPLEVEL_PROP_TRANSIENT_FOR:
1432 gdk_broadway_surface_set_transient_for (surface, g_value_get_object (value));
1433 g_object_notify_by_pspec (G_OBJECT (surface), pspec);
1434 break;
1435
1436 case LAST_PROP + GDK_TOPLEVEL_PROP_MODAL:
1437 break;
1438
1439 case LAST_PROP + GDK_TOPLEVEL_PROP_ICON_LIST:
1440 break;
1441
1442 case LAST_PROP + GDK_TOPLEVEL_PROP_DECORATED:
1443 break;
1444
1445 case LAST_PROP + GDK_TOPLEVEL_PROP_DELETABLE:
1446 break;
1447
1448 case LAST_PROP + GDK_TOPLEVEL_PROP_SHORTCUTS_INHIBITED:
1449 break;
1450
1451 default:
1452 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1453 break;
1454 }
1455 }
1456
1457 static void
gdk_broadway_toplevel_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1458 gdk_broadway_toplevel_get_property (GObject *object,
1459 guint prop_id,
1460 GValue *value,
1461 GParamSpec *pspec)
1462 {
1463 GdkSurface *surface = GDK_SURFACE (object);
1464
1465 switch (prop_id)
1466 {
1467 case LAST_PROP + GDK_TOPLEVEL_PROP_STATE:
1468 g_value_set_flags (value, surface->state);
1469 break;
1470
1471 case LAST_PROP + GDK_TOPLEVEL_PROP_TITLE:
1472 g_value_set_string (value, "");
1473 break;
1474
1475 case LAST_PROP + GDK_TOPLEVEL_PROP_STARTUP_ID:
1476 g_value_set_string (value, "");
1477 break;
1478
1479 case LAST_PROP + GDK_TOPLEVEL_PROP_TRANSIENT_FOR:
1480 g_value_set_object (value, surface->transient_for);
1481 break;
1482
1483 case LAST_PROP + GDK_TOPLEVEL_PROP_ICON_LIST:
1484 g_value_set_pointer (value, NULL);
1485 break;
1486
1487 case LAST_PROP + GDK_TOPLEVEL_PROP_DECORATED:
1488 break;
1489
1490 case LAST_PROP + GDK_TOPLEVEL_PROP_DELETABLE:
1491 break;
1492
1493 case LAST_PROP + GDK_TOPLEVEL_PROP_SHORTCUTS_INHIBITED:
1494 g_value_set_boolean (value, surface->shortcuts_inhibited);
1495 break;
1496
1497 default:
1498 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1499 break;
1500 }
1501 }
1502
1503 static void
gdk_broadway_toplevel_class_init(GdkBroadwayToplevelClass * class)1504 gdk_broadway_toplevel_class_init (GdkBroadwayToplevelClass *class)
1505 {
1506 GObjectClass *object_class = G_OBJECT_CLASS (class);
1507
1508 object_class->get_property = gdk_broadway_toplevel_get_property;
1509 object_class->set_property = gdk_broadway_toplevel_set_property;
1510
1511 gdk_toplevel_install_properties (object_class, 1);
1512 }
1513
1514 static void
show_surface(GdkSurface * surface)1515 show_surface (GdkSurface *surface)
1516 {
1517 gboolean was_mapped;
1518
1519 if (surface->destroyed)
1520 return;
1521
1522 was_mapped = GDK_SURFACE_IS_MAPPED (surface);
1523
1524 if (!was_mapped)
1525 gdk_surface_set_is_mapped (surface, TRUE);
1526
1527 gdk_broadway_surface_show (surface, FALSE);
1528
1529 if (!was_mapped)
1530 gdk_surface_invalidate_rect (surface, NULL);
1531 }
1532
1533 static void
gdk_broadway_toplevel_present(GdkToplevel * toplevel,GdkToplevelLayout * layout)1534 gdk_broadway_toplevel_present (GdkToplevel *toplevel,
1535 GdkToplevelLayout *layout)
1536 {
1537 GdkSurface *surface = GDK_SURFACE (toplevel);
1538 GdkBroadwaySurface *impl = GDK_BROADWAY_SURFACE (surface);
1539 GdkDisplay *display = gdk_surface_get_display (surface);
1540 GdkMonitor *monitor;
1541 GdkToplevelSize size;
1542 int bounds_width, bounds_height;
1543 int width, height;
1544 GdkGeometry geometry;
1545 GdkSurfaceHints mask;
1546 gboolean maximize;
1547
1548 gdk_broadway_surface_unminimize (surface);
1549
1550 monitor = gdk_display_get_monitor_at_surface (display, surface);
1551 if (monitor)
1552 {
1553 GdkRectangle monitor_geometry;
1554
1555 gdk_monitor_get_geometry (monitor, &monitor_geometry);
1556 bounds_width = monitor_geometry.width;
1557 bounds_height = monitor_geometry.height;
1558 }
1559 else
1560 {
1561 bounds_width = G_MAXINT;
1562 bounds_height = G_MAXINT;
1563 }
1564
1565 gdk_toplevel_size_init (&size, bounds_width, bounds_height);
1566 gdk_toplevel_notify_compute_size (toplevel, &size);
1567 g_warn_if_fail (size.width > 0);
1568 g_warn_if_fail (size.height > 0);
1569 width = size.width;
1570 height = size.height;
1571
1572 if (gdk_toplevel_layout_get_resizable (layout))
1573 {
1574 geometry.min_width = size.min_width;
1575 geometry.min_height = size.min_height;
1576 mask = GDK_HINT_MIN_SIZE;
1577 }
1578 else
1579 {
1580 geometry.max_width = geometry.min_width = width;
1581 geometry.max_height = geometry.min_height = height;
1582 mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
1583 }
1584 gdk_broadway_surface_set_geometry_hints (surface, &geometry, mask);
1585 gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height);
1586 gdk_broadway_surface_toplevel_resize (surface, width, height);
1587
1588 if (gdk_toplevel_layout_get_maximized (layout, &maximize))
1589 {
1590 if (maximize)
1591 gdk_broadway_surface_maximize (surface);
1592 else
1593 gdk_broadway_surface_unmaximize (surface);
1594 }
1595
1596 if (size.shadow.is_valid)
1597 {
1598 impl->shadow_left = size.shadow.left;
1599 impl->shadow_right = size.shadow.right;
1600 impl->shadow_top = size.shadow.top;
1601 impl->shadow_bottom = size.shadow.bottom;
1602 }
1603
1604 show_surface (surface);
1605 }
1606
1607 static gboolean
gdk_broadway_toplevel_minimize(GdkToplevel * toplevel)1608 gdk_broadway_toplevel_minimize (GdkToplevel *toplevel)
1609 {
1610 gdk_broadway_surface_minimize (GDK_SURFACE (toplevel));
1611
1612 return TRUE;
1613 }
1614
1615 static gboolean
gdk_broadway_toplevel_lower(GdkToplevel * toplevel)1616 gdk_broadway_toplevel_lower (GdkToplevel *toplevel)
1617 {
1618 return FALSE;
1619 }
1620
1621 static void
gdk_broadway_toplevel_focus(GdkToplevel * toplevel,guint32 timestamp)1622 gdk_broadway_toplevel_focus (GdkToplevel *toplevel,
1623 guint32 timestamp)
1624 {
1625 gdk_broadway_surface_focus (GDK_SURFACE (toplevel), timestamp);
1626 }
1627
1628 static gboolean
gdk_broadway_toplevel_show_window_menu(GdkToplevel * toplevel,GdkEvent * event)1629 gdk_broadway_toplevel_show_window_menu (GdkToplevel *toplevel,
1630 GdkEvent *event)
1631 {
1632 return FALSE;
1633 }
1634
1635 static void
gdk_broadway_toplevel_iface_init(GdkToplevelInterface * iface)1636 gdk_broadway_toplevel_iface_init (GdkToplevelInterface *iface)
1637 {
1638 iface->present = gdk_broadway_toplevel_present;
1639 iface->minimize = gdk_broadway_toplevel_minimize;
1640 iface->lower = gdk_broadway_toplevel_lower;
1641 iface->focus = gdk_broadway_toplevel_focus;
1642 iface->show_window_menu = gdk_broadway_toplevel_show_window_menu;
1643 iface->begin_resize = gdk_broadway_toplevel_begin_resize;
1644 iface->begin_move = gdk_broadway_toplevel_begin_move;
1645 }
1646
1647 typedef struct
1648 {
1649 GdkBroadwaySurface parent_instance;
1650 } GdkBroadwayDragSurface;
1651
1652 typedef struct
1653 {
1654 GdkBroadwaySurfaceClass parent_class;
1655 } GdkBroadwayDragSurfaceClass;
1656
1657 static void gdk_broadway_drag_surface_iface_init (GdkDragSurfaceInterface *iface);
1658
G_DEFINE_TYPE_WITH_CODE(GdkBroadwayDragSurface,gdk_broadway_drag_surface,GDK_TYPE_BROADWAY_SURFACE,G_IMPLEMENT_INTERFACE (GDK_TYPE_DRAG_SURFACE,gdk_broadway_drag_surface_iface_init))1659 G_DEFINE_TYPE_WITH_CODE (GdkBroadwayDragSurface, gdk_broadway_drag_surface, GDK_TYPE_BROADWAY_SURFACE,
1660 G_IMPLEMENT_INTERFACE (GDK_TYPE_DRAG_SURFACE,
1661 gdk_broadway_drag_surface_iface_init))
1662
1663 static void
1664 gdk_broadway_drag_surface_init (GdkBroadwayDragSurface *surface)
1665 {
1666 }
1667
1668 static void
gdk_broadway_drag_surface_class_init(GdkBroadwayDragSurfaceClass * class)1669 gdk_broadway_drag_surface_class_init (GdkBroadwayDragSurfaceClass *class)
1670 {
1671 }
1672
1673 static gboolean
gdk_broadway_drag_surface_present(GdkDragSurface * drag_surface,int width,int height)1674 gdk_broadway_drag_surface_present (GdkDragSurface *drag_surface,
1675 int width,
1676 int height)
1677 {
1678 GdkSurface *surface = GDK_SURFACE (drag_surface);
1679
1680 gdk_broadway_surface_toplevel_resize (surface, width, height);
1681 show_surface (surface);
1682
1683 return TRUE;
1684 }
1685
1686 static void
gdk_broadway_drag_surface_iface_init(GdkDragSurfaceInterface * iface)1687 gdk_broadway_drag_surface_iface_init (GdkDragSurfaceInterface *iface)
1688 {
1689 iface->present = gdk_broadway_drag_surface_present;
1690 }
1691