lightdm-gtk-greeter-team team mailing list archive
-
lightdm-gtk-greeter-team team
-
Mailing list archive
-
Message #00732
[Merge] lp:~kalgasnik/lightdm-gtk-greeter/screenshot-r316 into lp:lightdm-gtk-greeter
Andrew P. has proposed merging lp:~kalgasnik/lightdm-gtk-greeter/screenshot-r316 into lp:lightdm-gtk-greeter.
Requested reviews:
LightDM Gtk+ Greeter Development Team (lightdm-gtk-greeter-team)
For more details, see:
https://code.launchpad.net/~kalgasnik/lightdm-gtk-greeter/screenshot-r316/+merge/246953
1. Keyboard accelerators: controlled by greeter without passing them to GtkWindow
Some old code removed, logic of map/unmap changed.
2. PrintScreen: taking screenshot.
Option: max-screenshots-count = [integer_value]
value > 0: save only last [value] screenshots and remove old files
-1: allow any count of files in screenshots directory
0: disable PrintScreen key
Default value: 10.
Path to save files: /var/tmp/lightdm-gtk-greeter-screenshots or %TMP/lightdm-gtk-greeter-screenshots (if %TMP defined).
TODO: libcanberra to play capture/error sound.
--
Your team LightDM Gtk+ Greeter Development Team is requested to review the proposed merge of lp:~kalgasnik/lightdm-gtk-greeter/screenshot-r316 into lp:lightdm-gtk-greeter.
=== modified file 'src/greeterbackground.c'
--- src/greeterbackground.c 2014-12-10 07:59:02 +0000
+++ src/greeterbackground.c 2015-01-19 21:41:07 +0000
@@ -58,7 +58,7 @@
} BackgroundConfig;
/* Transition configuration
- Used to as part of <MonitorConfig> and <Monitor> */
+ Used as part of <MonitorConfig> and <Monitor> */
typedef struct
{
/* Transition duration, in ms */
@@ -144,8 +144,6 @@
/* Widget to display on active monitor */
GtkWidget* child;
- /* List of groups <GtkAccelGroup*> for greeter screens windows */
- GSList* accel_groups;
/* Mapping monitor name <gchar*> to its config <MonitorConfig*> */
GHashTable* configs;
@@ -296,7 +294,7 @@
static void set_surface_as_root (GdkScreen* screen,
cairo_surface_t* surface);
static gdouble transition_func_linear (gdouble x);
-static gdouble transition_func_easy_in_out (gdouble x);
+static gdouble transition_func_ease_in_out (gdouble x);
/* Implemented in lightdm-gtk-greeter.c */
gpointer greeter_save_focus(GtkWidget* widget);
@@ -317,7 +315,7 @@
.transition =
{
.duration = 500,
- .func = transition_func_easy_in_out,
+ .func = transition_func_ease_in_out,
.draw = (TransitionDraw)monitor_transition_draw_alpha
}
};
@@ -345,7 +343,6 @@
self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, GREETER_BACKGROUND_TYPE, GreeterBackgroundPrivate);
self->priv->screen = NULL;
self->priv->screen_monitors_changed_handler_id = 0;
- self->priv->accel_groups = NULL;
self->priv->configs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)monitor_config_free);
self->priv->default_config = monitor_config_copy(&DEFAULT_MONITOR_CONFIG, NULL);
@@ -439,7 +436,7 @@
priv->transition_types = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
g_hash_table_insert(priv->transition_types, g_strdup("none"), NULL);
g_hash_table_insert(priv->transition_types, g_strdup("linear"), transition_func_linear);
- g_hash_table_insert(priv->transition_types, g_strdup("easy-in-out"), transition_func_easy_in_out);
+ g_hash_table_insert(priv->transition_types, g_strdup("ease-in-out"), transition_func_ease_in_out);
}
if(!g_hash_table_lookup_extended(priv->transition_types, transition_type, NULL, (gpointer*)&config->transition.func))
{
@@ -574,10 +571,6 @@
gtk_style_context_add_class(gtk_widget_get_style_context(GTK_WIDGET(monitor->window)), "lightdm-gtk-greeter");
g_free(window_name);
- GSList* item;
- for(item = priv->accel_groups; item != NULL; item = g_slist_next(item))
- gtk_window_add_accel_group(monitor->window, item->data);
-
if(priv->follow_cursor)
g_signal_connect(G_OBJECT(monitor->window), "enter-notify-event",
G_CALLBACK(monitor_window_enter_notify_cb), monitor);
@@ -1031,25 +1024,6 @@
return priv->active_monitor ? &priv->active_monitor->geometry : NULL;
}
-void
-greeter_background_add_accel_group(GreeterBackground* background,
- GtkAccelGroup* group)
-{
- g_return_if_fail(GREETER_IS_BACKGROUND(background));
- g_return_if_fail(group != NULL);
- GreeterBackgroundPrivate* priv = background->priv;
-
- if(priv->monitors)
- {
- gint i;
- for(i = 0; i < priv->monitors_size; ++i)
- if(priv->monitors[i].window)
- gtk_window_add_accel_group(priv->monitors[i].window, group);
- }
-
- priv->accel_groups = g_slist_append(priv->accel_groups, group);
-}
-
static gboolean
background_config_initialize(BackgroundConfig* config,
const gchar* value)
@@ -1633,7 +1607,7 @@
}
static gdouble
-transition_func_easy_in_out(gdouble x)
+transition_func_ease_in_out(gdouble x)
{
return (1 - cos(M_PI*x))/2;
}
=== modified file 'src/greeterbackground.h'
--- src/greeterbackground.h 2014-11-03 10:39:58 +0000
+++ src/greeterbackground.h 2015-01-19 21:41:07 +0000
@@ -38,8 +38,6 @@
const gchar* path);
void greeter_background_save_xroot (GreeterBackground* background);
const GdkRectangle* greeter_background_get_active_monitor_geometry(GreeterBackground* background);
-void greeter_background_add_accel_group (GreeterBackground* background,
- GtkAccelGroup* group);
G_END_DECLS
=== modified file 'src/lightdm-gtk-greeter-fallback.css'
--- src/lightdm-gtk-greeter-fallback.css 2014-05-22 19:52:34 +0000
+++ src/lightdm-gtk-greeter-fallback.css 2015-01-19 21:41:07 +0000
@@ -1,12 +1,23 @@
#layout_menuitem>GtkLabel
{
- border: 1px solid alpha(@menu_fg_color, 0.8);
- border-radius: 0.5em;
- padding: 0px 0.25em;
- background: alpha(@menu_fg_color, 0.2);
+ border: 1px solid alpha(@menu_fg_color, 0.8);
+ border-radius: 0.5em;
+ padding: 0px 0.25em;
+ background: alpha(@menu_fg_color, 0.2);
}
#layout_menuitem
{
- padding: 1px;
+ padding: 1px;
+}
+
+/* Used as "screen-capture" effect */
+#capture-splash.capture-triggered
+{
+ background: alpha(@theme_base_color, 0.5);
+}
+
+#screen
+{
+ background: transparent;
}
=== modified file 'src/lightdm-gtk-greeter.c'
--- src/lightdm-gtk-greeter.c 2015-01-17 13:45:58 +0000
+++ src/lightdm-gtk-greeter.c 2015-01-19 21:41:07 +0000
@@ -68,6 +68,7 @@
/* Screen window */
static GtkOverlay *screen_overlay;
+static GtkAccelGroup *greeter_accel_group;
/* Login window */
static GtkWidget *login_window;
@@ -81,9 +82,10 @@
/* Panel */
static GtkWidget *panel_window, *menubar;
static GtkWidget *power_menuitem, *session_menuitem, *language_menuitem, *a11y_menuitem,
- *layout_menuitem, *clock_menuitem, *host_menuitem;
+ *layout_menuitem, *clock_menuitem, *host_menuitem, *tools_menuitem;
static GtkWidget *suspend_menuitem, *hibernate_menuitem, *restart_menuitem, *shutdown_menuitem;
static GtkWidget *contrast_menuitem, *font_menuitem, *keyboard_menuitem, *reader_menuitem;
+static GtkWidget *screenshot_menuitem;
static GtkWidget *clock_label, *session_badge;
static GtkMenu *session_menu, *language_menu, *layout_menu;
@@ -277,7 +279,19 @@
void a11y_keyboard_cb (GtkCheckMenuItem *item, gpointer user_data);
void a11y_reader_cb (GtkCheckMenuItem *item, gpointer user_data);
-/* Power indciator */
+/* Screen capture */
+static const gint SCREENSHOT_BLINK_DURATION = 300; /* Duration (in ms) of "screen capture" effect */
+static const gint SCREENSHOT_DEFAULT_MAX_COUNT = 10;
+
+static GtkWidget *screenshot_splash_widget = NULL;
+static guint screenshot_splash_finish_id = 0;
+
+static gint screenshot_max_count;
+void tools_screenshot_cb (GtkWidget *menuitem, gpointer userdata);
+static gint compare_file_info_dates (GFileInfo *a_info, GFileInfo *b_info);
+static gboolean take_screenshot (gint max_files_count);
+
+/* Power indicator */
static void power_menu_cb (GtkWidget *menuitem, gpointer userdata);
void suspend_cb (GtkWidget *widget, LightDMGreeter *greeter);
void hibernate_cb (GtkWidget *widget, LightDMGreeter *greeter);
@@ -1382,6 +1396,7 @@
g_hash_table_insert (builtin_items, "~layout", layout_menuitem);
g_hash_table_insert (builtin_items, "~host", host_menuitem);
g_hash_table_insert (builtin_items, "~clock", clock_menuitem);
+ g_hash_table_insert (builtin_items, "~tools", tools_menuitem);
g_hash_table_iter_init (&iter, builtin_items);
while (g_hash_table_iter_next (&iter, NULL, &iter_value))
@@ -1756,6 +1771,192 @@
menu_command_stop (a11y_reader_command);
}
+/* Taking screenshot */
+
+static gboolean
+screenshot_splash_timeout_cb (gpointer user_data)
+{
+ gtk_widget_hide (screenshot_splash_widget);
+ gtk_style_context_remove_class (gtk_widget_get_style_context (screenshot_splash_widget), "capture-triggered");
+ screenshot_splash_finish_id = 0;
+ return G_SOURCE_REMOVE;
+}
+
+void
+tools_screenshot_cb (GtkWidget *menuitem, gpointer userdata)
+{
+ if (screenshot_max_count == 0)
+ return;
+
+ if (take_screenshot (screenshot_max_count))
+ {
+ /* TODO: Playing "capture" sound */
+
+ if (!screenshot_splash_widget)
+ {
+ screenshot_splash_widget = gtk_event_box_new ();
+ gtk_widget_set_name (screenshot_splash_widget, "capture-splash");
+ gtk_event_box_set_visible_window (GTK_EVENT_BOX (screenshot_splash_widget), TRUE);
+ gtk_overlay_add_overlay (screen_overlay, screenshot_splash_widget);
+ }
+
+ if (!screenshot_splash_finish_id)
+ {
+ gtk_widget_show (screenshot_splash_widget);
+ gtk_style_context_add_class (gtk_widget_get_style_context (screenshot_splash_widget), "capture-triggered");
+ screenshot_splash_finish_id = g_timeout_add (SCREENSHOT_BLINK_DURATION, screenshot_splash_timeout_cb, NULL);
+ }
+ }
+ else
+ {
+ /* TODO: Playing "error" sound */
+ }
+}
+
+static gint
+compare_file_info_dates (GFileInfo *a_info, GFileInfo *b_info)
+{
+ guint64 a = g_file_info_get_attribute_uint64 (a_info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
+ guint64 b = g_file_info_get_attribute_uint64 (b_info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
+ return a < b ? -1 : a == b ? 0 : +1;
+}
+
+static gboolean
+take_screenshot (gint max_files_count)
+{
+ if (max_files_count == 0)
+ {
+ g_debug ("[Screenshot] Taking screenshot: aborted, max_files_count == 0");
+ return FALSE;
+ }
+
+ g_debug ("[Screenshot] Taking screenshot...");
+
+ const gchar *tmp_dir_variable = g_getenv ("TMPDIR");
+ gchar *output_dir;
+ GError *error = NULL;
+ gboolean failed = FALSE;
+
+ const gint SCREENSHOT_DIR_MODE = 0700;
+ const gchar *SCREENSHOT_DIR_NAME = "lightdm-gtk-greeter-screenshots";
+
+ if (tmp_dir_variable)
+ output_dir = g_build_filename (tmp_dir_variable, SCREENSHOT_DIR_NAME, NULL);
+ else
+ /* "/var/tmp" is usually more persistent than "/tmp" */
+ output_dir = g_build_filename (G_DIR_SEPARATOR_S, "var", "tmp", SCREENSHOT_DIR_NAME, NULL);
+
+ if (g_mkdir_with_parents (output_dir, SCREENSHOT_DIR_MODE) == -1)
+ {
+ g_warning ("[Screenshot] Failed to create directory '%s': %s", output_dir, g_strerror (errno));
+ g_free (output_dir);
+ return FALSE;
+ }
+
+ GDateTime *now = g_date_time_new_now_local ();
+ gchar *output_name = now ? g_date_time_format (now, "screenshot_%F_%T.png") : g_strdup ("screenshot.png");
+ g_date_time_unref (now);
+
+ if (max_files_count > 0)
+ {
+ GFileEnumerator *enumerator;
+ GFile *parent = g_file_new_for_path (output_dir);
+ enumerator = g_file_enumerate_children (parent,
+ G_FILE_ATTRIBUTE_STANDARD_TYPE ","
+ G_FILE_ATTRIBUTE_STANDARD_NAME ","
+ G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ G_FILE_QUERY_INFO_NONE,
+ NULL, &error);
+
+ if (!enumerator)
+ {
+ g_warning ("[Screenshot] Failed to enumerate screenshots directory: %s", error ? error->message : "unknown error");
+ g_clear_error (&error);
+ g_object_unref (parent);
+ g_free (output_name);
+ g_free (output_dir);
+ return FALSE;
+ }
+
+ gint files_count = 0;
+ GList *files = NULL;
+ GFileInfo *info;
+
+ while ((info = g_file_enumerator_next_file (enumerator, NULL, &error)))
+ {
+ if (g_file_info_get_file_type (info) == G_FILE_TYPE_REGULAR &&
+ g_strcmp0 (g_file_info_get_name (info), output_name) != 0)
+ {
+ files = g_list_prepend (files, info);
+ files_count++;
+ }
+ else
+ g_object_unref (info);
+ }
+ g_file_enumerator_close (enumerator, NULL, NULL);
+ g_object_unref (enumerator);
+
+ g_debug ("[Screenshot] Directory items count: %d, limit: %d", files_count, max_files_count);
+
+ if (files_count >= max_files_count)
+ {
+ GList *iter;
+ files = g_list_sort (files, (GCompareFunc)compare_file_info_dates);
+
+ for (iter = g_list_nth (files, files_count - max_files_count); iter && !failed; iter = g_list_previous (iter))
+ {
+ GFile *file = g_file_get_child (parent, g_file_info_get_name (iter->data));
+ if (!g_file_delete (file, NULL, &error))
+ {
+ g_warning ("[Screenshot] Failed to delete old screenshot '%s': %s",
+ g_file_info_get_name (iter->data),
+ error ? error->message : "unknown error");
+ g_clear_error (&error);
+ failed = TRUE;
+ }
+ g_object_unref (file);
+ }
+ }
+ g_list_free_full (files, g_object_unref);
+ g_object_unref (parent);
+
+ if (failed)
+ {
+ g_free (output_name);
+ g_free (output_dir);
+ return FALSE;
+ }
+ }
+
+ /* Finally, taking screenshot */
+
+ GdkWindow *root = gdk_get_default_root_window ();
+ GdkPixbuf *screenshot = gdk_pixbuf_get_from_window (root, 0, 0, gdk_window_get_width (root), gdk_window_get_height (root));
+
+ if (!screenshot)
+ g_warning ("[Screenshot] gdk_pixbuf_get_from_window(root) failed");
+ else
+ {
+ gchar *output_path = g_build_filename (output_dir, output_name, NULL);
+ if (!gdk_pixbuf_save (screenshot, output_path, "png", &error, NULL))
+ {
+ g_warning ("[Screenshot] Failed to save image as '%s': %s", output_path, error ? error->message : "unknown error");
+ g_clear_error (&error);
+ failed = TRUE;
+ }
+ else
+ g_debug ("[Screenshot] Image saved as '%s'", output_path);
+
+ g_object_unref (screenshot);
+ g_free (output_path);
+ }
+
+ g_free (output_name);
+ g_free (output_dir);
+
+ return screenshot && !failed;
+}
+
/* Power indicator */
static void
@@ -2462,32 +2663,25 @@
}
static GdkFilterReturn
-focus_upon_map (GdkXEvent *gxevent, GdkEvent *event, gpointer data)
+wm_window_filter (GdkXEvent *gxevent, GdkEvent *event, gpointer data)
{
XEvent* xevent = (XEvent*)gxevent;
- GdkWindow* keyboard_win = a11y_keyboard_command && a11y_keyboard_command->widget ?
- gtk_widget_get_window (GTK_WIDGET (a11y_keyboard_command->widget)) : NULL;
if (xevent->type == MapNotify)
{
- Window xwin = xevent->xmap.window;
- Window keyboard_xid = 0;
- GdkDisplay* display = gdk_x11_lookup_xdisplay (xevent->xmap.display);
- GdkWindow* win = gdk_x11_window_foreign_new_for_display (display, xwin);
+ GdkDisplay *display = gdk_x11_lookup_xdisplay (xevent->xmap.display);
+ GdkWindow *win = gdk_x11_window_foreign_new_for_display (display, xevent->xmap.window);
GdkWindowTypeHint win_type = gdk_window_get_type_hint (win);
- /* Check to see if this window is our onboard window, since we don't want to focus it. */
- if (keyboard_win)
- keyboard_xid = gdk_x11_window_get_xid (keyboard_win);
-
- if (xwin != keyboard_xid
- && win_type != GDK_WINDOW_TYPE_HINT_TOOLTIP
- && win_type != GDK_WINDOW_TYPE_HINT_NOTIFICATION)
- {
+/* if (win_type != GDK_WINDOW_TYPE_HINT_COMBO &&
+ win_type != GDK_WINDOW_TYPE_HINT_MENU &&
+ win_type != GDK_WINDOW_TYPE_HINT_POPUP_MENU &&
+ win_type != GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU &&
+ win_type != GDK_WINDOW_TYPE_HINT_TOOLTIP &&
+ win_type != GDK_WINDOW_TYPE_HINT_NOTIFICATION)
+*/
+ if (win_type == GDK_WINDOW_TYPE_HINT_DESKTOP ||
+ win_type == GDK_WINDOW_TYPE_HINT_DIALOG)
gdk_window_focus (win, GDK_CURRENT_TIME);
- /* Make sure to keep keyboard above */
- if (keyboard_win)
- gdk_window_raise (keyboard_win);
- }
}
else if (xevent->type == UnmapNotify)
{
@@ -2496,12 +2690,25 @@
XGetInputFocus (xevent->xunmap.display, &xwin, &revert_to);
if (revert_to == RevertToNone)
- {
- gdk_window_focus (gtk_widget_get_window (GTK_WIDGET (login_window)), GDK_CURRENT_TIME);
- /* Make sure to keep keyboard above */
- if (keyboard_win)
- gdk_window_raise (keyboard_win);
- }
+ gdk_window_focus (gtk_widget_get_window (GTK_WIDGET (screen_overlay)), GDK_CURRENT_TIME);
+ }
+ return GDK_FILTER_CONTINUE;
+}
+
+static GdkFilterReturn
+accelerators_window_filter (GdkXEvent *gxevent, GdkEvent *event, gpointer data)
+{
+ XKeyEvent* keyevent = (XKeyEvent*)gxevent;
+ if (keyevent->type == KeyPress)
+ {
+ KeySym accel_key = XLookupKeysym (keyevent, 0);
+ GdkModifierType accel_mods = keyevent->state & ~(Mod2Mask | Mod5Mask | LockMask);
+ gchar *accel_name = gtk_accelerator_name (accel_key, (accel_mods & gtk_accelerator_get_default_mod_mask ()));
+ GQuark accel_quark = g_quark_from_string (accel_name);
+ g_free (accel_name);
+
+ if (gtk_accel_group_activate (greeter_accel_group, accel_quark, G_OBJECT (screen_overlay), accel_key, accel_mods))
+ return GDK_FILTER_REMOVE;
}
return GDK_FILTER_CONTINUE;
}
@@ -2704,6 +2911,7 @@
/* Screen window */
screen_overlay = GTK_OVERLAY (gtk_builder_get_object (builder, "screen_overlay"));
+ greeter_accel_group = GTK_ACCEL_GROUP (gtk_builder_get_object (builder, "greeter_accel_group"));
/* Login window */
login_window = GTK_WIDGET (gtk_builder_get_object (builder, "login_window"));
@@ -2719,18 +2927,27 @@
/* Panel window*/
panel_window = GTK_WIDGET (gtk_builder_get_object (builder, "panel_window"));
menubar = GTK_WIDGET (gtk_builder_get_object (builder, "menubar"));
+
session_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "session_menuitem"));
session_menu = GTK_MENU (gtk_builder_get_object (builder, "session_menu"));
+
language_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "language_menuitem"));
language_menu = GTK_MENU (gtk_builder_get_object (builder, "language_menu"));
+
a11y_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "a11y_menuitem"));
contrast_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "high_contrast_menuitem"));
font_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "large_font_menuitem"));
keyboard_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "keyboard_menuitem"));
reader_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "reader_menuitem"));
+
power_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "power_menuitem"));
+
layout_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "layout_menuitem"));
layout_menu = GTK_MENU (gtk_builder_get_object (builder, "layout_menu"));
+
+ tools_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "tools_menuitem"));
+ screenshot_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "screenshot_menuitem"));
+
clock_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "clock_menuitem"));
host_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "host_menuitem"));
@@ -2751,6 +2968,7 @@
gtk_accel_map_add_entry ("<Login>/a11y/keyboard", GDK_KEY_F3, 0);
gtk_accel_map_add_entry ("<Login>/a11y/reader", GDK_KEY_F4, 0);
gtk_accel_map_add_entry ("<Login>/power/shutdown", GDK_KEY_F4, GDK_MOD1_MASK);
+ gtk_accel_map_add_entry ("<Login>/tools/screenshot", GDK_KEY_Print, 0);
init_indicators (config);
@@ -2953,6 +3171,17 @@
gdk_threads_add_timeout (1000, (GSourceFunc) clock_timeout_thread, NULL);
}
+ /* Screen capture */
+ screenshot_max_count = g_key_file_get_integer (config, "greeter", "max-screenshots-count", &error);
+ if (error)
+ {
+ if (error->code == G_KEY_FILE_ERROR_INVALID_VALUE)
+ g_warning ("[Configuration] Invalid '%s' value, using default: %d", "max-screenshots-count", SCREENSHOT_DEFAULT_MAX_COUNT);
+ screenshot_max_count = SCREENSHOT_DEFAULT_MAX_COUNT;
+ g_clear_error (&error);
+ }
+ gtk_widget_set_visible (screenshot_menuitem, screenshot_max_count != 0);
+
/* A bit of CSS */
GdkRGBA lightdm_gtk_greeter_override_defaults;
css_provider = gtk_css_provider_new ();
@@ -3018,9 +3247,6 @@
}
g_strfreev (config_groups);
- greeter_background_add_accel_group (greeter_background, GTK_ACCEL_GROUP (gtk_builder_get_object (builder, "a11y_accelgroup")));
- greeter_background_add_accel_group (greeter_background, GTK_ACCEL_GROUP (gtk_builder_get_object (builder, "power_accelgroup")));
-
greeter_background_connect (greeter_background, gdk_screen_get_default ());
if (lightdm_greeter_get_hide_users_hint (greeter))
@@ -3089,10 +3315,12 @@
}
g_strfreev (values);
- /* focus fix (source: unity-greeter) */
- GdkWindow* root_window = gdk_get_default_root_window ();
+ GdkWindow *root_window = gdk_get_default_root_window ();
gdk_window_set_events (root_window, gdk_window_get_events (root_window) | GDK_SUBSTRUCTURE_MASK);
- gdk_window_add_filter (root_window, focus_upon_map, NULL);
+ /* There is no window manager, so we need to implement some of its functionality */
+ gdk_window_add_filter (root_window, wm_window_filter, NULL);
+ /* Use "manual" accelerators control instead of passing accel groups to GreeterBackground's windows */
+ gdk_window_add_filter (gtk_widget_get_window (GTK_WIDGET (screen_overlay)), accelerators_window_filter, NULL);
gtk_widget_show (GTK_WIDGET (screen_overlay));
=== modified file 'src/lightdm-gtk-greeter.glade'
--- src/lightdm-gtk-greeter.glade 2014-12-10 07:59:02 +0000
+++ src/lightdm-gtk-greeter.glade 2015-01-19 21:41:07 +0000
@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
- <requires lib="gtk+" version="3.4"/>
+ <requires lib="gtk+" version="3.8"/>
<requires lib="greeter_menu_bar" version="1.0"/>
- <object class="GtkAccelGroup" id="a11y_accelgroup"/>
- <object class="GtkAccelGroup" id="power_accelgroup"/>
+ <object class="GtkAccelGroup" id="greeter_accel_group"/>
<object class="GtkEventBox" id="panel_window">
<property name="name">panel_window</property>
<property name="visible">True</property>
@@ -26,12 +25,13 @@
<object class="GtkMenu" id="power_menu">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="accel_group">power_accelgroup</property>
+ <property name="accel_group">greeter_accel_group</property>
<child>
<object class="GtkMenuItem" id="suspend_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Suspend</property>
+ <property name="use_underline">True</property>
<signal name="activate" handler="suspend_cb" swapped="no"/>
</object>
</child>
@@ -40,6 +40,7 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Hibernate</property>
+ <property name="use_underline">True</property>
<signal name="activate" handler="hibernate_cb" swapped="no"/>
</object>
</child>
@@ -48,6 +49,7 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Restart...</property>
+ <property name="use_underline">True</property>
<signal name="activate" handler="restart_cb" swapped="no"/>
</object>
</child>
@@ -58,6 +60,7 @@
<property name="can_focus">False</property>
<property name="accel_path"><Login>/power/shutdown</property>
<property name="label" translatable="yes">Shut Down...</property>
+ <property name="use_underline">True</property>
<signal name="activate" handler="shutdown_cb" swapped="no"/>
</object>
</child>
@@ -74,7 +77,7 @@
<object class="GtkMenu" id="a11y_menu">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="accel_group">a11y_accelgroup</property>
+ <property name="accel_group">greeter_accel_group</property>
<child>
<object class="GtkCheckMenuItem" id="large_font_menuitem">
<property name="use_action_appearance">False</property>
@@ -82,6 +85,7 @@
<property name="can_focus">False</property>
<property name="accel_path"><Login>/a11y/font</property>
<property name="label" translatable="yes">Large Font</property>
+ <property name="use_underline">True</property>
<signal name="toggled" handler="a11y_font_cb" swapped="no"/>
</object>
</child>
@@ -92,6 +96,7 @@
<property name="can_focus">False</property>
<property name="accel_path"><Login>/a11y/contrast</property>
<property name="label" translatable="yes">High Contrast</property>
+ <property name="use_underline">True</property>
<signal name="toggled" handler="a11y_contrast_cb" swapped="no"/>
</object>
</child>
@@ -163,6 +168,30 @@
</object>
</child>
<child>
+ <object class="GtkMenuItem" id="tools_menuitem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu" id="tools_menu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="accel_group">greeter_accel_group</property>
+ <child>
+ <object class="GtkMenuItem" id="screenshot_menuitem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="accel_path"><Login>/tools/screenshot</property>
+ <property name="label" translatable="yes">Take screenshot</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="tools_screenshot_cb" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
<object class="GtkSeparatorMenuItem" id="clock_menuitem">
<property name="name">clock_menuitem</property>
<property name="can_focus">False</property>
Follow ups