"show desktop button" applet



Hi,

I implemented the much-requested "show desktop" button today, here are
the libwnck and panel patches. metacity needed a bugfix also before it
would work, the metacity fix is already committed.

I'll commit this soon if no one complains. As it's tiny and there's no
API involved I don't think it merits a GEP unless someone finds it
really controversial.

Havoc

Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/libwnck/ChangeLog,v
retrieving revision 1.152
diff -u -p -u -r1.152 ChangeLog
--- ChangeLog	21 Sep 2002 15:54:23 -0000	1.152
+++ ChangeLog	24 Sep 2002 02:04:45 -0000
@@ -1,3 +1,28 @@
+2002-09-23  Havoc Pennington  <hp pobox com>
+
+	* libwnck/test-wnck.c (main): add test stuff for showing desktop
+	feature
+
+	* libwnck/xutils.c (_wnck_toggle_showing_desktop): new function
+	(_wnck_activate_workspace): fix a hardcoded gdk_display, but it
+	looks like there are a lot more
+
+	* libwnck/screen.c (wnck_screen_toggle_showing_desktop):
+	new function
+	(wnck_screen_get_showing_desktop): new function
+
+	* libwnck/workspace-accessible.c: include headers to avoid
+	warnings
+	(wnck_workspace_accessible_get_size): add comment about how this 
+	is totally broken
+
+	* libwnck/pager.c: remove some unused variables
+
+	* configure.in: version to 2.1.1 and bump current/age
+
+	* libwnck/screen.c: monitor _NET_SHOWING_DESKTOP and emit a signal
+	if it changed
+
 2002-09-17  Havoc Pennington  <hp redhat com>
 
 	* libwnck/window.c (update_transient_for): track a flag for
Index: configure.in
===================================================================
RCS file: /cvs/gnome/libwnck/configure.in,v
retrieving revision 1.60
diff -u -p -u -r1.60 configure.in
--- configure.in	17 Sep 2002 15:37:08 -0000	1.60
+++ configure.in	24 Sep 2002 02:04:45 -0000
@@ -2,13 +2,13 @@ AC_INIT(libwnck/window.h)
 
 AM_CONFIG_HEADER(config.h)
 
-AM_INIT_AUTOMAKE(libwnck, 2.1.0)
+AM_INIT_AUTOMAKE(libwnck, 2.1.1)
 AM_MAINTAINER_MODE
 
 dnl libtool versioning for libwnck
 
 dnl increment if the interface has additions, changes, removals.
-LIBWNCK_CURRENT=5
+LIBWNCK_CURRENT=6
 
 dnl increment any time the source changes; set to 
 dnl  0 if you increment CURRENT
@@ -17,7 +17,7 @@ LIBWNCK_REVISION=0
 dnl increment if any interfaces have been added; set to 0
 dnl  if any interfaces have been removed. removal has 
 dnl  precedence over adding, so set to 0 if both happened.
-LIBWNCK_AGE=1
+LIBWNCK_AGE=2
 
 AC_SUBST(LIBWNCK_CURRENT)
 AC_SUBST(LIBWNCK_REVISION)
Index: libwnck/pager.c
===================================================================
RCS file: /cvs/gnome/libwnck/libwnck/pager.c,v
retrieving revision 1.27
diff -u -p -u -r1.27 pager.c
--- libwnck/pager.c	16 Sep 2002 05:42:43 -0000	1.27
+++ libwnck/pager.c	24 Sep 2002 02:04:45 -0000
@@ -1171,7 +1171,7 @@ application_opened_callback       (WnckS
                                    WnckApplication *app,
                                    gpointer         data)
 {
-  WnckPager *pager = WNCK_PAGER (data);
+  /*   WnckPager *pager = WNCK_PAGER (data); */
 }
 
 static void
@@ -1179,7 +1179,7 @@ application_closed_callback       (WnckS
                                    WnckApplication *app,
                                    gpointer         data)
 {
-  WnckPager *pager = WNCK_PAGER (data);
+  /*   WnckPager *pager = WNCK_PAGER (data); */
 }
 
 static void
Index: libwnck/screen.c
===================================================================
RCS file: /cvs/gnome/libwnck/libwnck/screen.c,v
retrieving revision 1.19
diff -u -p -u -r1.19 screen.c
--- libwnck/screen.c	16 Sep 2002 05:58:38 -0000	1.19
+++ libwnck/screen.c	24 Sep 2002 02:04:45 -0000
@@ -52,6 +52,8 @@ struct _WnckScreenPrivate
   Pixmap bg_pixmap;
   
   guint update_handler;  
+
+  guint showing_desktop : 1;
   
   /* if you add flags, be sure to set them
    * when we create the screen so we get an initial update
@@ -62,6 +64,7 @@ struct _WnckScreenPrivate
   guint need_update_active_window : 1;
   guint need_update_workspace_names : 1;
   guint need_update_bg_pixmap : 1;
+  guint need_update_showing_desktop : 1;
 };
 
 enum {
@@ -75,6 +78,7 @@ enum {
   APPLICATION_OPENED,
   APPLICATION_CLOSED,
   BACKGROUND_CHANGED,
+  SHOWING_DESKTOP_CHANGED,
   LAST_SIGNAL
 };
 
@@ -87,6 +91,7 @@ static void update_workspace_list   (Wnc
 static void update_active_workspace (WnckScreen      *screen);
 static void update_active_window    (WnckScreen      *screen);
 static void update_workspace_names  (WnckScreen      *screen);
+static void update_showing_desktop  (WnckScreen      *screen);
 
 static void queue_update            (WnckScreen      *screen);
 static void unqueue_update          (WnckScreen      *screen);              
@@ -108,6 +113,7 @@ static void emit_application_opened     
 static void emit_application_closed       (WnckScreen      *screen,
                                            WnckApplication *app);
 static void emit_background_changed       (WnckScreen      *screen);
+static void emit_showing_desktop_changed  (WnckScreen      *screen);
 
 static gpointer parent_class;
 static guint signals[LAST_SIGNAL] = { 0 };
@@ -249,6 +255,19 @@ wnck_screen_class_init (WnckScreenClass 
                   NULL, NULL,
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
+  signals[SHOWING_DESKTOP_CHANGED] =
+    g_signal_new ("showing_desktop_changed",
+                  G_OBJECT_CLASS_TYPE (object_class),
+                  G_SIGNAL_RUN_LAST,
+#if 0
+                  /* FIXME when we can break ABI add this */
+                  G_STRUCT_OFFSET (WnckScreenClass, showing_desktop_changed),
+#else
+                  0,
+#endif
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
 }
 
 static void
@@ -298,6 +317,7 @@ wnck_screen_construct (WnckScreen *scree
   screen->priv->need_update_active_window = TRUE;
   screen->priv->need_update_workspace_names = TRUE;
   screen->priv->need_update_bg_pixmap = TRUE;
+  screen->priv->need_update_showing_desktop = TRUE;
   
   queue_update (screen);
 }
@@ -568,6 +588,12 @@ _wnck_screen_process_property_notify (Wn
       screen->priv->need_update_bg_pixmap = TRUE;
       queue_update (screen);
     }
+  else if (xevent->xproperty.atom ==
+           _wnck_atom_get ("_NET_SHOWING_DESKTOP"))
+    {
+      screen->priv->need_update_showing_desktop = TRUE;
+      queue_update (screen);
+    }
 }
 
 static gboolean
@@ -1149,6 +1175,26 @@ update_bg_pixmap (WnckScreen *screen)
 }
 
 static void
+update_showing_desktop (WnckScreen *screen)
+{
+  int showing_desktop;
+  
+  if (!screen->priv->need_update_showing_desktop)
+    return;
+  
+  screen->priv->need_update_showing_desktop = FALSE;
+
+  showing_desktop = FALSE;
+  _wnck_get_cardinal (screen->priv->xroot,
+                      _wnck_atom_get ("_NET_SHOWING_DESKTOP"),
+                      &showing_desktop);
+
+  screen->priv->showing_desktop = showing_desktop != 0;
+  
+  emit_showing_desktop_changed (screen);
+}
+
+static void
 do_update_now (WnckScreen *screen)
 {
   if (screen->priv->update_handler)
@@ -1165,7 +1211,8 @@ do_update_now (WnckScreen *screen)
   update_active_workspace (screen);
   update_active_window (screen);
   update_workspace_names (screen);
-
+  update_showing_desktop (screen);
+  
   update_bg_pixmap (screen);
 }
 
@@ -1288,6 +1335,14 @@ emit_background_changed (WnckScreen *scr
                  0);
 }
 
+static void
+emit_showing_desktop_changed (WnckScreen *screen)
+{
+  g_signal_emit (G_OBJECT (screen),
+                 signals[SHOWING_DESKTOP_CHANGED],
+                 0);
+}
+
 gboolean
 wnck_screen_net_wm_supports (WnckScreen *screen,
                              const char *atom)
@@ -1353,4 +1408,22 @@ wnck_screen_release_workspace_layout (Wn
   _wnck_release_desktop_layout_manager (screen->priv->xscreen,
                                         current_token);
 
+}
+
+gboolean
+wnck_screen_get_showing_desktop (WnckScreen *screen)
+{
+  g_return_val_if_fail (WNCK_IS_SCREEN (screen), FALSE);
+  
+  return screen->priv->showing_desktop;
+}
+
+void
+wnck_screen_toggle_showing_desktop (WnckScreen *screen,
+                                    gboolean    show)
+{
+  g_return_if_fail (WNCK_IS_SCREEN (screen));
+
+  _wnck_toggle_showing_desktop (screen->priv->xscreen,
+                                show);
 }
Index: libwnck/screen.h
===================================================================
RCS file: /cvs/gnome/libwnck/libwnck/screen.h,v
retrieving revision 1.10
diff -u -p -u -r1.10 screen.h
--- libwnck/screen.h	16 May 2002 04:11:47 -0000	1.10
+++ libwnck/screen.h	24 Sep 2002 02:04:45 -0000
@@ -82,6 +82,22 @@ struct _WnckScreenClass
 
   /* New background */
   void (* background_changed)       (WnckScreen      *screen);
+
+#if 0
+  /* FIXME uncomment all this next time we feel like breaking ABI */
+
+  /* Toggle showing desktop */
+  void (* showing_desktop_changed)  (WnckScreen      *screen);
+  
+  void (* pad1) (void);
+  void (* pad2) (void);
+  void (* pad3) (void);
+  void (* pad4) (void);
+  void (* pad5) (void);
+  void (* pad6) (void);
+  void (* pad7) (void);
+  void (* pad8) (void);
+#endif
 };
 
 GType wnck_screen_get_type (void) G_GNUC_CONST;
@@ -109,6 +125,10 @@ gulong wnck_screen_get_background_pixmap
 
 int wnck_screen_get_width (WnckScreen *screen);
 int wnck_screen_get_height (WnckScreen *screen);
+
+gboolean wnck_screen_get_showing_desktop    (WnckScreen *screen);
+void     wnck_screen_toggle_showing_desktop (WnckScreen *screen,
+                                             gboolean    show);
 
 int  wnck_screen_try_set_workspace_layout (WnckScreen *screen,
                                            int         current_token,
Index: libwnck/test-wnck.c
===================================================================
RCS file: /cvs/gnome/libwnck/libwnck/test-wnck.c,v
retrieving revision 1.11
diff -u -p -u -r1.11 test-wnck.c
--- libwnck/test-wnck.c	24 Oct 2001 23:14:18 -0000	1.11
+++ libwnck/test-wnck.c	24 Sep 2002 02:04:45 -0000
@@ -28,6 +28,8 @@ static void application_opened_callback 
                                                WnckApplication *app);
 static void application_closed_callback       (WnckScreen      *screen,
                                                WnckApplication *app);
+static void showing_desktop_changed_callback  (WnckScreen      *screen,
+                                               gpointer         data);
 static void window_name_changed_callback      (WnckWindow      *window,
                                                gpointer         data);
 static void window_state_changed_callback     (WnckWindow      *window,
@@ -87,7 +89,10 @@ main (int argc, char **argv)
   g_signal_connect (G_OBJECT (screen), "application_closed",
                     G_CALLBACK (application_closed_callback),
                     NULL);
-
+  g_signal_connect (G_OBJECT (screen), "showing_desktop_changed",
+                    G_CALLBACK (showing_desktop_changed_callback),
+                    NULL);
+  
   global_tree_model = create_tree_model ();
   global_tree_view = create_tree_view ();
   
@@ -219,6 +224,14 @@ application_closed_callback (WnckScreen 
 {
   g_print ("Application closed\n");
   queue_refill_model ();
+}
+
+static void
+showing_desktop_changed_callback (WnckScreen *screen,
+                                  gpointer    data)
+{
+  g_print ("Showing desktop now = %d\n",
+           wnck_screen_get_showing_desktop (screen));
 }
 
 static void
Index: libwnck/workspace-accessible.c
===================================================================
RCS file: /cvs/gnome/libwnck/libwnck/workspace-accessible.c,v
retrieving revision 1.2
diff -u -p -u -r1.2 workspace-accessible.c
--- libwnck/workspace-accessible.c	21 Aug 2002 06:57:32 -0000	1.2
+++ libwnck/workspace-accessible.c	24 Sep 2002 02:04:45 -0000
@@ -23,7 +23,7 @@
 #include <errno.h>
 #include <unistd.h>
 #include "workspace-accessible.h"
-
+#include "private.h"
 static void        wnck_workspace_accessible_class_init          (WnckWorkspaceAccessibleClass *klass);
 static const char* wnck_workspace_accessible_get_name            (AtkObject                    *obj);
 static const char* wnck_workspace_accessible_get_description     (AtkObject                    *obj);
@@ -150,6 +150,8 @@ wnck_workspace_accessible_get_size (AtkC
   AtkCoordType coords; 
   int x, y;
 
+  /* FIXME this is blatantly broken (coords uninitialized) */
+  
   wnck_workspace_accessible_get_extents (component, &x, &y, width, height, coords);
 }
 
Index: libwnck/xutils.c
===================================================================
RCS file: /cvs/gnome/libwnck/libwnck/xutils.c,v
retrieving revision 1.30
diff -u -p -u -r1.30 xutils.c
--- libwnck/xutils.c	7 Aug 2002 05:01:02 -0000	1.30
+++ libwnck/xutils.c	24 Sep 2002 02:04:45 -0000
@@ -959,6 +959,30 @@ _wnck_activate_workspace (Screen *screen
 	      &xev);
 }
 
+void
+_wnck_toggle_showing_desktop (Screen  *screen,
+                              gboolean show)
+{
+  XEvent xev;
+  
+  xev.xclient.type = ClientMessage;
+  xev.xclient.serial = 0;
+  xev.xclient.send_event = True;
+  xev.xclient.display = DisplayOfScreen (screen);
+  xev.xclient.window = RootWindowOfScreen (screen);
+  xev.xclient.message_type = _wnck_atom_get ("_NET_SHOWING_DESKTOP");
+  xev.xclient.format = 32;
+  xev.xclient.data.l[0] = show != FALSE;
+  xev.xclient.data.l[1] = 0;
+  xev.xclient.data.l[2] = 0;
+
+  XSendEvent (DisplayOfScreen (screen),
+	      RootWindowOfScreen (screen),
+              False,
+	      SubstructureRedirectMask | SubstructureNotifyMask,
+	      &xev);
+}
+
 Window
 _wnck_get_group_leader (Window xwindow)
 {
Index: libwnck/xutils.h
===================================================================
RCS file: /cvs/gnome/libwnck/libwnck/xutils.h,v
retrieving revision 1.18
diff -u -p -u -r1.18 xutils.h
--- libwnck/xutils.h	7 Aug 2002 05:01:02 -0000	1.18
+++ libwnck/xutils.h	24 Sep 2002 02:04:45 -0000
@@ -110,6 +110,9 @@ void   _wnck_keyboard_move    (Screen *s
 void   _wnck_keyboard_size    (Screen *screen,
                                Window  xwindow);
 
+void _wnck_toggle_showing_desktop (Screen  *screen,
+                                   gboolean show);
+
 typedef struct _WnckIconCache WnckIconCache;
 
 WnckIconCache *_wnck_icon_cache_new                  (void);
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gnome-panel/ChangeLog,v
retrieving revision 1.475
diff -u -p -u -r1.475 ChangeLog
--- ChangeLog	20 Sep 2002 06:17:48 -0000	1.475
+++ ChangeLog	24 Sep 2002 02:04:57 -0000
@@ -1,3 +1,7 @@
+2002-09-23  Havoc Pennington  <hp pobox com>
+
+	* configure.in: require a newer libwnck
+
 2002-09-20  James Willcox  <jwillcox gnome org>
 
 	* configure.in: Look for gtk-2.1, and define HAVE_GTK_MULTIHEAD for
Index: configure.in
===================================================================
RCS file: /cvs/gnome/gnome-panel/configure.in,v
retrieving revision 1.423
diff -u -p -u -r1.423 configure.in
--- configure.in	20 Sep 2002 06:17:48 -0000	1.423
+++ configure.in	24 Sep 2002 02:04:57 -0000
@@ -39,7 +39,7 @@ LIBGNOME_REQUIRED=2.0.0
 LIBGNOMEUI_REQUIRED=2.0.0
 ORBIT_REQUIRED=2.4.0
 GNOME_VFS_MODULE_REQUIRED=1.9.16
-LIBWNCK_REQUIRED=2.1.0
+LIBWNCK_REQUIRED=2.1.1
 
 AC_SUBST(GTK_REQUIRED)
 AC_SUBST(GDK_PIXBUF_REQUIRED)
Index: applets/gen_util/ChangeLog
===================================================================
RCS file: /cvs/gnome/gnome-panel/applets/gen_util/ChangeLog,v
retrieving revision 1.422
diff -u -p -u -r1.422 ChangeLog
--- applets/gen_util/ChangeLog	16 Sep 2002 07:14:45 -0000	1.422
+++ applets/gen_util/ChangeLog	24 Sep 2002 02:04:57 -0000
@@ -1,3 +1,11 @@
+2002-09-23  Havoc Pennington  <hp redhat com>
+
+	* clock.c (destroy_clock): free the timeformat string
+
+	* showdesktop.c: show desktop applet
+
+	* GNOME_GenUtilApplet_Factory.server.in.in: add ShowDesktopApplet
+
 2002-09-16  Mark McLoughlin  <mark skynet ie>
 
 	* Makefile.am, multihead-hacks.h: kill
Index: applets/gen_util/GNOME_GenUtilApplet_Factory.server.in.in
===================================================================
RCS file: /cvs/gnome/gnome-panel/applets/gen_util/GNOME_GenUtilApplet_Factory.server.in.in,v
retrieving revision 1.17
diff -u -p -u -r1.17 GNOME_GenUtilApplet_Factory.server.in.in
--- applets/gen_util/GNOME_GenUtilApplet_Factory.server.in.in	5 Mar 2002 10:55:12 -0000	1.17
+++ applets/gen_util/GNOME_GenUtilApplet_Factory.server.in.in	24 Sep 2002 02:04:57 -0000
@@ -75,4 +75,21 @@
 	<oaf_attribute name="panel:category" type="string" _value="Internet"/>
 
 </oaf_server>
+
+<oaf_server iid="OAFIID:GNOME_ShowDesktopApplet"
+	    type="factory" 
+	    location="OAFIID:GNOME_GenUtilApplet_Factory">
+
+	<oaf_attribute name="repo_ids" type="stringv">
+		<item value="IDL:GNOME/Vertigo/PanelAppletShell:1.0"/>
+		<item value="IDL:Bonobo/Control:1.0"/>
+		<item value="IDL:Bonobo/Unknown:1.0"/>
+	</oaf_attribute>
+	<oaf_attribute name="name" type="string" _value="Show Desktop Button"/>
+	<oaf_attribute name="description" type="string" _value="Button to hide application windows and show the desktop"/>
+	<oaf_attribute name="panel:icon" type="string" value="gnome-show-desktop.png"/>
+	<oaf_attribute name="panel:category" type="string" _value="Utility"/>
+
+</oaf_server>
+
 </oaf_info>
Index: applets/gen_util/GNOME_ShowDesktopApplet.xml
===================================================================
RCS file: applets/gen_util/GNOME_ShowDesktopApplet.xml
diff -N applets/gen_util/GNOME_ShowDesktopApplet.xml
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ applets/gen_util/GNOME_ShowDesktopApplet.xml	24 Sep 2002 02:04:57 -0000
@@ -0,0 +1,10 @@
+<Root>
+  <popups>
+    <popup name="button3">
+      <menuitem name="Show Desktop Help Item" verb="ShowDesktopHelp" _label="_Help"
+    		    pixtype="stock" pixname="gtk-help"/>
+      <menuitem name="Show Desktop About Item" verb="ShowDesktopAbout" _label="_About..."
+    		    pixtype="stock" pixname="gnome-stock-about"/>
+    </popup>
+  </popups>
+</Root>
Index: applets/gen_util/Makefile.am
===================================================================
RCS file: /cvs/gnome/gnome-panel/applets/gen_util/Makefile.am,v
retrieving revision 1.57
diff -u -p -u -r1.57 Makefile.am
--- applets/gen_util/Makefile.am	16 Sep 2002 07:14:45 -0000	1.57
+++ applets/gen_util/Makefile.am	24 Sep 2002 02:04:57 -0000
@@ -26,6 +26,10 @@ DISABLE_DEPRECATED_CFLAGS =			\
 gladedir   = $(datadir)/gen_util
 glade_DATA = pager.glade tasklist.glade
 
+pixmapdir = $(datadir)/pixmaps
+pixmap_DATA = \
+	gnome-show-desktop.png
+
 EGGFILES =                      \
 	egg-screen-exec.h       \
 	egg-screen-exec.c       \
@@ -40,6 +44,8 @@ libgen_util_applet_2_la_SOURCES = \
 	clock.h	\
 	pager.c	\
 	pager.h	\
+	showdesktop.c \
+	showdesktop.h \
 	tasklist.c \
 	tasklist.h \
 	mailcheck.c \
@@ -79,7 +85,8 @@ ui_DATA		= \
 	GNOME_ClockApplet.xml		\
 	GNOME_MailCheckApplet.xml	\
 	GNOME_PagerApplet.xml		\
-	GNOME_TasklistApplet.xml	
+	GNOME_ShowDesktopApplet.xml	\
+	GNOME_TasklistApplet.xml
 
 serverdir       = $(libdir)/bonobo/servers
 server_in_files = GNOME_GenUtilApplet_Factory.server.in
@@ -110,6 +117,7 @@ EXTRA_DIST = GNOME_GenUtilApplet_Factory
 	$(soundlist_in_files)				\
 	$(schemas_in_files)				\
 	$(glade_DATA)					\
+	$(pixmap_DATA)					\
 	$(ui_DATA)
 
 EGGDIR = $(srcdir)/../../../libegg/libegg/screen-exec
Index: applets/gen_util/clock.c
===================================================================
RCS file: /cvs/gnome/gnome-panel/applets/gen_util/clock.c,v
retrieving revision 1.84
diff -u -p -u -r1.84 clock.c
--- applets/gen_util/clock.c	16 Sep 2002 07:14:45 -0000	1.84
+++ applets/gen_util/clock.c	24 Sep 2002 02:04:57 -0000
@@ -367,6 +367,8 @@ destroy_clock(GtkWidget * widget, ClockD
 		cd->props = NULL;
 	}
 
+        g_free (cd->timeformat);
+        
 	g_free (cd);
 }
 
Index: applets/gen_util/gnome-show-desktop.png
===================================================================
RCS file: applets/gen_util/gnome-show-desktop.png
diff -N applets/gen_util/gnome-show-desktop.png
Binary files /dev/null and gnome-show-desktop.png differ
Index: applets/gen_util/main.c
===================================================================
RCS file: /cvs/gnome/gnome-panel/applets/gen_util/main.c,v
retrieving revision 1.19
diff -u -p -u -r1.19 main.c
--- applets/gen_util/main.c	4 Mar 2002 17:53:40 -0000	1.19
+++ applets/gen_util/main.c	24 Sep 2002 02:04:57 -0000
@@ -28,6 +28,7 @@
 #include "mailcheck.h"
 #include "clock.h"
 #include "pager.h"
+#include "showdesktop.h"
 #include "tasklist.h"
 
 static gboolean
@@ -49,6 +50,9 @@ genutil_factory (PanelApplet *applet,
 	if (!strcmp (iid, "OAFIID:GNOME_MailcheckApplet"))
 		retval = fill_mailcheck_applet(applet);
 
+	if (!strcmp (iid, "OAFIID:GNOME_ShowDesktopApplet"))
+		retval = fill_show_desktop_applet(applet);
+        
 	return retval;
 }
 
Index: applets/gen_util/showdesktop.c
===================================================================
RCS file: applets/gen_util/showdesktop.c
diff -N applets/gen_util/showdesktop.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ applets/gen_util/showdesktop.c	24 Sep 2002 02:04:57 -0000
@@ -0,0 +1,493 @@
+/* "Show desktop" panel applet */
+
+/*
+ * Copyright (C) 2002 Red Hat, Inc.
+ * Developed by Havoc Pennington
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "showdesktop.h"
+#include <gtk/gtktogglebutton.h>
+#include <gtk/gtktooltips.h>
+#include <gtk/gtkimage.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtkmessagedialog.h>
+#include <libgnome/libgnome.h>
+#include <libgnomeui/gnome-about.h>
+#define WNCK_I_KNOW_THIS_IS_UNSTABLE
+#include <libwnck/screen.h>
+#include "egg-screen-help.h"
+
+#include <string.h>
+
+typedef struct {
+	/* widgets */
+	GtkWidget *applet;
+	GtkWidget *button;
+        GtkWidget *image;
+        GdkPixbuf *icon;        
+        
+	PanelAppletOrient orient;
+	int size;
+
+        WnckScreen *wnck_screen;
+        
+        guint showing_desktop : 1;
+} ShowDesktopData;
+
+static void display_help_dialog  (BonoboUIComponent *uic,
+                                  ShowDesktopData   *sdd,
+                                  const gchar       *verbname);
+static void display_about_dialog (BonoboUIComponent *uic,
+                                  ShowDesktopData   *sdd,
+                                  const gchar       *verbname);
+
+static void update_icon           (ShowDesktopData *sdd);
+static void update_button_state   (ShowDesktopData *sdd);
+static void update_button_display (ShowDesktopData *sdd);
+
+static void button_toggled_callback       (GtkWidget       *button,
+                                           ShowDesktopData *sdd);
+static void show_desktop_changed_callback (WnckScreen      *screen,
+                                           ShowDesktopData *sdd);
+
+static void
+set_tooltip (GtkWidget  *widget,
+	     const char *tip)
+{
+	GtkTooltips *tooltips;
+
+	tooltips = g_object_get_data (G_OBJECT (widget), "tooltips");
+	if (!tooltips) {
+		tooltips = gtk_tooltips_new ();
+		g_object_ref (tooltips);
+		gtk_object_sink (GTK_OBJECT (tooltips));
+		g_object_set_data_full (G_OBJECT (widget), "tooltips", tooltips,
+                                        (GDestroyNotify) g_object_unref);
+	}
+
+	gtk_tooltips_set_tip (tooltips, widget, tip, NULL);
+}
+
+/* this is when the panel orientation changes */
+
+static void
+applet_change_orient (PanelApplet       *applet,
+		      PanelAppletOrient  orient,
+		      ShowDesktopData         *sdd)
+{
+  GtkOrientation new_orient;
+  
+  switch (orient)
+    {
+    case PANEL_APPLET_ORIENT_LEFT:
+    case PANEL_APPLET_ORIENT_RIGHT:
+      new_orient = GTK_ORIENTATION_VERTICAL;
+      break;
+    case PANEL_APPLET_ORIENT_UP:
+    case PANEL_APPLET_ORIENT_DOWN:
+    default:
+      new_orient = GTK_ORIENTATION_HORIZONTAL;
+      break;
+    }
+  
+  if (new_orient == sdd->orient)
+    return;
+  
+  sdd->orient = new_orient;
+
+  update_icon (sdd);
+}
+
+static void
+applet_change_background (PanelApplet               *applet,
+			  PanelAppletBackgroundType  type,
+			  GdkColor                  *color,
+			  const gchar               *pixmap,
+			  ShowDesktopData                 *sdd)
+{
+	if (type == PANEL_NO_BACKGROUND) {
+		GtkRcStyle *rc_style;
+
+		rc_style = gtk_rc_style_new ();
+
+		gtk_widget_modify_style (sdd->applet, rc_style);
+
+		g_object_unref (rc_style);
+
+	} else if (type == PANEL_COLOR_BACKGROUND)
+		gtk_widget_modify_bg (sdd->applet, GTK_STATE_NORMAL, color);
+
+	/* else if (type == PANEL_PIXMAP_BACKGROUND)
+	 * FIXME: Handle this when the panel support works again
+	 */
+}
+
+
+/* this is when the panel size changes */
+static void
+applet_change_pixel_size (PanelApplet *applet,
+			  gint         size,
+			  ShowDesktopData   *sdd)
+{
+        if (sdd->size == size)
+                return;
+        
+	sdd->size = size;
+
+        update_icon (sdd);
+}
+
+static void
+update_icon (ShowDesktopData *sdd)
+{
+        int width, height;
+        GdkPixbuf *scaled;
+        double aspect;
+        int icon_size;
+        
+        if (sdd->icon == NULL)
+                return;
+        
+        width = gdk_pixbuf_get_width (sdd->icon);
+        height = gdk_pixbuf_get_height (sdd->icon);
+
+        aspect = (double) width / (double) height;
+
+#define SPACE_FOR_BUTTON_BORDER 3
+        icon_size = sdd->size - SPACE_FOR_BUTTON_BORDER;
+        
+        scaled = NULL;
+        
+        /* Make it fit on the given panel */
+        switch (sdd->orient) {
+        case GTK_ORIENTATION_HORIZONTAL:
+                width = icon_size * aspect;
+                height = icon_size;
+                break;
+        case GTK_ORIENTATION_VERTICAL:
+                height = icon_size / aspect;
+                width = icon_size;
+                break;
+        }
+
+        scaled = gdk_pixbuf_scale_simple (sdd->icon,
+                                          width, height,
+                                          GDK_INTERP_BILINEAR);
+
+        if (scaled == NULL)
+                return;
+
+        gtk_image_set_from_pixbuf (GTK_IMAGE (sdd->image),
+                                   scaled);
+
+        g_object_unref (G_OBJECT (scaled));
+}
+
+static const BonoboUIVerb show_desktop_menu_verbs [] = {
+	BONOBO_UI_UNSAFE_VERB ("ShowDesktopHelp",        display_help_dialog),
+	BONOBO_UI_UNSAFE_VERB ("ShowDesktopAbout",       display_about_dialog),
+	BONOBO_UI_VERB_END
+};
+
+/* This updates things that should be consistent with the button's appearance,
+ * and update_button_state updates the button appearance itself
+ */
+static void
+update_button_display (ShowDesktopData *sdd)
+{
+        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (sdd->button))) {
+                set_tooltip (sdd->button,
+                             _("Click here to restore hidden windows."));
+        } else {
+                set_tooltip (sdd->button,
+                             _("Click here to hide all windows and show the desktop."));
+        }
+}
+
+static void
+update_button_state (ShowDesktopData *sdd)
+{        
+        if (sdd->showing_desktop) {
+                g_signal_handlers_block_by_func (G_OBJECT (sdd->button),
+                                                 G_CALLBACK (button_toggled_callback),
+                                                 sdd);
+                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sdd->button),
+                                              TRUE);
+                g_signal_handlers_unblock_by_func (G_OBJECT (sdd->button),
+                                                   G_CALLBACK (button_toggled_callback),
+                                                   sdd);
+        } else {
+                g_signal_handlers_block_by_func (G_OBJECT (sdd->button),
+                                                 G_CALLBACK (button_toggled_callback),
+                                                 sdd);
+                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sdd->button),
+                                              FALSE);
+                g_signal_handlers_unblock_by_func (G_OBJECT (sdd->button),
+                                                   G_CALLBACK (button_toggled_callback),
+                                                   sdd);
+        }
+
+        update_button_display (sdd);
+}
+
+static void
+applet_destroyed (GtkWidget       *applet,
+                  ShowDesktopData *sdd)
+{
+        g_object_unref (G_OBJECT (sdd->icon));
+        
+        g_free (sdd);
+}
+
+static gboolean
+do_not_eat_button_press (GtkWidget      *widget,
+                         GdkEventButton *event)
+{
+        if (event->button != 1) {
+                g_signal_stop_emission_by_name (widget, "button_press_event");
+        }
+
+        return FALSE;
+}
+
+gboolean
+fill_show_desktop_applet (PanelApplet *applet)
+{
+        ShowDesktopData *sdd;
+        char *file;
+        GError *error;
+        
+        sdd = g_new0 (ShowDesktopData, 1);                                
+
+        sdd->applet = GTK_WIDGET (applet);
+        
+	file = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_PIXMAP,
+	                                  "gnome-show-desktop.png", TRUE, NULL);
+        error = NULL;        
+	if (file) {
+		sdd->icon = gdk_pixbuf_new_from_file (file, &error);
+		g_free (file);
+	}
+
+        if (sdd->icon == NULL) {
+                g_printerr (_("Failed to load %s: %s\n"),
+                            file, error ? error->message : _("File not found"));
+                if (error)
+                        g_error_free (error);
+        }
+        
+        if (sdd->icon) {
+                sdd->image = gtk_image_new_from_pixbuf (sdd->icon);
+        } else {
+                sdd->image = gtk_image_new_from_stock (GTK_STOCK_MISSING_IMAGE,
+                                                       GTK_ICON_SIZE_SMALL_TOOLBAR);
+        }
+
+        switch (panel_applet_get_orient (applet)) {
+        case PANEL_APPLET_ORIENT_LEFT:
+        case PANEL_APPLET_ORIENT_RIGHT:
+                sdd->orient = GTK_ORIENTATION_VERTICAL;
+                break;
+        case PANEL_APPLET_ORIENT_UP:
+        case PANEL_APPLET_ORIENT_DOWN:
+        default:
+                sdd->orient = GTK_ORIENTATION_HORIZONTAL;
+                break;
+        }
+
+        sdd->size = panel_applet_get_size (PANEL_APPLET (sdd->applet));
+        
+        update_icon (sdd);
+        
+        sdd->button = gtk_toggle_button_new ();
+
+        g_signal_connect (G_OBJECT (sdd->button), "button_press_event",
+                          G_CALLBACK (do_not_eat_button_press), NULL);
+
+        g_signal_connect (G_OBJECT (sdd->button), "toggled",
+                          G_CALLBACK (button_toggled_callback), sdd);
+        
+        gtk_container_set_border_width (GTK_CONTAINER (sdd->button), 1);
+        gtk_container_add (GTK_CONTAINER (sdd->button), sdd->image);
+	gtk_container_add (GTK_CONTAINER (sdd->applet), sdd->button);
+
+        update_button_state (sdd);
+
+        sdd->wnck_screen =
+                wnck_screen_get (gdk_screen_get_number (gtk_widget_get_screen (sdd->applet)));
+
+        if (sdd->wnck_screen != NULL)
+                g_signal_connect (G_OBJECT (sdd->wnck_screen),
+                                  "showing_desktop_changed",
+                                  G_CALLBACK (show_desktop_changed_callback),
+                                  sdd);
+        else
+                g_warning ("Could not get WnckScreen!");
+        
+	/* FIXME: Update this comment. */
+	/* we have to bind change_orient before we do applet_widget_add
+	   since we need to get an initial change_orient signal to set our
+	   initial oriantation, and we get that during the _add call */
+	g_signal_connect (G_OBJECT (sdd->applet),
+			  "change_orient",
+			  G_CALLBACK (applet_change_orient),
+			  sdd);
+
+	/* similiar to the above in semantics*/
+	g_signal_connect (G_OBJECT (sdd->applet),
+			  "change_size",
+			  G_CALLBACK (applet_change_pixel_size),
+			  sdd);
+
+	/* FIXME: initial background, this needs some panel-applet voodoo */
+	g_signal_connect (G_OBJECT (sdd->applet),
+			  "change_background",
+			  G_CALLBACK (applet_change_background),
+			  sdd);
+        
+	panel_applet_setup_menu_from_file (PANEL_APPLET (sdd->applet),
+					   NULL,
+					   "GNOME_ShowDesktopApplet.xml",
+					   NULL,
+					   show_desktop_menu_verbs,
+					   sdd);
+
+        g_signal_connect (G_OBJECT (sdd->applet),
+                          "destroy",
+                          G_CALLBACK (applet_destroyed),
+                          sdd);
+        
+        gtk_widget_show_all (sdd->applet);
+        
+	return TRUE;
+}
+
+static void
+display_help_dialog (BonoboUIComponent *uic,
+		     ShowDesktopData         *sdd,
+		     const gchar       *verbname)
+{
+	GError *error = NULL;
+	static GnomeProgram *applet_program = NULL;
+
+	if (!applet_program) {
+                /* FIXME there is no way this crack is right; it's some junk
+                 * copied from clock.c
+                 */
+		int argc = 1;
+		char *argv[2] = { "show-desktop" };
+		applet_program = gnome_program_init ("show-desktop", VERSION,
+                                                     LIBGNOME_MODULE, argc, argv,
+                                                     GNOME_PROGRAM_STANDARD_PROPERTIES, NULL);
+	}
+
+	egg_screen_help_display_desktop (
+                gtk_widget_get_screen (sdd->applet),
+                applet_program, "show-desktop", "show-desktop",
+                NULL, &error);
+        
+	if (error) {
+		GtkWidget *dialog;
+		dialog = gtk_message_dialog_new (NULL,
+						 GTK_DIALOG_MODAL,
+						 GTK_MESSAGE_ERROR,
+						 GTK_BUTTONS_CLOSE,
+                                                 _("There was an error displaying help: %s"),
+						 error->message);
+
+		g_signal_connect (G_OBJECT (dialog), "response",
+				  G_CALLBACK (gtk_widget_destroy),
+				  NULL);
+
+		gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+		gtk_window_set_screen (GTK_WINDOW (dialog),
+				       gtk_widget_get_screen (sdd->applet));
+		gtk_widget_show (dialog);
+		g_error_free (error);
+	}
+}
+
+static void
+display_about_dialog (BonoboUIComponent *uic,
+		      ShowDesktopData   *sdd,
+		      const gchar       *verbname)
+{
+	static GtkWidget *about = NULL;
+
+	static const gchar *authors[] =
+                {
+                        "Havoc Pennington <hp redhat com>",
+                        NULL
+                };
+	static const char *documenters[] =
+                {
+                        NULL
+                };
+
+	/* Translator credits */
+	const char *translator_credits = _("translator_credits");
+
+	if (about) {
+		gtk_window_set_screen (GTK_WINDOW (about),
+				       gtk_widget_get_screen (sdd->applet));
+		gtk_window_present (GTK_WINDOW (about));
+		return;
+	}
+
+	about = gnome_about_new (_("Show Desktop Button"), VERSION,
+				 _("(C) 2002 Red Hat, Inc."),
+				 _("This button lets you hide all windows and show the desktop"),
+				 authors,
+				 documenters,
+				 strcmp (translator_credits, "translator_credits") != 0 ? translator_credits : NULL,
+				 sdd->icon);
+
+	gtk_window_set_wmclass (GTK_WINDOW (about), "show-desktop", "show-desktop");
+	gtk_window_set_screen (GTK_WINDOW (about),
+			       gtk_widget_get_screen (sdd->applet));
+
+	if (sdd->icon)
+		gtk_window_set_icon (GTK_WINDOW (about), sdd->icon);
+
+	g_signal_connect (G_OBJECT(about), "destroy",
+			  (GCallback)gtk_widget_destroyed, &about);
+
+	gtk_widget_show (about);
+}
+
+static void
+button_toggled_callback (GtkWidget       *button,
+                         ShowDesktopData *sdd)
+{
+        if (sdd->wnck_screen != NULL)
+                wnck_screen_toggle_showing_desktop (sdd->wnck_screen,
+                                                    gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)));
+
+        update_button_display (sdd);
+}
+
+static void
+show_desktop_changed_callback (WnckScreen      *screen,
+                               ShowDesktopData *sdd)
+{
+        if (sdd->wnck_screen != NULL)
+                sdd->showing_desktop =
+                        wnck_screen_get_showing_desktop (sdd->wnck_screen);
+        update_button_state (sdd);
+}
Index: applets/gen_util/showdesktop.h
===================================================================
RCS file: applets/gen_util/showdesktop.h
diff -N applets/gen_util/showdesktop.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ applets/gen_util/showdesktop.h	24 Sep 2002 02:04:57 -0000
@@ -0,0 +1,37 @@
+/* "Show desktop" panel applet */
+
+/* 
+ * Copyright (C) 2002 Red Hat, Inc.
+ * Developed by Havoc Pennington
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _SHOWDESKTOP_H_
+#define _SHOWDESKTOP_H_
+
+#include <glib/gmacros.h>
+#include <panel-applet.h>
+
+G_BEGIN_DECLS
+
+gboolean fill_show_desktop_applet (PanelApplet *applet);
+
+G_END_DECLS
+
+#endif
+
+


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