diff options
-rw-r--r-- | src/greeterbackground.c | 85 | ||||
-rw-r--r-- | src/lightdm-gtk-greeter-fallback.css | 10 | ||||
-rw-r--r-- | src/lightdm-gtk-greeter.c | 67 | ||||
-rw-r--r-- | src/lightdm-gtk-greeter.glade | 7 |
4 files changed, 102 insertions, 67 deletions
diff --git a/src/greeterbackground.c b/src/greeterbackground.c index 4487644..a4105dd 100644 --- a/src/greeterbackground.c +++ b/src/greeterbackground.c @@ -58,7 +58,7 @@ typedef struct } BackgroundConfig; /* Transition configuration - Used to as part of <MonitorConfig> and <Monitor> */ + Used as part of <MonitorConfig> and <Monitor> */ typedef struct { /* Transition duration, in ms */ @@ -177,9 +177,6 @@ struct _GreeterBackgroundPrivate gboolean follow_cursor; /* Use cursor position to determinate initial active monitor */ gboolean follow_cursor_to_init; - - /* Name => transition function, inited in set_monitor_config() */ - GHashTable* transition_types; }; enum @@ -296,7 +293,7 @@ static void set_root_pixmap_id (GdkScreen* screen, 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 +314,7 @@ static const MonitorConfig DEFAULT_MONITOR_CONFIG = .transition = { .duration = 500, - .func = transition_func_easy_in_out, + .func = transition_func_ease_in_out, .draw = (TransitionDraw)monitor_transition_draw_alpha } }; @@ -434,14 +431,13 @@ greeter_background_set_monitor_config(GreeterBackground* background, if(transition_type) { - if(!priv->transition_types) - { - 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); - } - if(!g_hash_table_lookup_extended(priv->transition_types, transition_type, NULL, (gpointer*)&config->transition.func)) + if(g_strcmp0(transition_type, "none") == 0) + config->transition.func = NULL; + else if(g_strcmp0(transition_type, "ease-in-out") == 0) + config->transition.func = transition_func_ease_in_out; + else if(g_strcmp0(transition_type, "linear") == 0) + config->transition.func = transition_func_linear; + else { g_warning("[Background] Invalid transition type for '%s' monitor: '%s'. Using fallback value.", name, transition_type); @@ -495,12 +491,18 @@ greeter_background_connect(GreeterBackground* background, g_return_if_fail(GREETER_IS_BACKGROUND(background)); g_return_if_fail(GDK_IS_SCREEN(screen)); - g_debug("[Background] Connecting to screen: %p", screen); + g_debug("[Background] Connecting to screen: %p (%dx%dpx, %dx%dmm)", screen, + gdk_screen_get_width(screen), gdk_screen_get_height(screen), + gdk_screen_get_width_mm(screen), gdk_screen_get_height_mm(screen)); GreeterBackgroundPrivate* priv = background->priv; - + gpointer saved_focus = NULL; if(priv->screen) + { + if (priv->active_monitor) + saved_focus = greeter_save_focus(priv->child); greeter_background_disconnect(background); + } priv->screen = screen; priv->monitors_size = gdk_screen_get_n_monitors(screen); @@ -513,7 +515,9 @@ greeter_background_connect(GreeterBackground* background, Monitor* first_not_skipped_monitor = NULL; GHashTable* images_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + cairo_region_t *screen_region = cairo_region_create(); gint i; + for(i = 0; i < priv->monitors_size; ++i) { const MonitorConfig* config; @@ -553,6 +557,15 @@ greeter_background_connect(GreeterBackground* background, config = &DEFAULT_MONITOR_CONFIG; } + /* Simple check to skip fully overlapped monitors. + Actually, it's can track only monitors in "mirrors" mode. Nothing more. */ + if(cairo_region_contains_rectangle(screen_region, &monitor->geometry) == CAIRO_REGION_OVERLAP_IN) + { + g_debug("[Background] Skipping monitor %s #%d, its area is already used by other monitors", printable_name, i); + continue; + } + cairo_region_union_rectangle(screen_region, &monitor->geometry); + if(!first_not_skipped_monitor) first_not_skipped_monitor = monitor; @@ -578,9 +591,8 @@ greeter_background_connect(GreeterBackground* background, 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); + g_signal_connect(G_OBJECT(monitor->window), "enter-notify-event", + G_CALLBACK(monitor_window_enter_notify_cb), monitor); if(config->user_bg) priv->customized_monitors = g_slist_prepend(priv->customized_monitors, monitor); @@ -624,9 +636,16 @@ greeter_background_connect(GreeterBackground* background, } } } + if(!priv->active_monitor) greeter_background_set_active_monitor(background, NULL); + if(saved_focus) + { + greeter_restore_focus(saved_focus); + g_free(saved_focus); + } + priv->screen_monitors_changed_handler_id = g_signal_connect(G_OBJECT(screen), "monitors-changed", G_CALLBACK(greeter_background_monitors_changed_cb), background); @@ -1393,8 +1412,30 @@ monitor_window_enter_notify_cb(GtkWidget* widget, GdkEventCrossing* event, const Monitor* monitor) { - if(monitor->object->priv->active_monitor != monitor && - greeter_background_monitor_enabled(monitor->object, monitor)) + if(monitor->object->priv->active_monitor == monitor) + { + GdkWindow *gdkwindow = gtk_widget_get_window (widget); + Window window = GDK_WINDOW_XID (gdkwindow); + Display *display = GDK_WINDOW_XDISPLAY (gdkwindow); + + static Atom wm_protocols = None; + static Atom wm_take_focus = None; + + if (!wm_protocols) + wm_protocols = XInternAtom(display, "WM_PROTOCOLS", False); + if (!wm_take_focus) + wm_take_focus = XInternAtom(display, "WM_TAKE_FOCUS", False); + + XEvent ev = {0}; + ev.xclient.type = ClientMessage; + ev.xclient.window = window; + ev.xclient.message_type = wm_protocols; + ev.xclient.format = 32; + ev.xclient.data.l[0] = wm_take_focus; + ev.xclient.data.l[1] = CurrentTime; + XSendEvent(display, window, False, 0L, &ev); + } + else if(monitor->object->priv->follow_cursor && greeter_background_monitor_enabled(monitor->object, monitor)) greeter_background_set_active_monitor(monitor->object, monitor); return FALSE; } @@ -1633,7 +1674,7 @@ transition_func_linear(gdouble x) } static gdouble -transition_func_easy_in_out(gdouble x) +transition_func_ease_in_out(gdouble x) { return (1 - cos(M_PI*x))/2; } diff --git a/src/lightdm-gtk-greeter-fallback.css b/src/lightdm-gtk-greeter-fallback.css index f98064b..1d28490 100644 --- a/src/lightdm-gtk-greeter-fallback.css +++ b/src/lightdm-gtk-greeter-fallback.css @@ -1,12 +1,12 @@ #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; } diff --git a/src/lightdm-gtk-greeter.c b/src/lightdm-gtk-greeter.c index 69627ab..7a08a44 100644 --- a/src/lightdm-gtk-greeter.c +++ b/src/lightdm-gtk-greeter.c @@ -53,6 +53,7 @@ #include "src/lightdm-gtk-greeter-css-fallback.h" #include "src/lightdm-gtk-greeter-css-application.h" + static LightDMGreeter *greeter; /* State file */ @@ -70,7 +71,8 @@ static void close_pid (GPid pid, gboolean remove); static void sigterm_cb (gpointer user_data); /* Screen window */ -static GtkOverlay *screen_overlay; +static GtkOverlay *screen_overlay; +static GtkWidget *screen_overlay_child; /* Login window */ static GtkWidget *login_window; @@ -283,7 +285,7 @@ void a11y_contrast_cb (GtkCheckMenuItem *item); void a11y_keyboard_cb (GtkCheckMenuItem *item, gpointer user_data); void a11y_reader_cb (GtkCheckMenuItem *item, gpointer user_data); -/* Power indciator */ +/* 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); @@ -316,12 +318,12 @@ greeter_save_focus(GtkWidget* widget) void greeter_restore_focus(const gpointer saved_data) { - if (!saved_data) + struct SavedFocusData *data = saved_data; + + if (!saved_data || !GTK_IS_WIDGET (data->widget)) return; - struct SavedFocusData *data = saved_data; - if (GTK_IS_WIDGET (data->widget)) - gtk_widget_grab_focus (data->widget); + gtk_widget_grab_focus (data->widget); if (GTK_IS_EDITABLE(data->widget) && data->editable_pos > -1) gtk_editable_set_position(GTK_EDITABLE(data->widget), data->editable_pos); } @@ -732,7 +734,7 @@ set_user_image (const gchar *username) } else { - g_warning ("Failed to load user image: %s", error->message); + g_debug ("Failed to load user image: %s", error->message); g_clear_error (&error); } } @@ -849,6 +851,7 @@ menu_command_run (MenuCommand *command) if (id != 0 && end_ptr > text) { socket = GTK_SOCKET (gtk_socket_new ()); + gtk_container_foreach (GTK_CONTAINER (command->widget), (GtkCallback)gtk_widget_destroy, NULL); gtk_container_add (GTK_CONTAINER (command->widget), GTK_WIDGET (socket)); gtk_socket_add_id (socket, id); gtk_widget_show_all (GTK_WIDGET (command->widget)); @@ -879,6 +882,7 @@ menu_command_run (MenuCommand *command) g_warning ("[Command/%s] Failed to run: %s", command->name, error->message); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (command->menu_item), FALSE); } + g_clear_error (&error); return command->pid; @@ -2513,54 +2517,40 @@ load_user_list (void) set_displayed_user (greeter, name); g_free (name); } - } g_free (last_user); } 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; + XEvent *xevent = (XEvent*)gxevent; 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_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) { Window xwin; - int revert_to; - XGetInputFocus (xevent->xunmap.display, &xwin, &revert_to); + int revert_to = RevertToNone; + 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_lower (gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET (screen_overlay)))); } + return GDK_FILTER_CONTINUE; } @@ -2769,6 +2759,7 @@ main (int argc, char **argv) /* Screen window */ screen_overlay = GTK_OVERLAY (gtk_builder_get_object (builder, "screen_overlay")); + screen_overlay_child = GTK_WIDGET (gtk_builder_get_object (builder, "screen_overlay_child")); /* Login window */ login_window = GTK_WIDGET (gtk_builder_get_object (builder, "login_window")); @@ -3140,10 +3131,10 @@ main (int argc, char **argv) } g_strfreev (values); - /* focus fix (source: unity-greeter) */ + /* There is no window manager, so we need to implement some of its functionality */ 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); + gdk_window_add_filter (root_window, wm_window_filter, NULL); gtk_widget_show (GTK_WIDGET (screen_overlay)); diff --git a/src/lightdm-gtk-greeter.glade b/src/lightdm-gtk-greeter.glade index 1230d2e..11fb826 100644 --- a/src/lightdm-gtk-greeter.glade +++ b/src/lightdm-gtk-greeter.glade @@ -282,6 +282,7 @@ <property name="name">cancel_button</property> <property name="visible">True</property> <property name="can_focus">True</property> + <property name="receives_default">False</property> <signal name="clicked" handler="power_button_clicked_cb" swapped="no"/> </object> <packing> @@ -296,6 +297,7 @@ <property name="name">power_ok_button</property> <property name="visible">True</property> <property name="can_focus">True</property> + <property name="receives_default">False</property> <signal name="clicked" handler="power_button_clicked_cb" swapped="no"/> </object> <packing> @@ -326,10 +328,9 @@ <property name="vexpand">True</property> <signal name="get-child-position" handler="screen_overlay_get_child_position_cb" swapped="no"/> <child> - <object class="GtkBox" id="screen-child"> + <object class="GtkEventBox" id="screen_overlay_child"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="orientation">vertical</property> <child> <placeholder/> </child> @@ -541,6 +542,7 @@ <property name="name">cancel_button</property> <property name="visible">True</property> <property name="can_focus">True</property> + <property name="receives_default">False</property> <signal name="clicked" handler="cancel_cb" swapped="no"/> </object> <packing> @@ -555,6 +557,7 @@ <property name="name">login_button</property> <property name="visible">True</property> <property name="can_focus">True</property> + <property name="receives_default">False</property> <signal name="clicked" handler="login_cb" swapped="no"/> </object> <packing> |