[gnome-shell] Add application menu area to panel
- From: Colin Walters <walters src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-shell] Add application menu area to panel
- Date: Tue, 11 Aug 2009 17:23:20 +0000 (UTC)
commit 74eac2187086b82b001f88bec64d779fd92ab63c
Author: Colin Walters <walters verbum org>
Date: Tue Aug 11 11:32:58 2009 -0400
Add application menu area to panel
This is a start at the "Active Appliction Item" component of the
shell design. Currently we just show the currently focused
application. When launching a new application, we show that as well.
The implementation here is not complete; basically when launching
we de-focus the active one, and the application well shows the
most recent startup sequence.
This kind of fails in the case of multiple sequences, and we
also don't correctly de-focus the current window in other
launch paths.
configure.ac | 6 ++-
js/ui/panel.js | 108 +++++++++++++++++++++++++++++++++++++++++++++
src/shell-app-monitor.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++
src/shell-app-monitor.h | 12 +++++
src/shell-app-system.c | 9 +++-
5 files changed, 244 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 06b5d4b..a93de64 100644
--- a/configure.ac
+++ b/configure.ac
@@ -43,7 +43,11 @@ fi
AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
-PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-unix-2.0 gtk+-2.0 dbus-glib-1 mutter-plugins gjs-gi-1.0 libgnome-menu $recorder_modules gconf-2.0 gdk-x11-2.0 clutter-x11-1.0 clutter-glx-1.0 gnome-desktop-2.0 >= 2.26)
+# Collect more than 20 libraries for a prize!
+PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-unix-2.0 gtk+-2.0 dbus-glib-1 mutter-plugins
+ gjs-gi-1.0 libgnome-menu $recorder_modules gconf-2.0
+ gdk-x11-2.0 clutter-x11-1.0 clutter-glx-1.0
+ gnome-desktop-2.0 >= 2.26 libstartup-notification-1.0)
PKG_CHECK_MODULES(TIDY, clutter-1.0)
PKG_CHECK_MODULES(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0)
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)
diff --git a/js/ui/panel.js b/js/ui/panel.js
index 16d3f68..dda10ab 100644
--- a/js/ui/panel.js
+++ b/js/ui/panel.js
@@ -8,6 +8,7 @@ const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Tweener = imports.ui.tweener;
+const Signals = imports.signals;
const Button = imports.ui.button;
const Main = imports.ui.main;
@@ -17,10 +18,14 @@ const TRAY_HEIGHT = PANEL_HEIGHT - 1;
const DEFAULT_PADDING = 4;
+const PANEL_ICON_SIZE = 24;
+
const PANEL_BACKGROUND_COLOR = new Clutter.Color();
PANEL_BACKGROUND_COLOR.from_pixel(0x000000ff);
const PANEL_FOREGROUND_COLOR = new Clutter.Color();
PANEL_FOREGROUND_COLOR.from_pixel(0xffffffff);
+const SN_BACKGROUND_COLOR = new Clutter.Color();
+SN_BACKGROUND_COLOR.from_pixel(0xffff00a0);
const TRANSPARENT_COLOR = new Clutter.Color();
TRANSPARENT_COLOR.from_pixel(0x00000000);
@@ -49,6 +54,105 @@ TRAY_BORDER_COLOR.from_pixel(0x00000033);
const TRAY_CORNER_RADIUS = 5;
const TRAY_BORDER_WIDTH = 0;
+
+function AppPanelMenu() {
+ this._init();
+}
+
+AppPanelMenu.prototype = {
+ _init: function() {
+ this._metaDisplay = Shell.Global.get().screen.get_display();
+
+ this._focusedApp = null;
+ this._activeSequence = null;
+ this._startupSequences = {};
+
+ this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
+ spacing: DEFAULT_PADDING,
+ y_align: Big.BoxAlignment.CENTER });
+ this._iconBox = new Big.Box({ width: PANEL_ICON_SIZE, height: PANEL_ICON_SIZE,
+ x_align: Big.BoxAlignment.CENTER,
+ y_align: Big.BoxAlignment.CENTER });
+ this.actor.append(this._iconBox, Big.BoxPackFlags.NONE);
+ let labelBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
+ y_align: Big.BoxAlignment.CENTER });
+ this._label = new Clutter.Text({ font_name: DEFAULT_FONT,
+ color: PANEL_FOREGROUND_COLOR,
+ text: "" });
+ labelBox.append(this._label, Big.BoxPackFlags.EXPAND);
+ this.actor.append(labelBox, Big.BoxPackFlags.NONE);
+
+ this._startupBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
+ y_align: Big.BoxAlignment.CENTER
+ });
+ this.actor.append(this._startupBox, Big.BoxPackFlags.NONE);
+
+ Main.overview.connect('hiding', Lang.bind(this, function () {
+ this.actor.opacity = 255;
+ }));
+ Main.overview.connect('showing', Lang.bind(this, function () {
+ this.actor.opacity = 192;
+ }));
+
+ this._metaDisplay.connect('notify::focus-window', Lang.bind(this, function () {
+ this._sync();
+ }));
+ Shell.AppMonitor.get_default().connect('startup-sequence-changed', Lang.bind(this, function() {
+ this._sync();
+ }));
+ this._sync();
+ },
+
+ _sync: function() {
+ let appMonitor = Shell.AppMonitor.get_default();
+
+ let focusWindow = this._metaDisplay.get_focus_window();
+ let focusedApp;
+ if (focusWindow == null) {
+ focusedApp = null;
+ } else {
+ focusedApp = appMonitor.get_window_app(focusWindow);
+ }
+
+ let lastSequence = null;
+ if (focusedApp == null) {
+ let sequences = appMonitor.get_startup_sequences();
+ if (sequences.length > 0)
+ lastSequence = sequences[sequences.length - 1];
+ }
+
+ // If the currently focused app hasn't changed and the current
+ // startup sequence hasn't changed, we have nothing to do
+ if (focusedApp == this._focusedApp
+ && ((lastSequence == null && this._activeSequence == null)
+ || (lastSequence != null && this._activeSequence != null
+ && lastSequence.get_id() == this._activeSequence.get_id())))
+ return;
+
+ this._focusedApp = focusedApp;
+ this._activeSequence = lastSequence;
+
+ this._iconBox.remove_all();
+ this._iconBox.hide();
+ this._label.text = '';
+ if (this._focusedApp != null) {
+ let icon = focusedApp.create_icon_texture(PANEL_ICON_SIZE);
+ this._iconBox.append(icon, Big.BoxPackFlags.NONE);
+ this._iconBox.show();
+ this._label.text = focusedApp.get_name();
+ } else if (this._activeSequence != null) {
+ let icon = this._activeSequence.create_icon(PANEL_ICON_SIZE);
+ this._iconBox.append(icon, Big.BoxPackFlags.NONE);
+ this._iconBox.show();
+ this._label.text = this._activeSequence.get_name();
+ }
+
+ this.emit('changed');
+ }
+}
+
+Signals.addSignalMethods(AppPanelMenu.prototype);
+
function Panel() {
this._init();
}
@@ -62,6 +166,7 @@ Panel.prototype = {
});
this._leftBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
y_align: Big.BoxAlignment.CENTER,
+ spacing: DEFAULT_PADDING,
padding_right: DEFAULT_PADDING });
this._centerBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
y_align: Big.BoxAlignment.CENTER });
@@ -166,6 +271,9 @@ Panel.prototype = {
this._leftBox.append(hotCorner, Big.BoxPackFlags.FIXED);
+ let appMenu = new AppPanelMenu();
+ this._leftBox.append(appMenu.actor, Big.BoxPackFlags.NONE);
+
/* center */
this._clock = new Clutter.Text({ font_name: DEFAULT_FONT,
diff --git a/src/shell-app-monitor.c b/src/shell-app-monitor.c
index b4d61b5..789dd14 100644
--- a/src/shell-app-monitor.c
+++ b/src/shell-app-monitor.c
@@ -11,6 +11,10 @@
#include <gconf/gconf-client.h>
#include <dbus/dbus-glib.h>
+#define SN_API_NOT_YET_FROZEN 1
+#include <libsn/sn.h>
+
+#include "shell-texture-cache.h"
#include "shell-app-monitor.h"
#include "shell-app-system.h"
#include "shell-global.h"
@@ -151,6 +155,7 @@ struct AppUsage
enum {
CHANGED,
+ STARTUP_SEQUENCE_CHANGED,
LAST_SIGNAL
};
@@ -198,6 +203,14 @@ static void shell_app_monitor_class_init(ShellAppMonitorClass *klass)
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
+
+ signals[STARTUP_SEQUENCE_CHANGED] = g_signal_new ("startup-sequence-changed",
+ SHELL_TYPE_APP_MONITOR,
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1, SHELL_TYPE_STARTUP_SEQUENCE);
}
static void
@@ -695,8 +708,18 @@ init_window_monitoring (ShellAppMonitor *self)
}
static void
+on_startup_sequence_changed (MetaScreen *screen,
+ SnStartupSequence *sequence,
+ ShellAppMonitor *self)
+{
+ /* Just proxy the signal */
+ g_signal_emit (G_OBJECT (self), signals[STARTUP_SEQUENCE_CHANGED], 0, sequence);
+}
+
+static void
shell_app_monitor_init (ShellAppMonitor *self)
{
+ MetaScreen *screen;
GdkDisplay *display;
char *path;
char *shell_config_dir;
@@ -704,6 +727,7 @@ shell_app_monitor_init (ShellAppMonitor *self)
/* FIXME: should we create as many monitors as there are GdkScreens? */
display = gdk_display_get_default ();
+ screen = shell_global_get_screen (shell_global_get ());
session_bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
self->session_proxy = dbus_g_proxy_new_for_name (session_bus, "org.gnome.SessionManager",
@@ -735,6 +759,9 @@ shell_app_monitor_init (ShellAppMonitor *self)
load_initial_windows (self);
init_window_monitoring (self);
+ g_signal_connect (G_OBJECT (screen), "startup-sequence-changed",
+ G_CALLBACK (on_startup_sequence_changed), self);
+
self->gconf_client = gconf_client_get_default ();
gconf_client_add_dir (self->gconf_client, APP_MONITOR_GCONF_DIR,
GCONF_CLIENT_PRELOAD_NONE, NULL);
@@ -1339,6 +1366,90 @@ on_enable_monitoring_key_changed (GConfClient *client,
update_enable_monitoring ((ShellAppMonitor *) monitor);
}
+
+/**
+ * shell_app_monitor_get_startup_sequences:
+ * @self:
+ *
+ * Returns: (transfer none) (element-type ShellStartupSequence): Currently active startup sequences
+ */
+GSList *
+shell_app_monitor_get_startup_sequences (ShellAppMonitor *self)
+{
+ ShellGlobal *global = shell_global_get ();
+ MetaScreen *screen = shell_global_get_screen (global);
+ return meta_screen_get_startup_sequences (screen);
+}
+
+/* sn_startup_sequence_ref returns void, so make a
+ * wrapper which returns self */
+SnStartupSequence *
+sequence_ref (SnStartupSequence *sequence)
+{
+ sn_startup_sequence_ref (sequence);
+ return sequence;
+}
+
+GType
+shell_startup_sequence_get_type (void)
+{
+ static GType gtype = G_TYPE_INVALID;
+ if (gtype == G_TYPE_INVALID)
+ {
+ gtype = g_boxed_type_register_static ("ShellStartupSequence",
+ (GBoxedCopyFunc)sequence_ref,
+ (GBoxedFreeFunc)sn_startup_sequence_unref);
+ }
+ return gtype;
+}
+
+const char *
+shell_startup_sequence_get_id (ShellStartupSequence *sequence)
+{
+ return sn_startup_sequence_get_id ((SnStartupSequence*)sequence);
+}
+
+const char *
+shell_startup_sequence_get_name (ShellStartupSequence *sequence)
+{
+ return sn_startup_sequence_get_name ((SnStartupSequence*)sequence);
+}
+
+gboolean
+shell_startup_sequence_get_completed (ShellStartupSequence *sequence)
+{
+ return sn_startup_sequence_get_completed ((SnStartupSequence*)sequence);
+}
+
+/**
+ * shell_startup_sequence_create_icon:
+ * @sequence:
+ * @size: Size in pixels of icon
+ *
+ * Returns: (transfer none): A new #ClutterTexture containing an icon for the sequence
+ */
+ClutterActor *
+shell_startup_sequence_create_icon (ShellStartupSequence *sequence, guint size)
+{
+ GThemedIcon *themed;
+ const char *icon_name;
+ ClutterActor *texture;
+
+ icon_name = sn_startup_sequence_get_icon_name ((SnStartupSequence*)sequence);
+ if (!icon_name)
+ {
+ texture = clutter_texture_new ();
+ clutter_actor_set_size (texture, size, size);
+ return texture;
+ }
+
+ themed = (GThemedIcon*)g_themed_icon_new (icon_name);
+ texture = shell_texture_cache_load_gicon (shell_texture_cache_get_default (),
+ G_ICON (themed), size);
+ g_object_unref (G_OBJECT (themed));
+ return texture;
+}
+
/**
* shell_app_monitor_get_default:
*
diff --git a/src/shell-app-monitor.h b/src/shell-app-monitor.h
index 41f7129..491f860 100644
--- a/src/shell-app-monitor.h
+++ b/src/shell-app-monitor.h
@@ -49,6 +49,18 @@ GSList *shell_app_monitor_get_windows_for_app (ShellAppMonitor *monitor, const c
/* Get whatever's running right now */
GSList *shell_app_monitor_get_running_app_ids (ShellAppMonitor *monitor, const char *context);
+GSList *shell_app_monitor_get_startup_sequences (ShellAppMonitor *monitor);
+
+/* Hidden typedef for SnStartupSequence */
+typedef struct _ShellStartupSequence ShellStartupSequence;
+#define SHELL_TYPE_STARTUP_SEQUENCE (shell_startup_sequence_get_type ())
+GType shell_startup_sequence_get_type (void);
+
+const char *shell_startup_sequence_get_id (ShellStartupSequence *sequence);
+const char *shell_startup_sequence_get_name (ShellStartupSequence *sequence);
+gboolean shell_startup_sequence_get_completed (ShellStartupSequence *sequence);
+ClutterActor *shell_startup_sequence_create_icon (ShellStartupSequence *sequence, guint size);
+
G_END_DECLS
#endif /* __SHELL_APP_MONITOR_H__ */
diff --git a/src/shell-app-system.c b/src/shell-app-system.c
index dc2f53b..d415f18 100644
--- a/src/shell-app-system.c
+++ b/src/shell-app-system.c
@@ -8,6 +8,7 @@
#include <gtk/gtk.h>
#include <gconf/gconf.h>
#include <gconf/gconf-client.h>
+#include <clutter/clutter.h>
#include "shell-global.h"
#include "shell-texture-cache.h"
@@ -922,7 +923,13 @@ shell_app_info_launch_full (ShellAppInfo *info,
display = meta_screen_get_display (screen);
if (timestamp == 0)
- timestamp = meta_display_get_current_time (display);
+ timestamp = clutter_get_current_event_time ();
+
+ /* Shell design calls for on application launch, no window is focused,
+ * and we have startup notification displayed.
+ */
+ meta_display_focus_the_no_focus_window (display, screen, timestamp);
+
if (workspace < 0)
workspace = meta_screen_get_active_workspace_index (screen);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]