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
This commit is contained in:
Havoc Pennington 2002-10-25 23:35:50 +00:00 committed by Havoc Pennington
parent c3a5c4c169
commit cb27f0c4be
11 changed files with 346 additions and 18 deletions

View File

@ -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

View File

@ -15,3 +15,5 @@
#undef HAVE_XFREE_XINERAMA
#undef HAVE_SHAPE
#undef HAVE_RANDR
#undef HAVE_STARTUP_NOTIFICATION

View File

@ -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}
"

View File

@ -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 \

View File

@ -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;

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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";

View File

@ -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;