92375c75f8
This is inspired by 98892391d7
where the usage of
`g_signal_handler_disconnect()` without resetting the corresponding
handler id later resulted in a bug. Using `g_clear_signal_handler()`
makes sure we avoid similar bugs and is almost always the better
alternative. We use it for new code, let's clean up the old code to
also use it.
A further benefit is that it can get called even if the passed id is
0, allowing us to remove a lot of now unnessecary checks, and the fact
that `g_clear_signal_handler()` checks for the right type size, forcing us
to clean up all places where we used `guint` instead of `gulong`.
No functional changes intended here and all changes should be trivial,
thus bundled in one big commit.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/940
188 lines
6.0 KiB
C
188 lines
6.0 KiB
C
/*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "compositor/compositor-private.h"
|
|
#include "core/window-private.h"
|
|
#include "wayland/meta-wayland-inhibit-shortcuts-dialog.h"
|
|
#include "wayland/meta-wayland.h"
|
|
#include "wayland/meta-window-wayland.h"
|
|
|
|
static GQuark quark_surface_inhibit_shortcuts_data = 0;
|
|
|
|
typedef struct _InhibitShortcutsData
|
|
{
|
|
MetaWaylandSurface *surface;
|
|
MetaWaylandSeat *seat;
|
|
MetaInhibitShortcutsDialog *dialog;
|
|
gulong response_handler_id;
|
|
gboolean has_last_response;
|
|
gboolean request_canceled;
|
|
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_destroy_dialog (InhibitShortcutsData *data)
|
|
{
|
|
g_clear_signal_handler (&data->response_handler_id, data->dialog);
|
|
meta_inhibit_shortcuts_dialog_hide (data->dialog);
|
|
g_clear_object (&data->dialog);
|
|
}
|
|
|
|
static void
|
|
surface_inhibit_shortcuts_data_free (InhibitShortcutsData *data)
|
|
{
|
|
if (data->dialog)
|
|
surface_inhibit_shortcuts_data_destroy_dialog (data);
|
|
g_free (data);
|
|
}
|
|
|
|
static void
|
|
on_surface_destroyed (MetaWaylandSurface *surface,
|
|
InhibitShortcutsData *data)
|
|
{
|
|
surface_inhibit_shortcuts_data_free (data);
|
|
g_object_set_qdata (G_OBJECT (surface),
|
|
quark_surface_inhibit_shortcuts_data,
|
|
NULL);
|
|
}
|
|
|
|
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;
|
|
data->has_last_response = TRUE;
|
|
|
|
/* If the request was canceled, we don't need to apply the choice made */
|
|
if (!data->request_canceled)
|
|
inhibit_shortcuts_dialog_response_apply (data);
|
|
|
|
meta_inhibit_shortcuts_dialog_hide (data->dialog);
|
|
surface_inhibit_shortcuts_data_destroy_dialog (data);
|
|
}
|
|
|
|
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)
|
|
return data;
|
|
|
|
data = g_new0 (InhibitShortcutsData, 1);
|
|
surface_inhibit_shortcuts_data_set (surface, data);
|
|
g_signal_connect (surface, "destroy",
|
|
G_CALLBACK (on_surface_destroyed),
|
|
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;
|
|
data->response_handler_id =
|
|
g_signal_connect (dialog, "response",
|
|
G_CALLBACK (inhibit_shortcuts_dialog_response_cb),
|
|
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 && data->has_last_response)
|
|
{
|
|
/* 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);
|
|
/* This is a new request */
|
|
data->request_canceled = FALSE;
|
|
|
|
meta_inhibit_shortcuts_dialog_show (data->dialog);
|
|
}
|
|
|
|
void
|
|
meta_wayland_surface_cancel_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_return_if_fail (data);
|
|
|
|
/* Keep the dialog on screen, but mark the request as canceled */
|
|
data->request_canceled = TRUE;
|
|
}
|
|
|
|
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");
|
|
}
|