From 46cb506f8fed1951d1332a37de9b81b44525a887 Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Wed, 14 Jun 2017 11:27:14 +0200 Subject: [PATCH] wayland: use the inhibit shortcuts dialog Plug the new MetaInhbitShortcutsDialog to the relevant Wayland protocol implementation. Also, remember the last user choice for a given surface to avoid asking continuously the same question. https://bugzilla.gnome.org/show_bug.cgi?id=783342 --- src/Makefile.am | 4 + .../meta-wayland-inhibit-shortcuts-dialog.c | 169 ++++++++++++++++++ .../meta-wayland-inhibit-shortcuts-dialog.h | 31 ++++ src/wayland/meta-wayland-inhibit-shortcuts.c | 6 +- src/wayland/meta-wayland.c | 2 + 5 files changed, 210 insertions(+), 2 deletions(-) create mode 100644 src/wayland/meta-wayland-inhibit-shortcuts-dialog.c create mode 100644 src/wayland/meta-wayland-inhibit-shortcuts-dialog.h diff --git a/src/Makefile.am b/src/Makefile.am index 4d45a8ad7..88b83374a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -237,6 +237,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \ core/meta-close-dialog-default-private.h \ core/meta-inhibit-shortcuts-dialog.c \ meta/meta-inhibit-shortcuts-dialog.h \ + core/meta-inhibit-shortcuts-dialog-default.c \ + core/meta-inhibit-shortcuts-dialog-default-private.h \ core/delete.c \ core/display.c \ core/display-private.h \ @@ -394,6 +396,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES += \ wayland/meta-wayland-gtk-shell.h \ wayland/meta-wayland-inhibit-shortcuts.c \ wayland/meta-wayland-inhibit-shortcuts.h \ + wayland/meta-wayland-inhibit-shortcuts-dialog.c \ + wayland/meta-wayland-inhibit-shortcuts-dialog.h \ $(NULL) endif diff --git a/src/wayland/meta-wayland-inhibit-shortcuts-dialog.c b/src/wayland/meta-wayland-inhibit-shortcuts-dialog.c new file mode 100644 index 000000000..6eb2208e7 --- /dev/null +++ b/src/wayland/meta-wayland-inhibit-shortcuts-dialog.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2017 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include + +#include "wayland/meta-window-wayland.h" +#include "wayland/meta-wayland.h" +#include "core/window-private.h" +#include "compositor/compositor-private.h" +#include "meta-wayland-inhibit-shortcuts-dialog.h" + +static GQuark quark_surface_inhibit_shortcuts_data = 0; + +typedef struct _InhibitShortcutsData +{ + MetaWaylandSurface *surface; + MetaWaylandSeat *seat; + MetaInhibitShortcutsDialog *dialog; + MetaInhibitShortcutsDialogResponse last_response; +} InhibitShortcutsData; + +static InhibitShortcutsData * +surface_inhibit_shortcuts_data_get (MetaWaylandSurface *surface) +{ + return g_object_get_qdata (G_OBJECT (surface), + quark_surface_inhibit_shortcuts_data); +} + +static void +surface_inhibit_shortcuts_data_set (MetaWaylandSurface *surface, + InhibitShortcutsData *data) +{ + g_object_set_qdata (G_OBJECT (surface), + quark_surface_inhibit_shortcuts_data, + data); +} + +static void +surface_inhibit_shortcuts_data_free (MetaWaylandSurface *surface, + InhibitShortcutsData *data) +{ + meta_inhibit_shortcuts_dialog_hide (data->dialog); + + g_free (data); +} + +static void +surface_inhibit_shortcuts_dialog_free (gpointer ptr, + GClosure *closure) +{ + InhibitShortcutsData *data = ptr; + + meta_wayland_surface_hide_inhibit_shortcuts_dialog (data->surface); +} + +static void +inhibit_shortcuts_dialog_response_apply (InhibitShortcutsData *data) +{ + if (data->last_response == META_INHIBIT_SHORTCUTS_DIALOG_RESPONSE_ALLOW) + meta_wayland_surface_inhibit_shortcuts (data->surface, data->seat); + else if (meta_wayland_surface_is_shortcuts_inhibited (data->surface, data->seat)) + meta_wayland_surface_restore_shortcuts (data->surface, data->seat); +} + +static void +inhibit_shortcuts_dialog_response_cb (MetaInhibitShortcutsDialog *dialog, + MetaInhibitShortcutsDialogResponse response, + InhibitShortcutsData *data) +{ + data->last_response = response; + inhibit_shortcuts_dialog_response_apply (data); + meta_wayland_surface_hide_inhibit_shortcuts_dialog (data->surface); +} + +static InhibitShortcutsData * +meta_wayland_surface_ensure_inhibit_shortcuts_dialog (MetaWaylandSurface *surface, + MetaWaylandSeat *seat) +{ + InhibitShortcutsData *data; + MetaWindow *window; + MetaDisplay *display; + MetaInhibitShortcutsDialog *dialog; + + data = surface_inhibit_shortcuts_data_get (surface); + if (data == NULL) + { + data = g_new (InhibitShortcutsData, 1); + surface_inhibit_shortcuts_data_set (surface, data); + } + else if (data->dialog != NULL) + /* There is a dialog already created, nothing to do */ + return data; + + window = meta_wayland_surface_get_toplevel_window (surface); + display = window->display; + dialog = + meta_compositor_create_inhibit_shortcuts_dialog (display->compositor, + window); + + data->surface = surface; + data->seat = seat; + data->dialog = dialog; + + g_signal_connect_data (dialog, "response", + G_CALLBACK (inhibit_shortcuts_dialog_response_cb), + data, surface_inhibit_shortcuts_dialog_free, + 0); + + g_signal_connect (surface, "destroy", + G_CALLBACK (surface_inhibit_shortcuts_data_free), + data); + + return data; +} + +void +meta_wayland_surface_show_inhibit_shortcuts_dialog (MetaWaylandSurface *surface, + MetaWaylandSeat *seat) +{ + InhibitShortcutsData *data; + + g_return_if_fail (META_IS_WAYLAND_SURFACE (surface)); + + data = surface_inhibit_shortcuts_data_get (surface); + if (data != NULL) + { + /* The dialog was shown before for this surface but is not showing + * anymore, reuse the last user response. + */ + inhibit_shortcuts_dialog_response_apply (data); + return; + } + + data = meta_wayland_surface_ensure_inhibit_shortcuts_dialog (surface, seat); + meta_inhibit_shortcuts_dialog_show (data->dialog); +} + +void +meta_wayland_surface_hide_inhibit_shortcuts_dialog (MetaWaylandSurface *surface) +{ + InhibitShortcutsData *data; + + g_return_if_fail (META_IS_WAYLAND_SURFACE (surface)); + + /* The closure notify will take care of actually hiding the dialog */ + data = surface_inhibit_shortcuts_data_get (surface); + g_signal_handlers_disconnect_by_data (surface, data); +} + +void +meta_wayland_surface_inhibit_shortcuts_dialog_init (void) +{ + quark_surface_inhibit_shortcuts_data = + g_quark_from_static_string ("-meta-wayland-surface-inhibit-shortcuts-data"); +} diff --git a/src/wayland/meta-wayland-inhibit-shortcuts-dialog.h b/src/wayland/meta-wayland-inhibit-shortcuts-dialog.h new file mode 100644 index 000000000..bd3fc42b0 --- /dev/null +++ b/src/wayland/meta-wayland-inhibit-shortcuts-dialog.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2017 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + */ + +#ifndef META_WAYLAND_INHIBIT_SHORTCUTS_DIALOG_H +#define META_WAYLAND_INHIBIT_SHORTCUTS_DIALOG_H + +#include "meta-wayland-private.h" + +void meta_wayland_surface_show_inhibit_shortcuts_dialog (MetaWaylandSurface *surface, + MetaWaylandSeat *seat); + +void meta_wayland_surface_hide_inhibit_shortcuts_dialog (MetaWaylandSurface *surface); + +void meta_wayland_surface_inhibit_shortcuts_dialog_init (void); + +#endif /* META_WAYLAND_INHIBIT_SHORTCUTS_DIALOG_H */ diff --git a/src/wayland/meta-wayland-inhibit-shortcuts.c b/src/wayland/meta-wayland-inhibit-shortcuts.c index e4b72643d..cd078917d 100644 --- a/src/wayland/meta-wayland-inhibit-shortcuts.c +++ b/src/wayland/meta-wayland-inhibit-shortcuts.c @@ -28,6 +28,7 @@ #include "wayland/meta-wayland-private.h" #include "wayland/meta-wayland-versions.h" #include "wayland/meta-wayland-inhibit-shortcuts.h" +#include "wayland/meta-wayland-inhibit-shortcuts-dialog.h" struct _MetaWaylandKeyboardShotscutsInhibit { @@ -48,6 +49,8 @@ zwp_keyboard_shortcuts_inhibit_destroy (struct wl_client *client, shortcut_inhibit = wl_resource_get_user_data (resource); if (shortcut_inhibit->surface) { + meta_wayland_surface_hide_inhibit_shortcuts_dialog (shortcut_inhibit->surface); + g_signal_handler_disconnect (shortcut_inhibit->surface, shortcut_inhibit->surface_destroyed_handler); @@ -135,13 +138,12 @@ zwp_keyboard_shortcuts_inhibit_manager_inhibit_shortcuts (struct wl_client *cl g_signal_connect (surface, "shortcuts-restored", G_CALLBACK (shortcuts_restored_cb), shortcut_inhibit); - shortcut_inhibit->surface_destroyed_handler = g_signal_connect (surface, "destroy", G_CALLBACK (surface_destroyed_cb), shortcut_inhibit); - meta_wayland_surface_inhibit_shortcuts (surface, seat); + meta_wayland_surface_show_inhibit_shortcuts_dialog (surface, seat); wl_resource_set_implementation (keyboard_shortcuts_inhibit_resource, &meta_keyboard_shortcuts_inhibit_interface, diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c index e25739100..414c7fb5b 100644 --- a/src/wayland/meta-wayland.c +++ b/src/wayland/meta-wayland.c @@ -43,6 +43,7 @@ #include "meta-wayland-xdg-foreign.h" #include "meta-wayland-dma-buf.h" #include "meta-wayland-inhibit-shortcuts.h" +#include "meta-wayland-inhibit-shortcuts-dialog.h" static MetaWaylandCompositor _meta_wayland_compositor; static char *_display_name_override; @@ -359,6 +360,7 @@ meta_wayland_init (void) meta_wayland_xdg_foreign_init (compositor); meta_wayland_dma_buf_init (compositor); meta_wayland_keyboard_shortcuts_inhibit_init (compositor); + meta_wayland_surface_inhibit_shortcuts_dialog_init (); if (!meta_xwayland_start (&compositor->xwayland_manager, compositor->wayland_display)) g_error ("Failed to start X Wayland");