diff --git a/js/ui/main.js b/js/ui/main.js index 9f132c645..fef838aee 100644 --- a/js/ui/main.js +++ b/js/ui/main.js @@ -98,8 +98,8 @@ Signals.addSignalMethods(ClutterFrameTicker.prototype); function start() { let global = Shell.Global.get(); - // Here we grab our DBus name, etc. - global.late_init(); + global.grab_dbus_service(); + global.start_task_panel(); Tweener.setFrameTicker(new ClutterFrameTicker()); diff --git a/scripts/launcher.py b/scripts/launcher.py index 28c5d91c1..0efd6cb3f 100644 --- a/scripts/launcher.py +++ b/scripts/launcher.py @@ -93,6 +93,7 @@ class Launcher: env.update({'GNOME_SHELL_JS' : self.js_dir, 'GNOME_SHELL_DATADIR' : self.data_dir, 'GI_TYPELIB_PATH' : self.plugin_dir, + 'PATH' : os.environ.get('PATH', '') + ':' + self.plugin_dir, 'LD_LIBRARY_PATH' : os.environ.get('LD_LIBRARY_PATH', '') + ':' + self.plugin_dir, 'GNOME_DISABLE_CRASH_DIALOG' : '1'}) diff --git a/src/gnomeshell-taskpanel.c b/src/gnomeshell-taskpanel.c index 1dca7808d..5e9d2177c 100644 --- a/src/gnomeshell-taskpanel.c +++ b/src/gnomeshell-taskpanel.c @@ -18,10 +18,12 @@ on_name_owner_changed (DBusGProxy *proxy, } static void -monitor_main_shell () +monitor_main_shell (const char *shell_name) { DBusGConnection *session; DBusGProxy *driver; + GError *error = NULL; + gboolean have_shell; session = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); @@ -29,6 +31,19 @@ monitor_main_shell () DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); + + if (!dbus_g_proxy_call (driver, "NameHasOwner", &error, G_TYPE_STRING, + shell_name, G_TYPE_INVALID, G_TYPE_BOOLEAN, + &have_shell, G_TYPE_INVALID)) + { + /* Shouldn't happen */ + exit (1); + } + if (!have_shell) + { + /* Shell doesn't exist; either crashed or was restarted. Just abort. */ + exit (0); + } dbus_g_proxy_add_signal (driver, "NameOwnerChanged", @@ -53,7 +68,12 @@ main (int argc, char **argv) gtk_init (&argc, &argv); - monitor_main_shell (); + if (argc != 2) { + g_printerr ("Usage: gnomeshell-taskpanel [PARENT_DBUS_SERVICE]\n"); + exit (1); + } + + monitor_main_shell (argv[1]); panel = shell_panel_window_new (); diff --git a/src/shell-global.c b/src/shell-global.c index 22ccd3a43..3aef2aea5 100644 --- a/src/shell-global.c +++ b/src/shell-global.c @@ -14,6 +14,8 @@ #include #include +#define SHELL_DBUS_SERVICE "org.gnome.Shell" + struct _ShellGlobal { GObject parent; @@ -460,25 +462,13 @@ shell_global_reexec_self (ShellGlobal *global) g_ptr_array_free (arr, TRUE); } -/** - * shell_global_late_init - * - * Perform once-only global initialization; currently this executes - * the external tasklist process and grabs the org.gnome.Shell DBus name. - */ void -shell_global_late_init (ShellGlobal *global) +shell_global_grab_dbus_service (ShellGlobal *global) { - static gboolean initialized = FALSE; GError *error = NULL; DBusGConnection *session; DBusGProxy *bus; guint32 request_name_result; - const char* panel_args[] = {"gnomeshell-taskpanel", NULL}; - - if (initialized) - return; - initialized = TRUE; session = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); @@ -488,20 +478,32 @@ shell_global_late_init (ShellGlobal *global) DBUS_INTERFACE_DBUS); if (!dbus_g_proxy_call (bus, "RequestName", &error, - G_TYPE_STRING, "org.gnome.Shell", + G_TYPE_STRING, SHELL_DBUS_SERVICE, G_TYPE_UINT, 0, G_TYPE_INVALID, G_TYPE_UINT, &request_name_result, - G_TYPE_INVALID)) { - g_print ("failed to acquire org.gnome.Shell: %s\n", error->message); - exit (0); - } - - if (!g_spawn_async (NULL, &panel_args, NULL, G_SPAWN_SEARCH_PATH, NULL, - NULL, NULL, &error)) { - g_critical ("failed to execute %s: %s", panel_args[0], error->message); - g_clear_error (&error); - } + G_TYPE_INVALID)) + { + g_print ("failed to acquire org.gnome.Shell: %s\n", error->message); + /* If we somehow got started again, it's not an error to be running + * already. So just exit 0. + */ + exit (0); + } g_object_unref (bus); +} + +void +shell_global_start_task_panel (ShellGlobal *global) +{ + const char* panel_args[] = {"gnomeshell-taskpanel", SHELL_DBUS_SERVICE, NULL}; + GError *error = NULL; + + if (!g_spawn_async (NULL, (char**) panel_args, NULL, G_SPAWN_SEARCH_PATH, NULL, + NULL, NULL, &error)) + { + g_critical ("failed to execute %s: %s", panel_args[0], error->message); + g_clear_error (&error); + } } \ No newline at end of file diff --git a/src/shell-global.h b/src/shell-global.h index a9119c13b..a6e268a80 100644 --- a/src/shell-global.h +++ b/src/shell-global.h @@ -38,7 +38,9 @@ GdkPixbuf *shell_get_thumbnail_for_recent_info(GtkRecentInfo *recent_info); ShellGlobal *shell_global_get (void); -void shell_global_late_init (ShellGlobal *global); +void shell_global_grab_dbus_service (ShellGlobal *global); + +void shell_global_start_task_panel (ShellGlobal *global); void shell_global_set_stage_input_area (ShellGlobal *global, int x, diff --git a/src/shell-panel-window.c b/src/shell-panel-window.c index 04e9fbd91..a0fd2ac00 100644 --- a/src/shell-panel-window.c +++ b/src/shell-panel-window.c @@ -10,16 +10,7 @@ enum { }; -static void shell_panel_window_dispose (GObject *object); static void shell_panel_window_finalize (GObject *object); -static void shell_panel_window_set_property ( GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec ); -static void shell_panel_window_get_property( GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec ); static void shell_panel_window_size_request (GtkWidget *self, GtkRequisition *req); static void shell_panel_window_size_allocate (GtkWidget *self, GtkAllocation *allocation); static void shell_panel_window_realize (GtkWidget *self); @@ -36,6 +27,8 @@ G_DEFINE_TYPE(ShellPanelWindow, shell_panel_window, GTK_TYPE_WINDOW); struct ShellPanelWindowPrivate { GtkAllocation workarea; guint width; + guint height; + Atom workarea_atom; }; static void @@ -44,11 +37,8 @@ shell_panel_window_class_init(ShellPanelWindowClass *klass) GObjectClass *gobject_class = (GObjectClass *)klass; GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; - gobject_class->dispose = shell_panel_window_dispose; gobject_class->finalize = shell_panel_window_finalize; - gobject_class->set_property = shell_panel_window_set_property; - gobject_class->get_property = shell_panel_window_get_property; - + widget_class->realize = shell_panel_window_realize; widget_class->size_request = shell_panel_window_size_request; widget_class->size_allocate = shell_panel_window_size_allocate; @@ -59,18 +49,13 @@ static void shell_panel_window_init (ShellPanelWindow *self) { self->priv = g_new0 (ShellPanelWindowPrivate, 1); + self->priv->workarea_atom = gdk_x11_get_xatom_by_name_for_display (gdk_display_get_default (), "_NET_WORKAREA"); + gtk_window_set_type_hint (GTK_WINDOW (self), GDK_WINDOW_TYPE_HINT_DOCK); gtk_window_set_focus_on_map (GTK_WINDOW (self), FALSE); gdk_window_add_filter (NULL, filter_func, self); } -static void shell_panel_window_dispose (GObject *object) -{ - ShellPanelWindow *self = (ShellPanelWindow*)object; - - G_OBJECT_CLASS (shell_panel_window_parent_class)->dispose(object); -} - static void shell_panel_window_finalize (GObject *object) { ShellPanelWindow *self = (ShellPanelWindow*)object; @@ -80,53 +65,24 @@ static void shell_panel_window_finalize (GObject *object) G_OBJECT_CLASS (shell_panel_window_parent_class)->finalize(object); } -static void shell_panel_window_set_property ( GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec ) -{ - ShellPanelWindow* self = SHELL_PANEL_WINDOW(object); - switch (property_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - - -static void shell_panel_window_get_property ( GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec ) -{ - ShellPanelWindow* self = SHELL_PANEL_WINDOW(object); - switch (property_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -ShellPanelWindow* shell_panel_window_new(void) -{ +ShellPanelWindow* shell_panel_window_new(void) { return (ShellPanelWindow*) g_object_new(SHELL_TYPE_PANEL_WINDOW, "type", GTK_WINDOW_TOPLEVEL, NULL); } - static void set_strut (ShellPanelWindow *self) { long *buf; - int x, y; int strut_size; strut_size = GTK_WIDGET (self)->allocation.height; - gtk_window_get_position (GTK_WINDOW (self), &x, &y); - - buf = g_new0(long, 4); - buf[3] = strut_size; + buf = g_new0 (long, 4); + buf[0] = 0; /* left */ + buf[1] = 0; /* right */ + buf[2] = 0; /* top */ + buf[3] = strut_size; /* bottom */ gdk_property_change (GTK_WIDGET (self)->window, gdk_atom_intern_static_string ("_NET_WM_STRUT"), gdk_atom_intern_static_string ("CARDINAL"), 32, GDK_PROP_MODE_REPLACE, @@ -171,26 +127,44 @@ shell_panel_window_show (GtkWidget *widget) static void handle_new_workarea (ShellPanelWindow *self) { - int monitor; GtkRequisition requisition; - GdkRectangle monitor_geometry; int x, y; int width; + int height; + int x_target, y_target; - monitor = gdk_screen_get_monitor_at_point (gdk_screen_get_default (), - self->priv->workarea.x, - self->priv->workarea.y); - gdk_screen_get_monitor_geometry (gdk_screen_get_default (), - monitor, &monitor_geometry); gtk_widget_size_request (GTK_WIDGET (self), &requisition); - x = self->priv->workarea.x; - y = monitor_geometry.y + monitor_geometry.height - requisition.height; - width = monitor_geometry.width - x; + /* If we don't have a workarea, just use monitor */ + if (self->priv->workarea.width == 0) + { + int monitor; + GdkRectangle monitor_geometry; + + monitor = gdk_screen_get_monitor_at_point (gdk_screen_get_default (), + 0, 0); + gdk_screen_get_monitor_geometry (gdk_screen_get_default (), + monitor, &monitor_geometry); + x = monitor_geometry.x; + y = monitor_geometry.y; + width = monitor_geometry.width; + height = monitor_geometry.height; + } + else + { + x = self->priv->workarea.x; + y = self->priv->workarea.y; + width = self->priv->workarea.width; + height = self->priv->workarea.height; + } + + x_target = x; + y_target = y + height - requisition.height; self->priv->width = width; - gtk_widget_set_size_request (GTK_WIDGET (self), width, PANEL_HEIGHT); - gtk_window_move (GTK_WINDOW (self), x, y); + self->priv->height = height; + gtk_widget_set_size_request (GTK_WIDGET (self), width - x_target, PANEL_HEIGHT); + gtk_window_move (GTK_WINDOW (self), x_target, y_target); } static void @@ -207,31 +181,38 @@ on_workarea_changed (ShellPanelWindow *self) workarea, 0, 4, FALSE, workarea, &type, &format, &nitems, &bytes_after, &data); - if ((format == 32) && (nitems == 4) && (bytes_after == 0)) { - int x, y, width, height; - data32 = (long*)data; - x = data32[0]; y = data32[1]; - width = data32[2]; height = data32[3]; - if (x == self->priv->workarea.x && - y == self->priv->workarea.y && - width == self->priv->workarea.width && - height == self->priv->workarea.height) - return; + if ((format == 32) && (nitems == 4) && (bytes_after == 0)) + { + int x, y, width, height; + data32 = (long*) data; + x = data32[0]; + y = data32[1]; + width = data32[2]; + height = data32[3]; + if (x == self->priv->workarea.x && y == self->priv->workarea.y + && width == self->priv->workarea.width + && height == self->priv->workarea.height) + return; - self->priv->workarea.x = x; - self->priv->workarea.y = y; - self->priv->workarea.width = width; - self->priv->workarea.height = height; + self->priv->workarea.x = x; + self->priv->workarea.y = y; + self->priv->workarea.width = width; + self->priv->workarea.height = height; - handle_new_workarea (self); - } else if (nitems == 0) { - self->priv->workarea.x = self->priv->workarea.y = 0; - self->priv->workarea.width = self->priv->workarea.height = -1; - handle_new_workarea (self); - } else { - g_printerr ("unexpected return from XGetWindowProperty: %d %ld %ld\n", - format, nitems, bytes_after); - } + handle_new_workarea (self); + } + else if (nitems == 0) + { + /* We have no workarea set; assume there are no other panels at this time */ + self->priv->workarea.x = self->priv->workarea.y = 0; + self->priv->workarea.width = self->priv->workarea.height = 0; + handle_new_workarea (self); + } + else + { + g_printerr ("unexpected return from XGetWindowProperty: %d %ld %ld\n", + format, nitems, bytes_after); + } } static GdkFilterReturn @@ -242,14 +223,13 @@ filter_func (GdkXEvent *gdk_xevent, ShellPanelWindow *self = SHELL_PANEL_WINDOW (data); GdkFilterReturn ret = GDK_FILTER_CONTINUE; XEvent *xevent = (XEvent *) event; - Atom workarea = gdk_x11_get_xatom_by_name_for_display (gdk_display_get_default (), "_NET_WORKAREA"); - switch (xevent->type) { + switch (xevent->type) + { case PropertyNotify: { - if (xevent->xproperty.atom != workarea) + if (xevent->xproperty.atom != self->priv->workarea_atom) break; - on_workarea_changed (self); } break;