1 /* GDK - The GIMP Drawing Kit
2  * gdkdisplay.c
3  *
4  * Copyright 2001 Sun Microsystems Inc.
5  *
6  * Erwann Chenede <erwann.chenede@sun.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "config.h"
23 
24 #include "gdkdisplay.h"
25 #include "gdkdisplayprivate.h"
26 
27 #include "gdkintl.h"
28 #include "gdk-private.h"
29 
30 #include "gdkclipboardprivate.h"
31 #include "gdkdeviceprivate.h"
32 #include "gdkdisplaymanagerprivate.h"
33 #include "gdkevents.h"
34 #include "gdkinternals.h"
35 #include "gdkmonitorprivate.h"
36 #include "gdkframeclockidleprivate.h"
37 
38 #include <math.h>
39 #include <glib.h>
40 
41 /**
42  * GdkDisplay:
43  *
44  * `GdkDisplay` objects are the GDK representation of a workstation.
45  *
46  * Their purpose are two-fold:
47  *
48  * - To manage and provide information about input devices (pointers, keyboards, etc)
49  * - To manage and provide information about output devices (monitors, projectors, etc)
50  *
51  * Most of the input device handling has been factored out into separate
52  * [class@Gdk.Seat] objects. Every display has a one or more seats, which
53  * can be accessed with [method@Gdk.Display.get_default_seat] and
54  * [method@Gdk.Display.list_seats].
55  *
56  * Output devices are represented by [class@Gdk.Monitor] objects, which can
57  * be accessed with [method@Gdk.Display.get_monitor_at_surface] and similar APIs.
58  */
59 
60 enum
61 {
62   PROP_0,
63   PROP_COMPOSITED,
64   PROP_RGBA,
65   PROP_INPUT_SHAPES,
66   LAST_PROP
67 };
68 
69 static GParamSpec *props[LAST_PROP] = { NULL, };
70 
71 enum {
72   OPENED,
73   CLOSED,
74   SEAT_ADDED,
75   SEAT_REMOVED,
76   SETTING_CHANGED,
77   LAST_SIGNAL
78 };
79 
80 typedef struct _GdkDisplayPrivate GdkDisplayPrivate;
81 
82 struct _GdkDisplayPrivate {
83   /* The base context that all other contexts inherit from.
84    * This context is never exposed to public API and is
85    * allowed to have a %NULL surface.
86    */
87   GdkGLContext *gl_context;
88   GError *gl_error;
89 
90   guint rgba : 1;
91   guint composited : 1;
92   guint input_shapes : 1;
93 
94   GdkDebugFlags debug_flags;
95 };
96 
97 static void gdk_display_dispose     (GObject         *object);
98 static void gdk_display_finalize    (GObject         *object);
99 
100 
101 static GdkAppLaunchContext *gdk_display_real_get_app_launch_context (GdkDisplay *display);
102 
103 static guint signals[LAST_SIGNAL] = { 0 };
104 
G_DEFINE_TYPE_WITH_PRIVATE(GdkDisplay,gdk_display,G_TYPE_OBJECT)105 G_DEFINE_TYPE_WITH_PRIVATE (GdkDisplay, gdk_display, G_TYPE_OBJECT)
106 
107 static void
108 gdk_display_get_property (GObject    *object,
109                           guint       prop_id,
110                           GValue     *value,
111                           GParamSpec *pspec)
112 {
113   GdkDisplay *display = GDK_DISPLAY (object);
114 
115   switch (prop_id)
116     {
117     case PROP_COMPOSITED:
118       g_value_set_boolean (value, gdk_display_is_composited (display));
119       break;
120 
121     case PROP_RGBA:
122       g_value_set_boolean (value, gdk_display_is_rgba (display));
123       break;
124 
125     case PROP_INPUT_SHAPES:
126       g_value_set_boolean (value, gdk_display_supports_input_shapes (display));
127       break;
128 
129     default:
130       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
131     }
132 }
133 
134 static void
gdk_display_real_make_default(GdkDisplay * display)135 gdk_display_real_make_default (GdkDisplay *display)
136 {
137 }
138 
139 static GdkGLContext *
gdk_display_default_init_gl(GdkDisplay * display,GError ** error)140 gdk_display_default_init_gl (GdkDisplay  *display,
141                              GError     **error)
142 {
143   g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
144                        _("The current backend does not support OpenGL"));
145 
146   return NULL;
147 }
148 
149 static GdkSeat *
gdk_display_real_get_default_seat(GdkDisplay * display)150 gdk_display_real_get_default_seat (GdkDisplay *display)
151 {
152   if (!display->seats)
153     return NULL;
154 
155   return display->seats->data;
156 }
157 
158 static void
gdk_display_real_opened(GdkDisplay * display)159 gdk_display_real_opened (GdkDisplay *display)
160 {
161   _gdk_display_manager_add_display (gdk_display_manager_get (), display);
162 }
163 
164 static void
gdk_display_class_init(GdkDisplayClass * class)165 gdk_display_class_init (GdkDisplayClass *class)
166 {
167   GObjectClass *object_class = G_OBJECT_CLASS (class);
168 
169   object_class->finalize = gdk_display_finalize;
170   object_class->dispose = gdk_display_dispose;
171   object_class->get_property = gdk_display_get_property;
172 
173   class->make_default = gdk_display_real_make_default;
174   class->get_app_launch_context = gdk_display_real_get_app_launch_context;
175   class->init_gl = gdk_display_default_init_gl;
176   class->get_default_seat = gdk_display_real_get_default_seat;
177   class->opened = gdk_display_real_opened;
178 
179   /**
180    * GdkDisplay:composited: (attributes org.gtk.Property.get=gdk_display_is_composited)
181    *
182    * %TRUE if the display properly composites the alpha channel.
183    */
184   props[PROP_COMPOSITED] =
185     g_param_spec_boolean ("composited",
186                           P_("Composited"),
187                           P_("Composited"),
188                           TRUE,
189                           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
190 
191   /**
192    * GdkDisplay:rgba: (attributes org.gtk.Property.get=gdk_display_is_rgba)
193    *
194    * %TRUE if the display supports an alpha channel.
195    */
196   props[PROP_RGBA] =
197     g_param_spec_boolean ("rgba",
198                           P_("RGBA"),
199                           P_("RGBA"),
200                           TRUE,
201                           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
202 
203   /**
204    * GdkDisplay:input-shapes: (attributes org.gtk.Property.get=gdk_display_supports_input_shapes)
205    *
206    * %TRUE if the display supports input shapes.
207    */
208   props[PROP_INPUT_SHAPES] =
209     g_param_spec_boolean ("input-shapes",
210                           P_("Input shapes"),
211                           P_("Input shapes"),
212                           TRUE,
213                           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
214 
215   g_object_class_install_properties (object_class, LAST_PROP, props);
216 
217   /**
218    * GdkDisplay::opened:
219    * @display: the object on which the signal is emitted
220    *
221    * Emitted when the connection to the windowing system for @display is opened.
222    */
223   signals[OPENED] =
224     g_signal_new (g_intern_static_string ("opened"),
225 		  G_OBJECT_CLASS_TYPE (object_class),
226                   G_SIGNAL_RUN_LAST,
227 		  G_STRUCT_OFFSET (GdkDisplayClass, opened),
228                   NULL, NULL,
229                   NULL,
230                   G_TYPE_NONE, 0);
231 
232   /**
233    * GdkDisplay::closed:
234    * @display: the object on which the signal is emitted
235    * @is_error: %TRUE if the display was closed due to an error
236    *
237    * Emitted when the connection to the windowing system for @display is closed.
238    */
239   signals[CLOSED] =
240     g_signal_new (g_intern_static_string ("closed"),
241 		  G_OBJECT_CLASS_TYPE (object_class),
242 		  G_SIGNAL_RUN_LAST,
243 		  G_STRUCT_OFFSET (GdkDisplayClass, closed),
244 		  NULL, NULL,
245                   NULL,
246 		  G_TYPE_NONE,
247 		  1,
248 		  G_TYPE_BOOLEAN);
249 
250   /**
251    * GdkDisplay::seat-added:
252    * @display: the object on which the signal is emitted
253    * @seat: the seat that was just added
254    *
255    * Emitted whenever a new seat is made known to the windowing system.
256    */
257   signals[SEAT_ADDED] =
258     g_signal_new (g_intern_static_string ("seat-added"),
259 		  G_OBJECT_CLASS_TYPE (object_class),
260 		  G_SIGNAL_RUN_LAST,
261 		  0, NULL, NULL,
262                   NULL,
263 		  G_TYPE_NONE, 1, GDK_TYPE_SEAT);
264 
265   /**
266    * GdkDisplay::seat-removed:
267    * @display: the object on which the signal is emitted
268    * @seat: the seat that was just removed
269    *
270    * Emitted whenever a seat is removed by the windowing system.
271    */
272   signals[SEAT_REMOVED] =
273     g_signal_new (g_intern_static_string ("seat-removed"),
274 		  G_OBJECT_CLASS_TYPE (object_class),
275 		  G_SIGNAL_RUN_LAST,
276 		  0, NULL, NULL,
277                   NULL,
278 		  G_TYPE_NONE, 1, GDK_TYPE_SEAT);
279 
280   /**
281    * GdkDisplay::setting-changed:
282    * @display: the object on which the signal is emitted
283    * @setting: the name of the setting that changed
284    *
285    * Emitted whenever a setting changes its value.
286    */
287   signals[SETTING_CHANGED] =
288     g_signal_new (g_intern_static_string ("setting-changed"),
289 		  G_OBJECT_CLASS_TYPE (object_class),
290 		  G_SIGNAL_RUN_LAST,
291 		  0, NULL, NULL,
292                   NULL,
293 		  G_TYPE_NONE, 1, G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE);
294 }
295 
296 static void
free_pointer_info(GdkPointerSurfaceInfo * info)297 free_pointer_info (GdkPointerSurfaceInfo *info)
298 {
299   g_clear_object (&info->surface_under_pointer);
300   g_slice_free (GdkPointerSurfaceInfo, info);
301 }
302 
303 static void
free_device_grab(GdkDeviceGrabInfo * info)304 free_device_grab (GdkDeviceGrabInfo *info)
305 {
306   g_object_unref (info->surface);
307   g_free (info);
308 }
309 
310 static gboolean
free_device_grabs_foreach(gpointer key,gpointer value,gpointer user_data)311 free_device_grabs_foreach (gpointer key,
312                            gpointer value,
313                            gpointer user_data)
314 {
315   GList *list = value;
316 
317   g_list_free_full (list, (GDestroyNotify) free_device_grab);
318 
319   return TRUE;
320 }
321 
322 static void
gdk_display_init(GdkDisplay * display)323 gdk_display_init (GdkDisplay *display)
324 {
325   GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
326 
327   display->double_click_time = 250;
328   display->double_click_distance = 5;
329 
330   display->device_grabs = g_hash_table_new (NULL, NULL);
331 
332   display->pointers_info = g_hash_table_new_full (NULL, NULL, NULL,
333                                                   (GDestroyNotify) free_pointer_info);
334 
335   g_queue_init (&display->queued_events);
336 
337   priv->debug_flags = _gdk_debug_flags;
338 
339   priv->composited = TRUE;
340   priv->rgba = TRUE;
341   priv->input_shapes = TRUE;
342 }
343 
344 static void
gdk_display_dispose(GObject * object)345 gdk_display_dispose (GObject *object)
346 {
347   GdkDisplay *display = GDK_DISPLAY (object);
348   GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
349 
350   _gdk_display_manager_remove_display (gdk_display_manager_get (), display);
351 
352   g_queue_clear (&display->queued_events);
353 
354   g_clear_object (&priv->gl_context);
355   g_clear_error (&priv->gl_error);
356 
357   G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object);
358 }
359 
360 static void
gdk_display_finalize(GObject * object)361 gdk_display_finalize (GObject *object)
362 {
363   GdkDisplay *display = GDK_DISPLAY (object);
364 
365   g_hash_table_foreach_remove (display->device_grabs,
366                                free_device_grabs_foreach,
367                                NULL);
368   g_hash_table_destroy (display->device_grabs);
369 
370   g_hash_table_destroy (display->pointers_info);
371 
372   g_list_free_full (display->seats, g_object_unref);
373 
374   G_OBJECT_CLASS (gdk_display_parent_class)->finalize (object);
375 }
376 
377 /**
378  * gdk_display_close:
379  * @display: a `GdkDisplay`
380  *
381  * Closes the connection to the windowing system for the given display.
382  *
383  * This cleans up associated resources.
384  */
385 void
gdk_display_close(GdkDisplay * display)386 gdk_display_close (GdkDisplay *display)
387 {
388   g_return_if_fail (GDK_IS_DISPLAY (display));
389 
390   if (!display->closed)
391     {
392       display->closed = TRUE;
393 
394       g_signal_emit (display, signals[CLOSED], 0, FALSE);
395       g_object_run_dispose (G_OBJECT (display));
396 
397       g_object_unref (display);
398     }
399 }
400 
401 /**
402  * gdk_display_is_closed:
403  * @display: a `GdkDisplay`
404  *
405  * Finds out if the display has been closed.
406  *
407  * Returns: %TRUE if the display is closed.
408  */
409 gboolean
gdk_display_is_closed(GdkDisplay * display)410 gdk_display_is_closed  (GdkDisplay  *display)
411 {
412   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
413 
414   return display->closed;
415 }
416 
417 /*<private>
418  * gdk_display_get_event:
419  * @display: a `GdkDisplay`
420  *
421  * Gets the next `GdkEvent` to be processed for @display,
422  * fetching events from the windowing system if necessary.
423  *
424  * Returns: (nullable) (transfer full): the next `GdkEvent`
425  *   to be processed
426  */
427 GdkEvent *
gdk_display_get_event(GdkDisplay * display)428 gdk_display_get_event (GdkDisplay *display)
429 {
430   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
431 
432   if (display->event_pause_count == 0)
433     GDK_DISPLAY_GET_CLASS (display)->queue_events (display);
434 
435   return _gdk_event_unqueue (display);
436 }
437 
438 /**
439  * gdk_display_put_event:
440  * @display: a `GdkDisplay`
441  * @event: (transfer none): a `GdkEvent`
442  *
443  * Appends the given event onto the front of the event
444  * queue for @display.
445  *
446  * This function is only useful in very special situations
447  * and should not be used by applications.
448  **/
449 void
gdk_display_put_event(GdkDisplay * display,GdkEvent * event)450 gdk_display_put_event (GdkDisplay *display,
451                        GdkEvent   *event)
452 {
453   g_return_if_fail (GDK_IS_DISPLAY (display));
454   g_return_if_fail (event != NULL);
455 
456   _gdk_event_queue_append (display, gdk_event_ref ((GdkEvent *)event));
457 }
458 
459 static void
generate_grab_broken_event(GdkDisplay * display,GdkSurface * surface,GdkDevice * device,gboolean implicit,GdkSurface * grab_surface)460 generate_grab_broken_event (GdkDisplay *display,
461                             GdkSurface  *surface,
462                             GdkDevice  *device,
463 			    gboolean    implicit,
464 			    GdkSurface  *grab_surface)
465 {
466   g_return_if_fail (surface != NULL);
467 
468   if (!GDK_SURFACE_DESTROYED (surface))
469     {
470       GdkEvent *event;
471 
472       event = gdk_grab_broken_event_new (surface,
473                                          device,
474                                          grab_surface,
475                                          implicit);
476 
477       _gdk_event_queue_append (display, event);
478     }
479 }
480 
481 GdkDeviceGrabInfo *
_gdk_display_get_last_device_grab(GdkDisplay * display,GdkDevice * device)482 _gdk_display_get_last_device_grab (GdkDisplay *display,
483                                    GdkDevice  *device)
484 {
485   GList *l;
486 
487   l = g_hash_table_lookup (display->device_grabs, device);
488 
489   if (l)
490     {
491       l = g_list_last (l);
492       return l->data;
493     }
494 
495   return NULL;
496 }
497 
498 GdkDeviceGrabInfo *
_gdk_display_add_device_grab(GdkDisplay * display,GdkDevice * device,GdkSurface * surface,gboolean owner_events,GdkEventMask event_mask,unsigned long serial_start,guint32 time,gboolean implicit)499 _gdk_display_add_device_grab (GdkDisplay       *display,
500                               GdkDevice        *device,
501                               GdkSurface        *surface,
502                               gboolean          owner_events,
503                               GdkEventMask      event_mask,
504                               unsigned long     serial_start,
505                               guint32           time,
506                               gboolean          implicit)
507 {
508   GdkDeviceGrabInfo *info, *other_info;
509   GList *grabs, *l;
510 
511   info = g_new0 (GdkDeviceGrabInfo, 1);
512 
513   info->surface = g_object_ref (surface);
514   info->serial_start = serial_start;
515   info->serial_end = G_MAXULONG;
516   info->owner_events = owner_events;
517   info->event_mask = event_mask;
518   info->time = time;
519   info->implicit = implicit;
520 
521   grabs = g_hash_table_lookup (display->device_grabs, device);
522 
523   /* Find the first grab that has a larger start time (if any) and insert
524    * before that. I.E we insert after already existing grabs with same
525    * start time */
526   for (l = grabs; l != NULL; l = l->next)
527     {
528       other_info = l->data;
529 
530       if (info->serial_start < other_info->serial_start)
531 	break;
532     }
533 
534   grabs = g_list_insert_before (grabs, l, info);
535 
536   /* Make sure the new grab end before next grab */
537   if (l)
538     {
539       other_info = l->data;
540       info->serial_end = other_info->serial_start;
541     }
542 
543   /* Find any previous grab and update its end time */
544   l = g_list_find (grabs, info);
545   l = l->prev;
546   if (l)
547     {
548       other_info = l->data;
549       other_info->serial_end = serial_start;
550     }
551 
552   g_hash_table_insert (display->device_grabs, device, grabs);
553 
554   return info;
555 }
556 
557 static GdkSurface *
get_current_toplevel(GdkDisplay * display,GdkDevice * device,int * x_out,int * y_out,GdkModifierType * state_out)558 get_current_toplevel (GdkDisplay      *display,
559                       GdkDevice       *device,
560                       int             *x_out,
561                       int             *y_out,
562 		      GdkModifierType *state_out)
563 {
564   GdkSurface *pointer_surface;
565   double x, y;
566   GdkModifierType state;
567 
568   pointer_surface = _gdk_device_surface_at_position (device, &x, &y, &state);
569 
570   if (pointer_surface != NULL &&
571       GDK_SURFACE_DESTROYED (pointer_surface))
572     pointer_surface = NULL;
573 
574   *x_out = round (x);
575   *y_out = round (y);
576   *state_out = state;
577 
578   return pointer_surface;
579 }
580 
581 static void
switch_to_pointer_grab(GdkDisplay * display,GdkDevice * device,GdkDeviceGrabInfo * grab,GdkDeviceGrabInfo * last_grab,guint32 time,gulong serial)582 switch_to_pointer_grab (GdkDisplay        *display,
583                         GdkDevice         *device,
584 			GdkDeviceGrabInfo *grab,
585 			GdkDeviceGrabInfo *last_grab,
586 			guint32            time,
587 			gulong             serial)
588 {
589   GdkSurface *new_toplevel;
590   GdkPointerSurfaceInfo *info;
591   GList *old_grabs;
592   GdkModifierType state;
593   int x = 0, y = 0;
594 
595   /* Temporarily unset pointer to make sure we send the crossing events below */
596   old_grabs = g_hash_table_lookup (display->device_grabs, device);
597   g_hash_table_steal (display->device_grabs, device);
598   info = _gdk_display_get_pointer_info (display, device);
599 
600   if (grab)
601     {
602       /* New grab is in effect */
603       if (!grab->implicit)
604 	{
605 	  /* !owner_event Grabbing a surface that we're not inside, current status is
606 	     now NULL (i.e. outside grabbed surface) */
607 	  if (!grab->owner_events && info->surface_under_pointer != grab->surface)
608 	    _gdk_display_set_surface_under_pointer (display, device, NULL);
609 	}
610 
611       grab->activated = TRUE;
612     }
613 
614   if (last_grab)
615     {
616       new_toplevel = NULL;
617 
618       if (grab == NULL /* ungrab */ ||
619 	  (!last_grab->owner_events && grab->owner_events) /* switched to owner_events */ )
620 	{
621           new_toplevel = get_current_toplevel (display, device, &x, &y, &state);
622 
623 	  if (new_toplevel)
624 	    {
625 	      /* w is now toplevel and x,y in toplevel coords */
626               _gdk_display_set_surface_under_pointer (display, device, new_toplevel);
627 	      info->toplevel_x = x;
628 	      info->toplevel_y = y;
629 	      info->state = state;
630 	    }
631 	}
632 
633       if (grab == NULL) /* Ungrabbed, send events */
634 	{
635 	  /* We're now ungrabbed, update the surface_under_pointer */
636 	  _gdk_display_set_surface_under_pointer (display, device, new_toplevel);
637 	}
638     }
639 
640   g_hash_table_insert (display->device_grabs, device, old_grabs);
641 }
642 
643 void
_gdk_display_update_last_event(GdkDisplay * display,GdkEvent * event)644 _gdk_display_update_last_event (GdkDisplay     *display,
645                                 GdkEvent       *event)
646 {
647   if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
648     display->last_event_time = gdk_event_get_time (event);
649 }
650 
651 void
_gdk_display_device_grab_update(GdkDisplay * display,GdkDevice * device,gulong current_serial)652 _gdk_display_device_grab_update (GdkDisplay *display,
653                                  GdkDevice  *device,
654                                  gulong      current_serial)
655 {
656   GdkDeviceGrabInfo *current_grab, *next_grab;
657   GList *grabs;
658   guint32 time;
659 
660   time = display->last_event_time;
661   grabs = g_hash_table_lookup (display->device_grabs, device);
662 
663   while (grabs != NULL)
664     {
665       current_grab = grabs->data;
666 
667       if (current_grab->serial_start > current_serial)
668 	return; /* Hasn't started yet */
669 
670       if (current_grab->serial_end > current_serial)
671 	{
672 	  /* This one hasn't ended yet.
673 	     its the currently active one or scheduled to be active */
674 
675 	  if (!current_grab->activated)
676             {
677               if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
678                 switch_to_pointer_grab (display, device, current_grab, NULL, time, current_serial);
679             }
680 
681 	  break;
682 	}
683 
684       next_grab = NULL;
685       if (grabs->next)
686 	{
687 	  /* This is the next active grab */
688 	  next_grab = grabs->next->data;
689 
690 	  if (next_grab->serial_start > current_serial)
691 	    next_grab = NULL; /* Actually its not yet active */
692 	}
693 
694       if ((next_grab == NULL && current_grab->implicit_ungrab) ||
695           (next_grab != NULL && current_grab->surface != next_grab->surface))
696         generate_grab_broken_event (display, GDK_SURFACE (current_grab->surface),
697                                     device,
698                                     current_grab->implicit,
699                                     next_grab? next_grab->surface : NULL);
700 
701       /* Remove old grab */
702       grabs = g_list_delete_link (grabs, grabs);
703       g_hash_table_insert (display->device_grabs, device, grabs);
704 
705       if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
706         switch_to_pointer_grab (display, device,
707                                 next_grab, current_grab,
708                                 time, current_serial);
709 
710       free_device_grab (current_grab);
711     }
712 }
713 
714 static GList *
grab_list_find(GList * grabs,gulong serial)715 grab_list_find (GList  *grabs,
716                 gulong  serial)
717 {
718   GdkDeviceGrabInfo *grab;
719 
720   while (grabs)
721     {
722       grab = grabs->data;
723 
724       if (serial >= grab->serial_start && serial < grab->serial_end)
725 	return grabs;
726 
727       grabs = grabs->next;
728     }
729 
730   return NULL;
731 }
732 
733 static GList *
find_device_grab(GdkDisplay * display,GdkDevice * device,gulong serial)734 find_device_grab (GdkDisplay *display,
735                    GdkDevice  *device,
736                    gulong      serial)
737 {
738   GList *l;
739 
740   l = g_hash_table_lookup (display->device_grabs, device);
741   return grab_list_find (l, serial);
742 }
743 
744 GdkDeviceGrabInfo *
_gdk_display_has_device_grab(GdkDisplay * display,GdkDevice * device,gulong serial)745 _gdk_display_has_device_grab (GdkDisplay *display,
746                               GdkDevice  *device,
747                               gulong      serial)
748 {
749   GList *l;
750 
751   l = find_device_grab (display, device, serial);
752   if (l)
753     return l->data;
754 
755   return NULL;
756 }
757 
758 /* Returns true if last grab was ended
759  * If if_child is non-NULL, end the grab only if the grabbed
760  * surface is the same as if_child or a descendant of it */
761 gboolean
_gdk_display_end_device_grab(GdkDisplay * display,GdkDevice * device,gulong serial,GdkSurface * if_child,gboolean implicit)762 _gdk_display_end_device_grab (GdkDisplay *display,
763                               GdkDevice  *device,
764                               gulong      serial,
765                               GdkSurface  *if_child,
766                               gboolean    implicit)
767 {
768   GdkDeviceGrabInfo *grab;
769   GList *l;
770 
771   l = find_device_grab (display, device, serial);
772 
773   if (l == NULL)
774     return FALSE;
775 
776   grab = l->data;
777   if (grab && (if_child == NULL || if_child == grab->surface))
778     {
779       grab->serial_end = serial;
780       grab->implicit_ungrab = implicit;
781       return l->next == NULL;
782     }
783 
784   return FALSE;
785 }
786 
787 GdkPointerSurfaceInfo *
_gdk_display_get_pointer_info(GdkDisplay * display,GdkDevice * device)788 _gdk_display_get_pointer_info (GdkDisplay *display,
789                                GdkDevice  *device)
790 {
791   GdkPointerSurfaceInfo *info;
792   GdkSeat *seat;
793 
794   if (device)
795     {
796       seat = gdk_device_get_seat (device);
797 
798       if (device == gdk_seat_get_keyboard (seat))
799         device = gdk_seat_get_pointer (seat);
800     }
801 
802   if (G_UNLIKELY (!device))
803     return NULL;
804 
805   info = g_hash_table_lookup (display->pointers_info, device);
806 
807   if (G_UNLIKELY (!info))
808     {
809       info = g_slice_new0 (GdkPointerSurfaceInfo);
810       g_hash_table_insert (display->pointers_info, device, info);
811     }
812 
813   return info;
814 }
815 
816 void
_gdk_display_pointer_info_foreach(GdkDisplay * display,GdkDisplayPointerInfoForeach func,gpointer user_data)817 _gdk_display_pointer_info_foreach (GdkDisplay                   *display,
818                                    GdkDisplayPointerInfoForeach  func,
819                                    gpointer                      user_data)
820 {
821   GHashTableIter iter;
822   gpointer key, value;
823 
824   g_hash_table_iter_init (&iter, display->pointers_info);
825 
826   while (g_hash_table_iter_next (&iter, &key, &value))
827     {
828       GdkPointerSurfaceInfo *info = value;
829       GdkDevice *device = key;
830 
831       (func) (display, device, info, user_data);
832     }
833 }
834 
835 /*< private >
836  * gdk_device_grab_info:
837  * @display: the display for which to get the grab information
838  * @device: device to get the grab information from
839  * @grab_surface: (out) (transfer none): location to store current grab surface
840  * @owner_events: (out): location to store boolean indicating whether
841  *   the @owner_events flag to gdk_device_grab() was %TRUE.
842  *
843  * Determines information about the current keyboard grab.
844  * This is not public API and must not be used by applications.
845  *
846  * Returns: %TRUE if this application currently has the
847  *  keyboard grabbed.
848  */
849 gboolean
gdk_device_grab_info(GdkDisplay * display,GdkDevice * device,GdkSurface ** grab_surface,gboolean * owner_events)850 gdk_device_grab_info (GdkDisplay  *display,
851                       GdkDevice   *device,
852                       GdkSurface  **grab_surface,
853                       gboolean    *owner_events)
854 {
855   GdkDeviceGrabInfo *info;
856 
857   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
858   g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
859 
860   info = _gdk_display_get_last_device_grab (display, device);
861 
862   if (info)
863     {
864       if (grab_surface)
865         *grab_surface = info->surface;
866       if (owner_events)
867         *owner_events = info->owner_events;
868 
869       return TRUE;
870     }
871   else
872     return FALSE;
873 }
874 
875 /**
876  * gdk_display_device_is_grabbed:
877  * @display: a `GdkDisplay`
878  * @device: a `GdkDevice`
879  *
880  * Returns %TRUE if there is an ongoing grab on @device for @display.
881  *
882  * Returns: %TRUE if there is a grab in effect for @device.
883  */
884 gboolean
gdk_display_device_is_grabbed(GdkDisplay * display,GdkDevice * device)885 gdk_display_device_is_grabbed (GdkDisplay *display,
886                                GdkDevice  *device)
887 {
888   GdkDeviceGrabInfo *info;
889 
890   g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
891   g_return_val_if_fail (GDK_IS_DEVICE (device), TRUE);
892 
893   /* What we're interested in is the steady state (ie last grab),
894      because we're interested e.g. if we grabbed so that we
895      can ungrab, even if our grab is not active just yet. */
896   info = _gdk_display_get_last_device_grab (display, device);
897 
898   return (info && !info->implicit);
899 }
900 
901 /**
902  * gdk_display_get_name:
903  * @display: a `GdkDisplay`
904  *
905  * Gets the name of the display.
906  *
907  * Returns: a string representing the display name. This string is owned
908  *   by GDK and should not be modified or freed.
909  */
910 const char *
gdk_display_get_name(GdkDisplay * display)911 gdk_display_get_name (GdkDisplay *display)
912 {
913   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
914 
915   return GDK_DISPLAY_GET_CLASS (display)->get_name (display);
916 }
917 
918 /**
919  * gdk_display_beep:
920  * @display: a `GdkDisplay`
921  *
922  * Emits a short beep on @display
923  */
924 void
gdk_display_beep(GdkDisplay * display)925 gdk_display_beep (GdkDisplay *display)
926 {
927   g_return_if_fail (GDK_IS_DISPLAY (display));
928 
929   GDK_DISPLAY_GET_CLASS (display)->beep (display);
930 }
931 
932 /**
933  * gdk_display_sync:
934  * @display: a `GdkDisplay`
935  *
936  * Flushes any requests queued for the windowing system and waits until all
937  * requests have been handled.
938  *
939  * This is often used for making sure that the display is synchronized
940  * with the current state of the program. Calling [method@Gdk.Display.sync]
941  * before [method@GdkX11.Display.error_trap_pop] makes sure that any errors
942  * generated from earlier requests are handled before the error trap is removed.
943  *
944  * This is most useful for X11. On windowing systems where requests are
945  * handled synchronously, this function will do nothing.
946  */
947 void
gdk_display_sync(GdkDisplay * display)948 gdk_display_sync (GdkDisplay *display)
949 {
950   g_return_if_fail (GDK_IS_DISPLAY (display));
951 
952   GDK_DISPLAY_GET_CLASS (display)->sync (display);
953 }
954 
955 /**
956  * gdk_display_flush:
957  * @display: a `GdkDisplay`
958  *
959  * Flushes any requests queued for the windowing system.
960  *
961  * This happens automatically when the main loop blocks waiting for new events,
962  * but if your application is drawing without returning control to the main loop,
963  * you may need to call this function explicitly. A common case where this function
964  * needs to be called is when an application is executing drawing commands
965  * from a thread other than the thread where the main loop is running.
966  *
967  * This is most useful for X11. On windowing systems where requests are
968  * handled synchronously, this function will do nothing.
969  */
970 void
gdk_display_flush(GdkDisplay * display)971 gdk_display_flush (GdkDisplay *display)
972 {
973   g_return_if_fail (GDK_IS_DISPLAY (display));
974 
975   GDK_DISPLAY_GET_CLASS (display)->flush (display);
976 }
977 
978 /**
979  * gdk_display_get_clipboard:
980  * @display: a `GdkDisplay`
981  *
982  * Gets the clipboard used for copy/paste operations.
983  *
984  * Returns: (transfer none): the display's clipboard
985  */
986 GdkClipboard *
gdk_display_get_clipboard(GdkDisplay * display)987 gdk_display_get_clipboard (GdkDisplay *display)
988 {
989   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
990 
991   if (display->clipboard == NULL)
992     display->clipboard = gdk_clipboard_new (display);
993 
994   return display->clipboard;
995 }
996 
997 /**
998  * gdk_display_get_primary_clipboard:
999  * @display: a `GdkDisplay`
1000  *
1001  * Gets the clipboard used for the primary selection.
1002  *
1003  * On backends where the primary clipboard is not supported natively,
1004  * GDK emulates this clipboard locally.
1005  *
1006  * Returns: (transfer none): the primary clipboard
1007  */
1008 GdkClipboard *
gdk_display_get_primary_clipboard(GdkDisplay * display)1009 gdk_display_get_primary_clipboard (GdkDisplay *display)
1010 {
1011   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1012 
1013   if (display->primary_clipboard == NULL)
1014     display->primary_clipboard = gdk_clipboard_new (display);
1015 
1016   return display->primary_clipboard;
1017 }
1018 
1019 /**
1020  * gdk_display_supports_input_shapes: (attributes org.gtk.Method.get_property=input-shapes)
1021  * @display: a `GdkDisplay`
1022  *
1023  * Returns %TRUE if the display supports input shapes.
1024  *
1025  * This means that [method@Gdk.Surface.set_input_region] can
1026  * be used to modify the input shape of surfaces on @display.
1027  *
1028  * On modern displays, this value is always %TRUE.
1029  *
1030  * Returns: %TRUE if surfaces with modified input shape are supported
1031  */
1032 gboolean
gdk_display_supports_input_shapes(GdkDisplay * display)1033 gdk_display_supports_input_shapes (GdkDisplay *display)
1034 {
1035   GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
1036 
1037   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1038 
1039   return priv->input_shapes;
1040 }
1041 
1042 void
gdk_display_set_input_shapes(GdkDisplay * display,gboolean input_shapes)1043 gdk_display_set_input_shapes (GdkDisplay *display,
1044                               gboolean    input_shapes)
1045 {
1046   GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
1047 
1048   g_return_if_fail (GDK_IS_DISPLAY (display));
1049 
1050   if (priv->input_shapes == input_shapes)
1051     return;
1052 
1053   priv->input_shapes = input_shapes;
1054 
1055   g_object_notify_by_pspec (G_OBJECT (display), props[PROP_INPUT_SHAPES]);
1056 }
1057 
1058 static GdkAppLaunchContext *
gdk_display_real_get_app_launch_context(GdkDisplay * display)1059 gdk_display_real_get_app_launch_context (GdkDisplay *display)
1060 {
1061   GdkAppLaunchContext *ctx;
1062 
1063   ctx = g_object_new (GDK_TYPE_APP_LAUNCH_CONTEXT,
1064                       "display", display,
1065                       NULL);
1066 
1067   return ctx;
1068 }
1069 
1070 /**
1071  * gdk_display_get_app_launch_context:
1072  * @display: a `GdkDisplay`
1073  *
1074  * Returns a `GdkAppLaunchContext` suitable for launching
1075  * applications on the given display.
1076  *
1077  * Returns: (transfer full): a new `GdkAppLaunchContext` for @display
1078  */
1079 GdkAppLaunchContext *
gdk_display_get_app_launch_context(GdkDisplay * display)1080 gdk_display_get_app_launch_context (GdkDisplay *display)
1081 {
1082   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1083 
1084   return GDK_DISPLAY_GET_CLASS (display)->get_app_launch_context (display);
1085 }
1086 
1087 /**
1088  * gdk_display_open:
1089  * @display_name: the name of the display to open
1090  *
1091  * Opens a display.
1092  *
1093  * If opening the display fails, `NULL` is returned.
1094  *
1095  * Returns: (nullable) (transfer none): a `GdkDisplay`
1096  */
1097 GdkDisplay *
gdk_display_open(const char * display_name)1098 gdk_display_open (const char *display_name)
1099 {
1100   return gdk_display_manager_open_display (gdk_display_manager_get (),
1101                                            display_name);
1102 }
1103 
1104 gulong
_gdk_display_get_next_serial(GdkDisplay * display)1105 _gdk_display_get_next_serial (GdkDisplay *display)
1106 {
1107   return GDK_DISPLAY_GET_CLASS (display)->get_next_serial (display);
1108 }
1109 
1110 /**
1111  * gdk_display_notify_startup_complete:
1112  * @display: a `GdkDisplay`
1113  * @startup_id: a startup-notification identifier, for which
1114  *   notification process should be completed
1115  *
1116  * Indicates to the GUI environment that the application has
1117  * finished loading, using a given identifier.
1118  *
1119  * GTK will call this function automatically for [class@Gtk.Window]
1120  * with custom startup-notification identifier unless
1121  * [method@Gtk.Window.set_auto_startup_notification]
1122  * is called to disable that feature.
1123  */
1124 void
gdk_display_notify_startup_complete(GdkDisplay * display,const char * startup_id)1125 gdk_display_notify_startup_complete (GdkDisplay  *display,
1126                                      const char *startup_id)
1127 {
1128   g_return_if_fail (GDK_IS_DISPLAY (display));
1129 
1130   GDK_DISPLAY_GET_CLASS (display)->notify_startup_complete (display, startup_id);
1131 }
1132 
1133 /**
1134  * gdk_display_get_startup_notification_id:
1135  * @display: a `GdkDisplay`
1136  *
1137  * Gets the startup notification ID for a Wayland display, or %NULL
1138  * if no ID has been defined.
1139  *
1140  * Returns: (nullable): the startup notification ID for @display
1141  */
1142 const char *
gdk_display_get_startup_notification_id(GdkDisplay * display)1143 gdk_display_get_startup_notification_id (GdkDisplay *display)
1144 {
1145   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1146 
1147   if (GDK_DISPLAY_GET_CLASS (display)->get_startup_notification_id == NULL)
1148     return NULL;
1149 
1150   return GDK_DISPLAY_GET_CLASS (display)->get_startup_notification_id (display);
1151 }
1152 
1153 void
_gdk_display_pause_events(GdkDisplay * display)1154 _gdk_display_pause_events (GdkDisplay *display)
1155 {
1156   display->event_pause_count++;
1157 }
1158 
1159 void
_gdk_display_unpause_events(GdkDisplay * display)1160 _gdk_display_unpause_events (GdkDisplay *display)
1161 {
1162   g_return_if_fail (display->event_pause_count > 0);
1163 
1164   display->event_pause_count--;
1165 }
1166 
1167 GdkSurface *
gdk_display_create_surface(GdkDisplay * display,GdkSurfaceType surface_type,GdkSurface * parent,int x,int y,int width,int height)1168 gdk_display_create_surface (GdkDisplay     *display,
1169                             GdkSurfaceType  surface_type,
1170                             GdkSurface     *parent,
1171                             int             x,
1172                             int             y,
1173                             int             width,
1174                             int             height)
1175 {
1176   return GDK_DISPLAY_GET_CLASS (display)->create_surface (display,
1177                                                           surface_type,
1178                                                           parent,
1179                                                           x, y, width, height);
1180 }
1181 
1182 /*< private >
1183  * gdk_display_get_keymap:
1184  * @display: the `GdkDisplay`
1185  *
1186  * Returns the `GdkKeymap` attached to @display.
1187  *
1188  * Returns: (transfer none): the `GdkKeymap` attached to @display.
1189  */
1190 GdkKeymap *
gdk_display_get_keymap(GdkDisplay * display)1191 gdk_display_get_keymap (GdkDisplay *display)
1192 {
1193   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1194 
1195   return GDK_DISPLAY_GET_CLASS (display)->get_keymap (display);
1196 }
1197 
1198 static void
gdk_display_init_gl(GdkDisplay * self)1199 gdk_display_init_gl (GdkDisplay *self)
1200 {
1201   GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
1202   GdkGLContext *context;
1203   gint64 before G_GNUC_UNUSED;
1204   gint64 before2 G_GNUC_UNUSED;
1205 
1206   before = GDK_PROFILER_CURRENT_TIME;
1207 
1208   if (GDK_DISPLAY_DEBUG_CHECK (self, GL_DISABLE))
1209     {
1210       g_set_error_literal (&priv->gl_error, GDK_GL_ERROR,
1211                            GDK_GL_ERROR_NOT_AVAILABLE,
1212                            _("GL support disabled via GDK_DEBUG"));
1213       return;
1214     }
1215 
1216   context = GDK_DISPLAY_GET_CLASS (self)->init_gl (self, &priv->gl_error);
1217   if (context == NULL)
1218     return;
1219 
1220   before2 = GDK_PROFILER_CURRENT_TIME;
1221 
1222   if (!gdk_gl_context_realize (context, &priv->gl_error))
1223     {
1224       g_object_unref (context);
1225       return;
1226     }
1227 
1228   gdk_profiler_end_mark (before2, "realize OpenGL context", NULL);
1229 
1230   /* Only assign after realize, so GdkGLContext::realize() can use
1231    * gdk_display_get_gl_context() == NULL to differentiate between
1232    * the display's context and any other context.
1233    */
1234   priv->gl_context = context;
1235 
1236   gdk_gl_backend_use (GDK_GL_CONTEXT_GET_CLASS (context)->backend_type);
1237 
1238   gdk_profiler_end_mark (before, "initialize OpenGL", NULL);
1239 }
1240 
1241 /**
1242  * gdk_display_prepare_gl:
1243  * @self: a `GdkDisplay`
1244  * @error: return location for a `GError`
1245  *
1246  * Checks that OpenGL is available for @self and ensures that it is
1247  * properly initialized.
1248  * When this fails, an @error will be set describing the error and this
1249  * function returns %FALSE.
1250  *
1251  * Note that even if this function succeeds, creating a `GdkGLContext`
1252  * may still fail.
1253  *
1254  * This function is idempotent. Calling it multiple times will just
1255  * return the same value or error.
1256  *
1257  * You never need to call this function, GDK will call it automatically
1258  * as needed. But you can use it as a check when setting up code that
1259  * might make use of OpenGL.
1260  *
1261  * Returns: %TRUE if the display supports OpenGL
1262  *
1263  * Since: 4.4
1264  **/
1265 gboolean
gdk_display_prepare_gl(GdkDisplay * self,GError ** error)1266 gdk_display_prepare_gl (GdkDisplay  *self,
1267                         GError     **error)
1268 {
1269   GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
1270 
1271   g_return_val_if_fail (GDK_IS_DISPLAY (self), FALSE);
1272   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1273 
1274   for (;;)
1275     {
1276       if (priv->gl_context)
1277         return TRUE;
1278 
1279       if (priv->gl_error != NULL)
1280         {
1281           if (error)
1282             *error = g_error_copy (priv->gl_error);
1283 
1284 
1285           return FALSE;
1286         }
1287 
1288       gdk_display_init_gl (self);
1289 
1290       /* try again */
1291     }
1292 }
1293 
1294 /*< private >
1295  * gdk_display_get_gl_context:
1296  * @self: the `GdkDisplay`
1297  *
1298  * Gets the GL context returned from [vfunc@Gdk.Display.init_gl]
1299  * previously.
1300  *
1301  * If that function has not been called yet or did fail, %NULL is
1302  * returned.
1303  * Call [method@Gdk.Display.prepare_gl] to avoid this.
1304  *
1305  * Returns: The `GdkGLContext`
1306  */
1307 GdkGLContext *
gdk_display_get_gl_context(GdkDisplay * self)1308 gdk_display_get_gl_context (GdkDisplay *self)
1309 {
1310   GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
1311 
1312   return priv->gl_context;
1313 }
1314 
1315 GdkDebugFlags
gdk_display_get_debug_flags(GdkDisplay * display)1316 gdk_display_get_debug_flags (GdkDisplay *display)
1317 {
1318   GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
1319 
1320   return display ? priv->debug_flags : _gdk_debug_flags;
1321 }
1322 
1323 void
gdk_display_set_debug_flags(GdkDisplay * display,GdkDebugFlags flags)1324 gdk_display_set_debug_flags (GdkDisplay    *display,
1325                              GdkDebugFlags  flags)
1326 {
1327   GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
1328 
1329   priv->debug_flags = flags;
1330 }
1331 
1332 /**
1333  * gdk_display_is_composited: (attributes org.gtk.Method.get_property=composited)
1334  * @display: a `GdkDisplay`
1335  *
1336  * Returns whether surfaces can reasonably be expected to have
1337  * their alpha channel drawn correctly on the screen.
1338  *
1339  * Check [method@Gdk.Display.is_rgba] for whether the display
1340  * supports an alpha channel.
1341  *
1342  * On X11 this function returns whether a compositing manager is
1343  * compositing on @display.
1344  *
1345  * On modern displays, this value is always %TRUE.
1346  *
1347  * Returns: Whether surfaces with RGBA visuals can reasonably
1348  *   be expected to have their alpha channels drawn correctly
1349  *   on the screen.
1350  */
1351 gboolean
gdk_display_is_composited(GdkDisplay * display)1352 gdk_display_is_composited (GdkDisplay *display)
1353 {
1354   GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
1355 
1356   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1357 
1358   return priv->composited;
1359 }
1360 
1361 void
gdk_display_set_composited(GdkDisplay * display,gboolean composited)1362 gdk_display_set_composited (GdkDisplay *display,
1363                             gboolean    composited)
1364 {
1365   GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
1366 
1367   g_return_if_fail (GDK_IS_DISPLAY (display));
1368 
1369   if (priv->composited == composited)
1370     return;
1371 
1372   priv->composited = composited;
1373 
1374   g_object_notify_by_pspec (G_OBJECT (display), props[PROP_COMPOSITED]);
1375 }
1376 
1377 /**
1378  * gdk_display_is_rgba: (attributes org.gtk.Method.get_property=rgba)
1379  * @display: a `GdkDisplay`
1380  *
1381  * Returns whether surfaces on this @display are created with an
1382  * alpha channel.
1383  *
1384  * Even if a %TRUE is returned, it is possible that the
1385  * surface’s alpha channel won’t be honored when displaying the
1386  * surface on the screen: in particular, for X an appropriate
1387  * windowing manager and compositing manager must be running to
1388  * provide appropriate display. Use [method@Gdk.Display.is_composited]
1389  * to check if that is the case.
1390  *
1391  * On modern displays, this value is always %TRUE.
1392  *
1393  * Returns: %TRUE if surfaces are created with an alpha channel or
1394  *   %FALSE if the display does not support this functionality.
1395  */
1396 gboolean
gdk_display_is_rgba(GdkDisplay * display)1397 gdk_display_is_rgba (GdkDisplay *display)
1398 {
1399   GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
1400 
1401   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1402 
1403   return priv->rgba;
1404 }
1405 
1406 void
gdk_display_set_rgba(GdkDisplay * display,gboolean rgba)1407 gdk_display_set_rgba (GdkDisplay *display,
1408                       gboolean    rgba)
1409 {
1410   GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
1411 
1412   g_return_if_fail (GDK_IS_DISPLAY (display));
1413 
1414   if (priv->rgba == rgba)
1415     return;
1416 
1417   priv->rgba = rgba;
1418 
1419   g_object_notify_by_pspec (G_OBJECT (display), props[PROP_RGBA]);
1420 }
1421 
1422 static void
device_removed_cb(GdkSeat * seat,GdkDevice * device,GdkDisplay * display)1423 device_removed_cb (GdkSeat    *seat,
1424                    GdkDevice  *device,
1425                    GdkDisplay *display)
1426 {
1427   g_hash_table_remove (display->device_grabs, device);
1428   g_hash_table_remove (display->pointers_info, device);
1429 
1430   /* FIXME: change core pointer and remove from device list */
1431 }
1432 
1433 void
gdk_display_add_seat(GdkDisplay * display,GdkSeat * seat)1434 gdk_display_add_seat (GdkDisplay *display,
1435                       GdkSeat    *seat)
1436 {
1437   g_return_if_fail (GDK_IS_DISPLAY (display));
1438   g_return_if_fail (GDK_IS_SEAT (seat));
1439 
1440   display->seats = g_list_append (display->seats, g_object_ref (seat));
1441   g_signal_emit (display, signals[SEAT_ADDED], 0, seat);
1442 
1443   g_signal_connect (seat, "device-removed", G_CALLBACK (device_removed_cb), display);
1444 }
1445 
1446 void
gdk_display_remove_seat(GdkDisplay * display,GdkSeat * seat)1447 gdk_display_remove_seat (GdkDisplay *display,
1448                          GdkSeat    *seat)
1449 {
1450   GList *link;
1451 
1452   g_return_if_fail (GDK_IS_DISPLAY (display));
1453   g_return_if_fail (GDK_IS_SEAT (seat));
1454 
1455   g_signal_handlers_disconnect_by_func (seat, G_CALLBACK (device_removed_cb), display);
1456 
1457   link = g_list_find (display->seats, seat);
1458 
1459   if (link)
1460     {
1461       display->seats = g_list_remove_link (display->seats, link);
1462       g_signal_emit (display, signals[SEAT_REMOVED], 0, seat);
1463       g_object_unref (link->data);
1464       g_list_free (link);
1465     }
1466 }
1467 
1468 /**
1469  * gdk_display_get_default_seat:
1470  * @display: a `GdkDisplay`
1471  *
1472  * Returns the default `GdkSeat` for this display.
1473  *
1474  * Note that a display may not have a seat. In this case,
1475  * this function will return %NULL.
1476  *
1477  * Returns: (transfer none) (nullable): the default seat.
1478  **/
1479 GdkSeat *
gdk_display_get_default_seat(GdkDisplay * display)1480 gdk_display_get_default_seat (GdkDisplay *display)
1481 {
1482   GdkDisplayClass *display_class;
1483 
1484   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1485 
1486   display_class = GDK_DISPLAY_GET_CLASS (display);
1487 
1488   return display_class->get_default_seat (display);
1489 }
1490 
1491 /**
1492  * gdk_display_list_seats:
1493  * @display: a `GdkDisplay`
1494  *
1495  * Returns the list of seats known to @display.
1496  *
1497  * Returns: (transfer container) (element-type GdkSeat): the
1498  *   list of seats known to the `GdkDisplay`
1499  */
1500 GList *
gdk_display_list_seats(GdkDisplay * display)1501 gdk_display_list_seats (GdkDisplay *display)
1502 {
1503   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1504 
1505   return g_list_copy (display->seats);
1506 }
1507 
1508 /**
1509  * gdk_display_get_monitors:
1510  * @self: a `GdkDisplay`
1511  *
1512  * Gets the list of monitors associated with this display.
1513  *
1514  * Subsequent calls to this function will always return the
1515  * same list for the same display.
1516  *
1517  * You can listen to the GListModel::items-changed signal on
1518  * this list to monitor changes to the monitor of this display.
1519  *
1520  * Returns: (transfer none): a `GListModel` of `GdkMonitor`
1521  */
1522 GListModel *
gdk_display_get_monitors(GdkDisplay * self)1523 gdk_display_get_monitors (GdkDisplay *self)
1524 {
1525   g_return_val_if_fail (GDK_IS_DISPLAY (self), NULL);
1526 
1527   return GDK_DISPLAY_GET_CLASS (self)->get_monitors (self);
1528 }
1529 
1530 /**
1531  * gdk_display_get_monitor_at_surface:
1532  * @display: a `GdkDisplay`
1533  * @surface: a `GdkSurface`
1534  *
1535  * Gets the monitor in which the largest area of @surface
1536  * resides.
1537  *
1538  * Returns a monitor close to @surface if it is outside
1539  * of all monitors.
1540  *
1541  * Returns: (transfer none): the monitor with the largest
1542  *   overlap with @surface
1543  */
1544 GdkMonitor *
gdk_display_get_monitor_at_surface(GdkDisplay * display,GdkSurface * surface)1545 gdk_display_get_monitor_at_surface (GdkDisplay *display,
1546                                    GdkSurface  *surface)
1547 {
1548   GdkRectangle win;
1549   GListModel *monitors;
1550   guint i;
1551   int area = 0;
1552   GdkMonitor *best = NULL;
1553   GdkDisplayClass *class;
1554 
1555   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1556 
1557   class = GDK_DISPLAY_GET_CLASS (display);
1558   if (class->get_monitor_at_surface)
1559     {
1560       best = class->get_monitor_at_surface (display, surface);
1561 
1562       if (best)
1563         return best;
1564     }
1565 
1566   /* the fallback implementation requires global coordinates */
1567   gdk_surface_get_geometry (surface, &win.x, &win.y, &win.width, &win.height);
1568   gdk_surface_get_origin (surface, &win.x, &win.y);
1569 
1570   monitors = gdk_display_get_monitors (display);
1571   for (i = 0; i < g_list_model_get_n_items (monitors); i++)
1572     {
1573       GdkMonitor *monitor;
1574       GdkRectangle mon, intersect;
1575       int overlap;
1576 
1577       monitor = g_list_model_get_item (monitors, i);
1578       gdk_monitor_get_geometry (monitor, &mon);
1579       gdk_rectangle_intersect (&win, &mon, &intersect);
1580       overlap = intersect.width *intersect.height;
1581       if (overlap > area)
1582         {
1583           area = overlap;
1584           best = monitor;
1585         }
1586       g_object_unref (monitor);
1587     }
1588 
1589   return best;
1590 }
1591 
1592 void
gdk_display_emit_opened(GdkDisplay * display)1593 gdk_display_emit_opened (GdkDisplay *display)
1594 {
1595   g_signal_emit (display, signals[OPENED], 0);
1596 }
1597 
1598 /**
1599  * gdk_display_get_setting:
1600  * @display: a `GdkDisplay`
1601  * @name: the name of the setting
1602  * @value: location to store the value of the setting
1603  *
1604  * Retrieves a desktop-wide setting such as double-click time
1605  * for the @display.
1606  *
1607  * Returns: %TRUE if the setting existed and a value was stored
1608  *   in @value, %FALSE otherwise
1609  */
1610 gboolean
gdk_display_get_setting(GdkDisplay * display,const char * name,GValue * value)1611 gdk_display_get_setting (GdkDisplay *display,
1612                          const char *name,
1613                          GValue     *value)
1614 {
1615   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1616   g_return_val_if_fail (name != NULL, FALSE);
1617   g_return_val_if_fail (value != NULL, FALSE);
1618 
1619   return GDK_DISPLAY_GET_CLASS (display)->get_setting (display, name, value);
1620 }
1621 
1622 void
gdk_display_setting_changed(GdkDisplay * display,const char * name)1623 gdk_display_setting_changed (GdkDisplay       *display,
1624                              const char       *name)
1625 {
1626   g_signal_emit (display, signals[SETTING_CHANGED], 0, name);
1627 }
1628 
1629 void
gdk_display_set_double_click_time(GdkDisplay * display,guint msec)1630 gdk_display_set_double_click_time (GdkDisplay *display,
1631                                    guint       msec)
1632 {
1633   display->double_click_time = msec;
1634 }
1635 
1636 void
gdk_display_set_double_click_distance(GdkDisplay * display,guint distance)1637 gdk_display_set_double_click_distance (GdkDisplay *display,
1638                                        guint       distance)
1639 {
1640   display->double_click_distance = distance;
1641 }
1642 
1643 void
gdk_display_set_cursor_theme(GdkDisplay * display,const char * name,int size)1644 gdk_display_set_cursor_theme (GdkDisplay *display,
1645                               const char *name,
1646                               int         size)
1647 {
1648   if (GDK_DISPLAY_GET_CLASS (display)->set_cursor_theme)
1649     GDK_DISPLAY_GET_CLASS (display)->set_cursor_theme (display, name, size);
1650 }
1651 
1652 /**
1653  * gdk_display_map_keyval:
1654  * @display: a `GdkDisplay`
1655  * @keyval: a keyval, such as %GDK_KEY_a, %GDK_KEY_Up, %GDK_KEY_Return, etc.
1656  * @keys: (out) (array length=n_keys) (transfer full): return location
1657  *   for an array of `GdkKeymapKey`
1658  * @n_keys: return location for number of elements in returned array
1659  *
1660  * Obtains a list of keycode/group/level combinations that will
1661  * generate @keyval.
1662  *
1663  * Groups and levels are two kinds of keyboard mode; in general, the level
1664  * determines whether the top or bottom symbol on a key is used, and the
1665  * group determines whether the left or right symbol is used.
1666  *
1667  * On US keyboards, the shift key changes the keyboard level, and there
1668  * are no groups. A group switch key might convert a keyboard between
1669  * Hebrew to English modes, for example.
1670  *
1671  * `GdkEventKey` contains a %group field that indicates the active
1672  * keyboard group. The level is computed from the modifier mask.
1673  *
1674  * The returned array should be freed with g_free().
1675  *
1676  * Returns: %TRUE if keys were found and returned
1677  */
1678 gboolean
gdk_display_map_keyval(GdkDisplay * display,guint keyval,GdkKeymapKey ** keys,int * n_keys)1679 gdk_display_map_keyval (GdkDisplay    *display,
1680                         guint          keyval,
1681                         GdkKeymapKey **keys,
1682                         int           *n_keys)
1683 {
1684   return gdk_keymap_get_entries_for_keyval (gdk_display_get_keymap (display),
1685                                             keyval,
1686                                             keys,
1687                                             n_keys);
1688 }
1689 
1690 /**
1691  * gdk_display_map_keycode:
1692  * @display: a `GdkDisplay`
1693  * @keycode: a keycode
1694  * @keys: (out) (array length=n_entries) (transfer full) (optional): return
1695  *   location for array of `GdkKeymapKey`
1696  * @keyvals: (out) (array length=n_entries) (transfer full) (optional): return
1697  *   location for array of keyvals
1698  * @n_entries: length of @keys and @keyvals
1699  *
1700  * Returns the keyvals bound to @keycode.
1701  *
1702  * The Nth `GdkKeymapKey` in @keys is bound to the Nth keyval in @keyvals.
1703  *
1704  * When a keycode is pressed by the user, the keyval from
1705  * this list of entries is selected by considering the effective
1706  * keyboard group and level.
1707  *
1708  * Free the returned arrays with g_free().
1709  *
1710  * Returns: %TRUE if there were any entries
1711  */
1712 gboolean
gdk_display_map_keycode(GdkDisplay * display,guint keycode,GdkKeymapKey ** keys,guint ** keyvals,int * n_entries)1713 gdk_display_map_keycode (GdkDisplay    *display,
1714                          guint          keycode,
1715                          GdkKeymapKey **keys,
1716                          guint        **keyvals,
1717                          int           *n_entries)
1718 {
1719   return gdk_keymap_get_entries_for_keycode (gdk_display_get_keymap (display),
1720                                              keycode,
1721                                              keys,
1722                                              keyvals,
1723                                              n_entries);
1724 }
1725 
1726 /**
1727  * gdk_display_translate_key:
1728  * @display: a `GdkDisplay`
1729  * @keycode: a keycode
1730  * @state: a modifier state
1731  * @group: active keyboard group
1732  * @keyval: (out) (optional): return location for keyval
1733  * @effective_group: (out) (optional): return location for effective group
1734  * @level: (out) (optional): return location for level
1735  * @consumed: (out) (optional): return location for modifiers that were used
1736  *   to determine the group or level
1737  *
1738  * Translates the contents of a `GdkEventKey` into a keyval, effective group,
1739  * and level.
1740  *
1741  * Modifiers that affected the translation and are thus unavailable for
1742  * application use are returned in @consumed_modifiers.
1743  *
1744  * The @effective_group is the group that was actually used for the
1745  * translation; some keys such as Enter are not affected by the active
1746  * keyboard group. The @level is derived from @state.
1747  *
1748  * @consumed_modifiers gives modifiers that should be masked out
1749  * from @state when comparing this key press to a keyboard shortcut.
1750  * For instance, on a US keyboard, the `plus` symbol is shifted, so
1751  * when comparing a key press to a `<Control>plus` accelerator `<Shift>`
1752  * should be masked out.
1753  *
1754  * This function should rarely be needed, since `GdkEventKey` already
1755  * contains the translated keyval. It is exported for the benefit of
1756  * virtualized test environments.
1757  *
1758  * Returns: %TRUE if there was a keyval bound to keycode/state/group.
1759  */
1760 gboolean
gdk_display_translate_key(GdkDisplay * display,guint keycode,GdkModifierType state,int group,guint * keyval,int * effective_group,int * level,GdkModifierType * consumed)1761 gdk_display_translate_key (GdkDisplay      *display,
1762                            guint            keycode,
1763                            GdkModifierType  state,
1764                            int              group,
1765                            guint           *keyval,
1766                            int             *effective_group,
1767                            int             *level,
1768                            GdkModifierType *consumed)
1769 {
1770   return gdk_keymap_translate_keyboard_state (gdk_display_get_keymap (display),
1771                                               keycode, state, group,
1772                                               keyval,
1773                                               effective_group,
1774                                               level,
1775                                               consumed);
1776 }
1777