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