gnome-session r4850 - in branches/dbus_based: . gnome-session



Author: mccann
Date: Sun Jul 27 02:51:16 2008
New Revision: 4850
URL: http://svn.gnome.org/viewvc/gnome-session?rev=4850&view=rev

Log:
2008-07-26  William Jon McCann  <jmccann redhat com>

	* configure.in:
	* gnome-session/Makefile.am:
	* gnome-session/gsm-inhibit-dialog.c (scale_pixbuf), (get_cmap),
	(pixbuf_get_from_pixmap), (get_pixmap_for_window),
	(get_pixbuf_for_window), (add_inhibitor), (setup_dialog),
	(gsm_inhibit_dialog_constructor):
	* gnome-session/test-inhibit.c (do_inhibit_for_window),
	(on_widget_show), (main):
	Add ability to get a window snapshot of application.



Modified:
   branches/dbus_based/ChangeLog
   branches/dbus_based/configure.in
   branches/dbus_based/gnome-session/Makefile.am
   branches/dbus_based/gnome-session/gsm-inhibit-dialog.c
   branches/dbus_based/gnome-session/test-inhibit.c

Modified: branches/dbus_based/configure.in
==============================================================================
--- branches/dbus_based/configure.in	(original)
+++ branches/dbus_based/configure.in	Sun Jul 27 02:51:16 2008
@@ -173,6 +173,19 @@
 AC_SUBST(X_LIBS)
 
 dnl ====================================================================
+dnl XRender checks
+dnl ====================================================================
+
+PKG_CHECK_MODULES(XRENDER, xrender, have_xrender=yes, have_xrender=no)
+AM_CONDITIONAL(HAVE_XRENDER, test x$have_xrender = xyes)
+if test $have_xrender=yes; then
+    AC_DEFINE(HAVE_XRENDER, 1, [Have the Render X extension])
+fi
+AC_SUBST(HAVE_XRENDER)
+AC_SUBST(XRENDER_CFLAGS)
+AC_SUBST(XRENDER_LIBS)
+
+dnl ====================================================================
 dnl Language Support
 dnl ====================================================================
 GETTEXT_PACKAGE=gnome-session-2.0
@@ -354,4 +367,5 @@
         Maintainer mode:          ${USE_MAINTAINER_MODE}
 
         PolicyKit support :       ${have_polkit}
+        XComposite support :      ${have_xcomposite}
 "

Modified: branches/dbus_based/gnome-session/Makefile.am
==============================================================================
--- branches/dbus_based/gnome-session/Makefile.am	(original)
+++ branches/dbus_based/gnome-session/Makefile.am	Sun Jul 27 02:51:16 2008
@@ -34,6 +34,7 @@
 	$(NULL)
 
 test_inhibit_LDADD =				\
+	$(GNOME_SESSION_LIBS)			\
 	$(DBUS_GLIB_LIBS)			\
 	$(NULL)
 

Modified: branches/dbus_based/gnome-session/gsm-inhibit-dialog.c
==============================================================================
--- branches/dbus_based/gnome-session/gsm-inhibit-dialog.c	(original)
+++ branches/dbus_based/gnome-session/gsm-inhibit-dialog.c	Sun Jul 27 02:51:16 2008
@@ -29,6 +29,7 @@
 #include <glib/gi18n.h>
 #include <glib-object.h>
 #include <gtk/gtk.h>
+#include <gdk/gdkx.h>
 
 #include <glade/glade-xml.h>
 #include <gconf/gconf-client.h>
@@ -37,6 +38,10 @@
 #include "eggdesktopfile.h"
 #include "util.h"
 
+#ifdef HAVE_XRENDER
+#include <X11/extensions/Xrender.h>
+#endif
+
 #define GSM_INHIBIT_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_INHIBIT_DIALOG, GsmInhibitDialogPrivate))
 
 #define GLADE_XML_FILE "gsm-inhibit-dialog.glade"
@@ -45,6 +50,10 @@
 #define DEFAULT_ICON_SIZE 64
 #endif
 
+#ifndef DEFAULT_SNAPSHOT_SIZE
+#define DEFAULT_SNAPSHOT_SIZE 128
+#endif
+
 #define DIALOG_RESPONSE_LOCK_SCREEN 1
 
 struct GsmInhibitDialogPrivate
@@ -53,6 +62,9 @@
         int                action;
         GsmInhibitorStore *inhibitors;
         GtkListStore      *list_store;
+        gboolean           have_xrender;
+        int                xrender_event_base;
+        int                xrender_error_base;
 };
 
 enum {
@@ -71,7 +83,7 @@
 
 static void     gsm_inhibit_dialog_class_init  (GsmInhibitDialogClass *klass);
 static void     gsm_inhibit_dialog_init        (GsmInhibitDialog      *inhibit_dialog);
-static void     gsm_inhibit_dialog_finalize    (GObject                     *object);
+static void     gsm_inhibit_dialog_finalize    (GObject               *object);
 
 G_DEFINE_TYPE (GsmInhibitDialog, gsm_inhibit_dialog, GTK_TYPE_DIALOG)
 
@@ -89,7 +101,7 @@
 
 static void
 on_response (GsmInhibitDialog *dialog,
-             gint                    response_id)
+             gint              response_id)
 {
         switch (response_id) {
         case DIALOG_RESPONSE_LOCK_SCREEN:
@@ -110,8 +122,8 @@
 
 static gboolean
 find_inhibitor (GsmInhibitDialog *dialog,
-                guint                   cookie,
-                GtkTreeIter            *iter)
+                guint             cookie,
+                GtkTreeIter      *iter)
 {
         GtkTreeModel *model;
         gboolean      found_item;
@@ -245,6 +257,210 @@
         return retval;
 }
 
+
+static GdkPixbuf *
+scale_pixbuf (GdkPixbuf *pixbuf,
+              int        max_width,
+              int        max_height,
+              gboolean   no_stretch_hint)
+{
+        int        pw;
+        int        ph;
+        float      scale_factor_x = 1.0;
+        float      scale_factor_y = 1.0;
+        float      scale_factor = 1.0;
+
+        pw = gdk_pixbuf_get_width (pixbuf);
+        ph = gdk_pixbuf_get_height (pixbuf);
+
+        /* Determine which dimension requires the smallest scale. */
+        scale_factor_x = (float) max_width / (float) pw;
+        scale_factor_y = (float) max_height / (float) ph;
+
+        if (scale_factor_x > scale_factor_y) {
+                scale_factor = scale_factor_y;
+        } else {
+                scale_factor = scale_factor_x;
+        }
+
+        /* always scale down, allow to disable scaling up */
+        if (scale_factor < 1.0 || !no_stretch_hint) {
+                int scale_x = (int) (pw * scale_factor);
+                int scale_y = (int) (ph * scale_factor);
+                g_debug ("Scaling to %dx%d", scale_x, scale_y);
+                return gdk_pixbuf_scale_simple (pixbuf,
+                                                scale_x,
+                                                scale_y,
+                                                GDK_INTERP_BILINEAR);
+        } else {
+                return g_object_ref (pixbuf);
+        }
+}
+
+#ifdef HAVE_XRENDER
+
+/* adapted from metacity */
+static GdkColormap*
+get_cmap (GdkPixmap *pixmap)
+{
+        GdkColormap *cmap;
+
+        cmap = gdk_drawable_get_colormap (pixmap);
+        if (cmap) {
+                g_object_ref (G_OBJECT (cmap));
+        }
+
+        if (cmap == NULL) {
+                if (gdk_drawable_get_depth (pixmap) == 1) {
+                        g_debug ("Using NULL colormap for snapshotting bitmap\n");
+                        cmap = NULL;
+                } else {
+                        g_debug ("Using system cmap to snapshot pixmap\n");
+                        cmap = gdk_screen_get_system_colormap (gdk_drawable_get_screen (pixmap));
+
+                        g_object_ref (G_OBJECT (cmap));
+                }
+        }
+
+        /* Be sure we aren't going to blow up due to visual mismatch */
+        if (cmap &&
+            (gdk_colormap_get_visual (cmap)->depth !=
+             gdk_drawable_get_depth (pixmap))) {
+                cmap = NULL;
+                g_debug ("Switching back to NULL cmap because of depth mismatch\n");
+        }
+
+        return cmap;
+}
+
+static GdkPixbuf *
+pixbuf_get_from_pixmap (Pixmap xpixmap)
+{
+        GdkDrawable *drawable;
+        GdkPixbuf   *retval;
+        GdkColormap *cmap;
+        int          width;
+        int          height;
+
+        retval = NULL;
+        cmap = NULL;
+
+        g_debug ("GsmInhibitDialog: getting foreign pixmap for %u", (guint)xpixmap);
+        drawable = gdk_pixmap_foreign_new (xpixmap);
+        if (GDK_IS_PIXMAP (drawable)) {
+                cmap = get_cmap (drawable);
+                gdk_drawable_get_size (drawable,
+                                       &width,
+                                       &height);
+                g_debug ("GsmInhibitDialog: getting pixbuf w=%d h=%d", width, height);
+
+                retval = gdk_pixbuf_get_from_drawable (NULL,
+                                                       drawable,
+                                                       cmap,
+                                                       0, 0,
+                                                       0, 0,
+                                                       width, height);
+        }
+        if (cmap) {
+                g_object_unref (G_OBJECT (cmap));
+        }
+        if (drawable) {
+                g_object_unref (G_OBJECT (drawable));
+        }
+
+        return retval;
+}
+
+static Pixmap
+get_pixmap_for_window (Window window)
+{
+        XWindowAttributes        attr;
+        XRenderPictureAttributes pa;
+        Pixmap                   pixmap;
+        XRenderPictFormat       *format;
+        Picture                  src_picture;
+        Picture                  dst_picture;
+        gboolean                 has_alpha;
+        int                      x;
+        int                      y;
+        int                      width;
+        int                      height;
+
+        XGetWindowAttributes (GDK_DISPLAY (), window, &attr);
+
+        format = XRenderFindVisualFormat (GDK_DISPLAY (), attr.visual);
+        has_alpha = (format->type == PictTypeDirect && format->direct.alphaMask);
+        x = attr.x;
+        y = attr.y;
+        width = attr.width;
+        height = attr.height;
+
+        pa.subwindow_mode = IncludeInferiors; /* Don't clip child widgets */
+
+        src_picture = XRenderCreatePicture (GDK_DISPLAY (), window, format, CPSubwindowMode, &pa);
+
+        pixmap = XCreatePixmap (GDK_DISPLAY (),
+                                window,
+                                width, height,
+                                attr.depth);
+
+        dst_picture = XRenderCreatePicture (GDK_DISPLAY (), pixmap, format, 0, 0);
+        XRenderComposite (GDK_DISPLAY (),
+                          has_alpha ? PictOpOver : PictOpSrc,
+                          src_picture,
+                          None,
+                          dst_picture,
+                          0, 0, 0, 0,
+                          0, 0,
+                          width, height);
+
+
+        return pixmap;
+}
+
+#endif /* HAVE_COMPOSITE */
+
+static GdkPixbuf *
+get_pixbuf_for_window (guint xid,
+                       int   width,
+                       int   height)
+{
+        GdkPixbuf *pixbuf = NULL;
+#ifdef HAVE_XRENDER
+        Window     xwindow;
+        Pixmap     xpixmap;
+
+        xwindow = (Window) xid;
+        xpixmap = get_pixmap_for_window (xwindow);
+        if (xpixmap == None) {
+                g_debug ("GsmInhibitDialog: Unable to get window snapshot for %u", xid);
+                return NULL;
+        } else {
+                g_debug ("GsmInhibitDialog: Got xpixmap %u", (guint)xpixmap);
+        }
+
+        pixbuf = pixbuf_get_from_pixmap (xpixmap);
+
+        if (xpixmap != None) {
+                gdk_error_trap_push ();
+                XFreePixmap (GDK_DISPLAY (), xpixmap);
+                gdk_display_sync (gdk_display_get_default ());
+                gdk_error_trap_pop ();
+        }
+
+        if (pixbuf != NULL) {
+                GdkPixbuf *scaled;
+                g_debug ("GsmInhibitDialog: scaling pixbuf to w=%d h=%d", width, height);
+                scaled = scale_pixbuf (pixbuf, width, height, TRUE);
+                g_object_unref (pixbuf);
+                pixbuf = scaled;
+        }
+#else
+        g_debug ("GsmInhibitDialog: no support for getting window snapshot");
+#endif
+        return pixbuf;
+}
+
 static void
 add_inhibitor (GsmInhibitDialog *dialog,
                GsmInhibitor     *inhibitor)
@@ -257,6 +473,7 @@
         EggDesktopFile *desktop_file;
         GError         *error;
         char          **search_dirs;
+        guint           xid;
 
         /* FIXME: get info from xid */
 
@@ -272,6 +489,15 @@
                 desktop_filename = g_strdup (app_id);
         }
 
+        xid = gsm_inhibitor_get_toplevel_xid (inhibitor);
+        g_debug ("GsmInhibitDialog: inhibitor has XID %u", xid);
+        if (xid > 0 && dialog->priv->have_xrender) {
+                pixbuf = get_pixbuf_for_window (xid, DEFAULT_SNAPSHOT_SIZE, DEFAULT_SNAPSHOT_SIZE);
+                if (pixbuf == NULL) {
+                        g_debug ("GsmInhibitDialog: unable to read pixbuf from %u", xid);
+                }
+        }
+
         if (desktop_filename != NULL) {
                 /* FIXME: maybe also append the autostart dirs ? */
                 search_dirs = gsm_util_get_app_dirs ();
@@ -301,12 +527,14 @@
                         name = egg_desktop_file_get_name (desktop_file);
                         icon_name = egg_desktop_file_get_icon (desktop_file);
 
-                        pixbuf = _load_icon (gtk_icon_theme_get_default (),
-                                             icon_name,
-                                             DEFAULT_ICON_SIZE,
-                                             DEFAULT_ICON_SIZE,
-                                             DEFAULT_ICON_SIZE,
-                                             NULL);
+                        if (pixbuf == NULL) {
+                                pixbuf = _load_icon (gtk_icon_theme_get_default (),
+                                                     icon_name,
+                                                     DEFAULT_ICON_SIZE,
+                                                     DEFAULT_ICON_SIZE,
+                                                     DEFAULT_ICON_SIZE,
+                                                     NULL);
+                        }
                 }
         }
 
@@ -384,9 +612,9 @@
 }
 
 static void
-on_store_inhibitor_added (GsmInhibitorStore      *store,
-                          guint                   cookie,
-                          GsmInhibitDialog *dialog)
+on_store_inhibitor_added (GsmInhibitorStore *store,
+                          guint              cookie,
+                          GsmInhibitDialog  *dialog)
 {
         GsmInhibitor *inhibitor;
         GtkTreeIter   iter;
@@ -404,9 +632,9 @@
 }
 
 static void
-on_store_inhibitor_removed (GsmInhibitorStore      *store,
-                            guint                   cookie,
-                            GsmInhibitDialog *dialog)
+on_store_inhibitor_removed (GsmInhibitorStore *store,
+                            guint              cookie,
+                            GsmInhibitDialog  *dialog)
 {
         GtkTreeIter   iter;
 
@@ -485,9 +713,9 @@
 
 static void
 gsm_inhibit_dialog_get_property (GObject        *object,
-                                        guint           prop_id,
-                                        GValue         *value,
-                                        GParamSpec     *pspec)
+                                 guint           prop_id,
+                                 GValue         *value,
+                                 GParamSpec     *pspec)
 {
         GsmInhibitDialog *dialog = GSM_INHIBIT_DIALOG (object);
 
@@ -505,11 +733,11 @@
 }
 
 static void
-name_cell_data_func (GtkTreeViewColumn      *tree_column,
-                     GtkCellRenderer        *cell,
-                     GtkTreeModel           *model,
-                     GtkTreeIter            *iter,
-                     GsmInhibitDialog *dialog)
+name_cell_data_func (GtkTreeViewColumn *tree_column,
+                     GtkCellRenderer   *cell,
+                     GtkTreeModel      *model,
+                     GtkTreeIter       *iter,
+                     GsmInhibitDialog  *dialog)
 {
         char    *name;
         char    *reason;
@@ -536,8 +764,8 @@
 }
 
 static gboolean
-add_to_model (guint                   cookie,
-              GsmInhibitor           *inhibitor,
+add_to_model (guint             cookie,
+              GsmInhibitor     *inhibitor,
               GsmInhibitDialog *dialog)
 {
         add_inhibitor (dialog, inhibitor);
@@ -612,9 +840,6 @@
 
         /* IMAGE COLUMN */
         renderer = gtk_cell_renderer_pixbuf_new ();
-        gtk_cell_renderer_set_fixed_size (renderer,
-                                          DEFAULT_ICON_SIZE,
-                                          DEFAULT_ICON_SIZE);
         column = gtk_tree_view_column_new ();
         gtk_tree_view_column_pack_start (column, renderer, FALSE);
         gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
@@ -645,8 +870,8 @@
 
 static GObject *
 gsm_inhibit_dialog_constructor (GType                  type,
-                                       guint                  n_construct_properties,
-                                       GObjectConstructParam *construct_properties)
+                                guint                  n_construct_properties,
+                                GObjectConstructParam *construct_properties)
 {
         GsmInhibitDialog *dialog;
 
@@ -654,7 +879,21 @@
                                                                                                                   n_construct_properties,
                                                                                                                   construct_properties));
 
+#ifdef HAVE_XRENDER
+        gdk_error_trap_push ();
+        if (XRenderQueryExtension (GDK_DISPLAY (), &dialog->priv->xrender_event_base, &dialog->priv->xrender_error_base)) {
+                g_warning ("GsmInhibitDialog: Initialized XRender extension");
+                dialog->priv->have_xrender = TRUE;
+        } else {
+                g_warning ("GsmInhibitDialog: Unable to initialize XRender extension");
+                dialog->priv->have_xrender = FALSE;
+        }
+        gdk_display_sync (gdk_display_get_default ());
+        gdk_error_trap_pop ();
+#endif /* HAVE_XRENDER */
+
         setup_dialog (dialog);
+
         gtk_widget_show_all (GTK_WIDGET (dialog));
 
         return G_OBJECT (dialog);
@@ -752,7 +991,7 @@
 
 GtkWidget *
 gsm_inhibit_dialog_new (GsmInhibitorStore *inhibitors,
-                               int                action)
+                        int                action)
 {
         GObject *object;
 

Modified: branches/dbus_based/gnome-session/test-inhibit.c
==============================================================================
--- branches/dbus_based/gnome-session/test-inhibit.c	(original)
+++ branches/dbus_based/gnome-session/test-inhibit.c	Sun Jul 27 02:51:16 2008
@@ -26,7 +26,8 @@
 #include <string.h>
 #include <unistd.h>
 
-#include <glib.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
 #include <dbus/dbus-glib.h>
 
 #define SM_DBUS_NAME      "org.gnome.SessionManager"
@@ -68,7 +69,7 @@
 } GsmInhibitFlag;
 
 static gboolean
-do_inhibit (void)
+do_inhibit_for_window (GdkWindow *window)
 {
         GError     *error;
         gboolean    res;
@@ -86,7 +87,7 @@
         app_id = "nautilus";
         reason = "A file transfer is in progress.";
 #endif
-        toplevel_xid = 0;
+        toplevel_xid = GDK_DRAWABLE_XID (window);
         flags = GSM_INHIBITOR_FLAG_LOGOUT
                 | GSM_INHIBITOR_FLAG_SWITCH_USER
                 | GSM_INHIBITOR_FLAG_SUSPEND;
@@ -147,15 +148,28 @@
         return TRUE;
 }
 
+static void
+on_widget_show (GtkWidget *dialog,
+                gpointer   data)
+{
+        gboolean res;
+
+        res = do_inhibit_for_window (dialog->window);
+        if (! res) {
+                g_warning ("Unable to register client with session manager");
+        }
+}
+
 int
 main (int   argc,
       char *argv[])
 {
-        gboolean res;
+        gboolean   res;
+        GtkWidget *dialog;
 
         g_log_set_always_fatal (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
 
-        g_type_init ();
+        gtk_init (&argc, &argv);
 
         res = session_manager_connect ();
         if (! res) {
@@ -163,12 +177,19 @@
                 exit (1);
         }
 
-        res = do_inhibit ();
-        if (! res) {
-                g_warning ("Unable to register client with session manager");
-        }
+        g_timeout_add_seconds (30, (GSourceFunc)gtk_main_quit, NULL);
+
+        dialog = gtk_message_dialog_new (NULL,
+                                         0,
+                                         GTK_MESSAGE_INFO,
+                                         GTK_BUTTONS_CANCEL,
+                                         "Inhibiting logout, switch user, and suspend.");
+
+        g_signal_connect (dialog, "response", G_CALLBACK (gtk_main_quit), NULL);
+        g_signal_connect (dialog, "show", G_CALLBACK (on_widget_show), NULL);
+        gtk_widget_show (dialog);
 
-        sleep (30);
+        gtk_main ();
 
         do_uninhibit ();
         session_manager_disconnect ();



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]