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 "gdk-private.h"
28
29#include "gdkdeviceprivate.h"
30#include "gdkdisplaymanagerprivate.h"
31#include "gdkevents.h"
32#include "gdkwindowimpl.h"
33#include "gdkinternals.h"
34#include "gdkmarshalers.h"
35#include "gdkscreen.h"
36#include "gdkmonitorprivate.h"
37
38#include <math.h>
39#include <glib.h>
40
41/* for the use of round() */
42#include "fallback-c89.c"
43
44/**
45 * SECTION:gdkdisplay
46 * @Short_description: Controls a set of GdkScreens and their associated input devices
47 * @Title: GdkDisplay
48 *
49 * #GdkDisplay objects purpose are two fold:
50 *
51 * - To manage and provide information about input devices (pointers and keyboards)
52 *
53 * - To manage and provide information about the available #GdkScreens
54 *
55 * GdkDisplay objects are the GDK representation of an X Display,
56 * which can be described as a workstation consisting of
57 * a keyboard, a pointing device (such as a mouse) and one or more
58 * screens.
59 * It is used to open and keep track of various GdkScreen objects
60 * currently instantiated by the application. It is also used to
61 * access the keyboard(s) and mouse pointer(s) of the display.
62 *
63 * Most of the input device handling has been factored out into
64 * the separate #GdkDeviceManager object. Every display has a
65 * device manager, which you can obtain using
66 * gdk_display_get_device_manager().
67 */
68
69
70enum {
71 OPENED,
72 CLOSED,
73 SEAT_ADDED,
74 SEAT_REMOVED,
75 MONITOR_ADDED,
76 MONITOR_REMOVED,
77 LAST_SIGNAL
78};
79
80static void gdk_display_dispose (GObject *object);
81static void gdk_display_finalize (GObject *object);
82static void gdk_display_put_event_nocopy (GdkDisplay *display,
83 GdkEvent *event);
84
85
86static GdkAppLaunchContext *gdk_display_real_get_app_launch_context (GdkDisplay *display);
87
88static guint signals[LAST_SIGNAL] = { 0 };
89
90G_DEFINE_TYPE (GdkDisplay, gdk_display, G_TYPE_OBJECT)
91
92static void
93gdk_display_real_make_default (GdkDisplay *display)
94{
95}
96
97static void
98device_removed_cb (GdkDeviceManager *device_manager,
99 GdkDevice *device,
100 GdkDisplay *display)
101{
102 g_hash_table_remove (display->multiple_click_info, device);
103 g_hash_table_remove (display->device_grabs, device);
104 g_hash_table_remove (display->pointers_info, device);
105
106 /* FIXME: change core pointer and remove from device list */
107}
108
109static void
110gdk_display_real_opened (GdkDisplay *display)
111{
112 GdkDeviceManager *device_manager;
113
114 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
115 device_manager = gdk_display_get_device_manager (display);
116 G_GNUC_END_IGNORE_DEPRECATIONS;
117
118 g_signal_connect (device_manager, "device-removed",
119 G_CALLBACK (device_removed_cb), display);
120
121 _gdk_display_manager_add_display (gdk_display_manager_get (), display);
122}
123
124static void
125gdk_display_real_event_data_copy (GdkDisplay *display,
126 const GdkEvent *src,
127 GdkEvent *dst)
128{
129}
130
131static void
132gdk_display_real_event_data_free (GdkDisplay *display,
133 GdkEvent *dst)
134{
135}
136
137static GdkSeat *
138gdk_display_real_get_default_seat (GdkDisplay *display)
139{
140 if (!display->seats)
141 return NULL;
142
143 return display->seats->data;
144}
145
146static void
147gdk_display_class_init (GdkDisplayClass *class)
148{
149 GObjectClass *object_class = G_OBJECT_CLASS (class);
150
151 object_class->finalize = gdk_display_finalize;
152 object_class->dispose = gdk_display_dispose;
153
154 class->get_app_launch_context = gdk_display_real_get_app_launch_context;
155 class->window_type = GDK_TYPE_WINDOW;
156
157 class->opened = gdk_display_real_opened;
158 class->make_default = gdk_display_real_make_default;
159 class->event_data_copy = gdk_display_real_event_data_copy;
160 class->event_data_free = gdk_display_real_event_data_free;
161 class->get_default_seat = gdk_display_real_get_default_seat;
162
163 /**
164 * GdkDisplay::opened:
165 * @display: the object on which the signal is emitted
166 *
167 * The ::opened signal is emitted when the connection to the windowing
168 * system for @display is opened.
169 */
170 signals[OPENED] =
171 g_signal_new (g_intern_static_string ("opened"),
172 G_OBJECT_CLASS_TYPE (object_class),
173 G_SIGNAL_RUN_LAST,
174 G_STRUCT_OFFSET (GdkDisplayClass, opened),
175 NULL, NULL,
176 g_cclosure_marshal_VOID__VOID,
177 G_TYPE_NONE, 0);
178
179 /**
180 * GdkDisplay::closed:
181 * @display: the object on which the signal is emitted
182 * @is_error: %TRUE if the display was closed due to an error
183 *
184 * The ::closed signal is emitted when the connection to the windowing
185 * system for @display is closed.
186 *
187 * Since: 2.2
188 */
189 signals[CLOSED] =
190 g_signal_new (g_intern_static_string ("closed"),
191 G_OBJECT_CLASS_TYPE (object_class),
192 G_SIGNAL_RUN_LAST,
193 G_STRUCT_OFFSET (GdkDisplayClass, closed),
194 NULL, NULL,
195 _gdk_marshal_VOID__BOOLEAN,
196 G_TYPE_NONE,
197 1,
198 G_TYPE_BOOLEAN);
199
200 /**
201 * GdkDisplay::seat-added:
202 * @display: the object on which the signal is emitted
203 * @seat: the seat that was just added
204 *
205 * The ::seat-added signal is emitted whenever a new seat is made
206 * known to the windowing system.
207 *
208 * Since: 3.20
209 */
210 signals[SEAT_ADDED] =
211 g_signal_new (g_intern_static_string ("seat-added"),
212 G_OBJECT_CLASS_TYPE (object_class),
213 G_SIGNAL_RUN_LAST,
214 0, NULL, NULL,
215 g_cclosure_marshal_VOID__OBJECT,
216 G_TYPE_NONE, 1, GDK_TYPE_SEAT);
217
218 /**
219 * GdkDisplay::seat-removed:
220 * @display: the object on which the signal is emitted
221 * @seat: the seat that was just removed
222 *
223 * The ::seat-removed signal is emitted whenever a seat is removed
224 * by the windowing system.
225 *
226 * Since: 3.20
227 */
228 signals[SEAT_REMOVED] =
229 g_signal_new (g_intern_static_string ("seat-removed"),
230 G_OBJECT_CLASS_TYPE (object_class),
231 G_SIGNAL_RUN_LAST,
232 0, NULL, NULL,
233 g_cclosure_marshal_VOID__OBJECT,
234 G_TYPE_NONE, 1, GDK_TYPE_SEAT);
235
236 /**
237 * GdkDisplay::monitor-added:
238 * @display: the objedct on which the signal is emitted
239 * @monitor: the monitor that was just added
240 *
241 * The ::monitor-added signal is emitted whenever a monitor is
242 * added.
243 *
244 * Since: 3.22
245 */
246 signals[MONITOR_ADDED] =
247 g_signal_new (g_intern_static_string ("monitor-added"),
248 G_OBJECT_CLASS_TYPE (object_class),
249 G_SIGNAL_RUN_LAST,
250 0, NULL, NULL,
251 g_cclosure_marshal_VOID__OBJECT,
252 G_TYPE_NONE, 1, GDK_TYPE_MONITOR);
253
254 /**
255 * GdkDisplay::monitor-removed:
256 * @display: the object on which the signal is emitted
257 * @monitor: the monitor that was just removed
258 *
259 * The ::monitor-removed signal is emitted whenever a monitor is
260 * removed.
261 *
262 * Since: 3.22
263 */
264 signals[MONITOR_REMOVED] =
265 g_signal_new (g_intern_static_string ("monitor-removed"),
266 G_OBJECT_CLASS_TYPE (object_class),
267 G_SIGNAL_RUN_LAST,
268 0, NULL, NULL,
269 g_cclosure_marshal_VOID__OBJECT,
270 G_TYPE_NONE, 1, GDK_TYPE_MONITOR);
271}
272
273static void
274free_pointer_info (GdkPointerWindowInfo *info)
275{
276 if (info->toplevel_under_pointer)
277 g_object_unref (info->toplevel_under_pointer);
278 g_slice_free (GdkPointerWindowInfo, info);
279}
280
281static void
282free_device_grab (GdkDeviceGrabInfo *info)
283{
284 g_object_unref (info->window);
285 g_object_unref (info->native_window);
286 g_free (info);
287}
288
289static gboolean
290free_device_grabs_foreach (gpointer key,
291 gpointer value,
292 gpointer user_data)
293{
294 GList *list = value;
295
296 g_list_free_full (list, (GDestroyNotify) free_device_grab);
297
298 return TRUE;
299}
300
301static void
302gdk_display_init (GdkDisplay *display)
303{
304 display->double_click_time = 250;
305 display->double_click_distance = 5;
306
307 display->touch_implicit_grabs = g_array_new (FALSE, FALSE, sizeof (GdkTouchGrabInfo));
308 display->device_grabs = g_hash_table_new (NULL, NULL);
309 display->motion_hint_info = g_hash_table_new_full (NULL, NULL, NULL,
310 (GDestroyNotify) g_free);
311
312 display->pointers_info = g_hash_table_new_full (NULL, NULL, NULL,
313 (GDestroyNotify) free_pointer_info);
314
315 display->multiple_click_info = g_hash_table_new_full (NULL, NULL, NULL,
316 (GDestroyNotify) g_free);
317
318 display->rendering_mode = _gdk_rendering_mode;
319}
320
321static void
322gdk_display_dispose (GObject *object)
323{
324 GdkDisplay *display = GDK_DISPLAY (object);
325 GdkDeviceManager *device_manager;
326
327 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
328 device_manager = gdk_display_get_device_manager (GDK_DISPLAY (object));
329 G_GNUC_END_IGNORE_DEPRECATIONS;
330
331 _gdk_display_manager_remove_display (gdk_display_manager_get (), display);
332
333 g_list_free_full (display->queued_events, (GDestroyNotify) gdk_event_free);
334 display->queued_events = NULL;
335 display->queued_tail = NULL;
336
337 g_list_foreach (display->input_devices, (GFunc) g_object_run_dispose, NULL);
338
339 if (device_manager)
340 {
341 /* this is to make it drop devices which may require using the X
342 * display and therefore can't be cleaned up in finalize.
343 * It will also disconnect device_removed_cb
344 */
345 g_object_run_dispose (G_OBJECT (display->device_manager));
346 }
347
348 G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object);
349}
350
351static void
352gdk_display_finalize (GObject *object)
353{
354 GdkDisplay *display = GDK_DISPLAY (object);
355
356 g_hash_table_foreach_remove (display->device_grabs,
357 free_device_grabs_foreach,
358 NULL);
359 g_hash_table_destroy (display->device_grabs);
360
361 g_array_free (display->touch_implicit_grabs, TRUE);
362
363 g_hash_table_destroy (display->motion_hint_info);
364 g_hash_table_destroy (display->pointers_info);
365 g_hash_table_destroy (display->multiple_click_info);
366
367 g_list_free_full (display->input_devices, g_object_unref);
368
369 if (display->device_manager)
370 g_object_unref (display->device_manager);
371
372 G_OBJECT_CLASS (gdk_display_parent_class)->finalize (object);
373}
374
375/**
376 * gdk_display_close:
377 * @display: a #GdkDisplay
378 *
379 * Closes the connection to the windowing system for the given display,
380 * and cleans up associated resources.
381 *
382 * Since: 2.2
383 */
384void
385gdk_display_close (GdkDisplay *display)
386{
387 g_return_if_fail (GDK_IS_DISPLAY (display));
388
389 if (!display->closed)
390 {
391 display->closed = TRUE;
392
393 g_signal_emit (display, signals[CLOSED], 0, FALSE);
394 g_object_run_dispose (G_OBJECT (display));
395
396 g_object_unref (display);
397 }
398}
399
400/**
401 * gdk_display_is_closed:
402 * @display: a #GdkDisplay
403 *
404 * Finds out if the display has been closed.
405 *
406 * Returns: %TRUE if the display is closed.
407 *
408 * Since: 2.22
409 */
410gboolean
411gdk_display_is_closed (GdkDisplay *display)
412{
413 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
414
415 return display->closed;
416}
417
418/**
419 * gdk_display_get_event:
420 * @display: a #GdkDisplay
421 *
422 * Gets the next #GdkEvent to be processed for @display, fetching events from the
423 * windowing system if necessary.
424 *
425 * Returns: (nullable): the next #GdkEvent to be processed, or %NULL
426 * if no events are pending. The returned #GdkEvent should be freed
427 * with gdk_event_free().
428 *
429 * Since: 2.2
430 **/
431GdkEvent*
432gdk_display_get_event (GdkDisplay *display)
433{
434 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
435
436 if (display->event_pause_count == 0)
437 GDK_DISPLAY_GET_CLASS (display)->queue_events (display);
438
439 return _gdk_event_unqueue (display);
440}
441
442/**
443 * gdk_display_peek_event:
444 * @display: a #GdkDisplay
445 *
446 * Gets a copy of the first #GdkEvent in the @display’s event queue, without
447 * removing the event from the queue. (Note that this function will
448 * not get more events from the windowing system. It only checks the events
449 * that have already been moved to the GDK event queue.)
450 *
451 * Returns: (nullable): a copy of the first #GdkEvent on the event
452 * queue, or %NULL if no events are in the queue. The returned
453 * #GdkEvent should be freed with gdk_event_free().
454 *
455 * Since: 2.2
456 **/
457GdkEvent*
458gdk_display_peek_event (GdkDisplay *display)
459{
460 GList *tmp_list;
461
462 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
463
464 tmp_list = _gdk_event_queue_find_first (display);
465
466 if (tmp_list)
467 return gdk_event_copy (tmp_list->data);
468 else
469 return NULL;
470}
471
472static void
473gdk_display_put_event_nocopy (GdkDisplay *display,
474 GdkEvent *event)
475{
476 _gdk_event_queue_append (display, event);
477 /* If the main loop is blocking in a different thread, wake it up */
478 g_main_context_wakeup (NULL);
479}
480
481/**
482 * gdk_display_put_event:
483 * @display: a #GdkDisplay
484 * @event: a #GdkEvent.
485 *
486 * Appends a copy of the given event onto the front of the event
487 * queue for @display.
488 *
489 * Since: 2.2
490 **/
491void
492gdk_display_put_event (GdkDisplay *display,
493 const GdkEvent *event)
494{
495 g_return_if_fail (GDK_IS_DISPLAY (display));
496 g_return_if_fail (event != NULL);
497
498 gdk_display_put_event_nocopy (display, gdk_event_copy (event));
499}
500
501/**
502 * gdk_display_pointer_ungrab:
503 * @display: a #GdkDisplay.
504 * @time_: a timestap (e.g. %GDK_CURRENT_TIME).
505 *
506 * Release any pointer grab.
507 *
508 * Since: 2.2
509 *
510 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
511 * instead.
512 */
513void
514gdk_display_pointer_ungrab (GdkDisplay *display,
515 guint32 time_)
516{
517 GList *seats, *s;
518 GdkDevice *device;
519
520 g_return_if_fail (GDK_IS_DISPLAY (display));
521
522 seats = gdk_display_list_seats (display);
523
524 for (s = seats; s; s = s->next)
525 {
526 device = gdk_seat_get_pointer (s->data);
527 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
528 gdk_device_ungrab (device, time_);
529 G_GNUC_END_IGNORE_DEPRECATIONS;
530 }
531
532 g_list_free (seats);
533}
534
535/**
536 * gdk_display_keyboard_ungrab:
537 * @display: a #GdkDisplay.
538 * @time_: a timestap (e.g #GDK_CURRENT_TIME).
539 *
540 * Release any keyboard grab
541 *
542 * Since: 2.2
543 *
544 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
545 * instead.
546 */
547void
548gdk_display_keyboard_ungrab (GdkDisplay *display,
549 guint32 time)
550{
551 GList *seats, *s;
552 GdkDevice *device;
553
554 g_return_if_fail (GDK_IS_DISPLAY (display));
555
556 seats = gdk_display_list_seats (display);
557
558 for (s = seats; s; s = s->next)
559 {
560 device = gdk_seat_get_keyboard (s->data);
561 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
562 gdk_device_ungrab (device, time);
563 G_GNUC_END_IGNORE_DEPRECATIONS;
564 }
565
566 g_list_free (seats);
567}
568
569/**
570 * gdk_beep:
571 *
572 * Emits a short beep on the default display.
573 **/
574void
575gdk_beep (void)
576{
577 gdk_display_beep (gdk_display_get_default ());
578}
579
580/**
581 * gdk_flush:
582 *
583 * Flushes the output buffers of all display connections and waits
584 * until all requests have been processed.
585 * This is rarely needed by applications.
586 */
587void
588gdk_flush (void)
589{
590 GSList *list, *l;
591
592 list = gdk_display_manager_list_displays (gdk_display_manager_get ());
593 for (l = list; l; l = l->next)
594 {
595 GdkDisplay *display = l->data;
596
597 GDK_DISPLAY_GET_CLASS (display)->sync (display);
598 }
599
600 g_slist_free (list);
601}
602
603void
604_gdk_display_enable_motion_hints (GdkDisplay *display,
605 GdkDevice *device)
606{
607 gulong *device_serial, serial;
608
609 device_serial = g_hash_table_lookup (display->motion_hint_info, device);
610
611 if (!device_serial)
612 {
613 device_serial = g_new0 (gulong, 1);
614 *device_serial = G_MAXULONG;
615 g_hash_table_insert (display->motion_hint_info, device, device_serial);
616 }
617
618 if (*device_serial != 0)
619 {
620 serial = _gdk_display_get_next_serial (display);
621 /* We might not actually generate the next request, so
622 make sure this triggers always, this may cause it to
623 trigger slightly too early, but this is just a hint
624 anyway. */
625 if (serial > 0)
626 serial--;
627 if (serial < *device_serial)
628 *device_serial = serial;
629 }
630}
631
632/**
633 * gdk_display_get_pointer:
634 * @display: a #GdkDisplay
635 * @screen: (out) (allow-none) (transfer none): location to store the screen that the
636 * cursor is on, or %NULL.
637 * @x: (out) (allow-none): location to store root window X coordinate of pointer, or %NULL.
638 * @y: (out) (allow-none): location to store root window Y coordinate of pointer, or %NULL.
639 * @mask: (out) (allow-none): location to store current modifier mask, or %NULL
640 *
641 * Gets the current location of the pointer and the current modifier
642 * mask for a given display.
643 *
644 * Since: 2.2
645 *
646 * Deprecated: 3.0: Use gdk_device_get_position() instead.
647 **/
648void
649gdk_display_get_pointer (GdkDisplay *display,
650 GdkScreen **screen,
651 gint *x,
652 gint *y,
653 GdkModifierType *mask)
654{
655 GdkScreen *default_screen;
656 GdkSeat *default_seat;
657 GdkWindow *root;
658 gdouble tmp_x, tmp_y;
659 GdkModifierType tmp_mask;
660
661 g_return_if_fail (GDK_IS_DISPLAY (display));
662
663 if (gdk_display_is_closed (display))
664 return;
665
666 default_screen = gdk_display_get_default_screen (display);
667 default_seat = gdk_display_get_default_seat (display);
668
669 /* We call _gdk_device_query_state() here manually instead of
670 * gdk_device_get_position() because we care about the modifier mask */
671
672 _gdk_device_query_state (gdk_seat_get_pointer (default_seat),
673 gdk_screen_get_root_window (default_screen),
674 &root, NULL,
675 &tmp_x, &tmp_y,
676 NULL, NULL,
677 &tmp_mask);
678
679 if (screen)
680 *screen = gdk_window_get_screen (root);
681 if (x)
682 *x = round (tmp_x);
683 if (y)
684 *y = round (tmp_y);
685 if (mask)
686 *mask = tmp_mask;
687}
688
689/**
690 * gdk_display_get_window_at_pointer:
691 * @display: a #GdkDisplay
692 * @win_x: (out) (allow-none): return location for x coordinate of the pointer location relative
693 * to the window origin, or %NULL
694 * @win_y: (out) (allow-none): return location for y coordinate of the pointer location relative
695 & to the window origin, or %NULL
696 *
697 * Obtains the window underneath the mouse pointer, returning the location
698 * of the pointer in that window in @win_x, @win_y for @screen. Returns %NULL
699 * if the window under the mouse pointer is not known to GDK (for example,
700 * belongs to another application).
701 *
702 * Returns: (nullable) (transfer none): the window under the mouse
703 * pointer, or %NULL
704 *
705 * Since: 2.2
706 *
707 * Deprecated: 3.0: Use gdk_device_get_window_at_position() instead.
708 **/
709GdkWindow *
710gdk_display_get_window_at_pointer (GdkDisplay *display,
711 gint *win_x,
712 gint *win_y)
713{
714 GdkDevice *pointer;
715
716 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
717
718 pointer = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
719
720 return gdk_device_get_window_at_position (pointer, win_x, win_y);
721}
722
723static void
724generate_grab_broken_event (GdkDisplay *display,
725 GdkWindow *window,
726 GdkDevice *device,
727 gboolean implicit,
728 GdkWindow *grab_window)
729{
730 g_return_if_fail (window != NULL);
731
732 if (!GDK_WINDOW_DESTROYED (window))
733 {
734 GdkEvent *event;
735
736 event = gdk_event_new (GDK_GRAB_BROKEN);
737 event->grab_broken.window = g_object_ref (window);
738 event->grab_broken.send_event = FALSE;
739 event->grab_broken.implicit = implicit;
740 event->grab_broken.grab_window = grab_window;
741 gdk_event_set_device (event, device);
742 event->grab_broken.keyboard = (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) ? TRUE : FALSE;
743
744 gdk_display_put_event_nocopy (display, event);
745 }
746}
747
748GdkDeviceGrabInfo *
749_gdk_display_get_last_device_grab (GdkDisplay *display,
750 GdkDevice *device)
751{
752 GList *l;
753
754 l = g_hash_table_lookup (display->device_grabs, device);
755
756 if (l)
757 {
758 l = g_list_last (l);
759 return l->data;
760 }
761
762 return NULL;
763}
764
765GdkDeviceGrabInfo *
766_gdk_display_add_device_grab (GdkDisplay *display,
767 GdkDevice *device,
768 GdkWindow *window,
769 GdkWindow *native_window,
770 GdkGrabOwnership grab_ownership,
771 gboolean owner_events,
772 GdkEventMask event_mask,
773 unsigned long serial_start,
774 guint32 time,
775 gboolean implicit)
776{
777 GdkDeviceGrabInfo *info, *other_info;
778 GList *grabs, *l;
779
780 info = g_new0 (GdkDeviceGrabInfo, 1);
781
782 info->window = g_object_ref (window);
783 info->native_window = g_object_ref (native_window);
784 info->serial_start = serial_start;
785 info->serial_end = G_MAXULONG;
786 info->owner_events = owner_events;
787 info->event_mask = event_mask;
788 info->time = time;
789 info->implicit = implicit;
790 info->ownership = grab_ownership;
791
792 grabs = g_hash_table_lookup (display->device_grabs, device);
793
794 /* Find the first grab that has a larger start time (if any) and insert
795 * before that. I.E we insert after already existing grabs with same
796 * start time */
797 for (l = grabs; l != NULL; l = l->next)
798 {
799 other_info = l->data;
800
801 if (info->serial_start < other_info->serial_start)
802 break;
803 }
804
805 grabs = g_list_insert_before (grabs, l, info);
806
807 /* Make sure the new grab end before next grab */
808 if (l)
809 {
810 other_info = l->data;
811 info->serial_end = other_info->serial_start;
812 }
813
814 /* Find any previous grab and update its end time */
815 l = g_list_find (grabs, info);
816 l = l->prev;
817 if (l)
818 {
819 other_info = l->data;
820 other_info->serial_end = serial_start;
821 }
822
823 g_hash_table_insert (display->device_grabs, device, grabs);
824
825 return info;
826}
827
828static void
829_gdk_display_break_touch_grabs (GdkDisplay *display,
830 GdkDevice *device,
831 GdkWindow *new_grab_window)
832{
833 guint i;
834
835 for (i = 0; i < display->touch_implicit_grabs->len; i++)
836 {
837 GdkTouchGrabInfo *info;
838
839 info = &g_array_index (display->touch_implicit_grabs,
840 GdkTouchGrabInfo, i);
841
842 if (info->device == device && info->window != new_grab_window)
843 generate_grab_broken_event (display, GDK_WINDOW (info->window),
844 device, TRUE, new_grab_window);
845 }
846}
847
848void
849_gdk_display_add_touch_grab (GdkDisplay *display,
850 GdkDevice *device,
851 GdkEventSequence *sequence,
852 GdkWindow *window,
853 GdkWindow *native_window,
854 GdkEventMask event_mask,
855 unsigned long serial,
856 guint32 time)
857{
858 GdkTouchGrabInfo info;
859
860 info.device = device;
861 info.sequence = sequence;
862 info.window = g_object_ref (window);
863 info.native_window = g_object_ref (native_window);
864 info.serial = serial;
865 info.event_mask = event_mask;
866 info.time = time;
867
868 g_array_append_val (display->touch_implicit_grabs, info);
869}
870
871gboolean
872_gdk_display_end_touch_grab (GdkDisplay *display,
873 GdkDevice *device,
874 GdkEventSequence *sequence)
875{
876 guint i;
877
878 for (i = 0; i < display->touch_implicit_grabs->len; i++)
879 {
880 GdkTouchGrabInfo *info;
881
882 info = &g_array_index (display->touch_implicit_grabs,
883 GdkTouchGrabInfo, i);
884
885 if (info->device == device && info->sequence == sequence)
886 {
887 g_array_remove_index_fast (display->touch_implicit_grabs, i);
888 return TRUE;
889 }
890 }
891
892 return FALSE;
893}
894
895/* _gdk_synthesize_crossing_events only works inside one toplevel.
896 This function splits things into two calls if needed, converting the
897 coordinates to the right toplevel */
898static void
899synthesize_crossing_events (GdkDisplay *display,
900 GdkDevice *device,
901 GdkDevice *source_device,
902 GdkWindow *src_window,
903 GdkWindow *dest_window,
904 GdkCrossingMode crossing_mode,
905 guint32 time,
906 gulong serial)
907{
908 GdkWindow *src_toplevel, *dest_toplevel;
909 GdkModifierType state;
910 double x, y;
911
912 if (src_window)
913 src_toplevel = gdk_window_get_toplevel (src_window);
914 else
915 src_toplevel = NULL;
916 if (dest_window)
917 dest_toplevel = gdk_window_get_toplevel (dest_window);
918 else
919 dest_toplevel = NULL;
920
921 if (src_toplevel == NULL && dest_toplevel == NULL)
922 return;
923
924 if (src_toplevel == NULL ||
925 src_toplevel == dest_toplevel)
926 {
927 /* Same toplevels */
928 gdk_window_get_device_position_double (dest_toplevel,
929 device,
930 &x, &y, &state);
931 _gdk_synthesize_crossing_events (display,
932 src_window,
933 dest_window,
934 device, source_device,
935 crossing_mode,
936 x, y, state,
937 time,
938 NULL,
939 serial, FALSE);
940 }
941 else if (dest_toplevel == NULL)
942 {
943 gdk_window_get_device_position_double (src_toplevel,
944 device,
945 &x, &y, &state);
946 _gdk_synthesize_crossing_events (display,
947 src_window,
948 NULL,
949 device, source_device,
950 crossing_mode,
951 x, y, state,
952 time,
953 NULL,
954 serial, FALSE);
955 }
956 else
957 {
958 /* Different toplevels */
959 gdk_window_get_device_position_double (src_toplevel,
960 device,
961 &x, &y, &state);
962 _gdk_synthesize_crossing_events (display,
963 src_window,
964 NULL,
965 device, source_device,
966 crossing_mode,
967 x, y, state,
968 time,
969 NULL,
970 serial, FALSE);
971 gdk_window_get_device_position_double (dest_toplevel,
972 device,
973 &x, &y, &state);
974 _gdk_synthesize_crossing_events (display,
975 NULL,
976 dest_window,
977 device, source_device,
978 crossing_mode,
979 x, y, state,
980 time,
981 NULL,
982 serial, FALSE);
983 }
984}
985
986static GdkWindow *
987get_current_toplevel (GdkDisplay *display,
988 GdkDevice *device,
989 int *x_out,
990 int *y_out,
991 GdkModifierType *state_out)
992{
993 GdkWindow *pointer_window;
994 gdouble x, y;
995 GdkModifierType state;
996
997 pointer_window = _gdk_device_window_at_position (device, &x, &y, &state, TRUE);
998
999 if (pointer_window != NULL &&
1000 (GDK_WINDOW_DESTROYED (pointer_window) ||
1001 GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
1002 GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
1003 pointer_window = NULL;
1004
1005 *x_out = round (x);
1006 *y_out = round (y);
1007 *state_out = state;
1008
1009 return pointer_window;
1010}
1011
1012static void
1013switch_to_pointer_grab (GdkDisplay *display,
1014 GdkDevice *device,
1015 GdkDevice *source_device,
1016 GdkDeviceGrabInfo *grab,
1017 GdkDeviceGrabInfo *last_grab,
1018 guint32 time,
1019 gulong serial)
1020{
1021 GdkWindow *src_window, *pointer_window, *new_toplevel;
1022 GdkPointerWindowInfo *info;
1023 GList *old_grabs;
1024 GdkModifierType state;
1025 int x = 0, y = 0;
1026
1027 /* Temporarily unset pointer to make sure we send the crossing events below */
1028 old_grabs = g_hash_table_lookup (display->device_grabs, device);
1029 g_hash_table_steal (display->device_grabs, device);
1030 info = _gdk_display_get_pointer_info (display, device);
1031
1032 if (grab)
1033 {
1034 /* New grab is in effect */
1035
1036 /* We need to generate crossing events for the grab.
1037 * However, there are never any crossing events for implicit grabs
1038 * TODO: ... Actually, this could happen if the pointer window
1039 * doesn't have button mask so a parent gets the event...
1040 */
1041 if (!grab->implicit)
1042 {
1043 /* We send GRAB crossing events from the window under the pointer to the
1044 grab window. Except if there is an old grab then we start from that */
1045 if (last_grab)
1046 src_window = last_grab->window;
1047 else
1048 src_window = info->window_under_pointer;
1049
1050 if (src_window != grab->window)
1051 synthesize_crossing_events (display, device, source_device,
1052 src_window, grab->window,
1053 GDK_CROSSING_GRAB, time, serial);
1054
1055 /* !owner_event Grabbing a window that we're not inside, current status is
1056 now NULL (i.e. outside grabbed window) */
1057 if (!grab->owner_events && info->window_under_pointer != grab->window)
1058 _gdk_display_set_window_under_pointer (display, device, NULL);
1059 }
1060
1061 grab->activated = TRUE;
1062 }
1063
1064 if (last_grab)
1065 {
1066 new_toplevel = NULL;
1067
1068 if (grab == NULL /* ungrab */ ||
1069 (!last_grab->owner_events && grab->owner_events) /* switched to owner_events */ )
1070 {
1071 /* We force check what window we're in, and update the toplevel_under_pointer info,
1072 * as that won't get told of this change with toplevel enter events.
1073 */
1074 if (info->toplevel_under_pointer)
1075 g_object_unref (info->toplevel_under_pointer);
1076 info->toplevel_under_pointer = NULL;
1077
1078 /* Ungrabbed slave devices don't have a position by
1079 * itself, rather depend on its master pointer, so
1080 * it doesn't make sense to track any position for
1081 * these after the grab
1082 */
1083 if (grab || gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_SLAVE)
1084 new_toplevel = get_current_toplevel (display, device, &x, &y, &state);
1085
1086 if (new_toplevel)
1087 {
1088 /* w is now toplevel and x,y in toplevel coords */
1089 info->toplevel_under_pointer = g_object_ref (new_toplevel);
1090 info->toplevel_x = x;
1091 info->toplevel_y = y;
1092 info->state = state;
1093 }
1094 }
1095
1096 if (grab == NULL) /* Ungrabbed, send events */
1097 {
1098 /* If the source device is a touch device, do not
1099 * propagate any enter event yet, until one is
1100 * synthesized when needed.
1101 */
1102 if (source_device &&
1103 (gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN))
1104 info->need_touch_press_enter = TRUE;
1105
1106 pointer_window = NULL;
1107
1108 if (new_toplevel &&
1109 !info->need_touch_press_enter)
1110 {
1111 /* Find (possibly virtual) child window */
1112 pointer_window =
1113 _gdk_window_find_descendant_at (new_toplevel,
1114 x, y,
1115 NULL, NULL);
1116 }
1117
1118 if (!info->need_touch_press_enter &&
1119 pointer_window != last_grab->window)
1120 synthesize_crossing_events (display, device, source_device,
1121 last_grab->window, pointer_window,
1122 GDK_CROSSING_UNGRAB, time, serial);
1123
1124 /* We're now ungrabbed, update the window_under_pointer */
1125 _gdk_display_set_window_under_pointer (display, device, pointer_window);
1126 }
1127 }
1128
1129 g_hash_table_insert (display->device_grabs, device, old_grabs);
1130}
1131
1132void
1133_gdk_display_update_last_event (GdkDisplay *display,
1134 const GdkEvent *event)
1135{
1136 if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
1137 display->last_event_time = gdk_event_get_time (event);
1138}
1139
1140void
1141_gdk_display_device_grab_update (GdkDisplay *display,
1142 GdkDevice *device,
1143 GdkDevice *source_device,
1144 gulong current_serial)
1145{
1146 GdkDeviceGrabInfo *current_grab, *next_grab;
1147 GList *grabs;
1148 guint32 time;
1149
1150 time = display->last_event_time;
1151 grabs = g_hash_table_lookup (display->device_grabs, device);
1152
1153 while (grabs != NULL)
1154 {
1155 current_grab = grabs->data;
1156
1157 if (current_grab->serial_start > current_serial)
1158 return; /* Hasn't started yet */
1159
1160 if (current_grab->serial_end > current_serial)
1161 {
1162 /* This one hasn't ended yet.
1163 its the currently active one or scheduled to be active */
1164
1165 if (!current_grab->activated)
1166 {
1167 if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
1168 switch_to_pointer_grab (display, device, source_device, current_grab, NULL, time, current_serial);
1169 }
1170
1171 break;
1172 }
1173
1174 next_grab = NULL;
1175 if (grabs->next)
1176 {
1177 /* This is the next active grab */
1178 next_grab = grabs->next->data;
1179
1180 if (next_grab->serial_start > current_serial)
1181 next_grab = NULL; /* Actually its not yet active */
1182 }
1183
1184 if (next_grab)
1185 _gdk_display_break_touch_grabs (display, device, next_grab->window);
1186
1187 if ((next_grab == NULL && current_grab->implicit_ungrab) ||
1188 (next_grab != NULL && current_grab->window != next_grab->window))
1189 generate_grab_broken_event (display, GDK_WINDOW (current_grab->window),
1190 device,
1191 current_grab->implicit,
1192 next_grab? next_grab->window : NULL);
1193
1194 /* Remove old grab */
1195 grabs = g_list_delete_link (grabs, grabs);
1196 g_hash_table_insert (display->device_grabs, device, grabs);
1197
1198 if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
1199 switch_to_pointer_grab (display, device, source_device,
1200 next_grab, current_grab,
1201 time, current_serial);
1202
1203 free_device_grab (current_grab);
1204 }
1205}
1206
1207static GList *
1208grab_list_find (GList *grabs,
1209 gulong serial)
1210{
1211 GdkDeviceGrabInfo *grab;
1212
1213 while (grabs)
1214 {
1215 grab = grabs->data;
1216
1217 if (serial >= grab->serial_start && serial < grab->serial_end)
1218 return grabs;
1219
1220 grabs = grabs->next;
1221 }
1222
1223 return NULL;
1224}
1225
1226static GList *
1227find_device_grab (GdkDisplay *display,
1228 GdkDevice *device,
1229 gulong serial)
1230{
1231 GList *l;
1232
1233 l = g_hash_table_lookup (display->device_grabs, device);
1234 return grab_list_find (l, serial);
1235}
1236
1237GdkDeviceGrabInfo *
1238_gdk_display_has_device_grab (GdkDisplay *display,
1239 GdkDevice *device,
1240 gulong serial)
1241{
1242 GList *l;
1243
1244 l = find_device_grab (display, device, serial);
1245 if (l)
1246 return l->data;
1247
1248 return NULL;
1249}
1250
1251GdkTouchGrabInfo *
1252_gdk_display_has_touch_grab (GdkDisplay *display,
1253 GdkDevice *device,
1254 GdkEventSequence *sequence,
1255 gulong serial)
1256{
1257 guint i;
1258
1259 for (i = 0; i < display->touch_implicit_grabs->len; i++)
1260 {
1261 GdkTouchGrabInfo *info;
1262
1263 info = &g_array_index (display->touch_implicit_grabs,
1264 GdkTouchGrabInfo, i);
1265
1266 if (info->device == device && info->sequence == sequence)
1267 {
1268 if (serial >= info->serial)
1269 return info;
1270 else
1271 return NULL;
1272 }
1273 }
1274
1275 return NULL;
1276}
1277
1278/* Returns true if last grab was ended
1279 * If if_child is non-NULL, end the grab only if the grabbed
1280 * window is the same as if_child or a descendant of it */
1281gboolean
1282_gdk_display_end_device_grab (GdkDisplay *display,
1283 GdkDevice *device,
1284 gulong serial,
1285 GdkWindow *if_child,
1286 gboolean implicit)
1287{
1288 GdkDeviceGrabInfo *grab;
1289 GList *l;
1290
1291 l = find_device_grab (display, device, serial);
1292
1293 if (l == NULL)
1294 return FALSE;
1295
1296 grab = l->data;
1297 if (grab &&
1298 (if_child == NULL ||
1299 _gdk_window_event_parent_of (if_child, grab->window)))
1300 {
1301 grab->serial_end = serial;
1302 grab->implicit_ungrab = implicit;
1303 return l->next == NULL;
1304 }
1305
1306 return FALSE;
1307}
1308
1309/* Returns TRUE if device events are not blocked by any grab */
1310gboolean
1311_gdk_display_check_grab_ownership (GdkDisplay *display,
1312 GdkDevice *device,
1313 gulong serial)
1314{
1315 GHashTableIter iter;
1316 gpointer key, value;
1317 GdkGrabOwnership higher_ownership, device_ownership;
1318 gboolean device_is_keyboard;
1319
1320 g_hash_table_iter_init (&iter, display->device_grabs);
1321 higher_ownership = device_ownership = GDK_OWNERSHIP_NONE;
1322 device_is_keyboard = (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD);
1323
1324 while (g_hash_table_iter_next (&iter, &key, &value))
1325 {
1326 GdkDeviceGrabInfo *grab;
1327 GdkDevice *dev;
1328 GList *grabs;
1329
1330 dev = key;
1331 grabs = value;
1332 grabs = grab_list_find (grabs, serial);
1333
1334 if (!grabs)
1335 continue;
1336
1337 /* Discard device if it's not of the same type */
1338 if ((device_is_keyboard && gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD) ||
1339 (!device_is_keyboard && gdk_device_get_source (dev) == GDK_SOURCE_KEYBOARD))
1340 continue;
1341
1342 grab = grabs->data;
1343
1344 if (dev == device)
1345 device_ownership = grab->ownership;
1346 else
1347 {
1348 if (grab->ownership > higher_ownership)
1349 higher_ownership = grab->ownership;
1350 }
1351 }
1352
1353 if (higher_ownership > device_ownership)
1354 {
1355 /* There's a higher priority ownership
1356 * going on for other device(s)
1357 */
1358 return FALSE;
1359 }
1360
1361 return TRUE;
1362}
1363
1364GdkPointerWindowInfo *
1365_gdk_display_get_pointer_info (GdkDisplay *display,
1366 GdkDevice *device)
1367{
1368 GdkPointerWindowInfo *info;
1369
1370 if (device && gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
1371 device = gdk_device_get_associated_device (device);
1372
1373 if (G_UNLIKELY (!device))
1374 return NULL;
1375
1376 info = g_hash_table_lookup (display->pointers_info, device);
1377
1378 if (G_UNLIKELY (!info))
1379 {
1380 info = g_slice_new0 (GdkPointerWindowInfo);
1381 g_hash_table_insert (display->pointers_info, device, info);
1382 }
1383
1384 return info;
1385}
1386
1387void
1388_gdk_display_pointer_info_foreach (GdkDisplay *display,
1389 GdkDisplayPointerInfoForeach func,
1390 gpointer user_data)
1391{
1392 GHashTableIter iter;
1393 gpointer key, value;
1394
1395 g_hash_table_iter_init (&iter, display->pointers_info);
1396
1397 while (g_hash_table_iter_next (&iter, &key, &value))
1398 {
1399 GdkPointerWindowInfo *info = value;
1400 GdkDevice *device = key;
1401
1402 (func) (display, device, info, user_data);
1403 }
1404}
1405
1406/*< private >
1407 * gdk_device_grab_info:
1408 * @display: the display for which to get the grab information
1409 * @device: device to get the grab information from
1410 * @grab_window: (out) (transfer none): location to store current grab window
1411 * @owner_events: (out): location to store boolean indicating whether
1412 * the @owner_events flag to gdk_keyboard_grab() or
1413 * gdk_pointer_grab() was %TRUE.
1414 *
1415 * Determines information about the current keyboard grab.
1416 * This is not public API and must not be used by applications.
1417 *
1418 * Returns: %TRUE if this application currently has the
1419 * keyboard grabbed.
1420 */
1421gboolean
1422gdk_device_grab_info (GdkDisplay *display,
1423 GdkDevice *device,
1424 GdkWindow **grab_window,
1425 gboolean *owner_events)
1426{
1427 GdkDeviceGrabInfo *info;
1428
1429 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1430 g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
1431
1432 info = _gdk_display_get_last_device_grab (display, device);
1433
1434 if (info)
1435 {
1436 if (grab_window)
1437 *grab_window = info->window;
1438 if (owner_events)
1439 *owner_events = info->owner_events;
1440
1441 return TRUE;
1442 }
1443 else
1444 return FALSE;
1445}
1446
1447/**
1448 * gdk_device_grab_info_libgtk_only:
1449 * @display: the display for which to get the grab information
1450 * @device: device to get the grab information from
1451 * @grab_window: (out) (transfer none): location to store current grab window
1452 * @owner_events: (out): location to store boolean indicating whether
1453 * the @owner_events flag to gdk_keyboard_grab() or
1454 * gdk_pointer_grab() was %TRUE.
1455 *
1456 * Determines information about the current keyboard grab.
1457 * This is not public API and must not be used by applications.
1458 *
1459 * Returns: %TRUE if this application currently has the
1460 * keyboard grabbed.
1461 *
1462 * Deprecated: 3.16: The symbol was never meant to be used outside
1463 * of GTK+
1464 */
1465gboolean
1466gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1467 GdkDevice *device,
1468 GdkWindow **grab_window,
1469 gboolean *owner_events)
1470{
1471 return gdk_device_grab_info (display, device, grab_window, owner_events);
1472}
1473
1474/**
1475 * gdk_display_pointer_is_grabbed:
1476 * @display: a #GdkDisplay
1477 *
1478 * Test if the pointer is grabbed.
1479 *
1480 * Returns: %TRUE if an active X pointer grab is in effect
1481 *
1482 * Since: 2.2
1483 *
1484 * Deprecated: 3.0: Use gdk_display_device_is_grabbed() instead.
1485 */
1486gboolean
1487gdk_display_pointer_is_grabbed (GdkDisplay *display)
1488{
1489 GList *seats, *s;
1490 GdkDevice *device;
1491
1492 g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1493
1494 seats = gdk_display_list_seats (display);
1495
1496 for (s = seats; s; s = s->next)
1497 {
1498 device = gdk_seat_get_pointer (s->data);
1499
1500 if (gdk_display_device_is_grabbed (display, device))
1501 {
1502 g_list_free (seats);
1503 return TRUE;
1504 }
1505 }
1506
1507 g_list_free (seats);
1508
1509 return FALSE;
1510}
1511
1512/**
1513 * gdk_display_device_is_grabbed:
1514 * @display: a #GdkDisplay
1515 * @device: a #GdkDevice
1516 *
1517 * Returns %TRUE if there is an ongoing grab on @device for @display.
1518 *
1519 * Returns: %TRUE if there is a grab in effect for @device.
1520 **/
1521gboolean
1522gdk_display_device_is_grabbed (GdkDisplay *display,
1523 GdkDevice *device)
1524{
1525 GdkDeviceGrabInfo *info;
1526
1527 g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1528 g_return_val_if_fail (GDK_IS_DEVICE (device), TRUE);
1529
1530 /* What we're interested in is the steady state (ie last grab),
1531 because we're interested e.g. if we grabbed so that we
1532 can ungrab, even if our grab is not active just yet. */
1533 info = _gdk_display_get_last_device_grab (display, device);
1534
1535 return (info && !info->implicit);
1536}
1537
1538/**
1539 * gdk_display_get_device_manager:
1540 * @display: a #GdkDisplay.
1541 *
1542 * Returns the #GdkDeviceManager associated to @display.
1543 *
1544 * Returns: (nullable) (transfer none): A #GdkDeviceManager, or
1545 * %NULL. This memory is owned by GDK and must not be freed
1546 * or unreferenced.
1547 *
1548 * Since: 3.0
1549 *
1550 * Deprecated: 3.20. Use gdk_display_get_default_seat() and #GdkSeat operations.
1551 **/
1552GdkDeviceManager *
1553gdk_display_get_device_manager (GdkDisplay *display)
1554{
1555 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1556
1557 return display->device_manager;
1558}
1559
1560/**
1561 * gdk_display_get_name:
1562 * @display: a #GdkDisplay
1563 *
1564 * Gets the name of the display.
1565 *
1566 * Returns: a string representing the display name. This string is owned
1567 * by GDK and should not be modified or freed.
1568 *
1569 * Since: 2.2
1570 */
1571const gchar *
1572gdk_display_get_name (GdkDisplay *display)
1573{
1574 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1575
1576 return GDK_DISPLAY_GET_CLASS (display)->get_name (display);
1577}
1578
1579/**
1580 * gdk_display_get_n_screens:
1581 * @display: a #GdkDisplay
1582 *
1583 * Gets the number of screen managed by the @display.
1584 *
1585 * Returns: number of screens.
1586 *
1587 * Since: 2.2
1588 *
1589 * Deprecated: 3.10: The number of screens is always 1.
1590 */
1591gint
1592gdk_display_get_n_screens (GdkDisplay *display)
1593{
1594 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
1595
1596 return 1;
1597}
1598
1599/**
1600 * gdk_display_get_screen:
1601 * @display: a #GdkDisplay
1602 * @screen_num: the screen number
1603 *
1604 * Returns a screen object for one of the screens of the display.
1605 *
1606 * Returns: (transfer none): the #GdkScreen object
1607 *
1608 * Since: 2.2
1609 * Deprecated: 3.20: There is only one screen; use gdk_display_get_default_screen() to get it.
1610 */
1611GdkScreen *
1612gdk_display_get_screen (GdkDisplay *display,
1613 gint screen_num)
1614{
1615 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1616 g_return_val_if_fail (screen_num == 0, NULL);
1617
1618 return gdk_display_get_default_screen (display);
1619}
1620
1621/**
1622 * gdk_display_get_default_screen:
1623 * @display: a #GdkDisplay
1624 *
1625 * Get the default #GdkScreen for @display.
1626 *
1627 * Returns: (transfer none): the default #GdkScreen object for @display
1628 *
1629 * Since: 2.2
1630 */
1631GdkScreen *
1632gdk_display_get_default_screen (GdkDisplay *display)
1633{
1634 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1635
1636 return GDK_DISPLAY_GET_CLASS (display)->get_default_screen (display);
1637}
1638
1639/**
1640 * gdk_display_beep:
1641 * @display: a #GdkDisplay
1642 *
1643 * Emits a short beep on @display
1644 *
1645 * Since: 2.2
1646 */
1647void
1648gdk_display_beep (GdkDisplay *display)
1649{
1650 g_return_if_fail (GDK_IS_DISPLAY (display));
1651
1652 GDK_DISPLAY_GET_CLASS (display)->beep (display);
1653}
1654
1655/**
1656 * gdk_display_sync:
1657 * @display: a #GdkDisplay
1658 *
1659 * Flushes any requests queued for the windowing system and waits until all
1660 * requests have been handled. This is often used for making sure that the
1661 * display is synchronized with the current state of the program. Calling
1662 * gdk_display_sync() before gdk_error_trap_pop() makes sure that any errors
1663 * generated from earlier requests are handled before the error trap is
1664 * removed.
1665 *
1666 * This is most useful for X11. On windowing systems where requests are
1667 * handled synchronously, this function will do nothing.
1668 *
1669 * Since: 2.2
1670 */
1671void
1672gdk_display_sync (GdkDisplay *display)
1673{
1674 g_return_if_fail (GDK_IS_DISPLAY (display));
1675
1676 GDK_DISPLAY_GET_CLASS (display)->sync (display);
1677}
1678
1679/**
1680 * gdk_display_flush:
1681 * @display: a #GdkDisplay
1682 *
1683 * Flushes any requests queued for the windowing system; this happens automatically
1684 * when the main loop blocks waiting for new events, but if your application
1685 * is drawing without returning control to the main loop, you may need
1686 * to call this function explicitly. A common case where this function
1687 * needs to be called is when an application is executing drawing commands
1688 * from a thread other than the thread where the main loop is running.
1689 *
1690 * This is most useful for X11. On windowing systems where requests are
1691 * handled synchronously, this function will do nothing.
1692 *
1693 * Since: 2.4
1694 */
1695void
1696gdk_display_flush (GdkDisplay *display)
1697{
1698 g_return_if_fail (GDK_IS_DISPLAY (display));
1699
1700 GDK_DISPLAY_GET_CLASS (display)->flush (display);
1701}
1702
1703/**
1704 * gdk_display_get_default_group:
1705 * @display: a #GdkDisplay
1706 *
1707 * Returns the default group leader window for all toplevel windows
1708 * on @display. This window is implicitly created by GDK.
1709 * See gdk_window_set_group().
1710 *
1711 * Returns: (transfer none): The default group leader window
1712 * for @display
1713 *
1714 * Since: 2.4
1715 **/
1716GdkWindow *
1717gdk_display_get_default_group (GdkDisplay *display)
1718{
1719 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1720
1721 return GDK_DISPLAY_GET_CLASS (display)->get_default_group (display);
1722}
1723
1724/**
1725 * gdk_display_supports_selection_notification:
1726 * @display: a #GdkDisplay
1727 *
1728 * Returns whether #GdkEventOwnerChange events will be
1729 * sent when the owner of a selection changes.
1730 *
1731 * Returns: whether #GdkEventOwnerChange events will
1732 * be sent.
1733 *
1734 * Since: 2.6
1735 **/
1736gboolean
1737gdk_display_supports_selection_notification (GdkDisplay *display)
1738{
1739 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1740
1741 return GDK_DISPLAY_GET_CLASS (display)->supports_selection_notification (display);
1742}
1743
1744/**
1745 * gdk_display_request_selection_notification:
1746 * @display: a #GdkDisplay
1747 * @selection: the #GdkAtom naming the selection for which
1748 * ownership change notification is requested
1749 *
1750 * Request #GdkEventOwnerChange events for ownership changes
1751 * of the selection named by the given atom.
1752 *
1753 * Returns: whether #GdkEventOwnerChange events will
1754 * be sent.
1755 *
1756 * Since: 2.6
1757 **/
1758gboolean
1759gdk_display_request_selection_notification (GdkDisplay *display,
1760 GdkAtom selection)
1761
1762{
1763 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1764
1765 return GDK_DISPLAY_GET_CLASS (display)->request_selection_notification (display, selection);
1766}
1767
1768/**
1769 * gdk_display_supports_clipboard_persistence:
1770 * @display: a #GdkDisplay
1771 *
1772 * Returns whether the speicifed display supports clipboard
1773 * persistance; i.e. if it’s possible to store the clipboard data after an
1774 * application has quit. On X11 this checks if a clipboard daemon is
1775 * running.
1776 *
1777 * Returns: %TRUE if the display supports clipboard persistance.
1778 *
1779 * Since: 2.6
1780 */
1781gboolean
1782gdk_display_supports_clipboard_persistence (GdkDisplay *display)
1783{
1784 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1785
1786 return GDK_DISPLAY_GET_CLASS (display)->supports_clipboard_persistence (display);
1787}
1788
1789/**
1790 * gdk_display_store_clipboard:
1791 * @display: a #GdkDisplay
1792 * @clipboard_window: a #GdkWindow belonging to the clipboard owner
1793 * @time_: a timestamp
1794 * @targets: (array length=n_targets): an array of targets
1795 * that should be saved, or %NULL
1796 * if all available targets should be saved.
1797 * @n_targets: length of the @targets array
1798 *
1799 * Issues a request to the clipboard manager to store the
1800 * clipboard data. On X11, this is a special program that works
1801 * according to the
1802 * [FreeDesktop Clipboard Specification](http://www.freedesktop.org/Standards/clipboard-manager-spec).
1803 *
1804 * Since: 2.6
1805 */
1806void
1807gdk_display_store_clipboard (GdkDisplay *display,
1808 GdkWindow *clipboard_window,
1809 guint32 time_,
1810 const GdkAtom *targets,
1811 gint n_targets)
1812{
1813 g_return_if_fail (GDK_IS_DISPLAY (display));
1814
1815 GDK_DISPLAY_GET_CLASS (display)->store_clipboard (display, clipboard_window, time_, targets, n_targets);
1816}
1817
1818/**
1819 * gdk_display_supports_shapes:
1820 * @display: a #GdkDisplay
1821 *
1822 * Returns %TRUE if gdk_window_shape_combine_mask() can
1823 * be used to create shaped windows on @display.
1824 *
1825 * Returns: %TRUE if shaped windows are supported
1826 *
1827 * Since: 2.10
1828 */
1829gboolean
1830gdk_display_supports_shapes (GdkDisplay *display)
1831{
1832 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1833
1834 return GDK_DISPLAY_GET_CLASS (display)->supports_shapes (display);
1835}
1836
1837/**
1838 * gdk_display_supports_input_shapes:
1839 * @display: a #GdkDisplay
1840 *
1841 * Returns %TRUE if gdk_window_input_shape_combine_mask() can
1842 * be used to modify the input shape of windows on @display.
1843 *
1844 * Returns: %TRUE if windows with modified input shape are supported
1845 *
1846 * Since: 2.10
1847 */
1848gboolean
1849gdk_display_supports_input_shapes (GdkDisplay *display)
1850{
1851 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1852
1853 return GDK_DISPLAY_GET_CLASS (display)->supports_input_shapes (display);
1854}
1855
1856/**
1857 * gdk_display_supports_composite:
1858 * @display: a #GdkDisplay
1859 *
1860 * Returns %TRUE if gdk_window_set_composited() can be used
1861 * to redirect drawing on the window using compositing.
1862 *
1863 * Currently this only works on X11 with XComposite and
1864 * XDamage extensions available.
1865 *
1866 * Returns: %TRUE if windows may be composited.
1867 *
1868 * Since: 2.12
1869 *
1870 * Deprecated: 3.16: Compositing is an outdated technology that
1871 * only ever worked on X11.
1872 */
1873gboolean
1874gdk_display_supports_composite (GdkDisplay *display)
1875{
1876 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1877
1878 return GDK_DISPLAY_GET_CLASS (display)->supports_composite (display);
1879}
1880
1881/**
1882 * gdk_display_list_devices:
1883 * @display: a #GdkDisplay
1884 *
1885 * Returns the list of available input devices attached to @display.
1886 * The list is statically allocated and should not be freed.
1887 *
1888 * Returns: (transfer none) (element-type GdkDevice):
1889 * a list of #GdkDevice
1890 *
1891 * Since: 2.2
1892 *
1893 * Deprecated: 3.0: Use gdk_device_manager_list_devices() instead.
1894 **/
1895GList *
1896gdk_display_list_devices (GdkDisplay *display)
1897{
1898 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1899
1900 if (!display->input_devices)
1901 {
1902 GdkSeat *seat;
1903
1904 seat = gdk_display_get_default_seat (display);
1905
1906 /* For backwards compatibility we only include pointing
1907 * devices (the core pointer and the slaves).
1908 * We store the list since this deprecated function does
1909 * not transfer the list ownership.
1910 */
1911 display->input_devices = gdk_seat_get_slaves (seat, GDK_SEAT_CAPABILITY_ALL_POINTING);
1912 display->input_devices = g_list_prepend (display->input_devices, gdk_seat_get_pointer (seat));
1913 g_list_foreach (display->input_devices, (GFunc) g_object_ref, NULL);
1914 }
1915
1916 return display->input_devices;
1917}
1918
1919static GdkAppLaunchContext *
1920gdk_display_real_get_app_launch_context (GdkDisplay *display)
1921{
1922 GdkAppLaunchContext *ctx;
1923
1924 ctx = g_object_new (GDK_TYPE_APP_LAUNCH_CONTEXT,
1925 "display", display,
1926 NULL);
1927
1928 return ctx;
1929}
1930
1931/**
1932 * gdk_display_get_app_launch_context:
1933 * @display: a #GdkDisplay
1934 *
1935 * Returns a #GdkAppLaunchContext suitable for launching
1936 * applications on the given display.
1937 *
1938 * Returns: (transfer full): a new #GdkAppLaunchContext for @display.
1939 * Free with g_object_unref() when done
1940 *
1941 * Since: 3.0
1942 */
1943GdkAppLaunchContext *
1944gdk_display_get_app_launch_context (GdkDisplay *display)
1945{
1946 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1947
1948 return GDK_DISPLAY_GET_CLASS (display)->get_app_launch_context (display);
1949}
1950
1951/**
1952 * gdk_display_open:
1953 * @display_name: the name of the display to open
1954 *
1955 * Opens a display.
1956 *
1957 * Returns: (nullable) (transfer none): a #GdkDisplay, or %NULL if the
1958 * display could not be opened
1959 *
1960 * Since: 2.2
1961 */
1962GdkDisplay *
1963gdk_display_open (const gchar *display_name)
1964{
1965 return gdk_display_manager_open_display (gdk_display_manager_get (),
1966 display_name);
1967}
1968
1969/**
1970 * gdk_display_has_pending:
1971 * @display: a #GdkDisplay
1972 *
1973 * Returns whether the display has events that are waiting
1974 * to be processed.
1975 *
1976 * Returns: %TRUE if there are events ready to be processed.
1977 *
1978 * Since: 3.0
1979 */
1980gboolean
1981gdk_display_has_pending (GdkDisplay *display)
1982{
1983 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1984
1985 return GDK_DISPLAY_GET_CLASS (display)->has_pending (display);
1986}
1987
1988/**
1989 * gdk_display_supports_cursor_alpha:
1990 * @display: a #GdkDisplay
1991 *
1992 * Returns %TRUE if cursors can use an 8bit alpha channel
1993 * on @display. Otherwise, cursors are restricted to bilevel
1994 * alpha (i.e. a mask).
1995 *
1996 * Returns: whether cursors can have alpha channels.
1997 *
1998 * Since: 2.4
1999 */
2000gboolean
2001gdk_display_supports_cursor_alpha (GdkDisplay *display)
2002{
2003 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
2004
2005 return GDK_DISPLAY_GET_CLASS (display)->supports_cursor_alpha (display);
2006}
2007
2008/**
2009 * gdk_display_supports_cursor_color:
2010 * @display: a #GdkDisplay
2011 *
2012 * Returns %TRUE if multicolored cursors are supported
2013 * on @display. Otherwise, cursors have only a forground
2014 * and a background color.
2015 *
2016 * Returns: whether cursors can have multiple colors.
2017 *
2018 * Since: 2.4
2019 */
2020gboolean
2021gdk_display_supports_cursor_color (GdkDisplay *display)
2022{
2023 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
2024
2025 return GDK_DISPLAY_GET_CLASS (display)->supports_cursor_color (display);
2026}
2027
2028/**
2029 * gdk_display_get_default_cursor_size:
2030 * @display: a #GdkDisplay
2031 *
2032 * Returns the default size to use for cursors on @display.
2033 *
2034 * Returns: the default cursor size.
2035 *
2036 * Since: 2.4
2037 */
2038guint
2039gdk_display_get_default_cursor_size (GdkDisplay *display)
2040{
2041 guint width, height;
2042
2043 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
2044
2045 GDK_DISPLAY_GET_CLASS (display)->get_default_cursor_size (display,
2046 &width,
2047 &height);
2048
2049 return MIN (width, height);
2050}
2051
2052/**
2053 * gdk_display_get_maximal_cursor_size:
2054 * @display: a #GdkDisplay
2055 * @width: (out): the return location for the maximal cursor width
2056 * @height: (out): the return location for the maximal cursor height
2057 *
2058 * Gets the maximal size to use for cursors on @display.
2059 *
2060 * Since: 2.4
2061 */
2062void
2063gdk_display_get_maximal_cursor_size (GdkDisplay *display,
2064 guint *width,
2065 guint *height)
2066{
2067 g_return_if_fail (GDK_IS_DISPLAY (display));
2068
2069 GDK_DISPLAY_GET_CLASS (display)->get_maximal_cursor_size (display,
2070 width,
2071 height);
2072}
2073
2074/**
2075 * gdk_display_warp_pointer:
2076 * @display: a #GdkDisplay
2077 * @screen: the screen of @display to warp the pointer to
2078 * @x: the x coordinate of the destination
2079 * @y: the y coordinate of the destination
2080 *
2081 * Warps the pointer of @display to the point @x,@y on
2082 * the screen @screen, unless the pointer is confined
2083 * to a window by a grab, in which case it will be moved
2084 * as far as allowed by the grab. Warping the pointer
2085 * creates events as if the user had moved the mouse
2086 * instantaneously to the destination.
2087 *
2088 * Note that the pointer should normally be under the
2089 * control of the user. This function was added to cover
2090 * some rare use cases like keyboard navigation support
2091 * for the color picker in the #GtkColorSelectionDialog.
2092 *
2093 * Since: 2.8
2094 *
2095 * Deprecated: 3.0: Use gdk_device_warp() instead.
2096 */
2097void
2098gdk_display_warp_pointer (GdkDisplay *display,
2099 GdkScreen *screen,
2100 gint x,
2101 gint y)
2102{
2103 GdkDevice *pointer;
2104
2105 g_return_if_fail (GDK_IS_DISPLAY (display));
2106
2107 pointer = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
2108 gdk_device_warp (pointer, screen, x, y);
2109}
2110
2111gulong
2112_gdk_display_get_next_serial (GdkDisplay *display)
2113{
2114 return GDK_DISPLAY_GET_CLASS (display)->get_next_serial (display);
2115}
2116
2117
2118/**
2119 * gdk_notify_startup_complete:
2120 *
2121 * Indicates to the GUI environment that the application has finished
2122 * loading. If the applications opens windows, this function is
2123 * normally called after opening the application’s initial set of
2124 * windows.
2125 *
2126 * GTK+ will call this function automatically after opening the first
2127 * #GtkWindow unless gtk_window_set_auto_startup_notification() is called
2128 * to disable that feature.
2129 *
2130 * Since: 2.2
2131 **/
2132void
2133gdk_notify_startup_complete (void)
2134{
2135 gdk_notify_startup_complete_with_id (NULL);
2136}
2137
2138/**
2139 * gdk_notify_startup_complete_with_id:
2140 * @startup_id: a startup-notification identifier, for which
2141 * notification process should be completed
2142 *
2143 * Indicates to the GUI environment that the application has
2144 * finished loading, using a given identifier.
2145 *
2146 * GTK+ will call this function automatically for #GtkWindow
2147 * with custom startup-notification identifier unless
2148 * gtk_window_set_auto_startup_notification() is called to
2149 * disable that feature.
2150 *
2151 * Since: 2.12
2152 */
2153void
2154gdk_notify_startup_complete_with_id (const gchar* startup_id)
2155{
2156 GdkDisplay *display;
2157
2158 display = gdk_display_get_default ();
2159 if (display)
2160 gdk_display_notify_startup_complete (display, startup_id);
2161}
2162
2163/**
2164 * gdk_display_notify_startup_complete:
2165 * @display: a #GdkDisplay
2166 * @startup_id: a startup-notification identifier, for which
2167 * notification process should be completed
2168 *
2169 * Indicates to the GUI environment that the application has
2170 * finished loading, using a given identifier.
2171 *
2172 * GTK+ will call this function automatically for #GtkWindow
2173 * with custom startup-notification identifier unless
2174 * gtk_window_set_auto_startup_notification() is called to
2175 * disable that feature.
2176 *
2177 * Since: 3.0
2178 */
2179void
2180gdk_display_notify_startup_complete (GdkDisplay *display,
2181 const gchar *startup_id)
2182{
2183 g_return_if_fail (GDK_IS_DISPLAY (display));
2184
2185 GDK_DISPLAY_GET_CLASS (display)->notify_startup_complete (display, startup_id);
2186}
2187
2188void
2189_gdk_display_pause_events (GdkDisplay *display)
2190{
2191 display->event_pause_count++;
2192}
2193
2194void
2195_gdk_display_unpause_events (GdkDisplay *display)
2196{
2197 g_return_if_fail (display->event_pause_count > 0);
2198
2199 display->event_pause_count--;
2200}
2201
2202void
2203_gdk_display_event_data_copy (GdkDisplay *display,
2204 const GdkEvent *event,
2205 GdkEvent *new_event)
2206{
2207 GDK_DISPLAY_GET_CLASS (display)->event_data_copy (display, event, new_event);
2208}
2209
2210void
2211_gdk_display_event_data_free (GdkDisplay *display,
2212 GdkEvent *event)
2213{
2214 GDK_DISPLAY_GET_CLASS (display)->event_data_free (display, event);
2215}
2216
2217void
2218_gdk_display_create_window_impl (GdkDisplay *display,
2219 GdkWindow *window,
2220 GdkWindow *real_parent,
2221 GdkScreen *screen,
2222 GdkEventMask event_mask,
2223 GdkWindowAttr *attributes,
2224 gint attributes_mask)
2225{
2226 GDK_DISPLAY_GET_CLASS (display)->create_window_impl (display,
2227 window,
2228 real_parent,
2229 screen,
2230 event_mask,
2231 attributes,
2232 attributes_mask);
2233}
2234
2235GdkWindow *
2236_gdk_display_create_window (GdkDisplay *display)
2237{
2238 return g_object_new (GDK_DISPLAY_GET_CLASS (display)->window_type, NULL);
2239}
2240
2241/**
2242 * gdk_keymap_get_for_display:
2243 * @display: the #GdkDisplay.
2244 *
2245 * Returns the #GdkKeymap attached to @display.
2246 *
2247 * Returns: (transfer none): the #GdkKeymap attached to @display.
2248 *
2249 * Since: 2.2
2250 */
2251GdkKeymap*
2252gdk_keymap_get_for_display (GdkDisplay *display)
2253{
2254 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
2255
2256 return GDK_DISPLAY_GET_CLASS (display)->get_keymap (display);
2257}
2258
2259typedef struct _GdkGlobalErrorTrap GdkGlobalErrorTrap;
2260
2261struct _GdkGlobalErrorTrap
2262{
2263 GSList *displays;
2264};
2265
2266static GQueue gdk_error_traps = G_QUEUE_INIT;
2267
2268/**
2269 * gdk_error_trap_push:
2270 *
2271 * This function allows X errors to be trapped instead of the normal
2272 * behavior of exiting the application. It should only be used if it
2273 * is not possible to avoid the X error in any other way. Errors are
2274 * ignored on all #GdkDisplay currently known to the
2275 * #GdkDisplayManager. If you don’t care which error happens and just
2276 * want to ignore everything, pop with gdk_error_trap_pop_ignored().
2277 * If you need the error code, use gdk_error_trap_pop() which may have
2278 * to block and wait for the error to arrive from the X server.
2279 *
2280 * This API exists on all platforms but only does anything on X.
2281 *
2282 * You can use gdk_x11_display_error_trap_push() to ignore errors
2283 * on only a single display.
2284 *
2285 * ## Trapping an X error
2286 *
2287 * |[<!-- language="C" -->
2288 * gdk_error_trap_push ();
2289 *
2290 * // ... Call the X function which may cause an error here ...
2291 *
2292 *
2293 * if (gdk_error_trap_pop ())
2294 * {
2295 * // ... Handle the error here ...
2296 * }
2297 * ]|
2298 */
2299void
2300gdk_error_trap_push (void)
2301{
2302 GdkDisplayManager *manager;
2303 GdkDisplayClass *class;
2304 GdkGlobalErrorTrap *trap;
2305 GSList *l;
2306
2307 manager = gdk_display_manager_get ();
2308 class = GDK_DISPLAY_GET_CLASS (gdk_display_manager_get_default_display (manager));
2309
2310 if (class->push_error_trap == NULL)
2311 return;
2312
2313 trap = g_slice_new (GdkGlobalErrorTrap);
2314 trap->displays = gdk_display_manager_list_displays (manager);
2315
2316 g_slist_foreach (trap->displays, (GFunc) g_object_ref, NULL);
2317 for (l = trap->displays; l != NULL; l = l->next)
2318 class->push_error_trap (l->data);
2319
2320 g_queue_push_head (&gdk_error_traps, trap);
2321}
2322
2323static gint
2324gdk_error_trap_pop_internal (gboolean need_code)
2325{
2326 GdkDisplayManager *manager;
2327 GdkDisplayClass *class;
2328 GdkGlobalErrorTrap *trap;
2329 gint result;
2330 GSList *l;
2331
2332 manager = gdk_display_manager_get ();
2333 class = GDK_DISPLAY_GET_CLASS (gdk_display_manager_get_default_display (manager));
2334
2335 if (class->pop_error_trap == NULL)
2336 return 0;
2337
2338 trap = g_queue_pop_head (&gdk_error_traps);
2339
2340 g_return_val_if_fail (trap != NULL, 0);
2341
2342 result = 0;
2343 for (l = trap->displays; l != NULL; l = l->next)
2344 {
2345 gint code = 0;
2346
2347 code = class->pop_error_trap (l->data, !need_code);
2348
2349 /* we use the error on the last display listed, why not. */
2350 if (code != 0)
2351 result = code;
2352 }
2353
2354 g_slist_free_full (trap->displays, g_object_unref);
2355 g_slice_free (GdkGlobalErrorTrap, trap);
2356
2357 return result;
2358}
2359
2360/**
2361 * gdk_error_trap_pop_ignored:
2362 *
2363 * Removes an error trap pushed with gdk_error_trap_push(), but
2364 * without bothering to wait and see whether an error occurred. If an
2365 * error arrives later asynchronously that was triggered while the
2366 * trap was pushed, that error will be ignored.
2367 *
2368 * Since: 3.0
2369 */
2370void
2371gdk_error_trap_pop_ignored (void)
2372{
2373 gdk_error_trap_pop_internal (FALSE);
2374}
2375
2376/**
2377 * gdk_error_trap_pop:
2378 *
2379 * Removes an error trap pushed with gdk_error_trap_push().
2380 * May block until an error has been definitively received
2381 * or not received from the X server. gdk_error_trap_pop_ignored()
2382 * is preferred if you don’t need to know whether an error
2383 * occurred, because it never has to block. If you don't
2384 * need the return value of gdk_error_trap_pop(), use
2385 * gdk_error_trap_pop_ignored().
2386 *
2387 * Prior to GDK 3.0, this function would not automatically
2388 * sync for you, so you had to gdk_flush() if your last
2389 * call to Xlib was not a blocking round trip.
2390 *
2391 * Returns: X error code or 0 on success
2392 */
2393gint
2394gdk_error_trap_pop (void)
2395{
2396 return gdk_error_trap_pop_internal (TRUE);
2397}
2398
2399/*< private >
2400 * gdk_display_make_gl_context_current:
2401 * @display: a #GdkDisplay
2402 * @context: (optional): a #GdkGLContext, or %NULL
2403 *
2404 * Makes the given @context the current GL context, or unsets
2405 * the current GL context if @context is %NULL.
2406 */
2407gboolean
2408gdk_display_make_gl_context_current (GdkDisplay *display,
2409 GdkGLContext *context)
2410{
2411 return GDK_DISPLAY_GET_CLASS (display)->make_gl_context_current (display, context);
2412}
2413
2414GdkRenderingMode
2415gdk_display_get_rendering_mode (GdkDisplay *display)
2416{
2417 return display->rendering_mode;
2418}
2419
2420void
2421gdk_display_set_rendering_mode (GdkDisplay *display,
2422 GdkRenderingMode mode)
2423{
2424 display->rendering_mode = mode;
2425}
2426
2427void
2428gdk_display_set_debug_updates (GdkDisplay *display,
2429 gboolean debug_updates)
2430{
2431 display->debug_updates = debug_updates;
2432 display->debug_updates_set = TRUE;
2433}
2434
2435gboolean
2436gdk_display_get_debug_updates (GdkDisplay *display)
2437{
2438 if (display->debug_updates_set)
2439 return display->debug_updates;
2440 else
2441 return _gdk_debug_updates;
2442}
2443
2444void
2445gdk_display_add_seat (GdkDisplay *display,
2446 GdkSeat *seat)
2447{
2448 g_return_if_fail (GDK_IS_DISPLAY (display));
2449 g_return_if_fail (GDK_IS_SEAT (seat));
2450
2451 display->seats = g_list_append (display->seats, g_object_ref (seat));
2452 g_signal_emit (display, signals[SEAT_ADDED], 0, seat);
2453}
2454
2455void
2456gdk_display_remove_seat (GdkDisplay *display,
2457 GdkSeat *seat)
2458{
2459 GList *link;
2460
2461 g_return_if_fail (GDK_IS_DISPLAY (display));
2462 g_return_if_fail (GDK_IS_SEAT (seat));
2463
2464 link = g_list_find (display->seats, seat);
2465
2466 if (link)
2467 {
2468 display->seats = g_list_remove_link (display->seats, link);
2469 g_signal_emit (display, signals[SEAT_REMOVED], 0, seat);
2470 g_object_unref (link->data);
2471 g_list_free (link);
2472 }
2473}
2474
2475/**
2476 * gdk_display_get_default_seat:
2477 * @display: a #GdkDisplay
2478 *
2479 * Returns the default #GdkSeat for this display.
2480 *
2481 * Returns: (transfer none): the default seat.
2482 *
2483 * Since: 3.20
2484 **/
2485GdkSeat *
2486gdk_display_get_default_seat (GdkDisplay *display)
2487{
2488 GdkDisplayClass *display_class;
2489
2490 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
2491
2492 display_class = GDK_DISPLAY_GET_CLASS (display);
2493
2494 return display_class->get_default_seat (display);
2495}
2496
2497/**
2498 * gdk_display_list_seats:
2499 * @display: a #GdkDisplay
2500 *
2501 * Returns the list of seats known to @display.
2502 *
2503 * Returns: (transfer container) (element-type GdkSeat): the
2504 * list of seats known to the #GdkDisplay
2505 *
2506 * Since: 3.20
2507 **/
2508GList *
2509gdk_display_list_seats (GdkDisplay *display)
2510{
2511 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
2512
2513 return g_list_copy (display->seats);
2514}
2515
2516/**
2517 * gdk_display_get_n_monitors:
2518 * @display: a #GdkDisplay
2519 *
2520 * Gets the number of monitors that belong to @display.
2521 *
2522 * The returned number is valid until the next emission of the
2523 * #GdkDisplay::monitor-added or #GdkDisplay::monitor-removed signal.
2524 *
2525 * Returns: the number of monitors
2526 * Since: 3.22
2527 */
2528int
2529gdk_display_get_n_monitors (GdkDisplay *display)
2530{
2531 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
2532
2533 if (GDK_DISPLAY_GET_CLASS (display)->get_n_monitors == NULL)
2534 return 1;
2535
2536 return GDK_DISPLAY_GET_CLASS (display)->get_n_monitors (display);
2537}
2538
2539static GdkMonitor *
2540get_fallback_monitor (GdkDisplay *display)
2541{
2542 static GdkMonitor *monitor = NULL;
2543 GdkScreen *screen;
2544
2545 if (monitor == NULL)
2546 {
2547 g_warning ("%s does not implement the monitor vfuncs", G_OBJECT_TYPE_NAME (display));
2548 monitor = gdk_monitor_new (display);
2549 gdk_monitor_set_manufacturer (monitor, "fallback");
2550 gdk_monitor_set_position (monitor, 0, 0);
2551 gdk_monitor_set_scale_factor (monitor, 1);
2552 }
2553
2554 screen = gdk_display_get_default_screen (display);
2555 gdk_monitor_set_size (monitor,
2556 gdk_screen_get_width (screen),
2557 gdk_screen_get_height (screen));
2558 gdk_monitor_set_physical_size (monitor,
2559 gdk_screen_get_width_mm (screen),
2560 gdk_screen_get_height_mm (screen));
2561
2562 return monitor;
2563}
2564
2565/**
2566 * gdk_display_get_monitor:
2567 * @display: a #GdkDisplay
2568 * @monitor_num: number of the monitor
2569 *
2570 * Gets a monitor associated with this display.
2571 *
2572 * Returns: (transfer none): the #GdkMonitor, or %NULL if
2573 * @monitor_num is not a valid monitor number
2574 * Since: 3.22
2575 */
2576GdkMonitor *
2577gdk_display_get_monitor (GdkDisplay *display,
2578 gint monitor_num)
2579{
2580 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
2581
2582 if (GDK_DISPLAY_GET_CLASS (display)->get_monitor == NULL)
2583 return get_fallback_monitor (display);
2584
2585 return GDK_DISPLAY_GET_CLASS (display)->get_monitor (display, monitor_num);
2586}
2587
2588/**
2589 * gdk_display_get_primary_monitor:
2590 * @display: a #GdkDisplay
2591 *
2592 * Gets the primary monitor for the display.
2593 *
2594 * The primary monitor is considered the monitor where the “main desktop”
2595 * lives. While normal application windows typically allow the window
2596 * manager to place the windows, specialized desktop applications
2597 * such as panels should place themselves on the primary monitor.
2598 *
2599 * Returns: (transfer none): the primary monitor, or %NULL if no primary
2600 * monitor is configured by the user
2601 * Since: 3.22
2602 */
2603GdkMonitor *
2604gdk_display_get_primary_monitor (GdkDisplay *display)
2605{
2606 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
2607
2608 if (GDK_DISPLAY_GET_CLASS (display)->get_primary_monitor)
2609 return GDK_DISPLAY_GET_CLASS (display)->get_primary_monitor (display);
2610
2611 return NULL;
2612}
2613
2614/**
2615 * gdk_display_get_monitor_at_point:
2616 * @display: a #GdkDisplay
2617 * @x: the x coordinate of the point
2618 * @y: the y coordinate of the point
2619 *
2620 * Gets the monitor in which the point (@x, @y) is located,
2621 * or a nearby monitor if the point is not in any monitor.
2622 *
2623 * Returns: (transfer none): the monitor containing the point
2624 * Since: 3.22
2625 */
2626GdkMonitor *
2627gdk_display_get_monitor_at_point (GdkDisplay *display,
2628 int x,
2629 int y)
2630{
2631 GdkMonitor *nearest = NULL;
2632 int nearest_dist = G_MAXINT;
2633 int n_monitors, i;
2634
2635 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
2636
2637 n_monitors = gdk_display_get_n_monitors (display);
2638 for (i = 0; i < n_monitors; i++)
2639 {
2640 GdkMonitor *monitor;
2641 GdkRectangle geometry;
2642 int dist_x, dist_y, dist;
2643
2644 monitor = gdk_display_get_monitor (display, i);
2645 gdk_monitor_get_geometry (monitor, &geometry);
2646
2647 if (x < geometry.x)
2648 dist_x = geometry.x - x;
2649 else if (geometry.x + geometry.width <= x)
2650 dist_x = x - (geometry.x + geometry.width) + 1;
2651 else
2652 dist_x = 0;
2653
2654 if (y < geometry.y)
2655 dist_y = geometry.y - y;
2656 else if (geometry.y + geometry.height <= y)
2657 dist_y = y - (geometry.y + geometry.height) + 1;
2658 else
2659 dist_y = 0;
2660
2661 dist = dist_x + dist_y;
2662 if (dist < nearest_dist)
2663 {
2664 nearest_dist = dist;
2665 nearest = monitor;
2666 }
2667
2668 if (nearest_dist == 0)
2669 break;
2670 }
2671
2672 return nearest;
2673}
2674
2675/**
2676 * gdk_display_get_monitor_at_window:
2677 * @display: a #GdkDisplay
2678 * @window: a #GdkWindow
2679 *
2680 * Gets the monitor in which the largest area of @window
2681 * resides, or a monitor close to @window if it is outside
2682 * of all monitors.
2683 *
2684 * Returns: (transfer none): the monitor with the largest overlap with @window
2685 * Since: 3.22
2686 */
2687GdkMonitor *
2688gdk_display_get_monitor_at_window (GdkDisplay *display,
2689 GdkWindow *window)
2690{
2691 GdkRectangle win;
2692 int n_monitors, i;
2693 int area = 0;
2694 GdkMonitor *best = NULL;
2695 GdkDisplayClass *class;
2696
2697 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
2698
2699 class = GDK_DISPLAY_GET_CLASS (display);
2700 if (class->get_monitor_at_window)
2701 {
2702 best = class->get_monitor_at_window (display, window);
2703
2704 if (best)
2705 return best;
2706 }
2707
2708 gdk_window_get_geometry (window, &win.x, &win.y, &win.width, &win.height);
2709 gdk_window_get_origin (window, &win.x, &win.y);
2710
2711 n_monitors = gdk_display_get_n_monitors (display);
2712 for (i = 0; i < n_monitors; i++)
2713 {
2714 GdkMonitor *monitor;
2715 GdkRectangle mon, intersect;
2716 int overlap;
2717
2718 monitor = gdk_display_get_monitor (display, i);
2719 gdk_monitor_get_geometry (monitor, &mon);
2720 gdk_rectangle_intersect (&win, &mon, &intersect);
2721 overlap = intersect.width *intersect.height;
2722 if (overlap > area)
2723 {
2724 area = overlap;
2725 best = monitor;
2726 }
2727 }
2728
2729 if (best)
2730 return best;
2731
2732 return gdk_display_get_monitor_at_point (display,
2733 win.x + win.width / 2,
2734 win.y + win.height / 2);
2735}
2736
2737void
2738gdk_display_monitor_added (GdkDisplay *display,
2739 GdkMonitor *monitor)
2740{
2741 g_signal_emit (display, signals[MONITOR_ADDED], 0, monitor);
2742}
2743
2744void
2745gdk_display_monitor_removed (GdkDisplay *display,
2746 GdkMonitor *monitor)
2747{
2748 g_signal_emit (display, signals[MONITOR_REMOVED], 0, monitor);
2749 gdk_monitor_invalidate (monitor);
2750}
2751