Commit 33d3dba4 authored by Alberts Muktupāvels's avatar Alberts Muktupāvels
Browse files

screensaver: queue key events while unlock dialog is not ready

Unlock dialog is created in idle after keyboard and/or mouse
activity and its visibility/readiness depends on PAM.

This means that first key event will never reach unlock dialog if
it was not already created/ready. If user is fast enough more key
events might not reach dialog.

Queue key events in this case and forward to password entry when
dialog becomes visible.

#49
parent 8e0b328c
Pipeline #172673 passed with stages
in 13 minutes and 9 seconds
......@@ -1049,3 +1049,10 @@ gf_unlock_dialog_set_user_switch_enabled (GfUnlockDialog *self,
update_user_switch_button (self);
}
void
gf_unlock_dialog_forward_key_event (GfUnlockDialog *self,
GdkEvent *event)
{
gtk_widget_event (self->prompt_entry, event);
}
......@@ -43,6 +43,9 @@ void gf_unlock_dialog_set_input_sources (GfUnlockDialog *self,
void gf_unlock_dialog_set_user_switch_enabled (GfUnlockDialog *self,
gboolean user_switch_enabled);
void gf_unlock_dialog_forward_key_event (GfUnlockDialog *self,
GdkEvent *event);
G_END_DECLS
#endif
......@@ -26,6 +26,8 @@
#include "gf-panel.h"
#include "gf-unlock-dialog.h"
#define MAX_QUEUED_EVENTS 16
struct _GfWindow
{
GtkWindow parent;
......@@ -41,6 +43,8 @@ struct _GfWindow
GfInputSources *input_sources;
GList *key_events;
gboolean lock_enabled;
gboolean user_switch_enabled;
......@@ -177,6 +181,21 @@ unlock_dialog_close_cb (GfUnlockDialog *dialog,
popdown_dialog (self);
}
static void
unlock_dialog_show_cb (GtkWidget *widget,
GfWindow *self)
{
GList *l;
self->key_events = g_list_reverse (self->key_events);
for (l = self->key_events; l != NULL; l = l->next)
gf_unlock_dialog_forward_key_event (GF_UNLOCK_DIALOG (widget), l->data);
g_list_free_full (self->key_events, (GDestroyNotify) gdk_event_free);
self->key_events = NULL;
}
static void
popup_dialog (GfWindow *self)
{
......@@ -199,6 +218,9 @@ popup_dialog (GfWindow *self)
g_signal_connect (self->unlock_dialog, "close",
G_CALLBACK (unlock_dialog_close_cb), self);
g_signal_connect (self->unlock_dialog, "show",
G_CALLBACK (unlock_dialog_show_cb), self);
gtk_box_pack_start (GTK_BOX (self->vbox), self->unlock_dialog, TRUE, TRUE, 0);
}
......@@ -285,6 +307,12 @@ gf_window_finalize (GObject *object)
g_clear_pointer (&self->surface, cairo_surface_destroy);
if (self->key_events != NULL)
{
g_list_free_full (self->key_events, (GDestroyNotify) gdk_event_free);
self->key_events = NULL;
}
if (self->emit_deactivated_idle_id != 0)
{
g_source_remove (self->emit_deactivated_idle_id);
......@@ -392,6 +420,24 @@ gf_window_key_press_event (GtkWidget *widget,
return TRUE;
}
if (self->unlock_dialog == NULL ||
!gtk_widget_is_visible (self->unlock_dialog))
{
/* Only cache MAX_QUEUED_EVENTS key events. If there are any more
* than this then something is wrong.
*
* Don't queue keys that may cause focus navigation in the dialog.
*/
if (g_list_length (self->key_events) < MAX_QUEUED_EVENTS &&
event->keyval != GDK_KEY_Tab &&
event->keyval != GDK_KEY_Up &&
event->keyval != GDK_KEY_Down)
{
self->key_events = g_list_prepend (self->key_events,
gdk_event_copy ((GdkEvent *) event));
}
}
return GTK_WIDGET_CLASS (gf_window_parent_class)->key_press_event (widget,
event);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment