summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHavoc Pennington <hp@pobox.com>2002-10-25 23:35:50 +0000
committerHavoc Pennington <hp@src.gnome.org>2002-10-25 23:35:50 +0000
commitcb27f0c4bea9a6aa402d46512eee1653b04b18a6 (patch)
tree68f8244781a0c6b43f7f34fc896295cbf67f7f28
parentc3a5c4c169811b4c052c5326656306ef0203565a (diff)
downloadmetacity-cb27f0c4bea9a6aa402d46512eee1653b04b18a6.tar.gz
metacity-cb27f0c4bea9a6aa402d46512eee1653b04b18a6.tar.bz2
Add "busy cursor on app startup" support, conditionally - works only if
2002-10-25 Havoc Pennington <hp@pobox.com> Add "busy cursor on app startup" support, conditionally - works only if libstartup-notification is found, and in practice requires a GTK patch that's not in yet. * src/screen.c: monitor startup events and set busy cursor if appropriate * src/display.c (meta_display_open): create SnDisplay * configure.in: check for startup notification, and add the cute "configure summary" at the end
-rw-r--r--ChangeLog14
-rw-r--r--acconfig.h2
-rw-r--r--configure.in58
-rw-r--r--src/Makefile.am2
-rw-r--r--src/common.h3
-rw-r--r--src/display.c48
-rw-r--r--src/display.h8
-rw-r--r--src/screen.c218
-rw-r--r--src/screen.h6
-rw-r--r--src/util.c2
-rw-r--r--src/util.h3
11 files changed, 346 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index 49e34a3..44bc825 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2002-10-25 Havoc Pennington <hp@pobox.com>
+
+ Add "busy cursor on app startup" support, conditionally - works
+ only if libstartup-notification is found, and in practice requires
+ a GTK patch that's not in yet.
+
+ * src/screen.c: monitor startup events and set busy cursor if
+ appropriate
+
+ * src/display.c (meta_display_open): create SnDisplay
+
+ * configure.in: check for startup notification,
+ and add the cute "configure summary" at the end
+
2002-10-24 Havoc Pennington <hp@redhat.com>
* src/theme.c (meta_frame_layout_calc_geometry): if only one
diff --git a/acconfig.h b/acconfig.h
index 3d823e3..7cf408a 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -15,3 +15,5 @@
#undef HAVE_XFREE_XINERAMA
#undef HAVE_SHAPE
#undef HAVE_RANDR
+#undef HAVE_STARTUP_NOTIFICATION
+
diff --git a/configure.in b/configure.in
index ced9248..879e12b 100644
--- a/configure.in
+++ b/configure.in
@@ -91,13 +91,27 @@ ALL_LINGUAS="az ca cs da de el es fr gl hu it ja ko lv ms no pl pt pt_BR ro ru s
AM_GLIB_GNU_GETTEXT
## here we get the flags we'll actually use
-PKG_CHECK_MODULES(METACITY, gtk+-2.0 >= 2.0.0 gconf-2.0 >= 1.1.9)
PKG_CHECK_MODULES(METACITY_MESSAGE, gtk+-2.0 >= 2.0.0)
PKG_CHECK_MODULES(METACITY_WINDOW_DEMO, gtk+-2.0 >= 2.0.0)
PKG_CHECK_MODULES(METACITY_PROPS, gtk+-2.0 >= 2.0.0 gconf-2.0 >= 1.1.9 libglade-2.0)
+STARTUP_NOTIFICATION_VERSION=0.2
+if $PKG_CONFIG --atleast-version $STARTUP_NOTIFICATION_VERSION libstartup-notification-1.0; then
+ echo "Building with libstartup-notification"
+ PKG_CHECK_MODULES(METACITY, gtk+-2.0 >= 2.0.0 gconf-2.0 >= 1.1.9 libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_VERSION)
+ AC_DEFINE(HAVE_STARTUP_NOTIFICATION)
+ with_startup_notification=yes
+else
+ echo "Building without libstartup-notification"
+ PKG_CHECK_MODULES(METACITY, gtk+-2.0 >= 2.0.0 gconf-2.0 >= 1.1.9)
+ with_startup_notification=no
+fi
+
if $PKG_CONFIG --atleast-version 2.1.0 gtk+-2.0; then
AC_DEFINE(HAVE_GTK_MULTIHEAD,,[gtk+ with multihead support found])
+ with_multihead=yes
+else
+ with_multihead=no
fi
AC_PATH_XTRA
@@ -108,6 +122,8 @@ ALL_X_LIBS="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
metacity_save_cppflags="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+use_solaris_xinerama=no
+use_xfree_xinerama=no
case "$host" in
*-*-solaris*)
# Check for solaris
@@ -150,25 +166,25 @@ esac
CPPFLAGS="$metacity_save_cppflags"
SHAPE_LIBS=
-found_shape=false
+found_shape=no
AC_CHECK_LIB(Xext, XShapeQueryExtension,
[AC_CHECK_HEADERS(X11/extensions/shape.h,
- SHAPE_LIBS=-lXext found_shape=true)],
+ SHAPE_LIBS=-lXext found_shape=yes)],
, $ALL_X_LIBS)
-if test "$found_shape" = "true"; then
+if test "$found_shape" = "no"; then
AC_DEFINE(HAVE_SHAPE)
fi
RANDR_LIBS=
-found_randr=false
+found_randr=no
AC_CHECK_LIB(Xrandr, XRRUpdateConfiguration,
[AC_CHECK_HEADERS(X11/extensions/Xrandr.h,
- RANDR_LIBS=-lXrandr, found_randr=true,
+ RANDR_LIBS=-lXrandr, found_randr=yes,
[#include <X11/Xlib.h>])],
, -lXrender $ALL_X_LIBS)
-if test "$found_randr" = "true"; then
+if test "$found_randr" = "yes"; then
AC_DEFINE(HAVE_RANDR)
fi
@@ -177,24 +193,24 @@ METACITY_MESSAGE_LIBS="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $METACITY_MESSAGE
METACITY_WINDOW_DEMO_LIBS="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $METACITY_WINDOW_DEMO_LIBS"
METACITY_PROPS_LIBS="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $METACITY_PROPS_LIBS"
-found_sm=false
+found_sm=no
case "$METACITY_LIBS" in
*-lSM*)
- found_sm=true
+ found_sm=yes
;;
*)
AC_CHECK_LIB(SM, SmcSaveYourselfDone,
[AC_CHECK_HEADERS(X11/SM/SMlib.h,
- METACITY_LIBS="-lSM -lICE $METACITY_LIBS" found_sm=true)],
+ METACITY_LIBS="-lSM -lICE $METACITY_LIBS" found_sm=no)],
, $METACITY_LIBS)
;;
esac
-if test "$found_sm" = "true"; then
+if test "$found_sm" = "yes"; then
AC_DEFINE(HAVE_SM)
fi
-AM_CONDITIONAL(HAVE_SM, test "$found_sm" = "true")
+AM_CONDITIONAL(HAVE_SM, test "$found_sm" = "yes")
HOST_ALIAS=$host_alias
AC_SUBST(HOST_ALIAS)
@@ -230,3 +246,21 @@ src/themes/Makefile
po/Makefile.in
metacity.spec
])
+
+dnl ==========================================================================
+echo "
+metacity-$VERSION:
+
+ prefix: ${prefix}
+ source code location: ${srcdir}
+ compiler: ${CC}
+
+ XFree86 Xinerama: ${use_xfree_xinerama}
+ Solaris Xinerama: ${use_solaris_xinerama}
+ Multihead: ${with_multihead}
+ Startup notification: ${with_startup_notification}
+ Session management: ${found_sm}
+ Shape extension: ${found_shape}
+ Resize-and-rotate: ${found_randr}
+
+"
diff --git a/src/Makefile.am b/src/Makefile.am
index fe789c2..2590a32 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,7 @@
SUBDIRS=wm-tester tools themes
-INCLUDES=@METACITY_CFLAGS@ -DMETACITY_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\" -DMETACITY_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" -DMETACITY_PKGDATADIR=\"$(pkgdatadir)\" -DMETACITY_DATADIR=\"$(datadir)\" -DG_LOG_DOMAIN=\"metacity\"
+INCLUDES=@METACITY_CFLAGS@ -DMETACITY_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\" -DMETACITY_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" -DMETACITY_PKGDATADIR=\"$(pkgdatadir)\" -DMETACITY_DATADIR=\"$(datadir)\" -DG_LOG_DOMAIN=\"metacity\" -DSN_API_NOT_YET_FROZEN=1
EGGFILES= \
eggaccelerators.c \
diff --git a/src/common.h b/src/common.h
index 204ccc3..f88dce5 100644
--- a/src/common.h
+++ b/src/common.h
@@ -129,7 +129,8 @@ typedef enum
META_CURSOR_NE_RESIZE,
META_CURSOR_NW_RESIZE,
META_CURSOR_MOVE_WINDOW,
- META_CURSOR_RESIZE_WINDOW
+ META_CURSOR_RESIZE_WINDOW,
+ META_CURSOR_BUSY
} MetaCursor;
diff --git a/src/display.c b/src/display.c
index 6be1903..8341304 100644
--- a/src/display.c
+++ b/src/display.c
@@ -138,6 +138,27 @@ remove_pending_pings_for_window (MetaDisplay *display, Window xwindow)
g_slist_free (dead);
}
+
+static void
+sn_error_trap_push (SnDisplay *sn_display,
+ Display *xdisplay)
+{
+ MetaDisplay *display;
+ display = meta_display_for_x_display (xdisplay);
+ if (display != NULL)
+ meta_error_trap_push (display);
+}
+
+static void
+sn_error_trap_pop (SnDisplay *sn_display,
+ Display *xdisplay)
+{
+ MetaDisplay *display;
+ display = meta_display_for_x_display (xdisplay);
+ if (display != NULL)
+ meta_error_trap_pop (display, FALSE);
+}
+
gboolean
meta_display_open (const char *name)
{
@@ -372,6 +393,12 @@ meta_display_open (const char *name)
display->groups_by_leader = NULL;
display->screens = NULL;
+
+#ifdef HAVE_STARTUP_NOTIFICATION
+ display->sn_display = sn_display_new (display->xdisplay,
+ sn_error_trap_push,
+ sn_error_trap_pop);
+#endif
#ifdef USE_GDK_DISPLAY
display->events = NULL;
@@ -594,14 +621,14 @@ meta_display_close (MetaDisplay *display)
g_source_remove (display->autoraise_timeout_id);
display->autoraise_timeout_id = 0;
}
-
+
#ifdef USE_GDK_DISPLAY
/* Stop caring about events */
meta_ui_remove_event_func (display->xdisplay,
event_callback,
display);
#endif
-
+
/* Free all screens */
tmp = display->screens;
while (tmp != NULL)
@@ -613,6 +640,14 @@ meta_display_close (MetaDisplay *display)
g_slist_free (display->screens);
display->screens = NULL;
+
+#ifdef HAVE_STARTUP_NOTIFICATION
+ if (display->sn_display)
+ {
+ sn_display_unref (display->sn_display);
+ display->sn_display = NULL;
+ }
+#endif
/* Must be after all calls to meta_window_free() since they
* unregister windows
@@ -967,6 +1002,10 @@ event_callback (XEvent *event,
if (dump_events)
meta_spew_event (display, event);
+
+#ifdef HAVE_STARTUP_NOTIFICATION
+ sn_display_process_event (display->sn_display, event);
+#endif
filter_out_event = FALSE;
display->current_time = event_get_time (display, event);
@@ -2192,7 +2231,10 @@ meta_display_create_x_cursor (MetaDisplay *display,
case META_CURSOR_RESIZE_WINDOW:
glyph = XC_fleur;
break;
-
+ case META_CURSOR_BUSY:
+ glyph = XC_watch;
+ break;
+
default:
g_assert_not_reached ();
glyph = 0; /* silence compiler */
diff --git a/src/display.h b/src/display.h
index 82a2d32..395e978 100644
--- a/src/display.h
+++ b/src/display.h
@@ -27,6 +27,10 @@
#include "eventqueue.h"
#include "common.h"
+#ifdef HAVE_STARTUP_NOTIFICATION
+#include <libsn/sn.h>
+#endif
+
#define meta_XFree(p) do { if ((p)) XFree ((p)); } while (0)
/* this doesn't really belong here, oh well. */
@@ -149,6 +153,10 @@ struct _MetaDisplay
Atom atom_net_wm_action_close;
Atom atom_net_wm_state_above;
Atom atom_net_wm_state_below;
+
+#ifdef HAVE_STARTUP_NOTIFICATION
+ SnDisplay *sn_display;
+#endif
/* This is the actual window from focus events,
* not the one we last set
diff --git a/src/screen.c b/src/screen.c
index e9dade2..4bcae0e 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -54,6 +54,11 @@ static void update_focus_mode (MetaScreen *screen);
static void prefs_changed_callback (MetaPreference pref,
gpointer data);
+#ifdef HAVE_STARTUP_NOTIFICATION
+static void meta_screen_sn_event (SnMonitorEvent *event,
+ void *user_data);
+#endif
+
static int
set_wm_check_hint (MetaScreen *screen)
{
@@ -580,6 +585,17 @@ meta_screen_new (MetaDisplay *display,
screen->stack = meta_stack_new (screen);
meta_prefs_add_listener (prefs_changed_callback, screen);
+
+#ifdef HAVE_STARTUP_NOTIFICATION
+ screen->sn_context =
+ sn_monitor_context_new (screen->display->sn_display,
+ screen->number,
+ meta_screen_sn_event,
+ screen,
+ NULL);
+ screen->startup_sequences = NULL;
+ screen->startup_sequence_timeout = 0;
+#endif
meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
screen->number, screen->screen_name, screen->xroot);
@@ -604,6 +620,24 @@ meta_screen_free (MetaScreen *screen)
meta_screen_ungrab_keys (screen);
+#ifdef HAVE_STARTUP_NOTIFICATION
+ g_slist_foreach (screen->startup_sequences,
+ (GFunc) sn_startup_sequence_unref, NULL);
+ g_slist_free (screen->startup_sequences);
+ screen->startup_sequences = NULL;
+
+ if (screen->startup_sequence_timeout != 0)
+ {
+ g_source_remove (screen->startup_sequence_timeout);
+ screen->startup_sequence_timeout = 0;
+ }
+ if (screen->sn_context)
+ {
+ sn_monitor_context_unref (screen->sn_context);
+ screen->sn_context = NULL;
+ }
+#endif
+
meta_ui_free (screen->ui);
meta_stack_free (screen->stack);
@@ -1619,3 +1653,187 @@ meta_screen_unshow_desktop (MetaScreen *screen)
meta_screen_focus_top_window (screen, NULL);
}
+
+#ifdef HAVE_STARTUP_NOTIFICATION
+static gboolean startup_sequence_timeout (void *data);
+
+static void
+update_startup_feedback (MetaScreen *screen)
+{
+ if (screen->startup_sequences != NULL)
+ {
+ meta_topic (META_DEBUG_STARTUP,
+ "Setting busy cursor\n");
+ meta_screen_set_cursor (screen, META_CURSOR_BUSY);
+ }
+ else
+ {
+ meta_topic (META_DEBUG_STARTUP,
+ "Setting default cursor\n");
+ meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
+ }
+}
+
+static void
+add_sequence (MetaScreen *screen,
+ SnStartupSequence *sequence)
+{
+ meta_topic (META_DEBUG_STARTUP,
+ "Adding sequence %s\n",
+ sn_startup_sequence_get_id (sequence));
+ sn_startup_sequence_ref (sequence);
+ screen->startup_sequences = g_slist_prepend (screen->startup_sequences,
+ sequence);
+
+ /* our timeout just polls every second, instead of bothering
+ * to compute exactly when we may next time out
+ */
+ if (screen->startup_sequence_timeout == 0)
+ screen->startup_sequence_timeout = g_timeout_add (1000,
+ startup_sequence_timeout,
+ screen);
+
+ update_startup_feedback (screen);
+}
+
+static void
+remove_sequence (MetaScreen *screen,
+ SnStartupSequence *sequence)
+{
+ meta_topic (META_DEBUG_STARTUP,
+ "Removing sequence %s\n",
+ sn_startup_sequence_get_id (sequence));
+
+ screen->startup_sequences = g_slist_remove (screen->startup_sequences,
+ sequence);
+ sn_startup_sequence_unref (sequence);
+
+ if (screen->startup_sequences == NULL &&
+ screen->startup_sequence_timeout != 0)
+ {
+ g_source_remove (screen->startup_sequence_timeout);
+ screen->startup_sequence_timeout = 0;
+ }
+
+ update_startup_feedback (screen);
+}
+
+typedef struct
+{
+ GSList *list;
+ GTimeVal now;
+} CollectTimedOutData;
+
+#define STARTUP_TIMEOUT 5000
+
+static void
+collect_timed_out_foreach (void *element,
+ void *data)
+{
+ CollectTimedOutData *ctod = data;
+ SnStartupSequence *sequence = element;
+ long tv_sec, tv_usec;
+ double elapsed;
+
+ sn_startup_sequence_get_last_active_time (sequence, &tv_sec, &tv_usec);
+
+ elapsed =
+ ((((double)ctod->now.tv_sec - tv_sec) * G_USEC_PER_SEC +
+ (ctod->now.tv_usec - tv_usec))) / 1000.0;
+
+ meta_topic (META_DEBUG_STARTUP,
+ "Sequence used %g seconds vs. %g max: %s\n",
+ elapsed, (double) STARTUP_TIMEOUT,
+ sn_startup_sequence_get_id (sequence));
+
+ if (elapsed > STARTUP_TIMEOUT)
+ ctod->list = g_slist_prepend (ctod->list, sequence);
+}
+
+static gboolean
+startup_sequence_timeout (void *data)
+{
+ MetaScreen *screen = data;
+ CollectTimedOutData ctod;
+ GSList *tmp;
+
+ ctod.list = NULL;
+ g_get_current_time (&ctod.now);
+ g_slist_foreach (screen->startup_sequences,
+ collect_timed_out_foreach,
+ &ctod);
+
+ tmp = ctod.list;
+ while (tmp != NULL)
+ {
+ SnStartupSequence *sequence = tmp->data;
+
+ meta_topic (META_DEBUG_STARTUP,
+ "Timed out sequence %s\n",
+ sn_startup_sequence_get_id (sequence));
+
+ remove_sequence (screen, sequence);
+
+ tmp = tmp->next;
+ }
+
+ g_slist_free (ctod.list);
+
+ if (screen->startup_sequences != NULL)
+ {
+ return TRUE;
+ }
+ else
+ {
+ /* remove */
+ screen->startup_sequence_timeout = 0;
+ return FALSE;
+ }
+}
+
+static void
+meta_screen_sn_event (SnMonitorEvent *event,
+ void *user_data)
+{
+ MetaScreen *screen;
+ SnStartupSequence *sequence;
+
+ screen = user_data;
+
+ sequence = sn_monitor_event_get_startup_sequence (event);
+
+ switch (sn_monitor_event_get_type (event))
+ {
+ case SN_MONITOR_EVENT_INITIATED:
+ {
+ meta_topic (META_DEBUG_STARTUP,
+ "Received startup initiated for %s\n",
+ sn_startup_sequence_get_id (sequence));
+ add_sequence (screen, sequence);
+ }
+ break;
+
+ case SN_MONITOR_EVENT_COMPLETED:
+ {
+ meta_topic (META_DEBUG_STARTUP,
+ "Received startup completed for %s\n",
+ sn_startup_sequence_get_id (sequence));
+ remove_sequence (screen,
+ sn_monitor_event_get_startup_sequence (event));
+ }
+ break;
+
+ case SN_MONITOR_EVENT_CHANGED:
+ meta_topic (META_DEBUG_STARTUP,
+ "Received startup changed for %s\n",
+ sn_startup_sequence_get_id (sequence));
+ break;
+
+ case SN_MONITOR_EVENT_CANCELED:
+ meta_topic (META_DEBUG_STARTUP,
+ "Received startup canceled for %s\n",
+ sn_startup_sequence_get_id (sequence));
+ break;
+ }
+}
+#endif
diff --git a/src/screen.h b/src/screen.h
index a5811b6..04de75c 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -79,6 +79,12 @@ struct _MetaScreen
/* Cache the current Xinerama */
int last_xinerama_index;
+
+#ifdef HAVE_STARTUP_NOTIFICATION
+ SnMonitorContext *sn_context;
+ GSList *startup_sequences;
+ guint startup_sequence_timeout;
+#endif
guint work_area_idle;
diff --git a/src/util.c b/src/util.c
index c6b6b7e..36851ee 100644
--- a/src/util.c
+++ b/src/util.c
@@ -258,6 +258,8 @@ topic_name (MetaDebugTopic topic)
return "SYNC";
case META_DEBUG_ERRORS:
return "ERRORS";
+ case META_DEBUG_STARTUP:
+ return "STARTUP";
}
return "Window manager";
diff --git a/src/util.h b/src/util.h
index 07ebc42..ae2e6ee 100644
--- a/src/util.h
+++ b/src/util.h
@@ -60,7 +60,8 @@ typedef enum
META_DEBUG_XINERAMA = 1 << 11,
META_DEBUG_KEYBINDINGS = 1 << 12,
META_DEBUG_SYNC = 1 << 13,
- META_DEBUG_ERRORS = 1 << 14
+ META_DEBUG_ERRORS = 1 << 14,
+ META_DEBUG_STARTUP = 1 << 15
} MetaDebugTopic;