diff --git a/0001-Add-an-API-to-show-a-message-on-the-locked-screen.patch b/0001-Add-an-API-to-show-a-message-on-the-locked-screen.patch new file mode 100644 index 0000000..70975c5 --- /dev/null +++ b/0001-Add-an-API-to-show-a-message-on-the-locked-screen.patch @@ -0,0 +1,410 @@ +From 370ae655619c8e0fbd8a092d7dc8dc6ad4ab1445 Mon Sep 17 00:00:00 2001 +From: William Jon McCann +Date: Mon, 2 Nov 2009 17:15:45 -0500 +Subject: [PATCH 1/3] Add an API to show a message on the locked screen + +Fixes https://bugzilla.gnome.org/show_bug.cgi?id=599258 +--- + src/gs-listener-dbus.c | 68 ++++++++++++++++++++++++++++++ + src/gs-listener-dbus.h | 4 ++ + src/gs-manager.c | 17 ++++++++ + src/gs-manager.h | 4 ++ + src/gs-marshal.list | 1 + + src/gs-monitor.c | 16 +++++++ + src/gs-window-x11.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++ + src/gs-window.h | 4 ++ + 8 files changed, 221 insertions(+), 0 deletions(-) + +diff --git a/src/gs-listener-dbus.c b/src/gs-listener-dbus.c +index 85a0328..e7690a5 100644 +--- a/src/gs-listener-dbus.c ++++ b/src/gs-listener-dbus.c +@@ -108,6 +108,7 @@ enum { + SIMULATE_USER_ACTIVITY, + ACTIVE_CHANGED, + THROTTLE_CHANGED, ++ SHOW_MESSAGE, + LAST_SIGNAL + }; + +@@ -1223,6 +1224,52 @@ listener_get_active_time (GSListener *listener, + } + + static DBusHandlerResult ++listener_show_message (GSListener *listener, ++ DBusConnection *connection, ++ DBusMessage *message) ++{ ++ DBusMessageIter iter; ++ DBusMessage *reply; ++ DBusError error; ++ ++ reply = dbus_message_new_method_return (message); ++ ++ dbus_message_iter_init_append (reply, &iter); ++ ++ if (reply == NULL) { ++ g_error ("No memory"); ++ } ++ ++ if (listener->priv->active) { ++ char *summary; ++ char *body; ++ char *icon; ++ ++ /* if we're not active we ignore the request */ ++ ++ dbus_error_init (&error); ++ if (! dbus_message_get_args (message, &error, ++ DBUS_TYPE_STRING, &summary, ++ DBUS_TYPE_STRING, &body, ++ DBUS_TYPE_STRING, &icon, ++ DBUS_TYPE_INVALID)) { ++ raise_syntax (connection, message, "ShowMessage"); ++ return DBUS_HANDLER_RESULT_HANDLED; ++ } ++ ++ g_signal_emit (listener, signals [SHOW_MESSAGE], 0, summary, body, icon); ++ } ++ ++ if (! dbus_connection_send (connection, reply, NULL)) { ++ g_error ("No memory"); ++ } ++ ++ dbus_message_unref (reply); ++ ++ return DBUS_HANDLER_RESULT_HANDLED; ++} ++ ++static DBusHandlerResult + do_introspect (DBusConnection *connection, + DBusMessage *message, + dbus_bool_t local_interface) +@@ -1278,6 +1325,11 @@ do_introspect (DBusConnection *connection, + " \n" + " \n" + " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" ++ " \n" + " \n" + " \n" + " \n" +@@ -1362,6 +1414,9 @@ listener_dbus_handle_session_message (DBusConnection *connection, + if (dbus_message_is_method_call (message, GS_LISTENER_SERVICE, "GetActiveTime")) { + return listener_get_active_time (listener, connection, message); + } ++ if (dbus_message_is_method_call (message, GS_LISTENER_SERVICE, "ShowMessage")) { ++ return listener_show_message (listener, connection, message); ++ } + if (dbus_message_is_method_call (message, GS_LISTENER_SERVICE, "SimulateUserActivity")) { + g_signal_emit (listener, signals [SIMULATE_USER_ACTIVITY], 0); + return DBUS_HANDLER_RESULT_HANDLED; +@@ -1796,6 +1851,19 @@ gs_listener_class_init (GSListenerClass *klass) + G_TYPE_NONE, + 1, + G_TYPE_BOOLEAN); ++ signals [SHOW_MESSAGE] = ++ g_signal_new ("show-message", ++ G_TYPE_FROM_CLASS (object_class), ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET (GSListenerClass, show_message), ++ NULL, ++ NULL, ++ gs_marshal_VOID__STRING_STRING_STRING, ++ G_TYPE_NONE, ++ 3, ++ G_TYPE_STRING, ++ G_TYPE_STRING, ++ G_TYPE_STRING); + + g_object_class_install_property (object_class, + PROP_ACTIVE, +diff --git a/src/gs-listener-dbus.h b/src/gs-listener-dbus.h +index a788e40..c57f367 100644 +--- a/src/gs-listener-dbus.h ++++ b/src/gs-listener-dbus.h +@@ -52,6 +52,10 @@ typedef struct + gboolean active); + void (* throttle_changed) (GSListener *listener, + gboolean throttled); ++ void (* show_message) (GSListener *listener, ++ const char *summary, ++ const char *body, ++ const char *icon); + + } GSListenerClass; + +diff --git a/src/gs-manager.c b/src/gs-manager.c +index bb0ddf6..1609f83 100644 +--- a/src/gs-manager.c ++++ b/src/gs-manager.c +@@ -1174,6 +1174,23 @@ find_window_at_pointer (GSManager *manager) + return window; + } + ++void ++gs_manager_show_message (GSManager *manager, ++ const char *summary, ++ const char *body, ++ const char *icon) ++{ ++ GSWindow *window; ++ ++ g_return_if_fail (GS_IS_MANAGER (manager)); ++ ++ /* Find the GSWindow that contains the pointer */ ++ window = find_window_at_pointer (manager); ++ gs_window_show_message (window, summary, body, icon); ++ ++ gs_manager_request_unlock (manager); ++} ++ + static gboolean + manager_maybe_grab_window (GSManager *manager, + GSWindow *window) +diff --git a/src/gs-manager.h b/src/gs-manager.h +index b0493ab..3a3e349 100644 +--- a/src/gs-manager.h ++++ b/src/gs-manager.h +@@ -95,6 +95,10 @@ void gs_manager_set_themes (GSManager *manager, + GSList *themes); + void gs_manager_set_mode (GSManager *manager, + GSSaverMode mode); ++void gs_manager_show_message (GSManager *manager, ++ const char *summary, ++ const char *body, ++ const char *icon); + gboolean gs_manager_request_unlock (GSManager *manager); + void gs_manager_cancel_unlock_request (GSManager *manager); + +diff --git a/src/gs-marshal.list b/src/gs-marshal.list +index 228ba92..9a4d620 100644 +--- a/src/gs-marshal.list ++++ b/src/gs-marshal.list +@@ -1,3 +1,4 @@ + BOOLEAN:VOID + BOOLEAN:INT + BOOLEAN:BOOLEAN ++VOID:STRING,STRING,STRING +diff --git a/src/gs-monitor.c b/src/gs-monitor.c +index 0fd4402..640ee74 100644 +--- a/src/gs-monitor.c ++++ b/src/gs-monitor.c +@@ -220,6 +220,19 @@ listener_cycle_cb (GSListener *listener, + gs_manager_cycle (monitor->priv->manager); + } + ++static void ++listener_show_message_cb (GSListener *listener, ++ const char *summary, ++ const char *body, ++ const char *icon, ++ GSMonitor *monitor) ++{ ++ gs_manager_show_message (monitor->priv->manager, ++ summary, ++ body, ++ icon); ++} ++ + static gboolean + listener_active_changed_cb (GSListener *listener, + gboolean active, +@@ -334,6 +347,7 @@ disconnect_listener_signals (GSMonitor *monitor) + g_signal_handlers_disconnect_by_func (monitor->priv->listener, listener_active_changed_cb, monitor); + g_signal_handlers_disconnect_by_func (monitor->priv->listener, listener_throttle_changed_cb, monitor); + g_signal_handlers_disconnect_by_func (monitor->priv->listener, listener_simulate_user_activity_cb, monitor); ++ g_signal_handlers_disconnect_by_func (monitor->priv->listener, listener_show_message_cb, monitor); + } + + static void +@@ -351,6 +365,8 @@ connect_listener_signals (GSMonitor *monitor) + G_CALLBACK (listener_throttle_changed_cb), monitor); + g_signal_connect (monitor->priv->listener, "simulate-user-activity", + G_CALLBACK (listener_simulate_user_activity_cb), monitor); ++ g_signal_connect (monitor->priv->listener, "show-message", ++ G_CALLBACK (listener_show_message_cb), monitor); + } + + static void +diff --git a/src/gs-window-x11.c b/src/gs-window-x11.c +index 2a74e10..5e0ebe5 100644 +--- a/src/gs-window-x11.c ++++ b/src/gs-window-x11.c +@@ -52,6 +52,7 @@ enum { + }; + + #define MAX_QUEUED_EVENTS 16 ++#define INFO_BAR_SECONDS 30 + + #define GS_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GS_TYPE_WINDOW, GSWindowPrivate)) + +@@ -77,6 +78,8 @@ struct GSWindowPrivate + GtkWidget *lock_box; + GtkWidget *lock_socket; + GtkWidget *keyboard_socket; ++ GtkWidget *info_bar; ++ GtkWidget *info_content; + + GdkPixmap *background_pixmap; + +@@ -87,6 +90,7 @@ struct GSWindowPrivate + guint dialog_response_signal_id; + + guint watchdog_timer_id; ++ guint info_bar_timer_id; + + gint lock_pid; + gint lock_watch_id; +@@ -896,6 +900,96 @@ gs_window_real_show (GtkWidget *widget) + gdk_window_add_filter (NULL, (GdkFilterFunc)xevent_filter, window); + } + ++static void ++set_info_text_and_icon (GSWindow *window, ++ const char *icon_stock_id, ++ const char *primary_text, ++ const char *secondary_text) ++{ ++ GtkWidget *content_area; ++ GtkWidget *hbox_content; ++ GtkWidget *image; ++ GtkWidget *vbox; ++ gchar *primary_markup; ++ gchar *secondary_markup; ++ GtkWidget *primary_label; ++ GtkWidget *secondary_label; ++ ++ hbox_content = gtk_hbox_new (FALSE, 8); ++ gtk_widget_show (hbox_content); ++ ++ image = gtk_image_new_from_stock (icon_stock_id, GTK_ICON_SIZE_DIALOG); ++ gtk_widget_show (image); ++ gtk_box_pack_start (GTK_BOX (hbox_content), image, FALSE, FALSE, 0); ++ gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0); ++ ++ vbox = gtk_vbox_new (FALSE, 6); ++ gtk_widget_show (vbox); ++ gtk_box_pack_start (GTK_BOX (hbox_content), vbox, FALSE, FALSE, 0); ++ ++ primary_markup = g_strdup_printf ("%s", primary_text); ++ primary_label = gtk_label_new (primary_markup); ++ g_free (primary_markup); ++ gtk_widget_show (primary_label); ++ gtk_box_pack_start (GTK_BOX (vbox), primary_label, TRUE, TRUE, 0); ++ gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE); ++ gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE); ++ gtk_misc_set_alignment (GTK_MISC (primary_label), 0, 0.5); ++ ++ if (secondary_text != NULL) { ++ secondary_markup = g_strdup_printf ("%s", ++ secondary_text); ++ secondary_label = gtk_label_new (secondary_markup); ++ g_free (secondary_markup); ++ gtk_widget_show (secondary_label); ++ gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0); ++ gtk_label_set_use_markup (GTK_LABEL (secondary_label), TRUE); ++ gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE); ++ gtk_misc_set_alignment (GTK_MISC (secondary_label), 0, 0.5); ++ } ++ ++ /* remove old content */ ++ content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (window->priv->info_bar)); ++ if (window->priv->info_content != NULL) { ++ gtk_container_remove (GTK_CONTAINER (content_area), window->priv->info_content); ++ } ++ gtk_box_pack_start (GTK_BOX (content_area), ++ hbox_content, ++ TRUE, FALSE, 0); ++ window->priv->info_content = hbox_content; ++} ++ ++static gboolean ++info_bar_timeout (GSWindow *window) ++{ ++ window->priv->info_bar_timer_id = 0; ++ gtk_widget_hide (window->priv->info_bar); ++ return FALSE; ++} ++ ++void ++gs_window_show_message (GSWindow *window, ++ const char *summary, ++ const char *body, ++ const char *icon) ++{ ++ g_return_if_fail (GS_IS_WINDOW (window)); ++ ++ set_info_text_and_icon (window, ++ icon, ++ summary, ++ body); ++ gtk_widget_show (window->priv->info_bar); ++ ++ if (window->priv->info_bar_timer_id > 0) { ++ g_source_remove (window->priv->info_bar_timer_id); ++ } ++ ++ window->priv->info_bar_timer_id = g_timeout_add_seconds (INFO_BAR_SECONDS, ++ (GSourceFunc)info_bar_timeout, ++ window); ++} ++ + void + gs_window_show (GSWindow *window) + { +@@ -2218,6 +2312,14 @@ gs_window_class_init (GSWindowClass *klass) + } + + static void ++create_info_bar (GSWindow *window) ++{ ++ window->priv->info_bar = gtk_info_bar_new (); ++ gtk_widget_set_no_show_all (window->priv->info_bar, TRUE); ++ gtk_box_pack_end (GTK_BOX (window->priv->vbox), window->priv->info_bar, FALSE, FALSE, 0); ++} ++ ++static void + gs_window_init (GSWindow *window) + { + window->priv = GS_WINDOW_GET_PRIVATE (window); +@@ -2258,6 +2360,7 @@ gs_window_init (GSWindow *window) + window->priv->drawing_area = gtk_drawing_area_new (); + gtk_widget_show (window->priv->drawing_area); + gtk_box_pack_start (GTK_BOX (window->priv->vbox), window->priv->drawing_area, TRUE, TRUE, 0); ++ create_info_bar (window); + + force_no_pixmap_background (window->priv->drawing_area); + } +@@ -2290,6 +2393,10 @@ gs_window_finalize (GObject *object) + g_free (window->priv->logout_command); + g_free (window->priv->keyboard_command); + ++ if (window->priv->info_bar_timer_id > 0) { ++ g_source_remove (window->priv->info_bar_timer_id); ++ } ++ + remove_watchdog_timer (window); + remove_popup_dialog_idle (window); + +diff --git a/src/gs-window.h b/src/gs-window.h +index 6440a6d..fc2287e 100644 +--- a/src/gs-window.h ++++ b/src/gs-window.h +@@ -83,6 +83,10 @@ void gs_window_set_logout_command (GSWindow *window, + const char *command); + void gs_window_set_status_message (GSWindow *window, + const char *status_message); ++void gs_window_show_message (GSWindow *window, ++ const char *summary, ++ const char *body, ++ const char *icon); + + void gs_window_request_unlock (GSWindow *window); + void gs_window_cancel_unlock_request (GSWindow *window); +-- +1.6.5.2 + diff --git a/gnome-screensaver.spec b/gnome-screensaver.spec index 1a76ae9..410ba78 100644 --- a/gnome-screensaver.spec +++ b/gnome-screensaver.spec @@ -14,7 +14,7 @@ Summary: GNOME Screensaver Name: gnome-screensaver Version: 2.28.0 -Release: 5%{?dist} +Release: 7%{?dist} License: GPLv2+ Group: Amusements/Graphics Source0: http://download.gnome.org/sources/gnome-screensaver/2.28/%{name}-%{version}.tar.bz2 @@ -25,9 +25,16 @@ Patch1: gnome-screensaver-2.20.0-default-theme.patch Patch2: gnome-screensaver-2.26.0-securitytoken.patch Patch7: gnome-screensaver-2.20.0-blank-by-default.patch Patch8: gnome-screensaver-2.20.0-selinux-permit.patch +# from upstream Patch9: xrandr-gamma.patch +# from upstream Patch10: multihead-issues.patch +# https://bugzilla.gnome.org/show_bug.cgi?id=598476 Patch11: ask-to-die.patch +# from upstream +Patch12: remove-session-inhibits.patch +# from upstream +Patch13: 0001-Add-an-API-to-show-a-message-on-the-locked-screen.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) URL: http://www.gnome.org @@ -83,6 +90,8 @@ simple, sane, secure defaults and be well integrated with the desktop. %patch9 -p1 -b .xrandr-gamma %patch10 -p1 -b .multihead-issues %patch11 -p1 -b .ask-to-die +%patch12 -p1 -b .remove-session-inhibits +%patch13 -p1 -b .message-api libtoolize --force --copy @@ -157,6 +166,10 @@ fi %doc %{_mandir}/man1/*.1.gz %changelog +* Fri Nov 6 2009 Matthias Clasen 2.28.0-7 +- Clean up session inhibitors if the owner falls off the bus +- Add an api to show messages + * Fri Oct 23 2009 Matthias Clasen 2.28.0-5 - Make the dialog ask to be killed after 5 attempts diff --git a/remove-session-inhibits.patch b/remove-session-inhibits.patch new file mode 100644 index 0000000..4733c2b --- /dev/null +++ b/remove-session-inhibits.patch @@ -0,0 +1,74 @@ +diff -up gnome-screensaver-2.28.0/src/gs-listener-dbus.c.remove-session-inhibits gnome-screensaver-2.28.0/src/gs-listener-dbus.c +--- gnome-screensaver-2.28.0/src/gs-listener-dbus.c.remove-session-inhibits 2009-08-19 19:19:14.000000000 -0400 ++++ gnome-screensaver-2.28.0/src/gs-listener-dbus.c 2009-11-02 18:07:57.129864647 -0500 +@@ -985,47 +985,40 @@ listener_dbus_remove_ref_entry (GSListen + } + + static gboolean +-listener_ref_entry_has_connection (gpointer key, +- gpointer value, +- gpointer user_data) +-{ +- GSListenerRefEntry *entry; +- const char *connection; +- gboolean matches; +- +- entry = (GSListenerRefEntry *)value; +- connection = (const char *) user_data; +- +- matches = FALSE; +- if (connection != NULL && entry->connection != NULL) { +- matches = (strcmp (connection, entry->connection) == 0); +- if (matches) { +- gs_debug ("removing %s from %s for reason '%s' on connection %s", +- get_name_for_entry_type (entry->entry_type), +- entry->application, +- entry->reason, +- entry->connection); +- } +- } +- +- return matches; +-} +- +-static gboolean + listener_ref_entry_remove_for_connection (GSListener *listener, + int entry_type, + const char *connection) + { + gboolean removed; +- guint n_removed; + GHashTable *hash; ++ GHashTableIter iter; ++ GSListenerRefEntry *entry; ++ ++ if (connection == NULL) ++ return FALSE; + + hash = get_hash_for_entry_type (listener, entry_type); + + removed = FALSE; +- n_removed = g_hash_table_foreach_remove (hash, listener_ref_entry_has_connection, (gpointer)connection); ++ g_hash_table_iter_init (&iter, hash); ++ while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&entry)) { ++ if (entry->connection != NULL && ++ strcmp (connection, entry->connection) == 0) { ++ gs_debug ("removing %s from %s for reason '%s' on connection %s", ++ get_name_for_entry_type (entry->entry_type), ++ entry->application, ++ entry->reason, ++ entry->connection); ++ ++ if (entry->entry_type == REF_ENTRY_TYPE_INHIBIT) { ++ /* remove inhibit from gnome session */ ++ remove_session_inhibit (listener, entry); ++ } + +- removed = (n_removed > 0); ++ g_hash_table_iter_remove (&iter); ++ removed = TRUE; ++ } ++ } + + return removed; + }