1 /*
2 * Copyright © 2020 Red Hat, Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authors: Matthias Clasen <mclasen@redhat.com>
18 */
19
20 #include "config.h"
21
22 #include "gdkintl.h"
23 #include "gdk-private.h"
24 #include "gdktoplevelprivate.h"
25
26 #include <graphene-gobject.h>
27 #include <math.h>
28
29 /**
30 * GdkToplevel:
31 *
32 * A `GdkToplevel` is a freestanding toplevel surface.
33 *
34 * The `GdkToplevel` interface provides useful APIs for interacting with
35 * the windowing system, such as controlling maximization and size of the
36 * surface, setting icons and transient parents for dialogs.
37 */
38
39 G_DEFINE_INTERFACE (GdkToplevel, gdk_toplevel, GDK_TYPE_SURFACE)
40
41 enum
42 {
43 COMPUTE_SIZE,
44
45 N_SIGNALS
46 };
47
48 static guint signals[N_SIGNALS] = { 0 };
49
50 static void
gdk_toplevel_default_present(GdkToplevel * toplevel,GdkToplevelLayout * layout)51 gdk_toplevel_default_present (GdkToplevel *toplevel,
52 GdkToplevelLayout *layout)
53 {
54 }
55
56 static gboolean
gdk_toplevel_default_minimize(GdkToplevel * toplevel)57 gdk_toplevel_default_minimize (GdkToplevel *toplevel)
58 {
59 return FALSE;
60 }
61
62 static gboolean
gdk_toplevel_default_lower(GdkToplevel * toplevel)63 gdk_toplevel_default_lower (GdkToplevel *toplevel)
64 {
65 return FALSE;
66 }
67
68 static void
gdk_toplevel_default_focus(GdkToplevel * toplevel,guint32 timestamp)69 gdk_toplevel_default_focus (GdkToplevel *toplevel,
70 guint32 timestamp)
71 {
72 }
73
74 static gboolean
gdk_toplevel_default_show_window_menu(GdkToplevel * toplevel,GdkEvent * event)75 gdk_toplevel_default_show_window_menu (GdkToplevel *toplevel,
76 GdkEvent *event)
77 {
78 return FALSE;
79 }
80
81 static gboolean
gdk_toplevel_default_titlebar_gesture(GdkToplevel * toplevel,GdkTitlebarGesture gesture)82 gdk_toplevel_default_titlebar_gesture (GdkToplevel *toplevel,
83 GdkTitlebarGesture gesture)
84 {
85 return FALSE;
86 }
87
88 static gboolean
gdk_toplevel_default_supports_edge_constraints(GdkToplevel * toplevel)89 gdk_toplevel_default_supports_edge_constraints (GdkToplevel *toplevel)
90 {
91 return FALSE;
92 }
93
94 static void
gdk_toplevel_default_inhibit_system_shortcuts(GdkToplevel * toplevel,GdkEvent * event)95 gdk_toplevel_default_inhibit_system_shortcuts (GdkToplevel *toplevel,
96 GdkEvent *event)
97 {
98 }
99
100 static void
gdk_toplevel_default_restore_system_shortcuts(GdkToplevel * toplevel)101 gdk_toplevel_default_restore_system_shortcuts (GdkToplevel *toplevel)
102 {
103 }
104
105 void
gdk_toplevel_notify_compute_size(GdkToplevel * toplevel,GdkToplevelSize * size)106 gdk_toplevel_notify_compute_size (GdkToplevel *toplevel,
107 GdkToplevelSize *size)
108 {
109 g_signal_emit (toplevel, signals[COMPUTE_SIZE], 0, size);
110 gdk_toplevel_size_validate (size);
111 }
112
113 static void
gdk_toplevel_default_init(GdkToplevelInterface * iface)114 gdk_toplevel_default_init (GdkToplevelInterface *iface)
115 {
116 iface->present = gdk_toplevel_default_present;
117 iface->minimize = gdk_toplevel_default_minimize;
118 iface->lower = gdk_toplevel_default_lower;
119 iface->focus = gdk_toplevel_default_focus;
120 iface->show_window_menu = gdk_toplevel_default_show_window_menu;
121 iface->supports_edge_constraints = gdk_toplevel_default_supports_edge_constraints;
122 iface->inhibit_system_shortcuts = gdk_toplevel_default_inhibit_system_shortcuts;
123 iface->restore_system_shortcuts = gdk_toplevel_default_restore_system_shortcuts;
124 iface->titlebar_gesture = gdk_toplevel_default_titlebar_gesture;
125
126 /**
127 * GdkToplevel:state: (attributes org.gtk.Property.get=gdk_toplevel_get_state)
128 *
129 * The state of the toplevel.
130 */
131 g_object_interface_install_property (iface,
132 g_param_spec_flags ("state",
133 P_("State"),
134 P_("State"),
135 GDK_TYPE_TOPLEVEL_STATE, 0,
136 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
137
138 /**
139 * GdkToplevel:title: (attributes org.gtk.Property.set=gdk_toplevel_set_title)
140 *
141 * The title of the surface.
142 */
143 g_object_interface_install_property (iface,
144 g_param_spec_string ("title",
145 "Title",
146 "The title of the surface",
147 NULL,
148 G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
149
150 /**
151 * GdkToplevel:startup-id: (attributes org.gtk.Property.set=gdk_toplevel_set_startup_id)
152 *
153 * The startup ID of the surface.
154 *
155 * See [class@Gdk.AppLaunchContext] for more information about
156 * startup feedback.
157 */
158 g_object_interface_install_property (iface,
159 g_param_spec_string ("startup-id",
160 "Startup ID",
161 "The startup ID of the surface",
162 NULL,
163 G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
164
165 /**
166 * GdkToplevel:transient-for: (attributes org.gtk.Property.set=gdk_toplevel_set_transient_for)
167 *
168 * The transient parent of the surface.
169 */
170 g_object_interface_install_property (iface,
171 g_param_spec_object ("transient-for",
172 "Transient For",
173 "The transient parent of the surface",
174 GDK_TYPE_SURFACE,
175 G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
176
177 /**
178 * GdkToplevel:modal: (attributes org.gtk.Property.set=gdk_toplevel_set_modal)
179 *
180 * Whether the surface is modal.
181 */
182 g_object_interface_install_property (iface,
183 g_param_spec_boolean ("modal",
184 "Modal",
185 "Whether the surface is modal",
186 FALSE,
187 G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
188
189 /**
190 * GdkToplevel:icon-list: (attributes org.gtk.Property.set=gdk_toplevel_set_icon_list)
191 *
192 * A list of textures to use as icon.
193 */
194 g_object_interface_install_property (iface,
195 g_param_spec_pointer ("icon-list",
196 "Icon List",
197 "The list of icon textures",
198 G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
199
200 /**
201 * GdkToplevel:decorated: (attributes org.gtk.Property.set=gdk_toplevel_set_decorated)
202 *
203 * Whether the window manager should add decorations.
204 */
205 g_object_interface_install_property (iface,
206 g_param_spec_boolean ("decorated",
207 "Decorated",
208 "Decorated",
209 FALSE,
210 G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
211
212 /**
213 * GdkToplevel:deletable: (attributes org.gtk.Property.set=gdk_toplevel_set_deletable)
214 *
215 * Whether the window manager should allow to close the surface.
216 */
217 g_object_interface_install_property (iface,
218 g_param_spec_boolean ("deletable",
219 "Deletable",
220 "Deletable",
221 FALSE,
222 G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
223
224 /**
225 * GdkToplevel:fullscreen-mode:
226 *
227 * The fullscreen mode of the surface.
228 */
229 g_object_interface_install_property (iface,
230 g_param_spec_enum ("fullscreen-mode",
231 "Fullscreen mode",
232 "Fullscreen mode",
233 GDK_TYPE_FULLSCREEN_MODE,
234 GDK_FULLSCREEN_ON_CURRENT_MONITOR,
235 G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
236
237 /**
238 * GdkToplevel:shortcuts-inhibited:
239 *
240 * Whether the surface should inhibit keyboard shortcuts.
241 */
242 g_object_interface_install_property (iface,
243 g_param_spec_boolean ("shortcuts-inhibited",
244 "Shortcuts inhibited",
245 "Whether keyboard shortcuts are inhibited",
246 FALSE,
247 G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY));
248
249 /**
250 * GdkToplevel::compute-size:
251 * @toplevel: a `GdkToplevel`
252 * @size: (type Gdk.ToplevelSize) (out caller-allocates): a `GdkToplevelSize`
253 *
254 * Emitted when the size for the surface needs to be computed, when
255 * it is present.
256 *
257 * It will normally be emitted during or after [method@Gdk.Toplevel.present],
258 * depending on the configuration received by the windowing system.
259 * It may also be emitted at any other point in time, in response
260 * to the windowing system spontaneously changing the configuration.
261 *
262 * It is the responsibility of the toplevel user to handle this signal
263 * and compute the desired size of the toplevel, given the information
264 * passed via the [struct@Gdk.ToplevelSize] object. Failing to do so
265 * will result in an arbitrary size being used as a result.
266 */
267 signals[COMPUTE_SIZE] =
268 g_signal_new ("compute-size",
269 GDK_TYPE_TOPLEVEL,
270 G_SIGNAL_RUN_LAST,
271 0,
272 NULL, NULL,
273 NULL,
274 G_TYPE_NONE, 1,
275 GDK_TYPE_TOPLEVEL_SIZE | G_SIGNAL_TYPE_STATIC_SCOPE);
276 }
277
278 guint
gdk_toplevel_install_properties(GObjectClass * object_class,guint first_prop)279 gdk_toplevel_install_properties (GObjectClass *object_class,
280 guint first_prop)
281 {
282 g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_STATE, "state");
283 g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_TITLE, "title");
284 g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_STARTUP_ID, "startup-id");
285 g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_TRANSIENT_FOR, "transient-for");
286 g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_MODAL, "modal");
287 g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_ICON_LIST, "icon-list");
288 g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_DECORATED, "decorated");
289 g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_DELETABLE, "deletable");
290 g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_FULLSCREEN_MODE, "fullscreen-mode");
291 g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_SHORTCUTS_INHIBITED, "shortcuts-inhibited");
292
293 return GDK_TOPLEVEL_NUM_PROPERTIES;
294 }
295
296 /**
297 * gdk_toplevel_present:
298 * @toplevel: the `GdkToplevel` to show
299 * @layout: the `GdkToplevelLayout` object used to layout
300 *
301 * Present @toplevel after having processed the `GdkToplevelLayout` rules.
302 *
303 * If the toplevel was previously not showing, it will be showed,
304 * otherwise it will change layout according to @layout.
305 *
306 * GDK may emit the [signal@Gdk.Toplevel::compute-size] signal to let
307 * the user of this toplevel compute the preferred size of the toplevel
308 * surface.
309 *
310 * Presenting is asynchronous and the specified layout parameters are not
311 * guaranteed to be respected.
312 */
313 void
gdk_toplevel_present(GdkToplevel * toplevel,GdkToplevelLayout * layout)314 gdk_toplevel_present (GdkToplevel *toplevel,
315 GdkToplevelLayout *layout)
316 {
317 g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
318 g_return_if_fail (layout != NULL);
319
320 GDK_TOPLEVEL_GET_IFACE (toplevel)->present (toplevel, layout);
321 }
322
323 /**
324 * gdk_toplevel_minimize:
325 * @toplevel: a `GdkToplevel`
326 *
327 * Asks to minimize the @toplevel.
328 *
329 * The windowing system may choose to ignore the request.
330 *
331 * Returns: %TRUE if the surface was minimized
332 */
333 gboolean
gdk_toplevel_minimize(GdkToplevel * toplevel)334 gdk_toplevel_minimize (GdkToplevel *toplevel)
335 {
336 g_return_val_if_fail (GDK_IS_TOPLEVEL (toplevel), FALSE);
337
338 return GDK_TOPLEVEL_GET_IFACE (toplevel)->minimize (toplevel);
339 }
340
341 /**
342 * gdk_toplevel_lower:
343 * @toplevel: a `GdkToplevel`
344 *
345 * Asks to lower the @toplevel below other windows.
346 *
347 * The windowing system may choose to ignore the request.
348 *
349 * Returns: %TRUE if the surface was lowered
350 */
351 gboolean
gdk_toplevel_lower(GdkToplevel * toplevel)352 gdk_toplevel_lower (GdkToplevel *toplevel)
353 {
354 g_return_val_if_fail (GDK_IS_TOPLEVEL (toplevel), FALSE);
355
356 return GDK_TOPLEVEL_GET_IFACE (toplevel)->lower (toplevel);
357 }
358
359 /**
360 * gdk_toplevel_focus:
361 * @toplevel: a `GdkToplevel`
362 * @timestamp: timestamp of the event triggering the surface focus
363 *
364 * Sets keyboard focus to @surface.
365 *
366 * In most cases, [method@Gtk.Window.present_with_time] should be
367 * used on a [class@Gtk.Window], rather than calling this function.
368 */
369 void
gdk_toplevel_focus(GdkToplevel * toplevel,guint32 timestamp)370 gdk_toplevel_focus (GdkToplevel *toplevel,
371 guint32 timestamp)
372 {
373 g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
374
375 GDK_TOPLEVEL_GET_IFACE (toplevel)->focus (toplevel, timestamp);
376 }
377
378 /**
379 * gdk_toplevel_get_state: (attributes org.gtk.Method.get_property=state)
380 * @toplevel: a `GdkToplevel`
381 *
382 * Gets the bitwise or of the currently active surface state flags,
383 * from the `GdkToplevelState` enumeration.
384 *
385 * Returns: surface state bitfield
386 */
387 GdkToplevelState
gdk_toplevel_get_state(GdkToplevel * toplevel)388 gdk_toplevel_get_state (GdkToplevel *toplevel)
389 {
390 GdkToplevelState state;
391
392 g_return_val_if_fail (GDK_IS_TOPLEVEL (toplevel), 0);
393
394 g_object_get (toplevel, "state", &state, NULL);
395
396 return state;
397 }
398
399 /**
400 * gdk_toplevel_set_title: (attributes org.gtk.Method.set_property=title)
401 * @toplevel: a `GdkToplevel`
402 * @title: title of @surface
403 *
404 * Sets the title of a toplevel surface.
405 *
406 * The title maybe be displayed in the titlebar,
407 * in lists of windows, etc.
408 */
409 void
gdk_toplevel_set_title(GdkToplevel * toplevel,const char * title)410 gdk_toplevel_set_title (GdkToplevel *toplevel,
411 const char *title)
412 {
413 g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
414
415 g_object_set (toplevel, "title", title, NULL);
416 }
417
418 /**
419 * gdk_toplevel_set_startup_id: (attributes org.gtk.Method.set_property=startup-id)
420 * @toplevel: a `GdkToplevel`
421 * @startup_id: a string with startup-notification identifier
422 *
423 * Sets the startup notification ID.
424 *
425 * When using GTK, typically you should use
426 * [method@Gtk.Window.set_startup_id] instead of this
427 * low-level function.
428 */
429 void
gdk_toplevel_set_startup_id(GdkToplevel * toplevel,const char * startup_id)430 gdk_toplevel_set_startup_id (GdkToplevel *toplevel,
431 const char *startup_id)
432 {
433 g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
434
435 g_object_set (toplevel, "startup-id", startup_id, NULL);
436 }
437
438 /**
439 * gdk_toplevel_set_transient_for: (attributes org.gtk.Method.set_property=transient-for)
440 * @toplevel: a `GdkToplevel`
441 * @parent: another toplevel `GdkSurface`
442 *
443 * Sets a transient-for parent.
444 *
445 * Indicates to the window manager that @surface is a transient
446 * dialog associated with the application surface @parent. This
447 * allows the window manager to do things like center @surface
448 * on @parent and keep @surface above @parent.
449 *
450 * See [method@Gtk.Window.set_transient_for] if you’re using
451 * [class@Gtk.Window] or [class@Gtk.Dialog].
452 */
453 void
gdk_toplevel_set_transient_for(GdkToplevel * toplevel,GdkSurface * parent)454 gdk_toplevel_set_transient_for (GdkToplevel *toplevel,
455 GdkSurface *parent)
456 {
457 g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
458
459 g_object_set (toplevel, "transient-for", parent, NULL);
460 }
461
462 /**
463 * gdk_toplevel_set_modal: (attributes org.gtk.Method.set_property=modal)
464 * @toplevel: a `GdkToplevel`
465 * @modal: %TRUE if the surface is modal, %FALSE otherwise.
466 *
467 * Sets the toplevel to be modal.
468 *
469 * The application can use this hint to tell the
470 * window manager that a certain surface has modal
471 * behaviour. The window manager can use this information
472 * to handle modal surfaces in a special way.
473 *
474 * You should only use this on surfaces for which you have
475 * previously called [method@Gdk.Toplevel.set_transient_for].
476 */
477 void
gdk_toplevel_set_modal(GdkToplevel * toplevel,gboolean modal)478 gdk_toplevel_set_modal (GdkToplevel *toplevel,
479 gboolean modal)
480 {
481 g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
482
483 g_object_set (toplevel, "modal", modal, NULL);
484 }
485
486 /**
487 * gdk_toplevel_set_icon_list: (attributes org.gtk.Method.set_property=icon-list)
488 * @toplevel: a `GdkToplevel`
489 * @surfaces: (transfer none) (element-type GdkTexture):
490 * A list of textures to use as icon, of different sizes
491 *
492 * Sets a list of icons for the surface.
493 *
494 * One of these will be used to represent the surface in iconic form.
495 * The icon may be shown in window lists or task bars. Which icon
496 * size is shown depends on the window manager. The window manager
497 * can scale the icon but setting several size icons can give better
498 * image quality.
499 *
500 * Note that some platforms don't support surface icons.
501 */
502 void
gdk_toplevel_set_icon_list(GdkToplevel * toplevel,GList * surfaces)503 gdk_toplevel_set_icon_list (GdkToplevel *toplevel,
504 GList *surfaces)
505 {
506 g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
507
508 g_object_set (toplevel, "icon-list", surfaces, NULL);
509 }
510
511 /**
512 * gdk_toplevel_show_window_menu:
513 * @toplevel: a `GdkToplevel`
514 * @event: a `GdkEvent` to show the menu for
515 *
516 * Asks the windowing system to show the window menu.
517 *
518 * The window menu is the menu shown when right-clicking the titlebar
519 * on traditional windows managed by the window manager. This is useful
520 * for windows using client-side decorations, activating it with a
521 * right-click on the window decorations.
522 *
523 * Returns: %TRUE if the window menu was shown and %FALSE otherwise.
524 */
525 gboolean
gdk_toplevel_show_window_menu(GdkToplevel * toplevel,GdkEvent * event)526 gdk_toplevel_show_window_menu (GdkToplevel *toplevel,
527 GdkEvent *event)
528 {
529 g_return_val_if_fail (GDK_IS_TOPLEVEL (toplevel), FALSE);
530
531 return GDK_TOPLEVEL_GET_IFACE (toplevel)->show_window_menu (toplevel, event);
532 }
533
534 /**
535 * gdk_toplevel_set_decorated: (attributes org.gtk.Method.set_property=decorated)
536 * @toplevel: a `GdkToplevel`
537 * @decorated: %TRUE to request decorations
538 *
539 * Sets the toplevel to be decorated.
540 *
541 * Setting @decorated to %FALSE hints the desktop environment
542 * that the surface has its own, client-side decorations and
543 * does not need to have window decorations added.
544 */
545 void
gdk_toplevel_set_decorated(GdkToplevel * toplevel,gboolean decorated)546 gdk_toplevel_set_decorated (GdkToplevel *toplevel,
547 gboolean decorated)
548 {
549 g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
550
551 g_object_set (toplevel, "decorated", decorated, NULL);
552 }
553
554 /**
555 * gdk_toplevel_set_deletable: (attributes org.gtk.Method.set_property=deletable)
556 * @toplevel: a `GdkToplevel`
557 * @deletable: %TRUE to request a delete button
558 *
559 * Sets the toplevel to be deletable.
560 *
561 * Setting @deletable to %TRUE hints the desktop environment
562 * that it should offer the user a way to close the surface.
563 */
564 void
gdk_toplevel_set_deletable(GdkToplevel * toplevel,gboolean deletable)565 gdk_toplevel_set_deletable (GdkToplevel *toplevel,
566 gboolean deletable)
567 {
568 g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
569
570 g_object_set (toplevel, "deletable", deletable, NULL);
571 }
572
573 /**
574 * gdk_toplevel_supports_edge_constraints:
575 * @toplevel: a `GdkToplevel`
576 *
577 * Returns whether the desktop environment supports
578 * tiled window states.
579 *
580 * Returns: %TRUE if the desktop environment supports tiled window states
581 */
582 gboolean
gdk_toplevel_supports_edge_constraints(GdkToplevel * toplevel)583 gdk_toplevel_supports_edge_constraints (GdkToplevel *toplevel)
584 {
585 g_return_val_if_fail (GDK_IS_TOPLEVEL (toplevel), FALSE);
586
587 return GDK_TOPLEVEL_GET_IFACE (toplevel)->supports_edge_constraints (toplevel);
588 }
589
590 /**
591 * gdk_toplevel_inhibit_system_shortcuts:
592 * @toplevel: a `GdkToplevel`
593 * @event: (nullable): the `GdkEvent` that is triggering the inhibit
594 * request, or %NULL if none is available
595 *
596 * Requests that the @toplevel inhibit the system shortcuts.
597 *
598 * This is asking the desktop environment/windowing system to let all
599 * keyboard events reach the surface, as long as it is focused, instead
600 * of triggering system actions.
601 *
602 * If granted, the rerouting remains active until the default shortcuts
603 * processing is restored with [method@Gdk.Toplevel.restore_system_shortcuts],
604 * or the request is revoked by the desktop environment, windowing system
605 * or the user.
606 *
607 * A typical use case for this API is remote desktop or virtual machine
608 * viewers which need to inhibit the default system keyboard shortcuts
609 * so that the remote session or virtual host gets those instead of the
610 * local environment.
611 *
612 * The windowing system or desktop environment may ask the user to grant
613 * or deny the request or even choose to ignore the request entirely.
614 *
615 * The caller can be notified whenever the request is granted or revoked
616 * by listening to the [property@Gdk.Toplevel:shortcuts-inhibited] property.
617 */
618 void
gdk_toplevel_inhibit_system_shortcuts(GdkToplevel * toplevel,GdkEvent * event)619 gdk_toplevel_inhibit_system_shortcuts (GdkToplevel *toplevel,
620 GdkEvent *event)
621 {
622 g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
623
624 GDK_TOPLEVEL_GET_IFACE (toplevel)->inhibit_system_shortcuts (toplevel,
625 event);
626 }
627
628 /**
629 * gdk_toplevel_restore_system_shortcuts:
630 * @toplevel: a `GdkToplevel`
631 *
632 * Restore default system keyboard shortcuts which were previously
633 * inhibited.
634 *
635 * This undoes the effect of [method@Gdk.Toplevel.inhibit_system_shortcuts].
636 */
637 void
gdk_toplevel_restore_system_shortcuts(GdkToplevel * toplevel)638 gdk_toplevel_restore_system_shortcuts (GdkToplevel *toplevel)
639 {
640 g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
641
642 GDK_TOPLEVEL_GET_IFACE (toplevel)->restore_system_shortcuts (toplevel);
643 }
644
645 /**
646 * gdk_toplevel_begin_resize:
647 * @toplevel: a `GdkToplevel`
648 * @edge: the edge or corner from which the drag is started
649 * @device: (nullable): the device used for the operation
650 * @button: the button being used to drag, or 0 for a keyboard-initiated drag
651 * @x: surface X coordinate of mouse click that began the drag
652 * @y: surface Y coordinate of mouse click that began the drag
653 * @timestamp: timestamp of mouse click that began the drag (use
654 * [method@Gdk.Event.get_time])
655 *
656 * Begins an interactive resize operation.
657 *
658 * You might use this function to implement a “window resize grip.”
659 */
660 void
gdk_toplevel_begin_resize(GdkToplevel * toplevel,GdkSurfaceEdge edge,GdkDevice * device,int button,double x,double y,guint32 timestamp)661 gdk_toplevel_begin_resize (GdkToplevel *toplevel,
662 GdkSurfaceEdge edge,
663 GdkDevice *device,
664 int button,
665 double x,
666 double y,
667 guint32 timestamp)
668 {
669 g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
670
671 if (device == NULL)
672 {
673 GdkSeat *seat = gdk_display_get_default_seat (GDK_SURFACE (toplevel)->display);
674 if (button == 0)
675 device = gdk_seat_get_keyboard (seat);
676 else
677 device = gdk_seat_get_pointer (seat);
678 }
679
680 GDK_TOPLEVEL_GET_IFACE (toplevel)->begin_resize (toplevel,
681 edge,
682 device,
683 button,
684 x, y,
685 timestamp);
686 }
687
688 /**
689 * gdk_toplevel_begin_move:
690 * @toplevel: a `GdkToplevel`
691 * @device: the device used for the operation
692 * @button: the button being used to drag, or 0 for a keyboard-initiated drag
693 * @x: surface X coordinate of mouse click that began the drag
694 * @y: surface Y coordinate of mouse click that began the drag
695 * @timestamp: timestamp of mouse click that began the drag (use
696 * [method@Gdk.Event.get_time])
697 *
698 * Begins an interactive move operation.
699 *
700 * You might use this function to implement draggable titlebars.
701 */
702 void
gdk_toplevel_begin_move(GdkToplevel * toplevel,GdkDevice * device,int button,double x,double y,guint32 timestamp)703 gdk_toplevel_begin_move (GdkToplevel *toplevel,
704 GdkDevice *device,
705 int button,
706 double x,
707 double y,
708 guint32 timestamp)
709 {
710 g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
711
712 if (device == NULL)
713 {
714 GdkSeat *seat = gdk_display_get_default_seat (GDK_SURFACE (toplevel)->display);
715 if (button == 0)
716 device = gdk_seat_get_keyboard (seat);
717 else
718 device = gdk_seat_get_pointer (seat);
719 }
720
721 GDK_TOPLEVEL_GET_IFACE (toplevel)->begin_move (toplevel,
722 device,
723 button,
724 x, y,
725 timestamp);
726 }
727
728 gboolean
gdk_toplevel_titlebar_gesture(GdkToplevel * toplevel,GdkTitlebarGesture gesture)729 gdk_toplevel_titlebar_gesture (GdkToplevel *toplevel,
730 GdkTitlebarGesture gesture)
731 {
732 g_return_val_if_fail (GDK_IS_TOPLEVEL (toplevel), FALSE);
733
734 return GDK_TOPLEVEL_GET_IFACE (toplevel)->titlebar_gesture (toplevel,
735 gesture);
736 }
737