Ticket #52281: patch_ui_gcr-prompt-dialog.c.diff

File patch_ui_gcr-prompt-dialog.c.diff, 8.1 KB (added by gwhitney, 8 years ago)

patchfile for gcr

  • ui/gcr-prompt-dialog.c

    old new  
    2727#include "gcr-secure-entry-buffer.h"
    2828
    2929#include <gtk/gtk.h>
    30 #include <gdk/gdkx.h>
     30#ifdef GDK_WINDOWING_X11
     31#include <gdk/gdkx.h>
     32#endif
    3133#include <glib/gi18n.h>
    3234
    3335/**
     
    107109        GtkEntryBuffer *password_buffer;
    108110        GtkEntryBuffer *confirm_buffer;
    109111        PromptMode mode;
    110         GdkDevice *grabbed_device;
     112        GdkSeat *grabbed_seat;
    111113        gulong grab_broken_id;
    112114        gboolean grab_disabled;
    113115        gboolean was_closed;
     
    141143        if (window == NULL)
    142144                return;
    143145
    144         handle = g_ascii_strtoll (self->pv->caller_window, &end, 10);
    145         if (!end || *end != '\0') {
     146        display = gtk_widget_get_display (GTK_WIDGET (self));
     147        transient_for = NULL;
     148        handle = 0;
     149        end = NULL;
     150#ifdef GDK_WINDOWING_X11
     151        if (GDK_IS_X11_DISPLAY (display)) {
     152                handle = g_ascii_strtoll (self->pv->caller_window, &end, 10);
     153                if (end && *end == '\0') {
     154                        transient_for = gdk_x11_window_foreign_new_for_display (display, (Window)handle);
     155                        if (transient_for == NULL) {
     156                                g_warning ("caller-window property doesn't represent a window on current display: %s",
     157                                           self->pv->caller_window);
     158                        }
     159                }
     160        }
     161#endif
     162        if (transient_for == NULL) {
     163                transient_for = gcr_prompt_util_window_of_mock_id (self->pv->caller_window);
     164                if (transient_for) { g_object_ref(transient_for); }
     165        }
     166        if (transient_for == NULL) {
    146167                g_warning ("couldn't parse caller-window property: %s", self->pv->caller_window);
    147168                return;
    148169        }
    149170
    150         display = gtk_widget_get_display (GTK_WIDGET (self));
    151         transient_for = gdk_x11_window_foreign_new_for_display (display, (Window)handle);
    152         if (transient_for == NULL) {
    153                 g_warning ("caller-window property doesn't represent a window on current display: %s",
    154                            self->pv->caller_window);
    155         } else {
    156                 gdk_window_set_transient_for (window, transient_for);
    157                 g_object_unref (transient_for);
    158         }
     171        gdk_window_set_transient_for (window, transient_for);
     172        g_object_unref (transient_for);
    159173
    160174        gtk_window_set_modal (GTK_WINDOW (self), TRUE);
    161175}
     
    401415{
    402416        GcrPromptDialog *self = GCR_PROMPT_DIALOG (user_data);
    403417        GdkGrabStatus status;
    404         guint32 at;
    405         GdkDevice *device = NULL;
    406         GdkDeviceManager *manager;
     418        GdkSeat *seat;
    407419        GdkDisplay *display;
    408         GList *devices, *l;
    409420
    410         if (self->pv->grabbed_device || !GRAB_KEYBOARD)
     421        if (self->pv->grabbed_seat || !GRAB_KEYBOARD)
    411422                return FALSE;
    412423
    413424        display = gtk_widget_get_display (widget);
    414         manager = gdk_display_get_device_manager (display);
    415         devices = gdk_device_manager_list_devices (manager, GDK_DEVICE_TYPE_MASTER);
    416         for (l = devices; l; l = g_list_next (l)) {
    417                 device = l->data;
    418                 if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
    419                         break;
    420         }
    421         g_list_free (devices);
     425        seat = gdk_display_get_default_seat (display);
    422426
    423         if (!device) {
    424                 g_message ("couldn't find device to grab");
     427        if (!seat) {
     428                g_message ("couldn't find seat to grab");
    425429                return FALSE;
    426430        }
    427431
    428         at = event ? gdk_event_get_time (event) : GDK_CURRENT_TIME;
    429         status = gdk_device_grab (device, gtk_widget_get_window (widget),
    430                                   GDK_OWNERSHIP_APPLICATION, TRUE,
    431                                   GDK_KEY_PRESS | GDK_KEY_RELEASE, NULL, at);
     432        status = gdk_seat_grab (seat, gtk_widget_get_window (widget),
     433                                GDK_SEAT_CAPABILITY_KEYBOARD, TRUE,
     434                                NULL, event, NULL, NULL);
    432435        if (status == GDK_GRAB_SUCCESS) {
    433436                self->pv->grab_broken_id = g_signal_connect (widget, "grab-broken-event",
    434437                                                             G_CALLBACK (on_grab_broken), self);
    435                 gtk_device_grab_add (widget, device, TRUE);
    436                 self->pv->grabbed_device = device;
     438                gtk_device_grab_add (widget, gdk_seat_get_keyboard (seat), TRUE);
     439                self->pv->grabbed_seat = seat;
    437440        } else {
    438441                g_message ("could not grab keyboard: %s", grab_status_message (status));
    439442        }
     
    447450                 GdkEvent *event,
    448451                 gpointer user_data)
    449452{
    450         guint32 at = event ? gdk_event_get_time (event) : GDK_CURRENT_TIME;
    451453        GcrPromptDialog *self = GCR_PROMPT_DIALOG (user_data);
    452454
    453         if (self->pv->grabbed_device) {
     455        if (self->pv->grabbed_seat) {
    454456                g_signal_handler_disconnect (widget, self->pv->grab_broken_id);
    455                 gdk_device_ungrab (self->pv->grabbed_device, at);
    456                 gtk_device_grab_remove (widget, self->pv->grabbed_device);
    457                 self->pv->grabbed_device = NULL;
     457                gdk_seat_ungrab (self->pv->grabbed_seat);
     458                gtk_device_grab_remove (widget,
     459                                        gdk_seat_get_keyboard (self->pv->grabbed_seat));
     460                self->pv->grabbed_seat = NULL;
    458461                self->pv->grab_broken_id = 0;
    459462        }
    460463
     
    725728        gcr_prompt_close (GCR_PROMPT (self));
    726729
    727730        ungrab_keyboard (GTK_WIDGET (self), NULL, self);
    728         g_assert (self->pv->grabbed_device == NULL);
     731        g_assert (self->pv->grabbed_seat == NULL);
    729732
    730733        G_OBJECT_CLASS (gcr_prompt_dialog_parent_class)->dispose (obj);
    731734}
     
    962965        iface->prompt_confirm_finish = gcr_prompt_dialog_confirm_finish;
    963966        iface->prompt_close = gcr_prompt_dialog_close;
    964967}
     968
     969#define MOCK_HANDLE_LENGTH 24
     970typedef struct {
     971        GdkWindow *win;
     972        gchar      han[MOCK_HANDLE_LENGTH];
     973} MockHandleEntry;
     974 
     975static GArray *
     976mock_handle_table() {
     977        static GArray *the_table = NULL;
     978        if (the_table == NULL) {
     979                the_table = g_array_new (FALSE, FALSE, sizeof(MockHandleEntry));
     980        }
     981        return the_table;
     982}
     983
     984static const gchar *
     985mock_handle_header() {
     986        static gchar the_header[16];
     987        static gboolean inited = FALSE;
     988        if (!inited) {
     989                g_snprintf (the_header, sizeof (the_header), "mh%ul", g_random_int());
     990                inited = TRUE;
     991        }
     992        return the_header;
     993}
     994
     995/**
     996 * gcr_prompt_util_mock_id_of_window:
     997 * @window: the GdkWindow
     998 *
     999 * Return a pointer to memory maintained internally by gcr_prompt which gives
     1000 * a mock string id for the given window, such that later passing a matching string to
     1001 * gcr_prompt_util_window_of_mock_id will give back the same GdkWindow, as long as bpth
     1002 * functions are called within the same process.
     1003 *
     1004 * Useful as an argument to gcr_prompt_set_caller_window for handling caller windows within
     1005 * the same process if no backend handles that allow windows to be identified across
     1006 * processes are available.
     1007 */
     1008const gchar *
     1009gcr_prompt_util_mock_id_of_window (GdkWindow *window)
     1010{
     1011        GArray *table = mock_handle_table();
     1012        guint i;
     1013        guint cursize = table->len;
     1014        gsize h;
     1015        MockHandleEntry maybeNewEntry;
     1016       
     1017        /* linear search: not expecting many prompts in a given process */
     1018        for (i = 0; i < cursize; ++i) {
     1019                if (g_array_index (table, MockHandleEntry,i).win == window) {
     1020                        return g_array_index (table, MockHandleEntry,i).han;
     1021                }
     1022        }
     1023        /* haven't seen this window yet, make a new entry */
     1024        maybeNewEntry.win = window;
     1025        h = g_strlcpy(maybeNewEntry.han, mock_handle_header(), MOCK_HANDLE_LENGTH);
     1026        g_snprintf(maybeNewEntry.han + h, MOCK_HANDLE_LENGTH - h, "%ul", cursize);
     1027        g_array_append_val (table, maybeNewEntry);
     1028        return g_array_index (table, MockHandleEntry, cursize).han;
     1029}
     1030
     1031/**
     1032 * gcr_prompt_util_window_of_mock_id:
     1033 * @try_handle: string to attempt to interpret as a mock handle
     1034 *
     1035 * If gcr_prompt_util_mock_id_of_window earlier in the same process returned a string
     1036 * matching the argument to this function, return the GdkWindow* that
     1037 * gcr_prompt_util_mock_id_of_window was called with, otherwise NULL.
     1038 *
     1039 * The pair of functions gcr_prompt_util_mock_id_of_window and
     1040 * gcr_prompt_util_window_of_mock_id attempt to ensure that a mock handle issued by another
     1041 * process will not be misconstrued as a mock handle for the current process.
     1042 */
     1043GdkWindow *
     1044gcr_prompt_util_window_of_mock_id (const gchar *try_handle)
     1045{
     1046        static guint h = 0;
     1047        GArray *table;
     1048        guint64 scanned;
     1049       
     1050        if (h == 0) {
     1051                h = strlen (mock_handle_header());
     1052        }
     1053        if (!g_str_has_prefix (try_handle, mock_handle_header())) {
     1054                return NULL;
     1055        }
     1056        if (!g_ascii_isdigit (try_handle[h])) {
     1057                return NULL;
     1058        }
     1059        scanned = g_ascii_strtoull (try_handle + h, NULL, 10);
     1060        table = mock_handle_table();
     1061        if (scanned >= table->len) {
     1062                return NULL;
     1063        }
     1064        return g_array_index (table, MockHandleEntry, scanned).win;
     1065}