From f14d7f891bfd55490bd988cbef5adc4025913367 Mon Sep 17 00:00:00 2001 From: Milo Casagrande Date: Tue, 3 Nov 2009 22:29:36 +0100 Subject: [PATCH 01/51] Updated Italian translation --- po/it.po | 61 +++++++++++++++++++++++--------------------------------- 1 file changed, 25 insertions(+), 36 deletions(-) diff --git a/po/it.po b/po/it.po index cdc36bb9f..ff145d7b7 100644 --- a/po/it.po +++ b/po/it.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: gnome-shell\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-10-10 12:20+0200\n" -"PO-Revision-Date: 2009-10-10 12:39+0200\n" +"POT-Creation-Date: 2009-11-03 22:26+0100\n" +"PO-Revision-Date: 2009-11-03 22:28+0100\n" "Last-Translator: Milo Casagrande \n" "Language-Team: Italian \n" "MIME-Version: 1.0\n" @@ -24,19 +24,23 @@ msgstr "GNOME Shell" msgid "Window management and application launching" msgstr "Gestione finestre e avvio applicazioni" -#: ../js/ui/appDisplay.js:335 +#: ../js/ui/appDisplay.js:332 msgid "Frequent" msgstr "Frequente" -#: ../js/ui/appIcon.js:462 +#: ../js/ui/appDisplay.js:867 +msgid "Drag here to add favorites" +msgstr "Trascinare qui per aggiungere ai preferiti" + +#: ../js/ui/appIcon.js:426 msgid "New Window" msgstr "Nuova finestra" -#: ../js/ui/appIcon.js:475 +#: ../js/ui/appIcon.js:430 msgid "Remove from Favorites" msgstr "Rimuovi dai preferiti" -#: ../js/ui/appIcon.js:476 +#: ../js/ui/appIcon.js:431 msgid "Add to Favorites" msgstr "Aggiungi ai preferiti" @@ -53,40 +57,40 @@ msgid "(see all)" msgstr "(vedi tutto)" #. **** Applications **** -#: ../js/ui/dash.js:763 ../js/ui/dash.js:825 +#: ../js/ui/dash.js:725 ../js/ui/dash.js:787 msgid "APPLICATIONS" msgstr "Applicazioni" #. **** Places **** #. Translators: This is in the sense of locations for documents, #. network locations, etc. -#: ../js/ui/dash.js:783 +#: ../js/ui/dash.js:745 msgid "PLACES" msgstr "Risorse" #. **** Documents **** -#: ../js/ui/dash.js:790 ../js/ui/dash.js:835 +#: ../js/ui/dash.js:752 ../js/ui/dash.js:797 msgid "RECENT DOCUMENTS" msgstr "Documenti recenti" #. **** Search Results **** -#: ../js/ui/dash.js:815 ../js/ui/dash.js:955 +#: ../js/ui/dash.js:777 ../js/ui/dash.js:961 msgid "SEARCH RESULTS" msgstr "Risultati ricerca" -#: ../js/ui/dash.js:830 +#: ../js/ui/dash.js:792 msgid "PREFERENCES" msgstr "Preferenze" #. Button on the left side of the panel. #. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview". -#: ../js/ui/panel.js:272 +#: ../js/ui/panel.js:274 msgid "Activities" msgstr "Attività" # (ndt) proviamo col k, se non funge, sappiamo il perché... #. Translators: This is a time format. -#: ../js/ui/panel.js:464 +#: ../js/ui/panel.js:491 msgid "%a %l:%M %p" msgstr "%a %k.%M" @@ -104,44 +108,44 @@ msgid "Execution of '%s' failed:" msgstr "Esecuzione di «%s» non riuscita:" #. Translators: This is a time format. -#: ../js/ui/widget.js:162 +#: ../js/ui/widget.js:163 msgid "%H:%M" msgstr "%k.%M" -#: ../js/ui/widget.js:316 +#: ../js/ui/widget.js:317 msgid "Applications" msgstr "Applicazioni" -#: ../js/ui/widget.js:341 +#: ../js/ui/widget.js:339 msgid "Recent Documents" msgstr "Documenti recenti" -#: ../src/shell-global.c:812 +#: ../src/shell-global.c:821 msgid "Less than a minute ago" msgstr "Meno di un minuto fa" -#: ../src/shell-global.c:815 +#: ../src/shell-global.c:824 #, c-format msgid "%d minute ago" msgid_plural "%d minutes ago" msgstr[0] "%d minuto fa" msgstr[1] "%d minuti fa" -#: ../src/shell-global.c:818 +#: ../src/shell-global.c:827 #, c-format msgid "%d hour ago" msgid_plural "%d hours ago" msgstr[0] "%d ora fa" msgstr[1] "%d ore fa" -#: ../src/shell-global.c:821 +#: ../src/shell-global.c:830 #, c-format msgid "%d day ago" msgid_plural "%d days ago" msgstr[0] "%d giorno fa" msgstr[1] "%d giorni fa" -#: ../src/shell-global.c:824 +#: ../src/shell-global.c:833 #, c-format msgid "%d week ago" msgid_plural "%d weeks ago" @@ -225,18 +229,3 @@ msgstr "Cerca" #, c-format msgid "%1$s: %2$s" msgstr "%1$s: %2$s" - -#~ msgid "Browse" -#~ msgstr "Esplora" - -# (ndt) è da valutare se è troppo lunga, è in una casella di ricerca -#~ msgid "Find apps or documents" -#~ msgstr "Trova programmi e documenti" - -# (ndt) no idea... -#~ msgid "Manager" -#~ msgstr "Manager" - -# (ndt) no idea... -#~ msgid "The user manager object this user is controlled by." -#~ msgstr "L'oggetto user manager che controlla questo utente." From 930a0b52f3dcd3c6e024e1e295499f66ac5204a9 Mon Sep 17 00:00:00 2001 From: Timo Jyrinki Date: Wed, 4 Nov 2009 11:17:20 +0200 Subject: [PATCH 02/51] Added Finnish translation. --- po/fi.po | 226 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 po/fi.po diff --git a/po/fi.po b/po/fi.po new file mode 100644 index 000000000..9fb695280 --- /dev/null +++ b/po/fi.po @@ -0,0 +1,226 @@ +# gnome-shell Finnish translation +# Copyright (C) 2009 Timo Jyrinki +# This file is distributed under the same license as the gnome-shell package. +# Timo Jyrinki , 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: gnome-shell\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-11-04 11:16+0200\n" +"PO-Revision-Date: 2009-11-04 11:16+0200\n" +"Last-Translator: Timo Jyrinki \n" +"Language-Team: Finnish \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: ../data/gnome-shell.desktop.in.in.h:1 +msgid "GNOME Shell" +msgstr "" + +#: ../data/gnome-shell.desktop.in.in.h:2 +msgid "Window management and application launching" +msgstr "Ikkunanhallinta ja sovelluksien käynnistäminen" + +#: ../js/ui/appDisplay.js:332 +msgid "Frequent" +msgstr "Usein käytetyt" + +#: ../js/ui/appDisplay.js:867 +msgid "Drag here to add favorites" +msgstr "Raahaa tähän lisätäksesi suosikkeihin" + +#: ../js/ui/appIcon.js:426 +msgid "New Window" +msgstr "Uusi ikkuna" + +#: ../js/ui/appIcon.js:430 +msgid "Remove from Favorites" +msgstr "Poista suosikeista" + +#: ../js/ui/appIcon.js:431 +msgid "Add to Favorites" +msgstr "Lisää suosikkeihin" + +#: ../js/ui/dash.js:283 +msgid "Find..." +msgstr "Etsi..." + +#: ../js/ui/dash.js:400 +msgid "More" +msgstr "Lisää" + +#: ../js/ui/dash.js:543 +msgid "(see all)" +msgstr "(näytä kaikki)" + +#. **** Applications **** +#: ../js/ui/dash.js:725 ../js/ui/dash.js:787 +msgid "APPLICATIONS" +msgstr "SOVELLUKSET" + +#. **** Places **** +#. Translators: This is in the sense of locations for documents, +#. network locations, etc. +#: ../js/ui/dash.js:745 +msgid "PLACES" +msgstr "SIJAINNIT" + +#. **** Documents **** +#: ../js/ui/dash.js:752 ../js/ui/dash.js:797 +msgid "RECENT DOCUMENTS" +msgstr "VIIMEISIMMÄT ASIAKIRJAT" + +#. **** Search Results **** +#: ../js/ui/dash.js:777 ../js/ui/dash.js:961 +msgid "SEARCH RESULTS" +msgstr "HAKUTULOKSET" + +#: ../js/ui/dash.js:792 +msgid "PREFERENCES" +msgstr "ASETUKSET" + +#. Button on the left side of the panel. +#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview". +#: ../js/ui/panel.js:274 +msgid "Activities" +msgstr "Toiminnot" + +#. Translators: This is a time format. +#: ../js/ui/panel.js:491 +msgid "%a %l:%M %p" +msgstr "%a %I.%M" + +#: ../js/ui/places.js:178 +msgid "Connect to..." +msgstr "Yhdistä..." + +#: ../js/ui/runDialog.js:96 +msgid "Please enter a command:" +msgstr "Syötä komento:" + +#: ../js/ui/runDialog.js:173 +#, c-format +msgid "Execution of '%s' failed:" +msgstr "" + +#. Translators: This is a time format. +#: ../js/ui/widget.js:163 +msgid "%H:%M" +msgstr "%I.%M" + +#: ../js/ui/widget.js:317 +msgid "Applications" +msgstr "Sovellukset" + +#: ../js/ui/widget.js:339 +msgid "Recent Documents" +msgstr "Viimeisimmät asiakirjat" + +#: ../src/shell-global.c:821 +msgid "Less than a minute ago" +msgstr "Alle minuutti sitten" + +#: ../src/shell-global.c:824 +#, c-format +msgid "%d minute ago" +msgid_plural "%d minutes ago" +msgstr[0] "%d minuutti sitten" +msgstr[1] "%d minuuttia sitten" + +#: ../src/shell-global.c:827 +#, c-format +msgid "%d hour ago" +msgid_plural "%d hours ago" +msgstr[0] "%d tunti sitten" +msgstr[1] "%d tuntia sitten" + +#: ../src/shell-global.c:830 +#, c-format +msgid "%d day ago" +msgid_plural "%d days ago" +msgstr[0] "%d päivä sitten" +msgstr[1] "%d päivää sitten" + +#: ../src/shell-global.c:833 +#, c-format +msgid "%d week ago" +msgid_plural "%d weeks ago" +msgstr[0] "%d viikko sitten" +msgstr[1] "%d viikkoa sitten" + +#: ../src/shell-status-menu.c:156 +msgid "Unknown" +msgstr "Tuntematon" + +#: ../src/shell-status-menu.c:212 +#, c-format +msgid "Can't lock screen: %s" +msgstr "Näyttöä ei voi lukita: %s" + +#: ../src/shell-status-menu.c:227 +#, c-format +msgid "Can't temporarily set screensaver to blank screen: %s" +msgstr "" + +#: ../src/shell-status-menu.c:351 +#, c-format +msgid "Can't logout: %s" +msgstr "" + +#: ../src/shell-status-menu.c:492 +msgid "Account Information..." +msgstr "Käyttäjätilin tiedot..." + +#: ../src/shell-status-menu.c:502 +msgid "Sidebar" +msgstr "Sivupalkki" + +#: ../src/shell-status-menu.c:510 +msgid "System Preferences..." +msgstr "Järjestelmän asetukset" + +#: ../src/shell-status-menu.c:525 +msgid "Lock Screen" +msgstr "Lukitse näyttö" + +#: ../src/shell-status-menu.c:535 +msgid "Switch User" +msgstr "Vaihda käyttäjää" + +#. Only show switch user if there are other users +#. Log Out +#: ../src/shell-status-menu.c:546 +msgid "Log Out..." +msgstr "Kirjaudu ulos..." + +#. Shut down +#: ../src/shell-status-menu.c:557 +msgid "Shut Down..." +msgstr "Sammuta..." + +#: ../src/shell-uri-util.c:87 +msgid "Home Folder" +msgstr "Kotikansio" + +#. Translators: this is the same string as the one found in +#. * nautilus +#: ../src/shell-uri-util.c:102 +msgid "File System" +msgstr "Tiedostojärjestelmä" + +#: ../src/shell-uri-util.c:248 +msgid "Search" +msgstr "Haku" + +#. Translators: the first string is the name of a gvfs +#. * method, and the second string is a path. For +#. * example, "Trash: some-directory". It means that the +#. * directory called "some-directory" is in the trash. +#. +#: ../src/shell-uri-util.c:298 +#, c-format +msgid "%1$s: %2$s" +msgstr "%1$s: %2$s" From dc232d4631b9d31200c89013625f1015a3b6e546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steve=20Fr=C3=A9cinaux?= Date: Wed, 14 Oct 2009 11:45:57 +0200 Subject: [PATCH 03/51] [AppSwitcher] Add a separator between windows in current and other workspaces. This make it is easier for the user to figure out on which workspace the windows are. For instance, terminals related to various activities and put on different workspaces were previously displayed as an uniform list, with no visible distinction between the ones from the current workspace and the others. Now they are physically separated by a thin gray line. This is also consistent with the way applications are displayed in the AppSwitcher. https://bugzilla.gnome.org/show_bug.cgi?id=597944 --- js/ui/altTab.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/js/ui/altTab.js b/js/ui/altTab.js index da4c99641..a1a5f1612 100644 --- a/js/ui/altTab.js +++ b/js/ui/altTab.js @@ -724,7 +724,19 @@ ThumbnailList.prototype = { _init : function(windows) { SwitcherList.prototype._init.call(this); + let activeWorkspace = global.screen.get_active_workspace(); + + // We fake the value of "separatorAdded" when the app has no window + // on the current workspace, to avoid displaying a useless separator in + // that case. + let separatorAdded = windows.length == 0 || windows[0].get_workspace() != activeWorkspace; + for (let i = 0; i < windows.length; i++) { + if (!separatorAdded && windows[i].get_workspace() != activeWorkspace) { + this.addSeparator(); + separatorAdded = true; + } + let mutterWindow = windows[i].get_compositor_private(); let windowTexture = mutterWindow.get_texture (); let [width, height] = windowTexture.get_size(); From f54926993431691d81fc2a43807e35d96e10fecb Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 23 Oct 2009 10:18:35 -0400 Subject: [PATCH 04/51] [StBoxLayout] Implement raise and lower Code copied from ClutterGroup. https://bugzilla.gnome.org/show_bug.cgi?id=599442 --- src/st/st-box-layout.c | 95 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 4 deletions(-) diff --git a/src/st/st-box-layout.c b/src/st/st-box-layout.c index 180d893c4..12b15081a 100644 --- a/src/st/st-box-layout.c +++ b/src/st/st-box-layout.c @@ -21,6 +21,20 @@ * */ +/* Portions copied from Clutter: + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + */ + /** * SECTION:st-box-layout * @short_description: a layout container arranging children in a single line @@ -294,8 +308,42 @@ st_box_container_lower (ClutterContainer *container, ClutterActor *actor, ClutterActor *sibling) { - /* XXX: not yet implemented */ - g_warning ("%s() not yet implemented", __FUNCTION__); + StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (container)->priv; + + /* copied from clutter/clutter/clutter-group.c */ + + priv->children = g_list_remove (priv->children, actor); + + /* Push to bottom */ + if (!sibling) + { + GList *last_item; + + last_item = g_list_first (priv->children); + + if (last_item) + sibling = last_item->data; + + priv->children = g_list_prepend (priv->children, actor); + } + else + { + gint pos; + + pos = g_list_index (priv->children, sibling); + + priv->children = g_list_insert (priv->children, actor, pos); + } + + /* See comment in group_raise for this */ + if (sibling && + clutter_actor_get_depth (sibling) != clutter_actor_get_depth (actor)) + { + clutter_actor_set_depth (actor, clutter_actor_get_depth (sibling)); + } + + if (CLUTTER_ACTOR_IS_VISIBLE (container)) + clutter_actor_queue_redraw (CLUTTER_ACTOR (container)); } static void @@ -303,8 +351,47 @@ st_box_container_raise (ClutterContainer *container, ClutterActor *actor, ClutterActor *sibling) { - /* XXX: not yet implemented */ - g_warning ("%s() not yet implemented", __FUNCTION__); + StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (container)->priv; + + priv->children = g_list_remove (priv->children, actor); + + /* copied from clutter/clutter/clutter-group.c */ + + /* Raise at the top */ + if (!sibling) + { + GList *last_item; + + last_item = g_list_last (priv->children); + + if (last_item) + sibling = last_item->data; + + priv->children = g_list_append (priv->children, actor); + } + else + { + gint pos; + + pos = g_list_index (priv->children, sibling) + 1; + + priv->children = g_list_insert (priv->children, actor, pos); + } + + /* set Z ordering a value below, this will then call sort + * as values are equal ordering shouldn't change but Z + * values will be correct. + * + * FIXME: optimise + */ + if (sibling && + clutter_actor_get_depth (sibling) != clutter_actor_get_depth (actor)) + { + clutter_actor_set_depth (actor, clutter_actor_get_depth (sibling)); + } + + if (CLUTTER_ACTOR_IS_VISIBLE (container)) + clutter_actor_queue_redraw (CLUTTER_ACTOR (container)); } static void From b8d9319c3269b2725de411403c3ef59c95a47f7b Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 23 Oct 2009 15:14:41 -0400 Subject: [PATCH 05/51] Add missing allow-none for st_bin_set_child https://bugzilla.gnome.org/show_bug.cgi?id=599442 --- src/st/st-bin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/st/st-bin.c b/src/st/st-bin.c index 4c862b62a..48347b6ba 100644 --- a/src/st/st-bin.c +++ b/src/st/st-bin.c @@ -545,7 +545,7 @@ st_bin_new (void) /** * st_bin_set_child: * @bin: a #StBin - * @child: a #ClutterActor, or %NULL + * @child: (allow-none): a #ClutterActor, or %NULL * * Sets @child as the child of @bin. * From 37a948e4eb3c2b8f012550b5f2d93c5a8b7cd2a4 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 23 Oct 2009 15:40:09 -0400 Subject: [PATCH 06/51] Add missing allow-none for set_style_pseudo_class https://bugzilla.gnome.org/show_bug.cgi?id=599442 --- src/st/st-widget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/st/st-widget.c b/src/st/st-widget.c index 2570ac62c..c2488ecb1 100644 --- a/src/st/st-widget.c +++ b/src/st/st-widget.c @@ -1052,7 +1052,7 @@ st_widget_get_style_pseudo_class (StWidget *actor) /** * st_widget_set_style_pseudo_class: * @actor: a #StWidget - * @pseudo_class: a new pseudo class string + * @pseudo_class: (allow-none): a new pseudo class string * * Set the style pseudo class */ From e2e513ff08a7cfd97b0297a02939a4c7abbff7a7 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 28 Oct 2009 12:52:08 -0400 Subject: [PATCH 07/51] Remove (out) "caller-allocates" annotations GObject Introspection+gjs doesn't presently support (out) for caller-allocates scenarios. https://bugzilla.gnome.org/show_bug.cgi?id=599442 --- src/st/st-theme-node.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/st/st-theme-node.c b/src/st/st-theme-node.c index e81e35ac5..0aba8b6d5 100644 --- a/src/st/st-theme-node.c +++ b/src/st/st-theme-node.c @@ -457,7 +457,7 @@ get_color_from_term (StThemeNode *node, * parent's parent, and so forth. Note that if the property has a * value of 'inherit' it will be inherited even if %FALSE is passed * in for @inherit; this only affects the default behavior for inheritance. - * @color: (out): location to store the color that was determined. + * @color: location to store the color that was determined. * If the property is not found, the value in this location * will not be changed. * @@ -513,7 +513,7 @@ st_theme_node_get_color (StThemeNode *node, * parent's parent, and so forth. Note that if the property has a * value of 'inherit' it will be inherited even if %FALSE is passed * in for @inherit; this only affects the default behavior for inheritance. - * @value: (out): location to store the value that was determined. + * @value: location to store the value that was determined. * If the property is not found, the value in this location * will not be changed. * @@ -740,7 +740,7 @@ get_length_internal (StThemeNode *node, * parent's parent, and so forth. Note that if the property has a * value of 'inherit' it will be inherited even if %FALSE is passed * in for @inherit; this only affects the default behavior for inheritance. - * @length: (out): location to store the length that was determined. + * @length: location to store the length that was determined. * If the property is not found, the value in this location * will not be changed. The returned length is resolved * to pixels. @@ -2199,7 +2199,7 @@ st_theme_node_adjust_preferred_height (StThemeNode *node, * st_theme_node_get_content_box: * @node: a #StThemeNode * @allocation: the box allocated to a #ClutterAlctor - * @content_box: (out): computed box occupied by the actor's content + * @content_box: computed box occupied by the actor's content * * Gets the box within an actor's allocation that contents the content * of an actor (excluding borders and padding). This is a convenience function From 4f456b968959669ce299ffcb6deee47cd0dda00d Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 28 Oct 2009 12:53:26 -0400 Subject: [PATCH 08/51] Implement non-uniform borders (when not using corner_radius) StTheme CSS supports different border widths for different sides. Implement it for StWidget by drawing the border internally. However, we don't support a nonzero corner-radius with nonuniform borders. https://bugzilla.gnome.org/show_bug.cgi?id=599442 --- src/st/st-widget.c | 178 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 138 insertions(+), 40 deletions(-) diff --git a/src/st/st-widget.c b/src/st/st-widget.c index c2488ecb1..d606497d5 100644 --- a/src/st/st-widget.c +++ b/src/st/st-widget.c @@ -63,6 +63,7 @@ struct _StWidgetPrivate gboolean has_tooltip : 1; gboolean is_style_dirty : 1; gboolean draw_bg_color : 1; + gboolean draw_border_internal : 1; StTooltip *tooltip; }; @@ -356,25 +357,25 @@ static void st_widget_real_draw_background (StWidget *self) { StWidgetPrivate *priv = self->priv; + ClutterActor *actor = CLUTTER_ACTOR (self); + ClutterActorBox allocation = { 0, }; + gfloat w, h; + guint8 opacity; + + clutter_actor_get_allocation_box (actor, &allocation); + w = allocation.x2 - allocation.x1; + h = allocation.y2 - allocation.y1; + + opacity = clutter_actor_get_paint_opacity (actor); /* Default implementation just draws the background * colour and the image on top */ if (priv->draw_bg_color) { - ClutterActor *actor = CLUTTER_ACTOR (self); - ClutterActorBox allocation = { 0, }; ClutterColor bg_color = priv->bg_color; - gfloat w, h; - bg_color.alpha = clutter_actor_get_paint_opacity (actor) - * bg_color.alpha - / 255; - - clutter_actor_get_allocation_box (actor, &allocation); - - w = allocation.x2 - allocation.x1; - h = allocation.y2 - allocation.y1; + bg_color.alpha = opacity * bg_color.alpha / 255; cogl_set_source_color4ub (bg_color.red, bg_color.green, @@ -383,6 +384,76 @@ st_widget_real_draw_background (StWidget *self) cogl_rectangle (0, 0, w, h); } + if (priv->draw_border_internal) + { + StThemeNode *node = st_widget_get_theme_node (self); + int side; + double border_top, border_right, border_bottom, border_left; + + border_top = st_theme_node_get_border_width (node, ST_SIDE_TOP); + border_right = st_theme_node_get_border_width (node, ST_SIDE_RIGHT); + border_bottom = st_theme_node_get_border_width (node, ST_SIDE_BOTTOM); + border_left = st_theme_node_get_border_width (node, ST_SIDE_LEFT); + + for (side = 0; side < 4; side++) + { + ClutterColor color; + + switch (side) + { + case ST_SIDE_TOP: + if (border_top <= 0) + continue; + break; + case ST_SIDE_RIGHT: + if (border_right <= 0) + continue; + break; + case ST_SIDE_BOTTOM: + if (border_bottom <= 0) + continue; + break; + case ST_SIDE_LEFT: + if (border_left <= 0) + continue; + break; + } + + st_theme_node_get_border_color (node, side, &color); + + color.alpha = (color.alpha * opacity) / 0xff; + + cogl_set_source_color4ub (color.red, + color.green, + color.blue, + color.alpha); + + /* Note top and bottom extend to the ends, left/right + * are constrained by them. See comment above about CSS + * conformance. + */ + switch (side) + { + case ST_SIDE_TOP: + cogl_rectangle (0, 0, + w, border_top); + break; + case ST_SIDE_RIGHT: + cogl_rectangle (w - border_right, border_top, + w, h - border_bottom); + break; + case ST_SIDE_BOTTOM: + cogl_rectangle (0, h - border_bottom, + w, h); + break; + case ST_SIDE_LEFT: + cogl_rectangle (0, border_top, + border_left, h - border_bottom); + break; + } + } + } + if (priv->border_image) clutter_actor_paint (priv->border_image); } @@ -491,6 +562,7 @@ st_widget_real_style_changed (StWidget *self) ClutterColor border_color = { 0, }; StSide side; StCorner corner; + gboolean uniform_border_width; /* application has request this widget is not stylable */ if (!priv->is_stylable) @@ -520,33 +592,6 @@ st_widget_real_style_changed (StWidget *self) texture_cache = st_texture_cache_get_default (); - /* StThemeNode supports different widths and colors for different sides - * of the border, and different radii for the different corners. We take - * the different border widths into account when positioning, but our current - * drawing code (using BigRectangle) can only handle a single width, color, - * and radius, so we arbitrarily pick the first non-zero width and radius, - * and use that. - */ - for (side = ST_SIDE_TOP; side <= ST_SIDE_LEFT; side++) - { - double width = st_theme_node_get_border_width (theme_node, side); - if (width > 0.5) - { - border_width = (int)(0.5 + width); - st_theme_node_get_border_color (theme_node, side, &border_color); - break; - } - } - - for (corner = ST_CORNER_TOPLEFT; corner <= ST_CORNER_BOTTOMLEFT; corner++) - { - double radius = st_theme_node_get_border_radius (theme_node, corner); - if (radius > 0.5) - { - border_radius = (int)(0.5 + radius); - break; - } - } /* Rough notes about the relationship of borders and backgrounds in CSS3; * see http://www.w3.org/TR/css3-background/ for more accurate details. @@ -565,6 +610,8 @@ st_widget_real_style_changed (StWidget *self) * zero width or a border image is being used. * * Deviations from the above as implemented here: + * - Nonuniform border widths combined with a non-zero border radius result + * in the border radius being ignored * - The combination of border image and a non-zero border radius is * not supported; the background color will be drawn with square * corners. @@ -576,6 +623,44 @@ st_widget_real_style_changed (StWidget *self) * and a single background image above it. */ + /* Check whether all border widths are the same. Also, acquire the + * first nonzero border width as well as the border color. + */ + uniform_border_width = TRUE; + border_width = st_theme_node_get_border_width (theme_node, ST_SIDE_TOP); + if (border_width > 0.5) + border_width = (int)(0.5 + border_width); + for (side = 0; side < 4; side++) + { + double width = st_theme_node_get_border_width (theme_node, side); + if (width > 0.5) + width = (int)(0.5 + width); + if (width > 0) + { + border_width = width; + st_theme_node_get_border_color (theme_node, side, &border_color); + } + if ((int)width != border_width) + { + uniform_border_width = FALSE; + break; + } + } + + /* Pick the first nonzero border radius, but only if we have a uniform border. */ + if (uniform_border_width) + { + for (corner = 0; corner < 4; corner++) + { + double radius = st_theme_node_get_border_radius (theme_node, corner); + if (radius > 0.5) + { + border_radius = (int)(0.5 + radius); + break; + } + } + } + border_image = st_theme_node_get_border_image (theme_node); if (border_image) { @@ -607,9 +692,9 @@ st_widget_real_style_changed (StWidget *self) has_changed = TRUE; relayout_needed = TRUE; } - else if ((border_width > 0 && border_color.alpha != 0) || - (border_radius > 0 && priv->bg_color.alpha != 0)) + else if (border_radius > 0) { + priv->draw_border_internal = FALSE; priv->draw_bg_color = FALSE; priv->border_image = g_object_new (BIG_TYPE_RECTANGLE, "color", &priv->bg_color, @@ -623,6 +708,19 @@ st_widget_real_style_changed (StWidget *self) has_changed = TRUE; relayout_needed = TRUE; } + else if (border_width > 0 && border_color.alpha != 0) + { + priv->draw_bg_color = TRUE; + priv->draw_border_internal = TRUE; + has_changed = TRUE; + relayout_needed = TRUE; + } + else if (priv->draw_border_internal) + { + priv->draw_border_internal = FALSE; + has_changed = TRUE; + relayout_needed = TRUE; + } bg_file = st_theme_node_get_background_image (theme_node); if (bg_file != NULL) From 626f679947298a99c761a171f092cb0990146856 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 22 Oct 2009 13:33:09 -0400 Subject: [PATCH 09/51] Port Dash section headers to CSS https://bugzilla.gnome.org/show_bug.cgi?id=599442 --- data/theme/gnome-shell.css | 46 +++++++++++- js/ui/dash.js | 140 +++++++++++++++++-------------------- 2 files changed, 108 insertions(+), 78 deletions(-) diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index 3e89954f7..4ef0e1d4e 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -74,6 +74,50 @@ StScrollBar StButton#vhandle:hover background-color: #314a6c; } +/* Dash */ + +#dash { + color: #5f5f5f; + background-color: rgba(0,0,0,0.75); + padding: 0px 14px; +} + +#searchEntry { + padding: 4px; + border-bottom: 1px solid #262626; +} + +#searchEntry:active { + background-color: #c4c4c4; +} + +.section-header { + border: 1px solid #262626; + -shell-gradient-top: #161616; + -shell-gradient-bottom: #000000; + font-weight: bold; + font-size: 12px; +} + +.section-header-inner { + border: 1px solid #000000; + padding: 0px 4px; +} + +.section-text-content { + padding: 4px 0px; +} + +.section-count { +} + +.more-link { + border-left: 1px solid #262626; + padding: 0px 0px 0px 4px; + color: #ffffff; + font-weight: normal; +} + /* LookingGlass */ #LookingGlassDialog @@ -192,4 +236,4 @@ StScrollBar StButton#vhandle:hover .switcher-list .separator { width: 1px; background: rgba(255,255,255,0.33); -} \ No newline at end of file +} diff --git a/js/ui/dash.js b/js/ui/dash.js index 2f367753a..5c05340cd 100644 --- a/js/ui/dash.js +++ b/js/ui/dash.js @@ -8,6 +8,7 @@ const Pango = imports.gi.Pango; const Shell = imports.gi.Shell; const Signals = imports.signals; const Lang = imports.lang; +const St = imports.gi.St; const Gettext = imports.gettext.domain('gnome-shell'); const _ = Gettext.gettext; @@ -22,8 +23,6 @@ const DEFAULT_PADDING = 4; const DEFAULT_SPACING = 4; const DASH_SECTION_PADDING = 6; const DASH_SECTION_SPACING = 40; -const DASH_CORNER_RADIUS = 5; -const DASH_PADDING_SIDE = 14; const BACKGROUND_COLOR = new Clutter.Color(); BACKGROUND_COLOR.from_pixel(0x000000c0); @@ -43,21 +42,9 @@ SEARCH_TEXT_COLOR.from_pixel(0x333333ff); const SEARCH_CURSOR_COLOR = BRIGHT_TEXT_COLOR; const HIGHLIGHTED_SEARCH_CURSOR_COLOR = SEARCH_TEXT_COLOR; -const HIGHLIGHTED_SEARCH_BACKGROUND_COLOR = new Clutter.Color(); -HIGHLIGHTED_SEARCH_BACKGROUND_COLOR.from_pixel(0xc4c4c4ff); - const SEARCH_BORDER_BOTTOM_COLOR = new Clutter.Color(); SEARCH_BORDER_BOTTOM_COLOR.from_pixel(0x191919ff); -const SECTION_BORDER_COLOR = new Clutter.Color(); -SECTION_BORDER_COLOR.from_pixel(0x262626ff); -const SECTION_BORDER = 1; -const SECTION_INNER_BORDER_COLOR = new Clutter.Color(); -SECTION_INNER_BORDER_COLOR.from_pixel(0x000000ff); -const SECTION_BACKGROUND_TOP_COLOR = new Clutter.Color(); -SECTION_BACKGROUND_TOP_COLOR.from_pixel(0x161616ff); -const SECTION_BACKGROUND_BOTTOM_COLOR = new Clutter.Color(); -SECTION_BACKGROUND_BOTTOM_COLOR.from_pixel(0x000000ff); const SECTION_INNER_SPACING = 8; const BROWSE_ACTIVATED_BG = new Clutter.Color(); @@ -265,14 +252,11 @@ function SearchEntry() { SearchEntry.prototype = { _init : function() { - this.actor = new Big.Box({ padding: DEFAULT_PADDING, - border_bottom: SECTION_BORDER, - border_color: SEARCH_BORDER_BOTTOM_COLOR, - corner_radius: DASH_CORNER_RADIUS, - reactive: true }); + this.actor = new St.BoxLayout({ name: "searchEntry", + reactive: true }); let box = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, y_align: Big.BoxAlignment.CENTER }); - this.actor.append(box, Big.BoxPackFlags.EXPAND); + this.actor.add(box, { expand: true }); this.actor.connect('button-press-event', Lang.bind(this, function () { this._resetTextState(true); return false; @@ -361,12 +345,12 @@ SearchEntry.prototype = { if (!searchEntryClicked) this._defaultText.hide(); this._iconBox.append(this._closeIcon, Big.BoxPackFlags.NONE); - this.actor.background_color = HIGHLIGHTED_SEARCH_BACKGROUND_COLOR; + this.actor.set_style_pseudo_class('active'); this.entry.cursor_color = HIGHLIGHTED_SEARCH_CURSOR_COLOR; } else { this._defaultText.show(); this._iconBox.append(this._magnifierIcon, Big.BoxPackFlags.NONE); - this.actor.background_color = BACKGROUND_COLOR; + this.actor.set_style_pseudo_class(null); this.entry.cursor_color = SEARCH_CURSOR_COLOR; } }, @@ -385,20 +369,12 @@ function MoreLink() { MoreLink.prototype = { _init : function () { - this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, - padding_right: DEFAULT_PADDING, - padding_left: DEFAULT_PADDING, - reactive: true, - x_align: Big.BoxAlignment.CENTER, - y_align: Big.BoxAlignment.CENTER, - border_left: SECTION_BORDER, - border_color: SECTION_BORDER_COLOR }); + this.actor = new St.BoxLayout({ style_class: "more-link", + reactive: true }); this.pane = null; - let text = new Clutter.Text({ font_name: "Sans 12px", - color: BRIGHT_TEXT_COLOR, - text: _("More") }); - this.actor.append(text, Big.BoxPackFlags.NONE); + let text = new St.Label({ text: _("More") }); + this.actor.add(text, { expand: true, y_fill: false }); this.actor.connect('button-press-event', Lang.bind(this, function (b, e) { if (this.pane == null) { @@ -449,52 +425,65 @@ function SectionHeader(title, suppressBrowse) { SectionHeader.prototype = { _init : function (title, suppressBrowse) { - this.actor = new Big.Box({ border: SECTION_BORDER, - border_color: SECTION_BORDER_COLOR }); - this._innerBox = new Big.Box({ border: SECTION_BORDER, - border_color: SECTION_INNER_BORDER_COLOR, - padding_left: DEFAULT_PADDING, - padding_right: DEFAULT_PADDING, - orientation: Big.BoxOrientation.HORIZONTAL, - spacing: DEFAULT_SPACING }); - this.actor.append(this._innerBox, Big.BoxPackFlags.EXPAND); - let backgroundGradient = Shell.create_vertical_gradient(SECTION_BACKGROUND_TOP_COLOR, - SECTION_BACKGROUND_BOTTOM_COLOR); - this._innerBox.add_actor(backgroundGradient); - this._innerBox.connect('notify::allocation', Lang.bind(this, function (actor) { - let [width, height] = actor.get_size(); - backgroundGradient.set_size(width, height); + this.actor = new St.Bin({ style_class: "section-header", + x_align: St.Align.START, + x_fill: true, + y_fill: true }); + this._innerBox = new St.BoxLayout({ style_class: "section-header-inner" }); + this.actor.set_child(this._innerBox); + + this._backgroundGradient = null; + this.actor.connect('style-changed', Lang.bind(this, this._onStyleChanged)); + this.actor.connect('notify::allocation', Lang.bind(this, function (actor) { + if (!this._backgroundGradient) + return; + this._onStyleChanged(); })); - this.backLink = new BackLink(); - this._innerBox.append(this.backLink.actor, Big.BoxPackFlags.NONE); - this.backLink.actor.hide(); + let textBox = new St.BoxLayout({ style_class: "section-text-content" }); + this.text = new St.Label({ style_class: "section-title", + text: title }); + textBox.add(this.text, { x_align: St.Align.START }); - this.backLink.actor.connect('activate', Lang.bind(this, function (actor) { - this.emit('back-link-activated'); - })); - - let textBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, - padding_top: DEFAULT_PADDING, - padding_bottom: DEFAULT_PADDING }); - this.text = new Clutter.Text({ color: TEXT_COLOR, - font_name: "Sans Bold 12px", - text: title }); - textBox.append(this.text, Big.BoxPackFlags.NONE); - - this.countText = new Clutter.Text({ color: TEXT_COLOR, - font_name: 'Sans Bold 14px' }); - textBox.append(this.countText, Big.BoxPackFlags.END); + this.countText = new St.Label({ style_class: "section-count" }); + textBox.add(this.countText, { x_align: St.Align.END }); this.countText.hide(); - this._innerBox.append(textBox, Big.BoxPackFlags.EXPAND); + this._innerBox.add(textBox, { expand: true }); if (!suppressBrowse) { this.moreLink = new MoreLink(); - this._innerBox.append(this.moreLink.actor, Big.BoxPackFlags.END); + this._innerBox.add(this.moreLink.actor, { x_align: St.Align.END }); } }, + _onStyleChanged: function () { + if (this._backgroundGradient) { + this._backgroundGradient.destroy(); + } + // Manually implement the gradient + let themeNode = this.actor.get_theme_node(); + let gradientTopColor = new Clutter.Color(); + if (!themeNode.get_color("-shell-gradient-top", false, gradientTopColor)) + return; + let gradientBottomColor = new Clutter.Color(); + if (!themeNode.get_color("-shell-gradient-bottom", false, gradientBottomColor)) + return; + this._backgroundGradient = Shell.create_vertical_gradient(gradientTopColor, + gradientBottomColor); + let box = this.actor.allocation; + let contentBox = new Clutter.ActorBox(); + themeNode.get_content_box(box, contentBox); + let width = contentBox.x2 - contentBox.x1; + let height = contentBox.y2 - contentBox.y1; + this._backgroundGradient.set_size(width, height); + // This will set a fixed position, which puts us outside of the normal box layout + this._backgroundGradient.set_position(0, 0); + + this._innerBox.add_actor(this._backgroundGradient); + this._backgroundGradient.lower_bottom(); + }, + setTitle : function(title) { this.text.text = title; }, @@ -598,12 +587,9 @@ Dash.prototype = { // of the Group actor ends up including the width of its hidden children, so we were getting a reactive object as // wide as the details pane that was blocking the clicks to the workspaces underneath it even when the details pane // was actually hidden. - this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, - background_color: BACKGROUND_COLOR, - corner_radius: DASH_CORNER_RADIUS, - padding_left: DASH_PADDING_SIDE, - padding_right: DASH_PADDING_SIDE, - reactive: true }); + this.actor = new St.BoxLayout({ name: "dash", + vertical: true, + reactive: true }); // Size for this one explicitly set from overlay.js this.searchArea = new Big.Box({ y_align: Big.BoxAlignment.CENTER }); @@ -611,8 +597,8 @@ Dash.prototype = { this.sectionArea = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, spacing: DASH_SECTION_SPACING }); - this.actor.append(this.searchArea, Big.BoxPackFlags.NONE); - this.actor.append(this.sectionArea, Big.BoxPackFlags.NONE); + this.actor.add(this.searchArea); + this.actor.add(this.sectionArea); // The currently active popup display this._activePane = null; From 869e744670e0f8f02799d590f0dd1a8ec2ca1570 Mon Sep 17 00:00:00 2001 From: Petr Kovar Date: Thu, 5 Nov 2009 18:04:36 +0100 Subject: [PATCH 10/51] Updated Czech translation --- po/cs.po | 52 ++++++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/po/cs.po b/po/cs.po index d5b59f74a..76cd5e5a4 100644 --- a/po/cs.po +++ b/po/cs.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: gnome-shell\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-10-10 19:02+0200\n" -"PO-Revision-Date: 2009-10-10 19:02+0200\n" +"POT-Creation-Date: 2009-11-05 18:03+0100\n" +"PO-Revision-Date: 2009-11-05 18:03+0100\n" "Last-Translator: Petr Kovar \n" "Language-Team: Czech \n" "MIME-Version: 1.0\n" @@ -25,68 +25,72 @@ msgstr "Prostředí GNOME Shell" msgid "Window management and application launching" msgstr "Správa oken a spouštění aplikací" -#: ../js/ui/appDisplay.js:335 +#: ../js/ui/appDisplay.js:332 msgid "Frequent" msgstr "Časté" -#: ../js/ui/appIcon.js:462 +#: ../js/ui/appDisplay.js:867 +msgid "Drag here to add favorites" +msgstr "Oblíbené přidáte přetažením sem" + +#: ../js/ui/appIcon.js:426 msgid "New Window" msgstr "Nové okno" -#: ../js/ui/appIcon.js:475 +#: ../js/ui/appIcon.js:430 msgid "Remove from Favorites" msgstr "Odstranit z oblíbených" -#: ../js/ui/appIcon.js:476 +#: ../js/ui/appIcon.js:431 msgid "Add to Favorites" msgstr "Přidat mezi oblíbené" -#: ../js/ui/dash.js:283 +#: ../js/ui/dash.js:267 msgid "Find..." msgstr "Najít..." -#: ../js/ui/dash.js:400 +#: ../js/ui/dash.js:376 msgid "More" msgstr "Více" -#: ../js/ui/dash.js:543 +#: ../js/ui/dash.js:532 msgid "(see all)" msgstr "(zobrazit vše)" #. **** Applications **** -#: ../js/ui/dash.js:763 ../js/ui/dash.js:825 +#: ../js/ui/dash.js:711 ../js/ui/dash.js:773 msgid "APPLICATIONS" msgstr "APLIKACE" #. **** Places **** #. Translators: This is in the sense of locations for documents, #. network locations, etc. -#: ../js/ui/dash.js:783 +#: ../js/ui/dash.js:731 msgid "PLACES" msgstr "MÍSTA" #. **** Documents **** -#: ../js/ui/dash.js:790 ../js/ui/dash.js:835 +#: ../js/ui/dash.js:738 ../js/ui/dash.js:783 msgid "RECENT DOCUMENTS" msgstr "NEDÁVNÉ DOKUMENTY" #. **** Search Results **** -#: ../js/ui/dash.js:815 ../js/ui/dash.js:955 +#: ../js/ui/dash.js:763 ../js/ui/dash.js:947 msgid "SEARCH RESULTS" msgstr "VÝSLEDKY HLEDÁNÍ" -#: ../js/ui/dash.js:830 +#: ../js/ui/dash.js:778 msgid "PREFERENCES" msgstr "PŘEDVOLBY" #. Button on the left side of the panel. #. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview". -#: ../js/ui/panel.js:272 +#: ../js/ui/panel.js:274 msgid "Activities" msgstr "Činnosti" #. Translators: This is a time format. -#: ../js/ui/panel.js:464 +#: ../js/ui/panel.js:491 msgid "%a %l:%M %p" msgstr "%a, %H:%M" @@ -104,23 +108,23 @@ msgid "Execution of '%s' failed:" msgstr "Vykonání \"%s\" selhalo:" #. Translators: This is a time format. -#: ../js/ui/widget.js:162 +#: ../js/ui/widget.js:163 msgid "%H:%M" msgstr "%H:%M" -#: ../js/ui/widget.js:316 +#: ../js/ui/widget.js:317 msgid "Applications" msgstr "Aplikace" -#: ../js/ui/widget.js:341 +#: ../js/ui/widget.js:339 msgid "Recent Documents" msgstr "Nedávné dokumenty" -#: ../src/shell-global.c:812 +#: ../src/shell-global.c:821 msgid "Less than a minute ago" msgstr "Před méně než minutou" -#: ../src/shell-global.c:815 +#: ../src/shell-global.c:824 #, c-format msgid "%d minute ago" msgid_plural "%d minutes ago" @@ -128,7 +132,7 @@ msgstr[0] "Před %d minutou" msgstr[1] "Před %d minutami" msgstr[2] "Před %d minutami" -#: ../src/shell-global.c:818 +#: ../src/shell-global.c:827 #, c-format msgid "%d hour ago" msgid_plural "%d hours ago" @@ -136,7 +140,7 @@ msgstr[0] "Před %d hodinou" msgstr[1] "Před %d hodinami" msgstr[2] "Před %d hodinami" -#: ../src/shell-global.c:821 +#: ../src/shell-global.c:830 #, c-format msgid "%d day ago" msgid_plural "%d days ago" @@ -144,7 +148,7 @@ msgstr[0] "Před %d dnem" msgstr[1] "Před %d dny" msgstr[2] "Před %d dny" -#: ../src/shell-global.c:824 +#: ../src/shell-global.c:833 #, c-format msgid "%d week ago" msgid_plural "%d weeks ago" From dcd7762253e959638dfcfdabc8881a7b5a9e632f Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 4 Nov 2009 15:48:26 -0500 Subject: [PATCH 11/51] [StThemeNode] Don't give negative width/height for content boxes If the space we're allocated is too small for our border + padding constraints, don't give negative allocations to callers. Squash to zero. It isn't really useful for callers to get negative content sizes, and certainly breaks most allocation code. https://bugzilla.gnome.org/show_bug.cgi?id=600734 --- src/st/st-theme-node.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/st/st-theme-node.c b/src/st/st-theme-node.c index 0aba8b6d5..cebd1afde 100644 --- a/src/st/st-theme-node.c +++ b/src/st/st-theme-node.c @@ -2211,14 +2211,33 @@ st_theme_node_get_content_box (StThemeNode *node, const ClutterActorBox *allocation, ClutterActorBox *content_box) { + double noncontent_left, noncontent_top, noncontent_right, noncontent_bottom; + double avail_width, avail_height, content_width, content_height; + g_return_if_fail (ST_IS_THEME_NODE (node)); ensure_geometry (node); - content_box->x1 = (int)(0.5 + node->border_width[ST_SIDE_LEFT]) + node->padding[ST_SIDE_LEFT]; - content_box->y1 = (int)(0.5 + node->border_width[ST_SIDE_TOP]) + node->padding[ST_SIDE_TOP]; - content_box->x2 = allocation->x2 - allocation->x1 - ((int)(0.5 + node->border_width[ST_SIDE_RIGHT]) + node->padding[ST_SIDE_RIGHT]); - content_box->y2 = allocation->y2 - allocation->y1 - ((int)(0.5 + node->border_width[ST_SIDE_BOTTOM]) + node->padding[ST_SIDE_BOTTOM]); + avail_width = allocation->x2 - allocation->x1; + avail_height = allocation->y2 - allocation->y1; + + noncontent_left = node->border_width[ST_SIDE_LEFT] + node->padding[ST_SIDE_LEFT]; + noncontent_top = node->border_width[ST_SIDE_TOP] + node->padding[ST_SIDE_TOP]; + noncontent_right = node->border_width[ST_SIDE_RIGHT] + node->padding[ST_SIDE_RIGHT]; + noncontent_bottom = node->border_width[ST_SIDE_BOTTOM] + node->padding[ST_SIDE_BOTTOM]; + + content_box->x1 = (int)(0.5 + noncontent_left); + content_box->y1 = (int)(0.5 + noncontent_top); + + content_width = avail_width - noncontent_left - noncontent_right; + if (content_width < 0) + content_width = 0; + content_height = avail_height - noncontent_top - noncontent_bottom; + if (content_height < 0) + content_height = 0; + + content_box->x2 = (int)(0.5 + content_box->x1 + content_width); + content_box->y2 = (int)(0.5 + content_box->y1 + content_height); } From fcac7ac0b349b5a2bcb3e3449d2b30e9f1e0cb06 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 5 Nov 2009 15:39:26 -0500 Subject: [PATCH 12/51] [gnome-shell.css] Remove blue background from scrollbars This makes it slightly less ugly. https://bugzilla.gnome.org/show_bug.cgi?id=600734 --- data/theme/gnome-shell.css | 1 - 1 file changed, 1 deletion(-) diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index 4ef0e1d4e..86ec44b84 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -19,7 +19,6 @@ StScrollBar { - background-color: #354761; padding: 0px; } From 5ee72d807dc72fb3595b71e5a17604ee14b6aa2f Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Sun, 8 Nov 2009 20:56:26 +0200 Subject: [PATCH 13/51] Updated Arabic translation --- po/ar.po | 54 +++++++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/po/ar.po b/po/ar.po index b593e3e3c..06cf8851a 100644 --- a/po/ar.po +++ b/po/ar.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: HEAD\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-10-13 15:24+0200\n" -"PO-Revision-Date: 2009-10-13 15:23+0300\n" +"POT-Creation-Date: 2009-11-08 20:55+0200\n" +"PO-Revision-Date: 2009-11-08 20:55+0300\n" "Last-Translator: Khaled Hosny \n" "Language-Team: Arabic \n" "MIME-Version: 1.0\n" @@ -16,7 +16,7 @@ msgstr "" "Language: ar\n" "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " "&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" -"X-Generator: Virtaal 0.4.0\n" +"X-Generator: Virtaal 0.4.1\n" #: ../data/gnome-shell.desktop.in.in.h:1 msgid "GNOME Shell" @@ -26,68 +26,72 @@ msgstr "صدفة جنوم" msgid "Window management and application launching" msgstr "إدارة النوافذ وإطلاق التطبيقات" -#: ../js/ui/appDisplay.js:335 +#: ../js/ui/appDisplay.js:332 msgid "Frequent" msgstr "متكرر" -#: ../js/ui/appIcon.js:462 +#: ../js/ui/appDisplay.js:867 +msgid "Drag here to add favorites" +msgstr "اسحب إلى هنا ليضاف إلى المفضّلة" + +#: ../js/ui/appIcon.js:426 msgid "New Window" msgstr "نافذة جديدة" -#: ../js/ui/appIcon.js:475 +#: ../js/ui/appIcon.js:430 msgid "Remove from Favorites" msgstr "أزِل من المفضّلة" -#: ../js/ui/appIcon.js:476 +#: ../js/ui/appIcon.js:431 msgid "Add to Favorites" msgstr "أضِف إلى المفضّلة" -#: ../js/ui/dash.js:283 +#: ../js/ui/dash.js:267 msgid "Find..." msgstr "ابحث..." -#: ../js/ui/dash.js:400 +#: ../js/ui/dash.js:376 msgid "More" msgstr "المزيد" -#: ../js/ui/dash.js:543 +#: ../js/ui/dash.js:532 msgid "(see all)" msgstr "(انظر الكل)" #. **** Applications **** -#: ../js/ui/dash.js:763 ../js/ui/dash.js:825 +#: ../js/ui/dash.js:711 ../js/ui/dash.js:773 msgid "APPLICATIONS" msgstr "التطبيقات" #. **** Places **** #. Translators: This is in the sense of locations for documents, #. network locations, etc. -#: ../js/ui/dash.js:783 +#: ../js/ui/dash.js:731 msgid "PLACES" msgstr "الأماكن" #. **** Documents **** -#: ../js/ui/dash.js:790 ../js/ui/dash.js:835 +#: ../js/ui/dash.js:738 ../js/ui/dash.js:783 msgid "RECENT DOCUMENTS" msgstr "المستندات الحديثة" #. **** Search Results **** -#: ../js/ui/dash.js:815 ../js/ui/dash.js:955 +#: ../js/ui/dash.js:763 ../js/ui/dash.js:947 msgid "SEARCH RESULTS" msgstr "نتائج البحث" -#: ../js/ui/dash.js:830 +#: ../js/ui/dash.js:778 msgid "PREFERENCES" msgstr "التفضيلات" #. Button on the left side of the panel. #. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview". -#: ../js/ui/panel.js:272 +#: ../js/ui/panel.js:274 msgid "Activities" msgstr "الأنشطة" #. Translators: This is a time format. -#: ../js/ui/panel.js:464 +#: ../js/ui/panel.js:491 msgid "%a %l:%M %p" msgstr "%A %Ol:%OM %p" @@ -105,23 +109,23 @@ msgid "Execution of '%s' failed:" msgstr "فشل تنفيذ '%s':‏" #. Translators: This is a time format. -#: ../js/ui/widget.js:162 +#: ../js/ui/widget.js:163 msgid "%H:%M" msgstr "%OH:%OM" -#: ../js/ui/widget.js:316 +#: ../js/ui/widget.js:317 msgid "Applications" msgstr "التطبيقات" -#: ../js/ui/widget.js:341 +#: ../js/ui/widget.js:339 msgid "Recent Documents" msgstr "المستندات الحديثة" -#: ../src/shell-global.c:812 +#: ../src/shell-global.c:821 msgid "Less than a minute ago" msgstr "منذ أقل من دقيقة" -#: ../src/shell-global.c:815 +#: ../src/shell-global.c:824 #, c-format msgid "%d minute ago" msgid_plural "%d minutes ago" @@ -132,7 +136,7 @@ msgstr[3] "منذ %d دقائق" msgstr[4] "منذ %d دقيقة" msgstr[5] "منذ %d دقيقة" -#: ../src/shell-global.c:818 +#: ../src/shell-global.c:827 #, c-format msgid "%d hour ago" msgid_plural "%d hours ago" @@ -143,7 +147,7 @@ msgstr[3] "منذ %d ساعات" msgstr[4] "منذ %d ساعة" msgstr[5] "منذ %d ساعة" -#: ../src/shell-global.c:821 +#: ../src/shell-global.c:830 #, c-format msgid "%d day ago" msgid_plural "%d days ago" @@ -154,7 +158,7 @@ msgstr[3] "منذ %d أيام" msgstr[4] "منذ %d يوما" msgstr[5] "منذ %d يوم" -#: ../src/shell-global.c:824 +#: ../src/shell-global.c:833 #, c-format msgid "%d week ago" msgid_plural "%d weeks ago" From 585bfe5b5a312eafcf8148f77b166bb041335771 Mon Sep 17 00:00:00 2001 From: "JP St. Pierre" Date: Sat, 31 Oct 2009 22:25:28 -0400 Subject: [PATCH 14/51] Make places results available in search Places is one of the dash sections and it should be included in search results. Factor out the code for getting and updating the information about places from Places to PlacesManager. Introduce PlaceInfo class that contains information about the place and can be used by classes that display it in different ways. Rename classes so that their names are consistent with corresponding classes in appDisplay.js and docDisplay.js https://bugzilla.gnome.org/show_bug.cgi?id=599125 --- js/ui/Makefile.am | 2 +- js/ui/dash.js | 13 +- js/ui/main.js | 3 + js/ui/{places.js => placeDisplay.js} | 568 +++++++++++++++++++-------- 4 files changed, 412 insertions(+), 174 deletions(-) rename js/ui/{places.js => placeDisplay.js} (50%) diff --git a/js/ui/Makefile.am b/js/ui/Makefile.am index bb12365e5..ebc7f53d3 100644 --- a/js/ui/Makefile.am +++ b/js/ui/Makefile.am @@ -19,7 +19,7 @@ dist_jsui_DATA = \ main.js \ overview.js \ panel.js \ - places.js \ + placeDisplay.js \ runDialog.js \ shellDBus.js \ sidebar.js \ diff --git a/js/ui/dash.js b/js/ui/dash.js index 5c05340cd..da4f8e887 100644 --- a/js/ui/dash.js +++ b/js/ui/dash.js @@ -14,7 +14,7 @@ const _ = Gettext.gettext; const AppDisplay = imports.ui.appDisplay; const DocDisplay = imports.ui.docDisplay; -const Places = imports.ui.places; +const PlaceDisplay = imports.ui.placeDisplay; const GenericDisplay = imports.ui.genericDisplay; const Button = imports.ui.button; const Main = imports.ui.main; @@ -60,6 +60,7 @@ PANE_BACKGROUND_COLOR.from_pixel(0x000000f4); const APPS = "apps"; const PREFS = "prefs"; const DOCS = "docs"; +const PLACES = "places"; /* * Returns the index in an array of a given length that is obtained @@ -81,7 +82,8 @@ function _createDisplay(displayType) { return new AppDisplay.AppDisplay(true); else if (displayType == DOCS) return new DocDisplay.DocDisplay(); - + else if (displayType == PLACES) + return new PlaceDisplay.PlaceDisplay(); return null; } @@ -729,7 +731,7 @@ Dash.prototype = { /* Translators: This is in the sense of locations for documents, network locations, etc. */ this._placesSection = new Section(_("PLACES"), true); - let placesDisplay = new Places.Places(); + let placesDisplay = new PlaceDisplay.DashPlaceDisplay(); this._placesSection.content.append(placesDisplay.actor, Big.BoxPackFlags.EXPAND); this.sectionArea.append(this._placesSection.actor, Big.BoxPackFlags.NONE); @@ -783,6 +785,11 @@ Dash.prototype = { title: _("RECENT DOCUMENTS"), header: null, resultArea: null + }, + { type: PLACES, + title: _("PLACES"), + header: null, + resultArea: null } ]; diff --git a/js/ui/main.js b/js/ui/main.js index aac26720b..5a0ad4cc9 100644 --- a/js/ui/main.js +++ b/js/ui/main.js @@ -16,6 +16,7 @@ const Chrome = imports.ui.chrome; const Environment = imports.ui.environment; const Overview = imports.ui.overview; const Panel = imports.ui.panel; +const PlaceDisplay = imports.ui.placeDisplay; const RunDialog = imports.ui.runDialog; const LookingGlass = imports.ui.lookingGlass; const ShellDBus = imports.ui.shellDBus; @@ -28,6 +29,7 @@ DEFAULT_BACKGROUND_COLOR.from_pixel(0x2266bbff); let chrome = null; let panel = null; let sidebar = null; +let placesManager = null; let overview = null; let runDialog = null; let lookingGlass = null; @@ -96,6 +98,7 @@ function start() { getRunDialog().open(); }); + placesManager = new PlaceDisplay.PlacesManager(); overview = new Overview.Overview(); chrome = new Chrome.Chrome(); panel = new Panel.Panel(); diff --git a/js/ui/places.js b/js/ui/placeDisplay.js similarity index 50% rename from js/ui/places.js rename to js/ui/placeDisplay.js index 9aa604de5..acee53e55 100644 --- a/js/ui/places.js +++ b/js/ui/placeDisplay.js @@ -23,120 +23,93 @@ const PLACES_VSPACING = 8; const PLACES_ICON_SIZE = 16; /** - * An entry in the places menu. + * Represents a place object, which is most normally a bookmark entry, + * a mount/volume, or a special place like the Home Folder, Computer, and Network. + * * @name: String title - * @iconFactory: A JavaScript callback which will create an icon texture - * @onActivate: A JavaScript callback to launch the entry + * @iconFactory: A JavaScript callback which will create an icon texture given a size parameter + * @launch: A JavaScript callback to launch the entry */ -function PlaceDisplay(name, iconFactory, onActivate) { - this._init(name, iconFactory, onActivate); +function PlaceInfo(name, iconFactory, launch) { + this._init(name, iconFactory, launch); } -PlaceDisplay.prototype = { - _init : function(name, iconFactory, onActivate) { - this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, - reactive: true, - spacing: 4 }); - this.actor.connect('button-release-event', Lang.bind(this, function (b, e) { - onActivate(this); - Main.overview.hide(); - })); - let text = new Clutter.Text({ font_name: "Sans 14px", - ellipsize: Pango.EllipsizeMode.END, - color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR, - text: name }); - let iconBox = new Big.Box({ y_align: Big.BoxAlignment.CENTER }); - this._icon = iconFactory(); - iconBox.append(this._icon, Big.BoxPackFlags.NONE); - this.actor.append(iconBox, Big.BoxPackFlags.NONE); - this.actor.append(text, Big.BoxPackFlags.EXPAND); - - this._iconFactory = iconFactory; - this._onActivate = onActivate; - - this.actor._delegate = this; - let draggable = DND.makeDraggable(this.actor); - }, - - getDragActorSource: function() { - return this._icon; - }, - - getDragActor: function(stageX, stageY) { - return this._iconFactory(); - }, - - //// Drag and drop methods //// - - shellWorkspaceLaunch : function() { - this._onActivate(); +PlaceInfo.prototype = { + _init: function(name, iconFactory, launch) { + this.name = name; + this.iconFactory = iconFactory; + this.launch = launch; + this.id = null; } -}; -Signals.addSignalMethods(PlaceDisplay.prototype); +} -function Places() { + +function PlacesManager() { this._init(); } -Places.prototype = { - _init : function() { - // Places is divided semi-arbitrarily into left and right; a grid would - // look better in that there would be an even number of items left+right, - // but it seems like we want some sort of differentiation between actions - // like "Connect to server..." and regular folders - this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, - spacing: 4 }); - this._leftBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL }); - this.actor.append(this._leftBox, Big.BoxPackFlags.EXPAND); - this._rightBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL }); - this.actor.append(this._rightBox, Big.BoxPackFlags.EXPAND); - - // Subdivide left into actions and devices - this._actionsBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, - spacing: PLACES_VSPACING }); - this._leftBox.append(this._actionsBox, Big.BoxPackFlags.NONE); - this._devBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, - spacing: PLACES_VSPACING, - padding_top: 6 }); - this._leftBox.append(this._devBox, Big.BoxPackFlags.NONE); - - // Right is bookmarks - this._dirsBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, - spacing: PLACES_VSPACING }); - this._rightBox.append(this._dirsBox, Big.BoxPackFlags.NONE); - +PlacesManager.prototype = { + _init: function() { let gconf = Shell.GConf.get_default(); gconf.watch_directory(NAUTILUS_PREFS_DIR); + this._mounts = []; + this._bookmarks = []; + this._isDesktopHome = false; + let homeFile = Gio.file_new_for_path (GLib.get_home_dir()); let homeUri = homeFile.get_uri(); let homeLabel = Shell.util_get_label_for_uri (homeUri); let homeIcon = Shell.util_get_icon_for_uri (homeUri); - let home = new PlaceDisplay(homeLabel, - function() { - return Shell.TextureCache.get_default().load_gicon(homeIcon, PLACES_ICON_SIZE); + this._home = new PlaceInfo(homeLabel, + function(size) { + return Shell.TextureCache.get_default().load_gicon(homeIcon, size); }, function() { Gio.app_info_launch_default_for_uri(homeUri, Main.createAppLaunchContext()); }); - this._actionsBox.append(home.actor, Big.BoxPackFlags.NONE); - let desktopPath = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP); let desktopFile = Gio.file_new_for_path (desktopPath); let desktopUri = desktopFile.get_uri(); let desktopLabel = Shell.util_get_label_for_uri (desktopUri); let desktopIcon = Shell.util_get_icon_for_uri (desktopUri); - this._desktopMenu = new PlaceDisplay(desktopLabel, - function() { - return Shell.TextureCache.get_default().load_gicon(desktopIcon, PLACES_ICON_SIZE); + this._desktopMenu = new PlaceInfo(desktopLabel, + function(size) { + return Shell.TextureCache.get_default().load_gicon(desktopIcon, size); }, function() { Gio.app_info_launch_default_for_uri(desktopUri, Main.createAppLaunchContext()); }); - this._actionsBox.append(this._desktopMenu.actor, Big.BoxPackFlags.NONE); - this._updateDesktopMenuVisibility(); - gconf.connect('changed::' + DESKTOP_IS_HOME_KEY, Lang.bind(this, this._updateDesktopMenuVisibility)); + + this._connect = new PlaceInfo(_("Connect to..."), + function (size) { + return Shell.TextureCache.get_default().load_icon_name("applications-internet", size); + }, + function () { + new Shell.Process({ args: ['nautilus-connect-server'] }).run(); + }); + + let networkApp = null; + try { + networkApp = Shell.AppSystem.get_default().load_from_desktop_file('gnome-network-scheme.desktop'); + } catch(e) { + try { + networkApp = Shell.AppSystem.get_default().load_from_desktop_file('network-scheme.desktop'); + } catch(e) { + log("Cannot create \"Network\" item, .desktop file not found or corrupt."); + } + } + + if (networkApp != null) { + this._network = new PlaceInfo(networkApp.get_name(), + function(size) { + return networkApp.create_icon_texture(size); + }, + function () { + networkApp.launch(); + }); + } /* * Show devices, code more or less ported from nautilus-places-sidebar.c @@ -153,37 +126,6 @@ Places.prototype = { this._volumeMonitor.connect('drive-changed', Lang.bind(this, this._updateDevices)); this._updateDevices(); - let networkApp = null; - try { - networkApp = Shell.AppSystem.get_default().load_from_desktop_file('gnome-network-scheme.desktop'); - } catch(e) { - try { - networkApp = Shell.AppSystem.get_default().load_from_desktop_file('network-scheme.desktop'); - } catch(e) { - log("Cannot create \"Network\" item, .desktop file not found or corrupt."); - } - } - - if (networkApp != null) { - let network = new PlaceDisplay(networkApp.get_name(), - function() { - return networkApp.create_icon_texture(PLACES_ICON_SIZE); - }, - function () { - networkApp.launch(); - }); - this._actionsBox.append(network.actor, Big.BoxPackFlags.NONE); - } - - let connect = new PlaceDisplay(_("Connect to..."), - function () { - return Shell.TextureCache.get_default().load_icon_name("applications-internet", PLACES_ICON_SIZE); - }, - function () { - new Shell.Process({ args: ['nautilus-connect-server'] }).run(); - }); - this._actionsBox.append(connect.actor, Big.BoxPackFlags.NONE); - this._bookmarksPath = GLib.build_filenamev([GLib.get_home_dir(), ".gtk-bookmarks"]); this._bookmarksFile = Gio.file_new_for_path(this._bookmarksPath); let monitor = this._bookmarksFile.monitor_file(Gio.FileMonitorFlags.NONE, null); @@ -200,14 +142,68 @@ Places.prototype = { })); this._reloadBookmarks(); + this._updateDesktopMenuVisibility(); + + gconf.connect('changed::' + DESKTOP_IS_HOME_KEY, Lang.bind(this, this._updateDesktopMenuVisibility)); + + }, + + _updateDevices: function() { + this._mounts = []; + + /* first go through all connected drives */ + let drives = this._volumeMonitor.get_connected_drives(); + for (let i = 0; i < drives.length; i++) { + let volumes = drives[i].get_volumes(); + for(let j = 0; j < volumes.length; j++) { + let mount = volumes[j].get_mount(); + if(mount != null) { + this._addMount(mount); + } + } + } + + /* add all volumes that is not associated with a drive */ + let volumes = this._volumeMonitor.get_volumes(); + for(let i = 0; i < volumes.length; i++) { + if(volumes[i].get_drive() != null) + continue; + + let mount = volumes[i].get_mount(); + if(mount != null) { + this._addMount(mount); + } + } + + /* add mounts that have no volume (/etc/mtab mounts, ftp, sftp,...) */ + let mounts = this._volumeMonitor.get_mounts(); + for(let i = 0; i < mounts.length; i++) { + if(mounts[i].is_shadowed()) + continue; + + if(mounts[i].get_volume()) + continue; + + this._addMount(mounts[i]); + } + + /* We emit two signals, one for a generic 'all places' update + * and the other for one specific to mounts. We do this because + * clients like PlaceDisplay may only care about places in general + * being updated while clients like DashPlaceDisplay care which + * specific type of place got updated. + */ + this.emit('mounts-updated'); + this.emit('places-updated'); + }, _reloadBookmarks: function() { - this._dirsBox.remove_all(); + this._bookmarks = []; if (!GLib.file_test(this._bookmarksPath, GLib.FileTest.EXISTS)) - return; + return; let [success, bookmarksContent, len] = GLib.file_get_contents(this._bookmarksPath); @@ -243,55 +239,28 @@ Places.prototype = { continue; let icon = Shell.util_get_icon_for_uri(bookmark); - let item = new PlaceDisplay(label, - function() { - return Shell.TextureCache.get_default().load_gicon(icon, PLACES_ICON_SIZE); + let item = new PlaceInfo(label, + function(size) { + return Shell.TextureCache.get_default().load_gicon(icon, size); }, function() { Gio.app_info_launch_default_for_uri(bookmark, Main.createAppLaunchContext()); }); - this._dirsBox.append(item.actor, Big.BoxPackFlags.NONE); + this._bookmarks.push(item); } + + /* See comment in _updateDevices for explanation why there are two signals. */ + this.emit('bookmarks-updated'); + this.emit('places-updated'); }, - _updateDevices: function() { - this._devBox.remove_all(); + _updateDesktopMenuVisibility: function() { + let gconf = Shell.GConf.get_default(); + this._isDesktopHome = gconf.get_boolean(DESKTOP_IS_HOME_KEY); - /* first go through all connected drives */ - let drives = this._volumeMonitor.get_connected_drives(); - for (let i = 0; i < drives.length; i++) { - let volumes = drives[i].get_volumes(); - for(let j = 0; j < volumes.length; j++) { - let mount = volumes[j].get_mount(); - if(mount != null) { - this._addMount(mount); - } - } - } - - /* add all volumes that is not associated with a drive */ - let volumes = this._volumeMonitor.get_volumes(); - for(let i = 0; i < volumes.length; i++) { - if(volumes[i].get_drive() != null) - continue; - - let mount = volumes[i].get_mount(); - if(mount != null) { - this._addMount(mount); - } - } - - /* add mounts that have no volume (/etc/mtab mounts, ftp, sftp,...) */ - let mounts = this._volumeMonitor.get_mounts(); - for(let i = 0; i < mounts.length; i++) { - if(mounts[i].is_shadowed()) - continue; - - if(mounts[i].get_volume()) - continue; - - this._addMount(mounts[i]); - } + /* See comment in _updateDevices for explanation why there are two signals. */ + this.emit('defaults-updated'); + this.emit('places-updated'); }, _addMount: function(mount) { @@ -299,23 +268,282 @@ Places.prototype = { let mountIcon = mount.get_icon(); let root = mount.get_root(); let mountUri = root.get_uri(); - let devItem = new PlaceDisplay(mountLabel, - function() { - return Shell.TextureCache.get_default().load_gicon(mountIcon, PLACES_ICON_SIZE); + let devItem = new PlaceInfo(mountLabel, + function(size) { + return Shell.TextureCache.get_default().load_gicon(mountIcon, size); }, function() { Gio.app_info_launch_default_for_uri(mountUri, Main.createAppLaunchContext()); }); - this._devBox.append(devItem.actor, Big.BoxPackFlags.NONE); + this._mounts.push(devItem); }, - _updateDesktopMenuVisibility: function() { - let gconf = Shell.GConf.get_default(); - let desktopIsHome = gconf.get_boolean(DESKTOP_IS_HOME_KEY); - if (desktopIsHome) - this._desktopMenu.actor.hide(); - else - this._desktopMenu.actor.show(); + getAllPlaces: function () { + return this.getDefaultPlaces().concat(this.getBookmarks(), this.getMounts()); + }, + + getDefaultPlaces: function () { + let places = [this._home]; + + if (this._isDesktopHome) + places.push(this._desktopMenu); + + if (this._network) + places.push(this._network); + + places.push(this._connect); + return places; + }, + + getBookmarks: function () { + return this._bookmarks; + }, + + getMounts: function () { + return this._mounts; + } +}; + +Signals.addSignalMethods(PlacesManager.prototype); + +/** + * An entry in the places menu. + * @info The corresponding PlaceInfo to populate this entry. + */ +function DashPlaceDisplayItem(info) { + this._init(info); +} + +DashPlaceDisplayItem.prototype = { + _init: function(info) { + this.name = info.name; + this._info = info; + this._icon = info.iconFactory(PLACES_ICON_SIZE); + this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, + reactive: true, + spacing: 4 }); + this.actor.connect('button-release-event', Lang.bind(this, function (b, e) { + this._info.launch(); + Main.overview.hide(); + })); + let text = new Clutter.Text({ font_name: 'Sans 14px', + ellipsize: Pango.EllipsizeMode.END, + color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR, + text: this.name }); + let iconBox = new Big.Box({ y_align: Big.BoxAlignment.CENTER }); + iconBox.append(this._icon, Big.BoxPackFlags.NONE); + this.actor.append(iconBox, Big.BoxPackFlags.NONE); + this.actor.append(text, Big.BoxPackFlags.EXPAND); + + this.actor._delegate = this; + let draggable = DND.makeDraggable(this.actor); + }, + + getDragActorSource: function() { + return this._icon; + }, + + getDragActor: function(stageX, stageY) { + return this._info.iconFactory(PLACES_ICON_SIZE); + }, + + //// Drag and drop methods //// + + shellWorkspaceLaunch: function() { + this._info.launch(); + } +}; + +function DashPlaceDisplay() { + this._init(); +} + +DashPlaceDisplay.prototype = { + _init: function() { + + // Places is divided semi-arbitrarily into left and right; a grid would + // look better in that there would be an even number of items left+right, + // but it seems like we want some sort of differentiation between actions + // like "Connect to server..." and regular folders + this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, + spacing: 4 }); + this._leftBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL }); + this.actor.append(this._leftBox, Big.BoxPackFlags.EXPAND); + this._rightBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL }); + this.actor.append(this._rightBox, Big.BoxPackFlags.EXPAND); + + // Subdivide left into actions and devices + this._actionsBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, + spacing: PLACES_VSPACING }); + + this._devBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, + spacing: PLACES_VSPACING, + padding_top: 6 }); + + this._dirsBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, + spacing: PLACES_VSPACING }); + + this._leftBox.append(this._actionsBox, Big.BoxPackFlags.NONE); + this._leftBox.append(this._devBox, Big.BoxPackFlags.NONE); + + this._rightBox.append(this._dirsBox, Big.BoxPackFlags.NONE); + + Main.placesManager.connect('defaults-updated', Lang.bind(this, this._updateDefaults)); + Main.placesManager.connect('bookmarks-updated', Lang.bind(this, this._updateBookmarks)); + Main.placesManager.connect('mounts-updated', Lang.bind(this, this._updateMounts)); + + this._updateDefaults(); + this._updateMounts(); + this._updateBookmarks(); + }, + + _updateDefaults: function() { + this._actionsBox.get_children().forEach(function (child) { + child.destroy(); + }); + + let places = Main.placesManager.getDefaultPlaces(); + for (let i = 0; i < places.length; i++) + this._actionsBox.append(new DashPlaceDisplayItem(places[i]).actor, Big.BoxPackFlags.NONE); + }, + + _updateMounts: function() { + this._devBox.get_children().forEach(function (child) { + child.destroy(); + }); + + let places = Main.placesManager.getMounts(); + for (let i = 0; i < places.length; i++) + this._devBox.append(new DashPlaceDisplayItem(places[i]).actor, Big.BoxPackFlags.NONE); + }, + + _updateBookmarks: function() { + this._dirsBox.get_children().forEach(function (child) { + child.destroy(); + }); + + let places = Main.placesManager.getBookmarks(); + for (let i = 0; i < places.length; i ++) + this._dirsBox.append(new DashPlaceDisplayItem(places[i]).actor, Big.BoxPackFlags.NONE); + } +}; + +Signals.addSignalMethods(DashPlaceDisplay.prototype); + + +function PlaceDisplayItem(placeInfo) { + this._init(placeInfo); +} + +PlaceDisplayItem.prototype = { + __proto__: GenericDisplay.GenericDisplayItem.prototype, + + _init : function(placeInfo) { + GenericDisplay.GenericDisplayItem.prototype._init.call(this); + this._info = placeInfo; + + this._setItemInfo(placeInfo.name, ''); + }, + + //// Public method overrides //// + + // Opens an application represented by this display item. + launch : function() { + this._info.launch(); + }, + + shellWorkspaceLaunch: function() { + this._info.launch(); + }, + + //// Protected method overrides //// + + // Returns an icon for the item. + _createIcon: function() { + return this._info.iconFactory(GenericDisplay.ITEM_DISPLAY_ICON_SIZE); + }, + + // Returns a preview icon for the item. + _createPreviewIcon: function() { + return this._info.iconFactory(GenericDisplay.PREVIEW_ICON_SIZE); + } + +}; + +function PlaceDisplay() { + this._init(); +} + +PlaceDisplay.prototype = { + __proto__: GenericDisplay.GenericDisplay.prototype, + + _init: function() { + GenericDisplay.GenericDisplay.prototype._init.call(this); + this._stale = true; + Main.placesManager.connect('places-updated', Lang.bind(this, function (e) { + this._stale = true; + })); + }, + + //// Protected method overrides //// + _refreshCache: function () { + if (!this._stale) + return true; + this._allItems = {}; + let array = Main.placesManager.getAllPlaces(); + for (let i = 0; i < array.length; i ++) { + // We are using an array id as placeInfo id because placeInfo doesn't have any + // other information piece that can be used as a unique id. There are different + // types of placeInfo, such as devices and directories that would result in differently + // structured ids. Also the home directory can show up in both the default places and in + // bookmarks which means its URI can't be used as a unique id. (This does mean it can + // appear twice in search results, though that doesn't happen at the moment because we + // name it "Home Folder" in default places and it's named with the user's system name + // if it appears as a bookmark.) + let placeInfo = array[i]; + placeInfo.id = i; + this._allItems[i] = placeInfo; + } + this._stale = false; + return false; + }, + + // Sets the list of the displayed items. + _setDefaultList: function() { + this._matchedItems = {}; + this._matchedItemKeys = []; + for (id in this._allItems) { + this._matchedItems[id] = 1; + this._matchedItemKeys.push(id); + } + this._matchedItemKeys.sort(Lang.bind(this, this._compareItems)); + }, + + // Checks if the item info can be a match for the search string by checking + // the name of the place. Item info is expected to be PlaceInfo. + // Returns a boolean flag indicating if itemInfo is a match. + _isInfoMatching: function(itemInfo, search) { + if (search == null || search == '') + return true; + + let name = itemInfo.name.toLowerCase(); + if (name.indexOf(search) >= 0) + return true; + + return false; + }, + + // Compares items associated with the item ids based on the alphabetical order + // of the item names. + // Returns an integer value indicating the result of the comparison. + _compareItems: function(itemIdA, itemIdB) { + let placeA = this._allItems[itemIdA]; + let placeB = this._allItems[itemIdB]; + return placeA.name.localeCompare(placeB.name); + }, + + // Creates a PlaceDisplayItem based on itemInfo, which is expected to be a PlaceInfo object. + _createDisplayItem: function(itemInfo) { + return new PlaceDisplayItem(itemInfo); } }; -Signals.addSignalMethods(Places.prototype); From 2f27f61a1fc97aa2a12fb6cf9656ef4fe70013da Mon Sep 17 00:00:00 2001 From: Marina Zhurakhinskaya Date: Mon, 9 Nov 2009 17:49:01 -0500 Subject: [PATCH 15/51] Remove trailing whitespaces in dash.js Trailing whitespaces cause warnings. --- js/ui/dash.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/ui/dash.js b/js/ui/dash.js index da4f8e887..823a15d81 100644 --- a/js/ui/dash.js +++ b/js/ui/dash.js @@ -66,7 +66,7 @@ const PLACES = "places"; * Returns the index in an array of a given length that is obtained * if the provided index is incremented by an increment and the array * is wrapped in if necessary. - * + * * index: prior index, expects 0 <= index < length * increment: the change in index, expects abs(increment) <= length * length: the length of the array @@ -318,7 +318,7 @@ SearchEntry.prototype = { else this.entry.text = ''; - // Return true to stop the signal emission, so that this.actor doesn't get + // Return true to stop the signal emission, so that this.actor doesn't get // the button-press-event and re-highlight itself. return true; })); @@ -341,7 +341,7 @@ SearchEntry.prototype = { _resetTextState: function (searchEntryClicked) { let text = this.getText(); this._iconBox.remove_all(); - // We highlight the search box if the user starts typing in it + // We highlight the search box if the user starts typing in it // or just clicks in it to indicate that the search is active. if (text != '' || searchEntryClicked) { if (!searchEntryClicked) From 07a8d5ed2dcaa104db992f49b701009b776d35b4 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 5 Nov 2009 17:19:36 -0500 Subject: [PATCH 16/51] When setting a search, do a redisplay immediately Commit 94bd6f17180f0a8cbdbf2a66a47469fce601a9e1 introduced a trick where we only do the heavy lifting for "redisplay" when we're mapped. However, the search system wants to get the count of matched items, and control the visibility of the display based on that. This introduces a circularity; avoid it by forcing the search to do a redisplay. In the future we should avoid this by separating out the "get matched things for search" from "display list of things". https://bugzilla.gnome.org/show_bug.cgi?id=600890 --- js/ui/genericDisplay.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/js/ui/genericDisplay.js b/js/ui/genericDisplay.js index 4744669a2..e58c2c632 100644 --- a/js/ui/genericDisplay.js +++ b/js/ui/genericDisplay.js @@ -20,7 +20,8 @@ const Main = imports.ui.main; const RedisplayFlags = { NONE: 0, RESET_CONTROLS: 1 << 0, FULL: 1 << 1, - SUBSEARCH: 1 << 2 }; + SUBSEARCH: 1 << 2, + IMMEDIATE: 1 << 3 }; const ITEM_DISPLAY_NAME_COLOR = new Clutter.Color(); ITEM_DISPLAY_NAME_COLOR.from_pixel(0xffffffff); @@ -369,16 +370,18 @@ GenericDisplay.prototype = { // Sets the search string and displays the matching items. setSearch: function(text) { let lowertext = text.toLowerCase(); - if (lowertext == this._search) + if (lowertext == this._search) { return; - let flags = RedisplayFlags.RESET_CONTROLS; + } + let flags = RedisplayFlags.RESET_CONTROLS | RedisplayFlags.IMMEDIATE; if (this._search != '') { // Because we combine search terms with OR, we have to be sure that no new term // was introduced before deciding that the new search results will be a subset of // the existing search results. if (lowertext.indexOf(this._search) == 0 && - lowertext.split(/\s+/).length == this._search.split(/\s+/).length) + lowertext.split(/\s+/).length == this._search.split(/\s+/).length) { flags |= RedisplayFlags.SUBSEARCH; + } } this._search = lowertext; this._redisplay(flags); @@ -643,9 +646,13 @@ GenericDisplay.prototype = { * SUBSEARCH - Indicates that the current _search is a superstring of the previous * one, which implies we only need to re-search through previous results. * FULL - Indicates that we need recreate all displayed items; implies RESET_CONTROLS as well + * IMMEDIATE - Do the full redisplay even if we're not mapped. This is useful + * if you want to get the number of matched items and show/hide a section based on + * that number. */ _redisplay: function(flags) { - if (!this._list.mapped) { + let immediate = (flags & RedisplayFlags.IMMEDIATE) > 0; + if (!immediate && !this._list.mapped) { this._pendingRedisplay |= flags; return; } From 1b75ae018471b5cfe9e07d4d93f67daceb3c62c1 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 11 Nov 2009 13:12:55 -0500 Subject: [PATCH 17/51] [lookingGlass] Paint border around current result if instanceof Clutter.Actor It's very convenient to drill down through object properties and be able to see exactly which portion of the screen those actors correspond to, without trying to guess with the inspector tool. --- js/ui/lookingGlass.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/js/ui/lookingGlass.js b/js/ui/lookingGlass.js index 35431f0ad..afe99b864 100644 --- a/js/ui/lookingGlass.js +++ b/js/ui/lookingGlass.js @@ -320,6 +320,10 @@ LookingGlass.prototype = { this._savedText = null; this._historyNavIndex = -1; this._history = []; + this._borderPaintTarget = null; + this._borderPaintId = 0; + this._borderDestroyId = 0; + this._readHistory(); this._open = false; @@ -487,6 +491,18 @@ LookingGlass.prototype = { this._results.push(result); this._resultsArea.append(result.actor, Big.BoxPackFlags.NONE); this._propInspector.setTarget(obj); + if (this._borderPaintTarget != null) { + this._borderPaintTarget.disconnect(this._borderPaintId); + this._borderPaintTarget = null; + } + if (obj instanceof Clutter.Actor) { + this._borderPaintTarget = obj; + this._borderPaintId = Shell.add_hook_paint_red_border(obj); + this._borderDestroyId = obj.connect('destroy', Lang.bind(this, function () { + this._borderDestroyId = 0; + this._borderPaintTarget = null; + })); + } let children = this._resultsArea.get_children(); if (children.length > this._maxItems) { this._results.shift(); @@ -582,6 +598,12 @@ LookingGlass.prototype = { this._open = false; Tweener.removeTweens(this.actor); + if (this._borderPaintTarget != null) { + this._borderPaintTarget.disconnect(this._borderPaintId); + this._borderPaintTarget.disconnect(this._borderDestroyId); + this._borderPaintTarget = null; + } + Main.popModal(this.actor); Tweener.addTween(this.actor, { time: 0.5, From af35dea019f69e2f63e98ff1dffe6a5ebb94a044 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 10 Nov 2009 10:02:02 -0500 Subject: [PATCH 18/51] [dash] Move BackLink to CSS The previous commit 626f679947298a99 broke the back links on search drilldown. https://bugzilla.gnome.org/show_bug.cgi?id=601413 --- data/Makefile.am | 4 ++-- data/theme/gnome-shell.css | 12 ++++++++++ data/{back.svg => theme/section-back.svg} | 0 js/ui/dash.js | 27 +++++++++-------------- 4 files changed, 25 insertions(+), 18 deletions(-) rename data/{back.svg => theme/section-back.svg} (100%) diff --git a/data/Makefile.am b/data/Makefile.am index 06827d0b3..8c090c08f 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -16,7 +16,6 @@ imagesdir = $(pkgdatadir)/images dist_images_DATA = \ add-workspace.svg \ app-well-glow.png \ - back.svg \ close.svg \ close-black.svg \ info.svg \ @@ -30,7 +29,8 @@ dist_theme_DATA = \ theme/scroll-button-down-hover.png \ theme/scroll-button-up.png \ theme/scroll-button-up-hover.png \ - theme/scroll-vhandle.png + theme/scroll-vhandle.png \ + theme/section-back.svg schemadir = @GCONF_SCHEMA_FILE_DIR@ schema_DATA = gnome-shell.schemas diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index 86ec44b84..a01d1eaf0 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -101,12 +101,24 @@ StScrollBar StButton#vhandle:hover .section-header-inner { border: 1px solid #000000; padding: 0px 4px; + spacing: 4px; } .section-text-content { padding: 4px 0px; } +.section-header-back { + padding: 0px 4px 0px 0px; + border-right: 1px solid #262626; +} + +.section-header-back-image { + background-image: url("section-back.svg"); + width: 12px; + height: 16px; +} + .section-count { } diff --git a/data/back.svg b/data/theme/section-back.svg similarity index 100% rename from data/back.svg rename to data/theme/section-back.svg diff --git a/js/ui/dash.js b/js/ui/dash.js index 823a15d81..fe7a4dafb 100644 --- a/js/ui/dash.js +++ b/js/ui/dash.js @@ -403,21 +403,9 @@ function BackLink() { BackLink.prototype = { _init : function () { - this.actor = new Shell.ButtonBox({ orientation: Big.BoxOrientation.HORIZONTAL, - padding_right: DEFAULT_PADDING, - padding_left: DEFAULT_PADDING, - reactive: true, - x_align: Big.BoxAlignment.CENTER, - y_align: Big.BoxAlignment.CENTER, - border_right: SECTION_BORDER, - border_color: SECTION_BORDER_COLOR }); - - let backIconUri = "file://" + global.imagedir + "back.svg"; - let backIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER, - backIconUri, - 12, - 16); - this.actor.append(backIcon, Big.BoxPackFlags.NONE); + this.actor = new St.Button({ style_class: "section-header-back", + reactive: true }); + this.actor.set_child(new St.Bin({ style_class: "section-header-back-image" })); } } @@ -442,13 +430,20 @@ SectionHeader.prototype = { this._onStyleChanged(); })); + this.backLink = new BackLink(); + this._innerBox.add(this.backLink.actor); + this.backLink.actor.hide(); + this.backLink.actor.connect('clicked', Lang.bind(this, function (actor) { + this.emit('back-link-activated'); + })); + let textBox = new St.BoxLayout({ style_class: "section-text-content" }); this.text = new St.Label({ style_class: "section-title", text: title }); textBox.add(this.text, { x_align: St.Align.START }); this.countText = new St.Label({ style_class: "section-count" }); - textBox.add(this.countText, { x_align: St.Align.END }); + textBox.add(this.countText, { expand: true, x_fill: false, x_align: St.Align.END }); this.countText.hide(); this._innerBox.add(textBox, { expand: true }); From ae744bf2065d8c49625c800ea8b67e75adbeba31 Mon Sep 17 00:00:00 2001 From: Gustavo Noronha Silva Date: Mon, 9 Nov 2009 15:54:44 -0200 Subject: [PATCH 19/51] Don't require applications to accept URIs for recent files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should not be required, since glib correctly deals with such applications by giving them the local gvfs path, and those applications which do support URIs keep being able to use the URIs in GFiles. Based on original work by Guido Günther . https://bugzilla.gnome.org/show_bug.cgi?id=601287 --- js/misc/docInfo.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/misc/docInfo.js b/js/misc/docInfo.js index 021dce412..8123e281b 100644 --- a/js/misc/docInfo.js +++ b/js/misc/docInfo.js @@ -36,8 +36,8 @@ DocInfo.prototype = { // shorter in terms of lines of code, we are not doing so // because that would duplicate the work of retrieving the // mime type. - - let appInfo = Gio.app_info_get_default_for_type(this.mimeType, true); + let needsUri = Gio.file_new_for_uri(this.uri).get_path() == null; + let appInfo = Gio.app_info_get_default_for_type(this.mimeType, needsUri); if (appInfo != null) { appInfo.launch_uris([this.uri], Main.createAppLaunchContext()); From bf7b1662373501e6b1b5a3c117080f6656c0d354 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 10 Nov 2009 14:25:41 -0500 Subject: [PATCH 20/51] [StBoxLayout] Add st_box_layout_remove_all, st_box_layout_destroy_children In a variety of places we're using boxes as data-modeling displays, and in doing so we often want to either remove the children or explictly destroy them. Now ideally Gjs would support callbacks, and this would make using the for_each functions possible, but even then these functions are more efficient and shorter to type, at least. https://bugzilla.gnome.org/show_bug.cgi?id=600734 --- src/st/st-box-layout.c | 47 ++++++++++++++++++++++++++++++++++++++++++ src/st/st-box-layout.h | 4 ++++ 2 files changed, 51 insertions(+) diff --git a/src/st/st-box-layout.c b/src/st/st-box-layout.c index 12b15081a..d0371d821 100644 --- a/src/st/st-box-layout.c +++ b/src/st/st-box-layout.c @@ -1338,3 +1338,50 @@ st_box_layout_get_pack_start (StBoxLayout *box) return box->priv->is_pack_start; } + +static void +st_box_layout_internal_remove_all (StBoxLayout *self, + gboolean destroy) +{ + StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (self)->priv; + ClutterActor *child; + + while (priv->children) + { + child = priv->children->data; + + g_object_ref (child); + priv->children = g_list_delete_link (priv->children, priv->children); + clutter_actor_unparent (child); + g_signal_emit_by_name (self, "actor-removed", child); + if (destroy) + clutter_actor_destroy (child); + g_object_unref (child); + } + + clutter_actor_queue_relayout ((ClutterActor*) self); +} + +/** + * st_box_layout_remove_all: + * @self: + * + * Efficiently unparent all children currently in this box. + */ +void +st_box_layout_remove_all (StBoxLayout *self) +{ + st_box_layout_internal_remove_all (self, FALSE); +} + +/** + * st_box_layout_destroy_children: + * @self: + * + * Efficiently unparent and destroy all children currently in this box. + */ +void +st_box_layout_destroy_children (StBoxLayout *self) +{ + st_box_layout_internal_remove_all (self, TRUE); +} diff --git a/src/st/st-box-layout.h b/src/st/st-box-layout.h index 30954a2ee..b57143ba4 100644 --- a/src/st/st-box-layout.h +++ b/src/st/st-box-layout.h @@ -89,6 +89,10 @@ void st_box_layout_set_pack_start (StBoxLayout *box, gboolean pack_start); gboolean st_box_layout_get_pack_start (StBoxLayout *box); +void st_box_layout_remove_all (StBoxLayout *box); + +void st_box_layout_destroy_children (StBoxLayout *box); + G_END_DECLS #endif /* _ST_BOX_LAYOUT_H */ From 057f0effedc8bbe1087be0395c8534264a3eec3e Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 10 Nov 2009 15:46:30 -0500 Subject: [PATCH 21/51] [StBoxLayout] Add st_box_layout_get_n_children https://bugzilla.gnome.org/show_bug.cgi?id=600734 --- src/st/st-box-layout.c | 12 ++++++++++++ src/st/st-box-layout.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/src/st/st-box-layout.c b/src/st/st-box-layout.c index d0371d821..8885f6a93 100644 --- a/src/st/st-box-layout.c +++ b/src/st/st-box-layout.c @@ -1385,3 +1385,15 @@ st_box_layout_destroy_children (StBoxLayout *self) { st_box_layout_internal_remove_all (self, TRUE); } + +/** + * st_box_layout_get_n_children: + * @self: a #StBoxLayout + * + * Returns the number of children in this box. + */ +guint +st_box_layout_get_n_children (StBoxLayout *self) +{ + return g_list_length (self->priv->children); +} diff --git a/src/st/st-box-layout.h b/src/st/st-box-layout.h index b57143ba4..21cd0b757 100644 --- a/src/st/st-box-layout.h +++ b/src/st/st-box-layout.h @@ -93,6 +93,8 @@ void st_box_layout_remove_all (StBoxLayout *box); void st_box_layout_destroy_children (StBoxLayout *box); +guint st_box_layout_get_n_children (StBoxLayout *box); + G_END_DECLS #endif /* _ST_BOX_LAYOUT_H */ From 8040ad61c67620c8ef9f6a18eb1a04ab5f7fe983 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 11 Nov 2009 11:54:08 -0500 Subject: [PATCH 22/51] [StBoxLayout] Add missing _queue_relayout in _add_actor https://bugzilla.gnome.org/show_bug.cgi?id=600734 --- src/st/st-box-layout.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/st/st-box-layout.c b/src/st/st-box-layout.c index 8885f6a93..90c7d71f6 100644 --- a/src/st/st-box-layout.c +++ b/src/st/st-box-layout.c @@ -260,6 +260,8 @@ st_box_container_add_actor (ClutterContainer *container, priv->children = g_list_append (priv->children, actor); + clutter_actor_queue_relayout (CLUTTER_ACTOR (container)); + g_signal_emit_by_name (container, "actor-added", actor); } From 263d738ef66a0f1fc55f58d5c7fb369066a55df3 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 11 Nov 2009 16:22:22 -0500 Subject: [PATCH 23/51] [StTooltip] Fix _get_preferred_width It was ignoring the label width. https://bugzilla.gnome.org/show_bug.cgi?id=600734 --- src/st/st-tooltip.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/st/st-tooltip.c b/src/st/st-tooltip.c index 5232dbc41..1fbec22e3 100644 --- a/src/st/st-tooltip.c +++ b/src/st/st-tooltip.c @@ -148,7 +148,6 @@ st_tooltip_get_preferred_width (ClutterActor *self, { StTooltipPrivate *priv = ST_TOOLTIP (self)->priv; StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self)); - gfloat min_label_w, natural_label_w; gfloat label_height, arrow_height; ClutterActor *arrow_image; @@ -180,13 +179,8 @@ st_tooltip_get_preferred_width (ClutterActor *self, { clutter_actor_get_preferred_width (priv->label, label_height, - &min_label_w, - &natural_label_w); - } - else - { - min_label_w = 0; - natural_label_w = 0; + min_width_p, + natural_width_p); } st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p); From 1626e8c09ae8ebb8b7a1d3d80c319fcf305fa94d Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 11 Nov 2009 16:22:42 -0500 Subject: [PATCH 24/51] [StTooltip CSS] Add some style Not final, but stands out and doesn't look completely wrong, at least. https://bugzilla.gnome.org/show_bug.cgi?id=600734 --- data/theme/gnome-shell.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index a01d1eaf0..ec4cfa573 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -60,6 +60,14 @@ StScrollBar StButton#vhandle:hover border-image: url("scroll-vhandle.png") 5; } +StTooltip { + border: 1px solid rgba(79,111,173,0.9); + border-radius: 5px; + padding: 4px; + background-color: rgba(79,111,173,0.9); + color: #ffffff; +} + /* Panel */ .panel-button { From d51384fb86c6d351a16b0b032b592df613130c38 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 3 Nov 2009 18:36:44 -0500 Subject: [PATCH 25/51] switch to scrolling GenericDisplay, remove menus from apps Temporarily removed search-by-menu from apps as well, will readd later as a ShellApp feature. https://bugzilla.gnome.org/show_bug.cgi?id=600734 --- js/ui/appDisplay.js | 199 +++------------------------------------- js/ui/dash.js | 49 ++++------ js/ui/docDisplay.js | 10 +- js/ui/genericDisplay.js | 148 +++++++++--------------------- js/ui/placeDisplay.js | 8 +- 5 files changed, 86 insertions(+), 328 deletions(-) diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js index db2b507e3..c88191016 100644 --- a/js/ui/appDisplay.js +++ b/js/ui/appDisplay.js @@ -166,15 +166,15 @@ Signals.addSignalMethods(MenuItem.prototype); * showPrefs - a boolean indicating if this AppDisplay should contain preference * applets, rather than applications */ -function AppDisplay(showPrefs) { - this._init(showPrefs); +function AppDisplay(showPrefs, flags) { + this._init(showPrefs, flags); } AppDisplay.prototype = { __proto__: GenericDisplay.GenericDisplay.prototype, - _init : function(showPrefs) { - GenericDisplay.GenericDisplay.prototype._init.call(this); + _init : function(showPrefs, flags) { + GenericDisplay.GenericDisplay.prototype._init.call(this, flags); this._showPrefs = showPrefs; @@ -190,156 +190,10 @@ AppDisplay.prototype = { this._appsStale = true; this._redisplay(GenericDisplay.RedisplayFlags.NONE); })); - - this._focusInMenus = true; - this._activeMenuIndex = -1; - this._activeMenu = null; - this._activeMenuApps = null; - this._menuDisplay = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, - spacing: MENU_SPACING - }); - - this.connect('expanded', Lang.bind(this, function (self) { - this._filterReset(); - })); - this._filterReset(); - }, - - moveRight: function() { - if (this._expanded && this._focusInMenu) { - this._focusInMenu = false; - this._activeMenu.setState(MENU_ENTERED); - this.selectFirstItem(); - } - }, - - moveLeft: function() { - if (this._expanded && !this._focusInMenu) { - this._activeMenu.setState(MENU_SELECTED); - this.unsetSelected(); - this._focusInMenu = true; - } - }, - - // Override genericDisplay.js - getNavigationArea: function() { - return this._menuDisplay; - }, - - selectUp: function() { - if (!(this._expanded && this._focusInMenu)) - return GenericDisplay.GenericDisplay.prototype.selectUp.call(this); - this._selectMenuIndex(this._activeMenuIndex - 1); - return true; - }, - - selectDown: function() { - if (!(this._expanded && this._focusInMenu)) - return GenericDisplay.GenericDisplay.prototype.selectDown.call(this); - this._selectMenuIndex(this._activeMenuIndex+1); - return true; - }, - - setSearch: function(text) { - let lowertext = text.toLowerCase(); - if (lowertext == this._search) - return; - - // We prepare menu matches up-front, so that we don't - // need to go over all menu items for each application - // and then get all applications for a matching menu - // to see if a particular application passed to - // _isInfoMatching() is a match. - let terms = lowertext.split(/\s+/); - this._menuSearchAppMatches = {}; - for (let i = 0; i < terms.length; i++) { - let term = terms[i]; - this._menuSearchAppMatches[term] = {}; - for (let j = 0; j < this._menus.length; j++) { - let menuItem = this._menus[j]; - // Match only on the beginning of the words in category names, - // because otherwise it introduces unnecessary noise in the results. - if (menuItem.name.toLowerCase().indexOf(term) == 0 || - menuItem.name.toLowerCase().indexOf(" " + term) > 0) { - let menuApps = this._appSystem.get_applications_for_menu(menuItem.id); - for (let k = 0; k < menuApps.length; k++) { - let menuApp = menuApps[k]; - this._menuSearchAppMatches[term][menuApp.get_id()] = true; - } - } - } - } - - GenericDisplay.GenericDisplay.prototype.setSearch.call(this, text); - }, - - // Protected overrides - - _filterActive: function() { - // We always have a filter now since a menu must be selected - return true; - }, - - _filterReset: function() { - GenericDisplay.GenericDisplay.prototype._filterReset.call(this); - this._selectMenuIndex(0); }, //// Private //// - _emitStateChange: function() { - this.emit('state-changed'); - }, - - _selectMenuIndex: function(index) { - if (index < 0 || index >= this._menus.length) - return; - this._menuDisplays[index].setState(MENU_SELECTED); - }, - - _getMostUsed: function() { - let context = ""; - let usage = Shell.AppUsage.get_default(); - return usage.get_most_used(context, 30); - }, - - _addMenuItem: function(name, id, index) { - let display = new MenuItem(name, id); - this._menuDisplays.push(display); - display.connect('state-changed', Lang.bind(this, function (display) { - let activated = display.getState() != MENU_UNSELECTED; - if (!activated && display == this._activeMenu) { - this._activeMenuIndex = -1; - this._activeMenu = null; - } else if (activated) { - if (display != this._activeMenu && this._activeMenu != null) - this._activeMenu.setState(MENU_UNSELECTED); - this._activeMenuIndex = index; - this._activeMenu = display; - if (id == null) { - this._activeMenuApps = this._getMostUsed(); - } else { - this._activeMenuApps = this._appSystem.get_applications_for_menu(id); - } - } - this._redisplay(GenericDisplay.RedisplayFlags.FULL); - })); - this._menuDisplay.append(display.actor, 0); - }, - - _redisplayMenus: function() { - this._menuDisplay.remove_all(); - this._addMenuItem(_("Frequent"), null, 'gtk-select-all'); - // Adding an empty box here results in double spacing between - // "Frequent" and the other items. - let separator_actor = new Big.Box(); - this._menuDisplay.append(separator_actor, 0); - for (let i = 0; i < this._menus.length; i++) { - let menu = this._menus[i]; - this._addMenuItem(menu.name, menu.id, i+1); - } - }, - _addApp: function(appInfo) { let appId = appInfo.get_id(); this._allItems[appId] = appInfo; @@ -363,33 +217,33 @@ AppDisplay.prototype = { } } else { // Loop over the toplevel menu items, load the set of desktop file ids - // associated with each one, skipping empty menus + // associated with each one. let allMenus = this._appSystem.get_menus(); - this._menus = []; for (let i = 0; i < allMenus.length; i++) { let menu = allMenus[i]; let menuApps = this._appSystem.get_applications_for_menu(menu.id); - let hasVisibleApps = menuApps.some(function (app) { return !app.get_is_nodisplay(); }); - if (!hasVisibleApps) { - continue; - } - this._menus.push(menu); + for (let j = 0; j < menuApps.length; j++) { let app = menuApps[j]; this._addApp(app); } } - this._redisplayMenus(); } this._appsStale = false; return false; }, - // Stub this out; the app display always has a category selected _setDefaultList : function() { - this._matchedItems = {}; + this._matchedItems = this._allItems; this._matchedItemKeys = []; + for (let itemId in this._matchedItems) { + let app = this._allItems[itemId]; + if (app.get_is_nodisplay()) + continue; + this._matchedItemKeys.push(itemId); + } + this._matchedItemKeys.sort(Lang.bind(this, this._compareItems)); }, // Compares items associated with the item ids based on the alphabetical order @@ -409,25 +263,7 @@ AppDisplay.prototype = { // Don't show nodisplay items here if (itemInfo.get_is_nodisplay()) return false; - // Search takes precedence; not typically useful to search within a - // menu - if (this._activeMenu == null || search != "") - return this._isInfoMatchingSearch(itemInfo, search); - else - return this._isInfoMatchingMenu(itemInfo); - }, - _isInfoMatchingMenu: function(itemInfo) { - let id = itemInfo.get_id(); - for (let i = 0; i < this._activeMenuApps.length; i++) { - let activeApp = this._activeMenuApps[i]; - if (activeApp.get_id() == id) - return true; - } - return false; - }, - - _isInfoMatchingSearch: function(itemInfo, search) { if (search == null || search == '') return true; @@ -455,13 +291,6 @@ AppDisplay.prototype = { return true; } - if (this._menuSearchAppMatches[search]) { - if (this._menuSearchAppMatches[search].hasOwnProperty(itemInfo.get_id())) - return true; - } else { - log("Missing an entry for search term " + search + " in this._menuSearchAppMatches"); - } - return false; }, diff --git a/js/ui/dash.js b/js/ui/dash.js index fe7a4dafb..06cfd9910 100644 --- a/js/ui/dash.js +++ b/js/ui/dash.js @@ -75,15 +75,15 @@ function _getIndexWrapped(index, increment, length) { return (index + increment + length) % length; } -function _createDisplay(displayType) { +function _createDisplay(displayType, flags) { if (displayType == APPS) - return new AppDisplay.AppDisplay(); + return new AppDisplay.AppDisplay(false, flags); else if (displayType == PREFS) - return new AppDisplay.AppDisplay(true); + return new AppDisplay.AppDisplay(true, flags); else if (displayType == DOCS) - return new DocDisplay.DocDisplay(); + return new DocDisplay.DocDisplay(flags); else if (displayType == PLACES) - return new PlaceDisplay.PlaceDisplay(); + return new PlaceDisplay.PlaceDisplay(flags); return null; } @@ -162,32 +162,20 @@ Pane.prototype = { } Signals.addSignalMethods(Pane.prototype); -function ResultArea(displayType, enableNavigation) { - this._init(displayType, enableNavigation); +function ResultArea(displayType, flags) { + this._init(displayType, flags); } ResultArea.prototype = { - _init : function(displayType, enableNavigation) { + _init : function(displayType, flags) { this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL }); this.resultsContainer = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, spacing: DEFAULT_PADDING }); this.actor.append(this.resultsContainer, Big.BoxPackFlags.EXPAND); - this.navContainer = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL }); - this.resultsContainer.append(this.navContainer, Big.BoxPackFlags.NONE); - - this.display = _createDisplay(displayType); - - this.navArea = this.display.getNavigationArea(); - if (enableNavigation && this.navArea) - this.navContainer.append(this.navArea, Big.BoxPackFlags.EXPAND); + this.display = _createDisplay(displayType, flags); this.resultsContainer.append(this.display.actor, Big.BoxPackFlags.EXPAND); - - this.controlBox = new Big.Box({ x_align: Big.BoxAlignment.CENTER }); - this.controlBox.append(this.display.displayControl, Big.BoxPackFlags.NONE); - this.actor.append(this.controlBox, Big.BoxPackFlags.NONE); - this.display.load(); } } @@ -235,8 +223,8 @@ ResultPane.prototype = { // Create a display of displayType and pack it into this pane's // content area. Return the display. - packResults: function(displayType, enableNavigation) { - let resultArea = new ResultArea(displayType, enableNavigation); + packResults: function(displayType) { + let resultArea = new ResultArea(displayType); createPaneForDetails(this._dash, resultArea.display); @@ -713,7 +701,7 @@ Dash.prototype = { this._appsSection.header.moreLink.connect('activated', Lang.bind(this, function (link) { if (this._moreAppsPane == null) { this._moreAppsPane = new ResultPane(this); - this._moreAppsPane.packResults(APPS, true); + this._moreAppsPane.packResults(APPS); this._addPane(this._moreAppsPane); link.setPane(this._moreAppsPane); } @@ -741,7 +729,7 @@ Dash.prototype = { this._docsSection.header.moreLink.connect('activated', Lang.bind(this, function (link) { if (this._moreDocsPane == null) { this._moreDocsPane = new ResultPane(this); - this._moreDocsPane.packResults(DOCS, true); + this._moreDocsPane.packResults(DOCS); this._addPane(this._moreDocsPane); link.setPane(this._moreDocsPane); } @@ -796,8 +784,7 @@ Dash.prototype = { this._showSingleSearchSection(section.type); })); this._searchResultsSection.content.append(section.header.actor, Big.BoxPackFlags.NONE); - section.resultArea = new ResultArea(section.type, false); - section.resultArea.controlBox.hide(); + section.resultArea = new ResultArea(section.type, GenericDisplay.GenericDisplayFlags.DISABLE_VSCROLLING); this._searchResultsSection.content.append(section.resultArea.actor, Big.BoxPackFlags.EXPAND); createPaneForDetails(this, section.resultArea.display); } @@ -847,6 +834,11 @@ Dash.prototype = { } } + // Here work around a bug that I never quite tracked down + // the root cause of; it appeared that the search results + // section was getting a 0 height allocation. + this._searchResultsSection.content.queue_relayout(); + return false; }, @@ -914,7 +906,6 @@ Dash.prototype = { if (section.type == type) { // This will be the only section shown. section.resultArea.display.selectFirstItem(); - section.resultArea.controlBox.show(); let itemCount = section.resultArea.display.getMatchedItemsCount(); let itemCountText = itemCount + ""; section.header.actor.hide(); @@ -938,8 +929,6 @@ Dash.prototype = { let section = this._searchSections[i]; if (section.type == this._searchResultsSingleShownSection) { // This will no longer be the only section shown. - section.resultArea.display.displayPage(0); - section.resultArea.controlBox.hide(); let itemCount = section.resultArea.display.getMatchedItemsCount(); if (itemCount != 0) { section.header.actor.show(); diff --git a/js/ui/docDisplay.js b/js/ui/docDisplay.js index 9596b0b43..011ba7724 100644 --- a/js/ui/docDisplay.js +++ b/js/ui/docDisplay.js @@ -111,19 +111,19 @@ DocDisplayItem.prototype = { /* This class represents a display containing a collection of document items. * The documents are sorted by how recently they were last visited. */ -function DocDisplay() { - this._init(); +function DocDisplay(flags) { + this._init(flags); } DocDisplay.prototype = { __proto__: GenericDisplay.GenericDisplay.prototype, - _init : function() { - GenericDisplay.GenericDisplay.prototype._init.call(this); + _init : function(flags) { + GenericDisplay.GenericDisplay.prototype._init.call(this, flags); // We keep a single timeout callback for updating last visited times // for all the items in the display. This avoids creating individual // callbacks for each item in the display. So proper time updates - // for individual items and item details depend on the item being + // for individual items and item details depend on the item being // associated with one of the displays. this._updateTimeoutTargetTime = -1; this._updateTimeoutId = 0; diff --git a/js/ui/genericDisplay.js b/js/ui/genericDisplay.js index e58c2c632..c154f74f0 100644 --- a/js/ui/genericDisplay.js +++ b/js/ui/genericDisplay.js @@ -11,6 +11,7 @@ const Meta = imports.gi.Meta; const Pango = imports.gi.Pango; const Signals = imports.signals; const Shell = imports.gi.Shell; +const St = imports.gi.St; const Button = imports.ui.button; const DND = imports.ui.dnd; @@ -18,7 +19,6 @@ const Link = imports.ui.link; const Main = imports.ui.main; const RedisplayFlags = { NONE: 0, - RESET_CONTROLS: 1 << 0, FULL: 1 << 1, SUBSEARCH: 1 << 2, IMMEDIATE: 1 << 3 }; @@ -320,31 +320,36 @@ GenericDisplayItem.prototype = { Signals.addSignalMethods(GenericDisplayItem.prototype); +const GenericDisplayFlags = { + DISABLE_VSCROLLING: 1 << 0 +} + /* This is a virtual class that represents a display containing a collection of items * that can be filtered with a search string. */ -function GenericDisplay() { - this._init(); +function GenericDisplay(flags) { + this._init(flags); } GenericDisplay.prototype = { - _init : function() { + _init : function(flags) { + let disableVScrolling = (flags & GenericDisplayFlags.DISABLE_VSCROLLING) != 0; this._search = ''; this._expanded = false; - this._maxItemsPerPage = null; - this._list = new Shell.OverflowList({ spacing: 6.0, - item_height: ITEM_DISPLAY_HEIGHT }); - - this._list.connect('notify::n-pages', Lang.bind(this, function () { - this._updateDisplayControl(true); - })); - this._list.connect('notify::page', Lang.bind(this, function () { - this._updateDisplayControl(false); - })); + if (disableVScrolling) { + this.actor = this._list = new Shell.OverflowList({ spacing: 6, + item_height: ITEM_DISPLAY_HEIGHT }); + } else { + this.actor = new St.ScrollView({ x_fill: true, y_fill: true }); + this.actor.get_hscroll_bar().hide(); + this._list = new St.BoxLayout({ style_class: "generic-display-container", + vertical: true }); + this.actor.add_actor(this._list); + } this._pendingRedisplay = RedisplayFlags.NONE; - this._list.connect('notify::mapped', Lang.bind(this, this._onMappedNotify)); + this.actor.connect('notify::mapped', Lang.bind(this, this._onMappedNotify)); // map where Object represents the item info this._allItems = {}; @@ -356,13 +361,6 @@ GenericDisplay.prototype = { this._displayedItems = {}; this._openDetailIndex = -1; this._selectedIndex = -1; - // These two are public - .actor is the normal "actor subclass" property, - // but we also expose a .displayControl actor which is separate. - // See also getNavigationArea. - this.actor = this._list; - this.displayControl = new Big.Box({ background_color: ITEM_DISPLAY_BACKGROUND_COLOR, - spacing: 12, - orientation: Big.BoxOrientation.HORIZONTAL}); }, //// Public methods //// @@ -373,7 +371,7 @@ GenericDisplay.prototype = { if (lowertext == this._search) { return; } - let flags = RedisplayFlags.RESET_CONTROLS | RedisplayFlags.IMMEDIATE; + let flags = RedisplayFlags.IMMEDIATE; if (this._search != '') { // Because we combine search terms with OR, we have to be sure that no new term // was introduced before deciding that the new search results will be a subset of @@ -401,7 +399,7 @@ GenericDisplay.prototype = { // to the bottom one. Returns true if the selection actually moved up, false if it wrapped // around to the bottom. selectUp: function() { - let count = this._list.displayedCount; + let count = this._getVisibleCount(); let selectedUp = true; let prev = this._selectedIndex - 1; if (this._selectedIndex <= 0) { @@ -416,7 +414,7 @@ GenericDisplay.prototype = { // to the top one. Returns true if the selection actually moved down, false if it wrapped // around to the top. selectDown: function() { - let count = this._list.displayedCount; + let count = this._getVisibleCount(); let selectedDown = true; let next = this._selectedIndex + 1; if (this._selectedIndex == count - 1) { @@ -435,7 +433,7 @@ GenericDisplay.prototype = { // Selects the last item among the displayed items. selectLastItem: function() { - let count = this._list.displayedCount; + let count = this._getVisibleCount(); if (this.hasItems()) this._selectIndex(count - 1); }, @@ -472,6 +470,8 @@ GenericDisplay.prototype = { resetState: function() { this._filterReset(); this._openDetailIndex = -1; + if (!(this.actor instanceof Shell.OverflowList)) + this.actor.get_vscroll_bar().get_adjustment().value = 0; }, // Returns an actor which acts as a sidebar; this is used for @@ -485,15 +485,6 @@ GenericDisplay.prototype = { return item.createDetailsActor(); }, - // Displays the page specified by the pageNumber argument. - displayPage: function(pageNumber) { - // Cleanup from the previous selection, but don't unset this._selectedIndex - if (this.hasSelected()) { - this._findDisplayedByIndex(this._selectedIndex).markSelected(false); - } - this._list.page = pageNumber; - }, - //// Protected methods //// _recreateDisplayItems: function() { @@ -519,14 +510,14 @@ GenericDisplay.prototype = { Lang.bind(this, function() { // update the selection - this._selectIndex(this._list.get_actor_index(displayItem.actor)); + this._selectIndex(this._list.get_children().indexOf(displayItem.actor)); this.activateSelected(); })); displayItem.connect('show-details', Lang.bind(this, function() { - let index = this._list.get_actor_index(displayItem.actor); + let index = this._list.get_children().indexOf(displayItem.actor); /* Close the details pane if already open */ if (index == this._openDetailIndex) { this._openDetailIndex = -1; @@ -541,9 +532,10 @@ GenericDisplay.prototype = { // Removes an item identifed by the itemId from the displayed items. _removeDisplayItem: function(itemId) { - let count = this._list.displayedCount; + let children = this._list.get_children(); + let count = children.length; let displayItem = this._displayedItems[itemId]; - let displayItemIndex = this._list.get_actor_index(displayItem.actor); + let displayItemIndex = children.indexOf(displayItem.actor); if (this.hasSelected() && count == 1) { this.unsetSelected(); @@ -638,28 +630,22 @@ GenericDisplay.prototype = { /* * Updates the displayed items, applying the search string if one exists. * @flags: Flags controlling redisplay behavior as follows: - * RESET_CONTROLS - indicates if the page selection should be reset when displaying the matching results. - * We reset the page selection when the change in results was initiated by the user by - * entering a different search criteria or by viewing the results list in a different - * size mode, but we keep the page selection the same if the results got updated on - * their own while the user was browsing through the result pages. * SUBSEARCH - Indicates that the current _search is a superstring of the previous * one, which implies we only need to re-search through previous results. - * FULL - Indicates that we need recreate all displayed items; implies RESET_CONTROLS as well + * FULL - Indicates that we need recreate all displayed items. * IMMEDIATE - Do the full redisplay even if we're not mapped. This is useful * if you want to get the number of matched items and show/hide a section based on * that number. */ _redisplay: function(flags) { - let immediate = (flags & RedisplayFlags.IMMEDIATE) > 0; - if (!immediate && !this._list.mapped) { + let immediate = (flags & RedisplayFlags.IMMEDIATE) != 0; + if (!immediate && !this.actor.mapped) { this._pendingRedisplay |= flags; return; } - let isSubSearch = (flags & RedisplayFlags.SUBSEARCH) > 0; - let fullReload = (flags & RedisplayFlags.FULL) > 0; - let resetPage = (flags & RedisplayFlags.RESET_CONTROLS) > 0 || fullReload; + let isSubSearch = (flags & RedisplayFlags.SUBSEARCH) != 0; + let fullReload = (flags & RedisplayFlags.FULL) != 0; let hadSelected = this.hasSelected(); this.unsetSelected(); @@ -681,9 +667,6 @@ GenericDisplay.prototype = { this._redisplayReordering(); } - if (resetPage) - this._list.page = 0; - if (hadSelected) { this._selectedIndex = -1; this.selectFirstItem(); @@ -783,59 +766,10 @@ GenericDisplay.prototype = { return matchScores; }, - /* - * Updates the display control to reflect the matched items set and the page selected. - * - * resetDisplayControl - indicates if the display control should be re-created because - * the results or the space allocated for them changed. If it's false, - * the existing display control is used and only the page links are - * updated to reflect the current page selection. - */ - _updateDisplayControl: function(resetDisplayControl) { - if (resetDisplayControl) { - this.displayControl.remove_all(); - let nPages = this._list.n_pages; - // Don't show the page indicator if there is only one page. - if (nPages == 1) - return; - let pageNumber = this._list.page; - for (let i = 0; i < nPages; i++) { - let pageControl = new Link.Link({ color: (i == pageNumber) ? DISPLAY_CONTROL_SELECTED_COLOR : ITEM_DISPLAY_DESCRIPTION_COLOR, - font_name: "Sans Bold 16px", - text: (i+1) + "", - reactive: (i == pageNumber) ? false : true}); - this.displayControl.append(pageControl.actor, Big.BoxPackFlags.NONE); - - // we use pageNumberLocalScope to get the page number right in the callback function - let pageNumberLocalScope = i; - pageControl.connect('clicked', - Lang.bind(this, - function(o, event) { - this.displayPage(pageNumberLocalScope); - })); - } - } else { - let pageControlActors = this.displayControl.get_children(); - for (let i = 0; i < pageControlActors.length; i++) { - let pageControlActor = pageControlActors[i]; - if (i == this._list.page) { - pageControlActor.color = DISPLAY_CONTROL_SELECTED_COLOR; - pageControlActor.reactive = false; - } else { - pageControlActor.color = ITEM_DISPLAY_DESCRIPTION_COLOR; - pageControlActor.reactive = true; - } - } - } - if (this.hasSelected()) { - this.selectFirstItem(); - } - }, - // Returns a display item based on its index in the ordering of the // display children. _findDisplayedByIndex: function(index) { - let actor = this._list.get_displayed_actor(index); + let actor = this._list.get_children()[index]; return this._findDisplayedByActor(actor); }, @@ -869,8 +803,14 @@ GenericDisplay.prototype = { this.emit('selected'); }, + _getVisibleCount: function() { + if (this.actor instanceof Shell.OverflowList) + return this._list.displayed_count; + return this._list.get_n_children(); + }, + _onMappedNotify: function () { - let mapped = this._list.mapped; + let mapped = this.actor.mapped; if (mapped && this._pendingRedisplay > RedisplayFlags.NONE) this._redisplay(this._pendingRedisplay); diff --git a/js/ui/placeDisplay.js b/js/ui/placeDisplay.js index acee53e55..af92c666c 100644 --- a/js/ui/placeDisplay.js +++ b/js/ui/placeDisplay.js @@ -470,15 +470,15 @@ PlaceDisplayItem.prototype = { }; -function PlaceDisplay() { - this._init(); +function PlaceDisplay(flags) { + this._init(flags); } PlaceDisplay.prototype = { __proto__: GenericDisplay.GenericDisplay.prototype, - _init: function() { - GenericDisplay.GenericDisplay.prototype._init.call(this); + _init: function(flags) { + GenericDisplay.GenericDisplay.prototype._init.call(this, flags); this._stale = true; Main.placesManager.connect('places-updated', Lang.bind(this, function (e) { this._stale = true; From bc255a525fab492dc02914a25dd094c74dafb7ee Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 6 Nov 2009 14:55:03 -0500 Subject: [PATCH 26/51] [overview] Port pane to CSS https://bugzilla.gnome.org/show_bug.cgi?id=600734 --- data/Makefile.am | 2 +- data/{ => theme}/close.svg | 0 data/theme/gnome-shell.css | 13 +++++++++++++ js/ui/dash.js | 40 +++++++++++++------------------------- 4 files changed, 27 insertions(+), 28 deletions(-) rename data/{ => theme}/close.svg (100%) diff --git a/data/Makefile.am b/data/Makefile.am index 8c090c08f..1f5857d77 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -16,7 +16,6 @@ imagesdir = $(pkgdatadir)/images dist_images_DATA = \ add-workspace.svg \ app-well-glow.png \ - close.svg \ close-black.svg \ info.svg \ magnifier.svg \ @@ -25,6 +24,7 @@ dist_images_DATA = \ themedir = $(pkgdatadir)/theme dist_theme_DATA = \ theme/gnome-shell.css \ + theme/close.svg \ theme/scroll-button-down.png \ theme/scroll-button-down-hover.png \ theme/scroll-button-up.png \ diff --git a/data/close.svg b/data/theme/close.svg similarity index 100% rename from data/close.svg rename to data/theme/close.svg diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index ec4cfa573..a1e49211b 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -137,6 +137,19 @@ StTooltip { font-weight: normal; } +.dash-pane { + background-color: rgba(0,0,0,0.95); + border: 1px solid #262626; + padding: 4px; + spacing: 4px; +} + +.dash-pane-close { + background-image: url("close.svg"); + width: 16px; + height: 16px; +} + /* LookingGlass */ #LookingGlassDialog diff --git a/js/ui/dash.js b/js/ui/dash.js index 06cfd9910..3a536ec34 100644 --- a/js/ui/dash.js +++ b/js/ui/dash.js @@ -50,13 +50,6 @@ const SECTION_INNER_SPACING = 8; const BROWSE_ACTIVATED_BG = new Clutter.Color(); BROWSE_ACTIVATED_BG.from_pixel(0x303030f0); -const PANE_BORDER_COLOR = new Clutter.Color(); -PANE_BORDER_COLOR.from_pixel(0x101d3cfa); -const PANE_BORDER_WIDTH = 2; - -const PANE_BACKGROUND_COLOR = new Clutter.Color(); -PANE_BACKGROUND_COLOR.from_pixel(0x000000f4); - const APPS = "apps"; const PREFS = "prefs"; const DOCS = "docs"; @@ -95,36 +88,29 @@ Pane.prototype = { _init: function () { this._open = false; - this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, - background_color: PANE_BACKGROUND_COLOR, - border: PANE_BORDER_WIDTH, - border_color: PANE_BORDER_COLOR, - padding: DEFAULT_PADDING, - reactive: true }); + this.actor = new St.BoxLayout({ style_class: "dash-pane", + vertical: true, + reactive: true }); this.actor.connect('button-press-event', Lang.bind(this, function (a, e) { // Eat button press events so they don't go through and close the pane return true; })); - let chromeTop = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, - spacing: 6 }); + let chromeTop = new St.BoxLayout(); - let closeIconUri = "file://" + global.imagedir + "close.svg"; - let closeIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER, - closeIconUri, - 16, - 16); + let closeIcon = new St.Bin({ style_class: "dash-pane-close" }); closeIcon.reactive = true; closeIcon.connect('button-press-event', Lang.bind(this, function (b, e) { this.close(); return true; })); - chromeTop.append(closeIcon, Big.BoxPackFlags.END); - this.actor.append(chromeTop, Big.BoxPackFlags.NONE); + let dummy = new St.Bin(); + chromeTop.add(dummy, { expand: true }); + chromeTop.add(closeIcon, { x_align: St.Align.END }); + this.actor.add(chromeTop); - this.content = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, - spacing: DEFAULT_PADDING }); - this.actor.append(this.content, Big.BoxPackFlags.EXPAND); + this.content = new St.BoxLayout({ vertical: true }); + this.actor.add(this.content, { expand: true }); // Hidden by default this.actor.hide(); @@ -200,7 +186,7 @@ function createPaneForDetails(dash, display) { if (index >= 0) { detailPane.destroyContent(); let details = display.createDetailsForIndex(index); - detailPane.content.append(details, Big.BoxPackFlags.EXPAND); + detailPane.content.add(details, { expand: true }); detailPane.open(); } else { detailPane.close(); @@ -228,7 +214,7 @@ ResultPane.prototype = { createPaneForDetails(this._dash, resultArea.display); - this.content.append(resultArea.actor, Big.BoxPackFlags.EXPAND); + this.content.add(resultArea.actor, { expand: true }); this.connect('open-state-changed', Lang.bind(this, function(pane, isOpen) { resultArea.display.resetState(); })); From 66cab3b8ed2e7e881c661619b3c7db39455859af Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 6 Nov 2009 16:08:07 -0500 Subject: [PATCH 27/51] [genericDisplay+other] Port to CSS, style cleanups Mostly a straightforward porting of style code to CSS, except that various bits of other code referenced a few GenericDisplay constants, so those needed to be ported as well. Add some padding at the top between the close button and the items. Center the text and description. https://bugzilla.gnome.org/show_bug.cgi?id=600734 --- data/theme/gnome-shell.css | 54 +++++++++++++++++++++++ js/ui/appIcon.js | 9 ++-- js/ui/dash.js | 22 +++++----- js/ui/docDisplay.js | 7 ++- js/ui/genericDisplay.js | 89 ++++++++++++-------------------------- js/ui/placeDisplay.js | 8 ++-- 6 files changed, 102 insertions(+), 87 deletions(-) diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index a1e49211b..bd8b58eea 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -98,6 +98,10 @@ StTooltip { background-color: #c4c4c4; } +.dash-section { + spacing: 8px; +} + .section-header { border: 1px solid #262626; -shell-gradient-top: #161616; @@ -130,6 +134,12 @@ StTooltip { .section-count { } +.dash-section-content { + font-size: 14px; + color: #ffffff; + spacing: 8px; +} + .more-link { border-left: 1px solid #262626; padding: 0px 0px 0px 4px; @@ -150,6 +160,50 @@ StTooltip { height: 16px; } +/* GenericDisplay */ + +.generic-display-container { + spacing: 4px; +} + +.generic-display-item { + height: 50px; + border-radius: 4px; + color: #ffffff; + font-size: 14px; + spacing: 4px; +} + +.generic-display-item:selected { + background-color: rgba(79,111,173,0.66); +} + +.generic-display-item-text { + spacing: 4px; +} + +.generic-display-item-description { + font-size: 12px; + color: #bababa; +} + +.generic-display-details { + font-size: 14px; + color: #ffffff; +} + +.generic-display-details-name { + font-weight: bold; +} + +/* AppIcon */ + +.app-icon-label { + font-size: 12px; +} + +/* Places */ + /* LookingGlass */ #LookingGlassDialog diff --git a/js/ui/appIcon.js b/js/ui/appIcon.js index b2cc8af68..571e05097 100644 --- a/js/ui/appIcon.js +++ b/js/ui/appIcon.js @@ -8,6 +8,7 @@ const Mainloop = imports.mainloop; const Pango = imports.gi.Pango; const Shell = imports.gi.Shell; const Signals = imports.signals; +const St = imports.gi.St; const Gettext = imports.gettext.domain('gnome-shell'); const _ = Gettext.gettext; @@ -99,11 +100,9 @@ AppIcon.prototype = { nameBox.connect('allocate', Lang.bind(this, this._nameBoxAllocate)); this._nameBox = nameBox; - this._name = new Clutter.Text({ color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR, - font_name: "Sans 12px", - line_alignment: Pango.Alignment.CENTER, - ellipsize: Pango.EllipsizeMode.END, - text: this.app.get_name() }); + this._name = new St.Label({ style_class: "app-icon-label", + text: this.app.get_name() }); + this._name.clutter_text.line_alignment = Pango.Alignment.CENTER; nameBox.add_actor(this._name); if (this._showGlow) { this._glowBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL }); diff --git a/js/ui/dash.js b/js/ui/dash.js index 3a536ec34..29a47c673 100644 --- a/js/ui/dash.js +++ b/js/ui/dash.js @@ -45,8 +45,6 @@ const HIGHLIGHTED_SEARCH_CURSOR_COLOR = SEARCH_TEXT_COLOR; const SEARCH_BORDER_BOTTOM_COLOR = new Clutter.Color(); SEARCH_BORDER_BOTTOM_COLOR.from_pixel(0x191919ff); -const SECTION_INNER_SPACING = 8; - const BROWSE_ACTIVATED_BG = new Clutter.Color(); BROWSE_ACTIVATED_BG.from_pixel(0x303030f0); @@ -535,11 +533,13 @@ function Section(titleString, suppressBrowse) { Section.prototype = { _init: function(titleString, suppressBrowse) { - this.actor = new Big.Box({ spacing: SECTION_INNER_SPACING }); + this.actor = new St.BoxLayout({ style_class: 'dash-section', + vertical: true }); this.header = new SectionHeader(titleString, suppressBrowse); - this.actor.append(this.header.actor, Big.BoxPackFlags.NONE); - this.content = new Big.Box({spacing: SECTION_INNER_SPACING }); - this.actor.append(this.content, Big.BoxPackFlags.EXPAND); + this.actor.add(this.header.actor); + this.content = new St.BoxLayout({ style_class: 'dash-section-content', + vertical: true }); + this.actor.add(this.content); } } @@ -681,7 +681,7 @@ Dash.prototype = { this._appsSection = new Section(_("APPLICATIONS")); let appWell = new AppDisplay.AppWell(); - this._appsSection.content.append(appWell.actor, Big.BoxPackFlags.EXPAND); + this._appsSection.content.add(appWell.actor, { expand: true }); this._moreAppsPane = null; this._appsSection.header.moreLink.connect('activated', Lang.bind(this, function (link) { @@ -701,7 +701,7 @@ Dash.prototype = { network locations, etc. */ this._placesSection = new Section(_("PLACES"), true); let placesDisplay = new PlaceDisplay.DashPlaceDisplay(); - this._placesSection.content.append(placesDisplay.actor, Big.BoxPackFlags.EXPAND); + this._placesSection.content.add(placesDisplay.actor, { expand: true }); this.sectionArea.append(this._placesSection.actor, Big.BoxPackFlags.NONE); /***** Documents *****/ @@ -709,7 +709,7 @@ Dash.prototype = { this._docsSection = new Section(_("RECENT DOCUMENTS")); this._docDisplay = new DocDisplay.DashDocDisplay(); - this._docsSection.content.append(this._docDisplay.actor, Big.BoxPackFlags.EXPAND); + this._docsSection.content.add(this._docDisplay.actor, { expand: true }); this._moreDocsPane = null; this._docsSection.header.moreLink.connect('activated', Lang.bind(this, function (link) { @@ -769,9 +769,9 @@ Dash.prototype = { function () { this._showSingleSearchSection(section.type); })); - this._searchResultsSection.content.append(section.header.actor, Big.BoxPackFlags.NONE); + this._searchResultsSection.content.add(section.header.actor); section.resultArea = new ResultArea(section.type, GenericDisplay.GenericDisplayFlags.DISABLE_VSCROLLING); - this._searchResultsSection.content.append(section.resultArea.actor, Big.BoxPackFlags.EXPAND); + this._searchResultsSection.content.add(section.resultArea.actor, { expand: true }); createPaneForDetails(this, section.resultArea.display); } diff --git a/js/ui/docDisplay.js b/js/ui/docDisplay.js index 011ba7724..2b67f50ba 100644 --- a/js/ui/docDisplay.js +++ b/js/ui/docDisplay.js @@ -8,6 +8,7 @@ const Lang = imports.lang; const Pango = imports.gi.Pango; const Shell = imports.gi.Shell; const Signals = imports.signals; +const St = imports.gi.St; const Mainloop = imports.mainloop; const DocInfo = imports.misc.docInfo; @@ -278,10 +279,8 @@ DashDocDisplayItem.prototype = { let iconBox = new Big.Box({ y_align: Big.BoxAlignment.CENTER }); iconBox.append(this._icon, Big.BoxPackFlags.NONE); this.actor.append(iconBox, Big.BoxPackFlags.NONE); - let name = new Clutter.Text({ font_name: "Sans 14px", - color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR, - ellipsize: Pango.EllipsizeMode.END, - text: docInfo.name }); + let name = new St.Label({ style_class: "dash-recent-docs-item", + text: docInfo.name }); this.actor.append(name, Big.BoxPackFlags.EXPAND); let draggable = DND.makeDraggable(this.actor); diff --git a/js/ui/genericDisplay.js b/js/ui/genericDisplay.js index c154f74f0..8ee03343b 100644 --- a/js/ui/genericDisplay.js +++ b/js/ui/genericDisplay.js @@ -23,14 +23,8 @@ const RedisplayFlags = { NONE: 0, SUBSEARCH: 1 << 2, IMMEDIATE: 1 << 3 }; -const ITEM_DISPLAY_NAME_COLOR = new Clutter.Color(); -ITEM_DISPLAY_NAME_COLOR.from_pixel(0xffffffff); const ITEM_DISPLAY_DESCRIPTION_COLOR = new Clutter.Color(); ITEM_DISPLAY_DESCRIPTION_COLOR.from_pixel(0xffffffbb); -const ITEM_DISPLAY_BACKGROUND_COLOR = new Clutter.Color(); -ITEM_DISPLAY_BACKGROUND_COLOR.from_pixel(0x00000000); -const ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR = new Clutter.Color(); -ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR.from_pixel(0x4f6fadaa); const DISPLAY_CONTROL_SELECTED_COLOR = new Clutter.Color(); DISPLAY_CONTROL_SELECTED_COLOR.from_pixel(0x112288ff); const PREVIEW_BOX_BACKGROUND_COLOR = new Clutter.Color(); @@ -38,10 +32,7 @@ PREVIEW_BOX_BACKGROUND_COLOR.from_pixel(0xADADADf0); const DEFAULT_PADDING = 4; -const ITEM_DISPLAY_HEIGHT = 50; const ITEM_DISPLAY_ICON_SIZE = 48; -const ITEM_DISPLAY_PADDING = 1; -const ITEM_DISPLAY_PADDING_RIGHT = 2; const DEFAULT_COLUMN_GAP = 6; const PREVIEW_ICON_SIZE = 96; @@ -64,12 +55,8 @@ function GenericDisplayItem() { GenericDisplayItem.prototype = { _init: function() { - this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, - spacing: ITEM_DISPLAY_PADDING, - reactive: true, - background_color: ITEM_DISPLAY_BACKGROUND_COLOR, - corner_radius: 4, - height: ITEM_DISPLAY_HEIGHT }); + this.actor = new St.BoxLayout({ style_class: "generic-display-item", + reactive: true }); this.actor._delegate = this; this.actor.connect('button-release-event', @@ -83,16 +70,12 @@ GenericDisplayItem.prototype = { let draggable = DND.makeDraggable(this.actor); draggable.connect('drag-begin', Lang.bind(this, this._onDragBegin)); - this._infoContent = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, - spacing: DEFAULT_PADDING }); - this.actor.append(this._infoContent, Big.BoxPackFlags.EXPAND); + this._iconBin = new St.Bin(); + this.actor.add(this._iconBin); - this._iconBox = new Big.Box(); - this._infoContent.append(this._iconBox, Big.BoxPackFlags.NONE); - - this._infoText = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, - spacing: DEFAULT_PADDING }); - this._infoContent.append(this._infoText, Big.BoxPackFlags.EXPAND); + this._infoText = new St.BoxLayout({ style_class: "generic-display-item-text", + vertical: true }); + this.actor.add(this._infoText, { expand: true, y_fill: false }); let infoIconUri = "file://" + global.imagedir + "info.svg"; let infoIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER, @@ -105,7 +88,7 @@ GenericDisplayItem.prototype = { padding_left: DEFAULT_PADDING, padding_right: DEFAULT_PADDING, y_align: Big.BoxAlignment.CENTER }); buttonBox.append(this._informationButton.actor, Big.BoxPackFlags.NONE); - this.actor.append(buttonBox, Big.BoxPackFlags.END); + this.actor.add(buttonBox, { x_fill: false, x_align: St.Align.END }); // Connecting to the button-press-event for the information button ensures that the actor, // which is a draggable actor, does not get the button-press-event and doesn't initiate @@ -161,16 +144,8 @@ GenericDisplayItem.prototype = { // Highlights the item by setting a different background color than the default // if isSelected is true, removes the highlighting otherwise. markSelected: function(isSelected) { - let color; - if (isSelected) { - color = ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR; - this._informationButton.forceShow(true); - } - else { - color = ITEM_DISPLAY_BACKGROUND_COLOR; - this._informationButton.forceShow(false); - } - this.actor.background_color = color; + this.actor.set_style_pseudo_class(isSelected ? "selected" : null); + this._informationButton.forceShow(isSelected) }, /* @@ -186,19 +161,14 @@ GenericDisplayItem.prototype = { spacing: PREVIEW_BOX_SPACING }); // Inner box with name and description - let textDetails = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, - spacing: PREVIEW_BOX_SPACING }); - let detailsName = new Clutter.Text({ color: ITEM_DISPLAY_NAME_COLOR, - font_name: "Sans bold 14px", - line_wrap: true, - text: this._name.text }); - textDetails.append(detailsName, Big.BoxPackFlags.NONE); + let textDetails = new St.BoxLayout({ style_class: 'generic-display-details', + vertical: true }); + let detailsName = new St.Label({ style_class: 'generic-display-details-name', + text: this._name.text }); + textDetails.add(detailsName); - let detailsDescription = new Clutter.Text({ color: ITEM_DISPLAY_NAME_COLOR, - font_name: "Sans 14px", - line_wrap: true, - text: this._description.text }); - textDetails.append(detailsDescription, Big.BoxPackFlags.NONE); + let detailsDescription = new St.Label({ text: this._description.text }); + textDetails.add(detailsDescription); this._detailsDescriptions.push(detailsDescription); @@ -224,7 +194,7 @@ GenericDisplayItem.prototype = { // Destroys the item. destroy: function() { - this.actor.destroy(); + this.actor.destroy(); }, //// Pure virtual public methods //// @@ -261,20 +231,15 @@ GenericDisplayItem.prototype = { } this._icon = this._createIcon(); - this._iconBox.append(this._icon, Big.BoxPackFlags.NONE); + this._iconBin.set_child(this._icon); - this._name = new Clutter.Text({ color: ITEM_DISPLAY_NAME_COLOR, - font_name: "Sans 14px", - ellipsize: Pango.EllipsizeMode.END, - text: nameText }); - this._infoText.append(this._name, Big.BoxPackFlags.EXPAND); + this._name = new St.Label({ style_class: "generic-display-item-name", + text: nameText }); + this._infoText.add(this._name); - this._description = new Clutter.Text({ color: ITEM_DISPLAY_DESCRIPTION_COLOR, - font_name: "Sans 12px", - ellipsize: Pango.EllipsizeMode.END, - text: descriptionText ? descriptionText : "" - }); - this._infoText.append(this._description, Big.BoxPackFlags.EXPAND); + this._description = new St.Label({ style_class: "generic-display-item-description", + text: descriptionText ? descriptionText : "" }); + this._infoText.add(this._description); }, // Sets the description text for the item, including the description text @@ -339,11 +304,11 @@ GenericDisplay.prototype = { if (disableVScrolling) { this.actor = this._list = new Shell.OverflowList({ spacing: 6, - item_height: ITEM_DISPLAY_HEIGHT }); + item_height: 50 }); } else { this.actor = new St.ScrollView({ x_fill: true, y_fill: true }); this.actor.get_hscroll_bar().hide(); - this._list = new St.BoxLayout({ style_class: "generic-display-container", + this._list = new St.BoxLayout({ style_class: 'generic-display-container', vertical: true }); this.actor.add_actor(this._list); } diff --git a/js/ui/placeDisplay.js b/js/ui/placeDisplay.js index af92c666c..3746c96b2 100644 --- a/js/ui/placeDisplay.js +++ b/js/ui/placeDisplay.js @@ -9,6 +9,7 @@ const Shell = imports.gi.Shell; const Lang = imports.lang; const Mainloop = imports.mainloop; const Signals = imports.signals; +const St = imports.gi.St; const Gettext = imports.gettext.domain('gnome-shell'); const _ = Gettext.gettext; @@ -43,7 +44,6 @@ PlaceInfo.prototype = { } } - function PlacesManager() { this._init(); } @@ -326,10 +326,8 @@ DashPlaceDisplayItem.prototype = { this._info.launch(); Main.overview.hide(); })); - let text = new Clutter.Text({ font_name: 'Sans 14px', - ellipsize: Pango.EllipsizeMode.END, - color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR, - text: this.name }); + let text = new St.Label({ style_class: 'places-item', + text: info.name }); let iconBox = new Big.Box({ y_align: Big.BoxAlignment.CENTER }); iconBox.append(this._icon, Big.BoxPackFlags.NONE); this.actor.append(iconBox, Big.BoxPackFlags.NONE); From ce90dda76f28448dadf19099020b570fdfc66387 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 6 Nov 2009 17:15:34 -0500 Subject: [PATCH 28/51] [overview] Constrain popup panes, dim workspaces when active Rather than the popup panes taking up the whole non-panel height, constrain them to the height of the workspaces, which is also the "dash content area". https://bugzilla.gnome.org/show_bug.cgi?id=600734 --- js/ui/overview.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/js/ui/overview.js b/js/ui/overview.js index dad7822fa..e49119275 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -123,8 +123,7 @@ Overview.prototype = { // Container to hold popup pane chrome. this._paneContainer = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, - spacing: 6 - }); + spacing: 6 }); // Note here we explicitly don't set the paneContainer to be reactive yet; that's done // inside the notify::visible handler on panes. this._paneContainer.connect('button-release-event', Lang.bind(this, function(background) { @@ -197,9 +196,9 @@ Overview.prototype = { this._backOver.set_size(global.screen_width, global.screen_height); this._paneContainer.set_position(this._dash.actor.x + this._dash.actor.width + DEFAULT_PADDING, - contentY); + this._workspacesY); // Dynamic width - this._paneContainer.height = contentHeight; + this._paneContainer.height = this._workspacesHeight; this._transparentBackground.set_position(this._paneContainer.x, this._paneContainer.y); this._transparentBackground.set_size(primary.width - this._paneContainer.x, @@ -228,6 +227,7 @@ Overview.prototype = { this._activeDisplayPane.close(); return true; })); + this._workspaces.actor.opacity = 64; } else if (pane == this._activeDisplayPane) { this._activeDisplayPane = null; if (backgroundEventId != null) { @@ -236,6 +236,7 @@ Overview.prototype = { } this._transparentBackground.lower_bottom(); this._paneContainer.lower_bottom(); + this._workspaces.actor.opacity = 255; } })); }, From bf68f9f0cf5178ee62329fe9a2ba0c3da989b7d2 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 6 Nov 2009 17:32:23 -0500 Subject: [PATCH 29/51] [dash] Port section container to CSS, lower spacing Newer mockup has smaller spacing. https://bugzilla.gnome.org/show_bug.cgi?id=600734 --- data/theme/gnome-shell.css | 4 ++++ js/ui/dash.js | 12 ++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index bd8b58eea..c067443f7 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -89,6 +89,10 @@ StTooltip { padding: 0px 14px; } +#dashSections { + spacing: 12px; +} + #searchEntry { padding: 4px; border-bottom: 1px solid #262626; diff --git a/js/ui/dash.js b/js/ui/dash.js index 29a47c673..f757aaeaa 100644 --- a/js/ui/dash.js +++ b/js/ui/dash.js @@ -565,8 +565,8 @@ Dash.prototype = { // Size for this one explicitly set from overlay.js this.searchArea = new Big.Box({ y_align: Big.BoxAlignment.CENTER }); - this.sectionArea = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, - spacing: DASH_SECTION_SPACING }); + this.sectionArea = new St.BoxLayout({ name: "dashSections", + vertical: true }); this.actor.add(this.searchArea); this.actor.add(this.sectionArea); @@ -693,7 +693,7 @@ Dash.prototype = { } })); - this.sectionArea.append(this._appsSection.actor, Big.BoxPackFlags.NONE); + this.sectionArea.add(this._appsSection.actor); /***** Places *****/ @@ -702,7 +702,7 @@ Dash.prototype = { this._placesSection = new Section(_("PLACES"), true); let placesDisplay = new PlaceDisplay.DashPlaceDisplay(); this._placesSection.content.add(placesDisplay.actor, { expand: true }); - this.sectionArea.append(this._placesSection.actor, Big.BoxPackFlags.NONE); + this.sectionArea.add(this._placesSection.actor); /***** Documents *****/ @@ -727,7 +727,7 @@ Dash.prototype = { })); this._docDisplay.emit('changed'); - this.sectionArea.append(this._docsSection.actor, Big.BoxPackFlags.EXPAND); + this.sectionArea.add(this._docsSection.actor, { expand: true }); /***** Search Results *****/ @@ -775,7 +775,7 @@ Dash.prototype = { createPaneForDetails(this, section.resultArea.display); } - this.sectionArea.append(this._searchResultsSection.actor, Big.BoxPackFlags.EXPAND); + this.sectionArea.add(this._searchResultsSection.actor, { expand: true }); this._searchResultsSection.actor.hide(); }, From 426d7bc515cf3d7afb3ba6480c6ca085061296a1 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 11 Nov 2009 14:13:38 -0500 Subject: [PATCH 30/51] [dash] Port search section headers to CSS Experimented with moving the (see all) into a tooltip, but given that we're not emphasizing the drilldown, removed for now. https://bugzilla.gnome.org/show_bug.cgi?id=600734 --- data/theme/gnome-shell.css | 11 +++++++++ js/ui/dash.js | 46 +++++++++----------------------------- 2 files changed, 22 insertions(+), 35 deletions(-) diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index c067443f7..a8bf9ba92 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -93,6 +93,17 @@ StTooltip { spacing: 12px; } +.dash-search-section-header { + padding: 6px 0px; + spacing: 4px; + font-size: 12px; + color: #bbbbbb; +} + +.dash-search-section-title, dash-search-section-count { + font-weight: bold; +} + #searchEntry { padding: 4px; border-bottom: 1px solid #262626; diff --git a/js/ui/dash.js b/js/ui/dash.js index f757aaeaa..89a549281 100644 --- a/js/ui/dash.js +++ b/js/ui/dash.js @@ -21,8 +21,6 @@ const Main = imports.ui.main; const DEFAULT_PADDING = 4; const DEFAULT_SPACING = 4; -const DASH_SECTION_PADDING = 6; -const DASH_SECTION_SPACING = 40; const BACKGROUND_COLOR = new Clutter.Color(); BACKGROUND_COLOR.from_pixel(0x000000c0); @@ -489,41 +487,19 @@ function SearchSectionHeader(title, onClick) { SearchSectionHeader.prototype = { _init : function(title, onClick) { - let box = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, - padding_top: DASH_SECTION_PADDING, - padding_bottom: DASH_SECTION_PADDING, - spacing: DEFAULT_SPACING }); - let titleText = new Clutter.Text({ color: BRIGHTER_TEXT_COLOR, - font_name: 'Sans Bold 12px', - text: title }); - this.tooltip = new Clutter.Text({ color: BRIGHTER_TEXT_COLOR, - font_name: 'Sans 12px', - text: _("(see all)") }); - this.countText = new Clutter.Text({ color: BRIGHTER_TEXT_COLOR, - font_name: 'Sans Bold 14px' }); + this.actor = new St.Button({ style_class: "dash-search-section-header", + x_fill: true, + y_fill: true }); + let box = new St.BoxLayout(); + this.actor.set_child(box); + let titleText = new St.Label({ style_class: "dash-search-section-title", + text: title }); + this.countText = new St.Label({ style_class: "dash-search-section-count" }); - box.append(titleText, Big.BoxPackFlags.NONE); - box.append(this.tooltip, Big.BoxPackFlags.NONE); - box.append(this.countText, Big.BoxPackFlags.END); + box.add(titleText); + box.add(this.countText, { expand: true, x_fill: false, x_align: St.Align.END }); - this.tooltip.hide(); - - let button = new Button.Button(box, PRELIGHT_COLOR, BACKGROUND_COLOR, - TEXT_COLOR); - button.actor.height = box.height; - button.actor.padding_left = DEFAULT_PADDING; - button.actor.padding_right = DEFAULT_PADDING; - - button.actor.connect('activate', onClick); - button.actor.connect('notify::hover', Lang.bind(this, this._updateTooltip)); - this.actor = button.actor; - }, - - _updateTooltip : function(actor) { - if (actor.hover) - this.tooltip.show(); - else - this.tooltip.hide(); + this.actor.connect('clicked', onClick); } } From 06cf6c51f312316a2d6c229c86b36aafd541fb19 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 10 Nov 2009 14:31:59 -0500 Subject: [PATCH 31/51] [placeDisplay] Port more to CSS, lower spacing Newer mockups have smaller spacing here. https://bugzilla.gnome.org/show_bug.cgi?id=600734 --- data/theme/gnome-shell.css | 8 ++++++++ js/ui/placeDisplay.js | 33 +++++++++++++-------------------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index a8bf9ba92..f09b81f3c 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -219,6 +219,14 @@ StTooltip { /* Places */ +.places-actions { + spacing: 4px; +} + +#placesDevices { + padding-top: 4px; +} + /* LookingGlass */ #LookingGlassDialog diff --git a/js/ui/placeDisplay.js b/js/ui/placeDisplay.js index 3746c96b2..aa5003eb4 100644 --- a/js/ui/placeDisplay.js +++ b/js/ui/placeDisplay.js @@ -20,7 +20,6 @@ const GenericDisplay = imports.ui.genericDisplay; const NAUTILUS_PREFS_DIR = '/apps/nautilus/preferences'; const DESKTOP_IS_HOME_KEY = NAUTILUS_PREFS_DIR + '/desktop_is_home_dir'; -const PLACES_VSPACING = 8; const PLACES_ICON_SIZE = 16; /** @@ -371,15 +370,15 @@ DashPlaceDisplay.prototype = { this.actor.append(this._rightBox, Big.BoxPackFlags.EXPAND); // Subdivide left into actions and devices - this._actionsBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, - spacing: PLACES_VSPACING }); + this._actionsBox = new St.BoxLayout({ style_class: 'places-actions', + vertical: true }); - this._devBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, - spacing: PLACES_VSPACING, - padding_top: 6 }); + this._devBox = new St.BoxLayout({ style_class: 'places-actions', + name: 'placesDevices', + vertical: true }); - this._dirsBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, - spacing: PLACES_VSPACING }); + this._dirsBox = new St.BoxLayout({ style_class: 'places-actions', + vertical: true }); this._leftBox.append(this._actionsBox, Big.BoxPackFlags.NONE); this._leftBox.append(this._devBox, Big.BoxPackFlags.NONE); @@ -396,33 +395,27 @@ DashPlaceDisplay.prototype = { }, _updateDefaults: function() { - this._actionsBox.get_children().forEach(function (child) { - child.destroy(); - }); + this._actionsBox.destroy_children(); let places = Main.placesManager.getDefaultPlaces(); for (let i = 0; i < places.length; i++) - this._actionsBox.append(new DashPlaceDisplayItem(places[i]).actor, Big.BoxPackFlags.NONE); + this._actionsBox.add(new DashPlaceDisplayItem(places[i]).actor); }, _updateMounts: function() { - this._devBox.get_children().forEach(function (child) { - child.destroy(); - }); + this._devBox.destroy_children(); let places = Main.placesManager.getMounts(); for (let i = 0; i < places.length; i++) - this._devBox.append(new DashPlaceDisplayItem(places[i]).actor, Big.BoxPackFlags.NONE); + this._devBox.add(new DashPlaceDisplayItem(places[i]).actor); }, _updateBookmarks: function() { - this._dirsBox.get_children().forEach(function (child) { - child.destroy(); - }); + this._dirsBox.destroy_children(); let places = Main.placesManager.getBookmarks(); for (let i = 0; i < places.length; i ++) - this._dirsBox.append(new DashPlaceDisplayItem(places[i]).actor, Big.BoxPackFlags.NONE); + this._dirsBox.add(new DashPlaceDisplayItem(places[i]).actor); } }; From 4014313910e1300c9f587ca325ad3ea1a276be77 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 6 Nov 2009 18:32:41 -0500 Subject: [PATCH 32/51] [dash] Swap More for triangle In newer mockup. https://bugzilla.gnome.org/show_bug.cgi?id=600734 --- data/Makefile.am | 3 +- data/theme/gnome-shell.css | 10 +++-- data/theme/section-more.svg | 87 +++++++++++++++++++++++++++++++++++++ js/ui/dash.js | 4 +- 4 files changed, 97 insertions(+), 7 deletions(-) create mode 100755 data/theme/section-more.svg diff --git a/data/Makefile.am b/data/Makefile.am index 1f5857d77..912ad3dbe 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -30,7 +30,8 @@ dist_theme_DATA = \ theme/scroll-button-up.png \ theme/scroll-button-up-hover.png \ theme/scroll-vhandle.png \ - theme/section-back.svg + theme/section-back.svg \ + theme/section-more.svg schemadir = @GCONF_SCHEMA_FILE_DIR@ schema_DATA = gnome-shell.schemas diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index f09b81f3c..3e0288477 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -156,10 +156,12 @@ StTooltip { } .more-link { - border-left: 1px solid #262626; - padding: 0px 0px 0px 4px; - color: #ffffff; - font-weight: normal; +} + +.more-link-expander { + background-image: url("section-more.svg"); + width: 9px; + height: 9px; } .dash-pane { diff --git a/data/theme/section-more.svg b/data/theme/section-more.svg new file mode 100755 index 000000000..74f579d63 --- /dev/null +++ b/data/theme/section-more.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/js/ui/dash.js b/js/ui/dash.js index 89a549281..fd5d947a9 100644 --- a/js/ui/dash.js +++ b/js/ui/dash.js @@ -345,8 +345,8 @@ MoreLink.prototype = { reactive: true }); this.pane = null; - let text = new St.Label({ text: _("More") }); - this.actor.add(text, { expand: true, y_fill: false }); + let expander = new St.Bin({ style_class: "more-link-expander" }); + this.actor.add(expander, { expand: true, y_fill: false }); this.actor.connect('button-press-event', Lang.bind(this, function (b, e) { if (this.pane == null) { From fec2ea5e9c0e0cc78d6238a951fe520a3347a1c1 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 12 Nov 2009 13:09:20 -0500 Subject: [PATCH 33/51] [dash] Convert pane close to St.Button, avoiding release event propagation The workspaces was handling the release event after closing the pane, catch it before closing by using St.Button. --- js/ui/dash.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/js/ui/dash.js b/js/ui/dash.js index fd5d947a9..3398fce9e 100644 --- a/js/ui/dash.js +++ b/js/ui/dash.js @@ -94,11 +94,9 @@ Pane.prototype = { let chromeTop = new St.BoxLayout(); - let closeIcon = new St.Bin({ style_class: "dash-pane-close" }); - closeIcon.reactive = true; - closeIcon.connect('button-press-event', Lang.bind(this, function (b, e) { + let closeIcon = new St.Button({ style_class: "dash-pane-close" }); + closeIcon.connect('clicked', Lang.bind(this, function (b, e) { this.close(); - return true; })); let dummy = new St.Bin(); chromeTop.add(dummy, { expand: true }); From 48f8e4943dd9261e0b87b31489f434f5b1e61cda Mon Sep 17 00:00:00 2001 From: Marina Zhurakhinskaya Date: Thu, 12 Nov 2009 16:31:16 -0500 Subject: [PATCH 34/51] Rename places.js to placeDisplay.js places.js was renamed in the code --- po/POTFILES.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/po/POTFILES.in b/po/POTFILES.in index a44a0f173..6e72d3962 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -4,7 +4,7 @@ js/ui/appIcon.js js/ui/dash.js js/ui/overview.js js/ui/panel.js -js/ui/places.js +js/ui/placeDisplay.js js/ui/runDialog.js js/ui/widget.js src/gdmuser/gdm-user.c From 7c796b2d2ad7b2de6ccaf36ad0288a473dd69d4b Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 12 Nov 2009 18:17:58 -0500 Subject: [PATCH 35/51] [shellDBus] Avoid sending undefined over DBus DBus doesn't have a notion of null/undefined, so do the lame thing and return the empty string. --- js/ui/shellDBus.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js index 1d998efff..8ff743ecc 100644 --- a/js/ui/shellDBus.js +++ b/js/ui/shellDBus.js @@ -48,6 +48,9 @@ GnomeShell.prototype = { let success; try { returnValue = JSON.stringify(eval(code)); + // A hack; DBus doesn't have null/undefined + if (returnValue == undefined) + returnValue = ""; success = true; } catch (e) { returnValue = JSON.stringify(e); From 8c05003acf87f201f7989869e3c1f4d6e46c74b2 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 12 Nov 2009 18:18:34 -0500 Subject: [PATCH 36/51] Add gnome-shell --eval-file Convenience utility function for evaluating an arbitrary JavaScript file. --- src/gnome-shell.in | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/gnome-shell.in b/src/gnome-shell.in index 2acc967ed..e5ef5095e 100644 --- a/src/gnome-shell.in +++ b/src/gnome-shell.in @@ -212,6 +212,8 @@ parser.add_option("", "--geometry", metavar="GEOMETRY", default="1024x768"); parser.add_option("-w", "--wide", action="store_true", help="Use widescreen (1280x800) with Xephyr") +parser.add_option("", "--eval-file", metavar="EVAL_FILE", + help="Evaluate the contents of the given JavaScript file") options, args = parser.parse_args() @@ -219,6 +221,20 @@ if args: parser.print_usage() sys.exit(1) +if options.eval_file: + import dbus + + f = open(options.eval_file) + contents = f.read() + f.close() + + session = dbus.SessionBus() + shell = session.get_object('org.gnome.Shell', '/org/gnome/Shell') + shell = dbus.Interface(shell, 'org.gnome.Shell') + result = shell.Eval(contents) + print result + sys.exit(0) + if options.debug_command: options.debug = True elif options.debug: From 9ddebf0480620988fa754a7088bcac6e6fc83cf0 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 10 Nov 2009 12:12:27 -0500 Subject: [PATCH 37/51] Introspect src/gdmuser In addition to the Makefile changes, we also change uid_t to gulong in the public API (which matches how it was already represented in the gobject properties). https://bugzilla.gnome.org/show_bug.cgi?id=601458 --- src/Makefile.am | 21 ++++++++++++++++++++- src/gdmuser/gdm-user-manager.c | 2 +- src/gdmuser/gdm-user-manager.h | 2 +- src/gdmuser/gdm-user.c | 2 +- src/gdmuser/gdm-user.h | 2 +- 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 3ed60b43c..1970e85f3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -165,7 +165,7 @@ libgnome_shell_la_LIBADD = \ libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags) typelibdir = $(pkglibdir) -typelib_DATA = Shell-0.1.typelib Big-1.0.typelib St-1.0.typelib +typelib_DATA = Shell-0.1.typelib Big-1.0.typelib St-1.0.typelib Gdm-1.0.typelib Shell-0.1.gir: $(mutter) $(G_IR_SCANNER) Big-1.0.gir St-1.0.gir libgnome-shell.la Makefile $(AM_V_GEN) $(G_IR_SCANNER) \ @@ -237,3 +237,22 @@ St-1.0.typelib: St-1.0.gir $< -o $@ CLEANFILES += St-1.0.typelib + +Gdm-1.0.gir: $(mutter) $(G_IR_SCANNER) libgdmuser-1.0.la Makefile + $(AM_V_GEN) $(G_IR_SCANNER) \ + --namespace=Gdm \ + --nsversion=1.0 \ + --include=GObject-2.0 \ + --include=GdkPixbuf-2.0 \ + --libtool="$(LIBTOOL)" \ + --library=libgdmuser-1.0.la \ + $(addprefix $(srcdir)/,$(gdmuser_source_h)) \ + $(addprefix $(srcdir)/,$(gdmuser_source_c)) \ + $(gdmuser_cflags) \ + -o $@ +CLEANFILES += Gdm-1.0.gir + +Gdm-1.0.typelib: libbig-1.0.la Gdm-1.0.gir + $(AM_V_GEN) $(G_IR_COMPILER) Gdm-1.0.gir -o $@ +CLEANFILES += Gdm-1.0.typelib + diff --git a/src/gdmuser/gdm-user-manager.c b/src/gdmuser/gdm-user-manager.c index 167ca7d55..e636b3564 100644 --- a/src/gdmuser/gdm-user-manager.c +++ b/src/gdmuser/gdm-user-manager.c @@ -998,7 +998,7 @@ gdm_user_manager_get_user (GdmUserManager *manager, GdmUser * gdm_user_manager_get_user_by_uid (GdmUserManager *manager, - uid_t uid) + gulong uid) { GdmUser *user; struct passwd *pwent; diff --git a/src/gdmuser/gdm-user-manager.h b/src/gdmuser/gdm-user-manager.h index 6c696e585..bb1118090 100644 --- a/src/gdmuser/gdm-user-manager.h +++ b/src/gdmuser/gdm-user-manager.h @@ -75,7 +75,7 @@ GSList * gdm_user_manager_list_users (GdmUserManager *mana GdmUser * gdm_user_manager_get_user (GdmUserManager *manager, const char *user_name); GdmUser * gdm_user_manager_get_user_by_uid (GdmUserManager *manager, - uid_t uid); + gulong uid); gboolean gdm_user_manager_activate_user_session (GdmUserManager *manager, GdmUser *user); diff --git a/src/gdmuser/gdm-user.c b/src/gdmuser/gdm-user.c index 4accb56ed..940c6877b 100644 --- a/src/gdmuser/gdm-user.c +++ b/src/gdmuser/gdm-user.c @@ -516,7 +516,7 @@ _gdm_user_icon_changed (GdmUser *user) * Since: 1.0 **/ -uid_t +gulong gdm_user_get_uid (GdmUser *user) { g_return_val_if_fail (GDM_IS_USER (user), -1); diff --git a/src/gdmuser/gdm-user.h b/src/gdmuser/gdm-user.h index 4edd3baf4..ee5dc509b 100644 --- a/src/gdmuser/gdm-user.h +++ b/src/gdmuser/gdm-user.h @@ -39,7 +39,7 @@ typedef struct _GdmUser GdmUser; GType gdm_user_get_type (void) G_GNUC_CONST; -uid_t gdm_user_get_uid (GdmUser *user); +gulong gdm_user_get_uid (GdmUser *user); G_CONST_RETURN char *gdm_user_get_user_name (GdmUser *user); G_CONST_RETURN char *gdm_user_get_real_name (GdmUser *user); G_CONST_RETURN char *gdm_user_get_home_directory (GdmUser *user); From 985d7077884fa7670de906e2db31383fd28f73cf Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 10 Nov 2009 12:13:58 -0500 Subject: [PATCH 38/51] Port ShellStatusMenu to javascript https://bugzilla.gnome.org/show_bug.cgi?id=601458 --- data/theme/gnome-shell.css | 7 + js/ui/Makefile.am | 1 + js/ui/panel.js | 12 +- js/ui/statusMenu.js | 202 ++++++++++ src/Makefile.am | 2 - src/shell-global.c | 33 ++ src/shell-global.h | 4 + src/shell-status-menu.c | 732 ------------------------------------- src/shell-status-menu.h | 45 --- 9 files changed, 253 insertions(+), 785 deletions(-) create mode 100644 js/ui/statusMenu.js delete mode 100644 src/shell-status-menu.c delete mode 100644 src/shell-status-menu.h diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index 3e0288477..351b4aadb 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -348,3 +348,10 @@ StTooltip { width: 1px; background: rgba(255,255,255,0.33); } + +/* Status Menu */ +#StatusMenu { + spacing: 4px; + font: 16px sans-serif; + color: white; +} diff --git a/js/ui/Makefile.am b/js/ui/Makefile.am index ebc7f53d3..a74fb862e 100644 --- a/js/ui/Makefile.am +++ b/js/ui/Makefile.am @@ -23,6 +23,7 @@ dist_jsui_DATA = \ runDialog.js \ shellDBus.js \ sidebar.js \ + statusMenu.js \ tweener.js \ widget.js \ widgetBox.js \ diff --git a/js/ui/panel.js b/js/ui/panel.js index 447bb854e..9e2fdb431 100644 --- a/js/ui/panel.js +++ b/js/ui/panel.js @@ -16,6 +16,7 @@ const _ = Gettext.gettext; const Button = imports.ui.button; const Calendar = imports.ui.calendar; const Main = imports.ui.main; +const StatusMenu = imports.ui.statusMenu; const PANEL_HEIGHT = 26; const TRAY_HEIGHT = PANEL_HEIGHT - 1; @@ -176,6 +177,8 @@ Panel.prototype = { this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL }); + this.actor._delegate = this; + let backgroundGradient = Shell.create_vertical_gradient(BACKGROUND_TOP, BACKGROUND_BOTTOM); this.actor.connect('notify::allocation', Lang.bind(this, function () { @@ -371,11 +374,8 @@ Panel.prototype = { this._traymanager.manage_stage(global.stage); let statusbox = new Big.Box(); - let statusmenu = this._statusmenu = new Shell.StatusMenu(); - statusmenu.get_icon().hide(); - statusmenu.get_name().fontName = DEFAULT_FONT; - statusmenu.get_name().color = PANEL_FOREGROUND_COLOR; - statusbox.append(this._statusmenu, Big.BoxPackFlags.NONE); + let statusmenu = this._statusmenu = new StatusMenu.StatusMenu(); + statusbox.append(this._statusmenu.actor, Big.BoxPackFlags.NONE); let statusbutton = new Button.Button(statusbox, PANEL_BUTTON_COLOR, PRESSED_BUTTON_BACKGROUND_COLOR, @@ -385,7 +385,7 @@ Panel.prototype = { if (e.get_button() == 1 && e.get_click_count() == 1) { statusmenu.toggle(e); // The statusmenu might not pop up if it couldn't get a pointer grab - if (statusmenu.is_active()) + if (statusmenu.isActive()) statusbutton.actor.active = true; return true; } else { diff --git a/js/ui/statusMenu.js b/js/ui/statusMenu.js new file mode 100644 index 000000000..a4de8bf92 --- /dev/null +++ b/js/ui/statusMenu.js @@ -0,0 +1,202 @@ +/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ + +const Gdm = imports.gi.Gdm; +const GLib = imports.gi.GLib; +const Gtk = imports.gi.Gtk; +const Lang = imports.lang; +const Shell = imports.gi.Shell; +const St = imports.gi.St; +const Signals = imports.signals; +const Gettext = imports.gettext.domain('gnome-shell'); +const _ = Gettext.gettext; + +const Panel = imports.ui.panel; + +// Adapted from gdm/gui/user-switch-applet/applet.c +// +// Copyright (C) 2004-2005 James M. Cape . +// Copyright (C) 2008,2009 Red Hat, Inc. + +const SIDEBAR_VISIBLE_KEY = 'sidebar/visible'; + +function StatusMenu() { + this._init(); +} + +StatusMenu.prototype = { + _init: function() { + this._gdm = Gdm.UserManager.ref_default(); + this._user = this._gdm.get_user(GLib.get_user_name()); + + this.actor = new St.BoxLayout({ name: 'StatusMenu' }); + this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); + + this._name = new St.Label({ text: this._user.get_real_name() }); + this.actor.add(this._name, { expand: true, y_align: St.Align.MIDDLE }); + this._userNameChangedId = this._user.connect('notify::display-name', Lang.bind(this, this._updateUserName)); + + this._createSubMenu(); + this._gdm.connect('users-loaded', Lang.bind(this, this._updateSwitchUser)); + this._gdm.connect('user-added', Lang.bind(this, this._updateSwitchUser)); + this._gdm.connect('user-removed', Lang.bind(this, this._updateSwitchUser)); + }, + + _onDestroy: function() { + this._user.disconnect(this._userNameChangedId); + }, + + _updateUserName: function() { + this._name.set_text(this._user.get_real_name()); + }, + + _updateSwitchUser: function() { + let users = this._gdm.list_users(); + if (users.length > 1) + this._loginScreenItem.show(); + else + this._loginScreenItem.hide(); + }, + + // The menu + + _createImageMenuItem: function(label, iconName) { + let image = new Gtk.Image(); + let item = new Gtk.ImageMenuItem({ label: label, + image: image }); + item.connect('style-set', Lang.bind(this, + function() { + image.set_from_icon_name(iconName, Gtk.IconSize.MENU); + })); + + return item; + }, + + _createSubMenu: function() { + this._menu = new Gtk.Menu(); + this._menu.connect('deactivate', Lang.bind(this, function() { this.emit('deactivated'); })); + + let item; + + item = this._createImageMenuItem(_('Account Information...'), 'user-info'); + item.connect('activate', Lang.bind(this, this._onAccountInformationActivate)); + this._menu.append(item); + item.show(); + + let gconf = Shell.GConf.get_default(); + item = new Gtk.CheckMenuItem({ label: _('Sidebar'), + active: gconf.get_boolean(SIDEBAR_VISIBLE_KEY) }); + item.connect('activate', Lang.bind(this, + function() { + gconf.set_boolean(SIDEBAR_VISIBLE_KEY, this._sidebarItem.active); + })); + this._menu.append(item); + item.show(); + + item = this._createImageMenuItem(_('System Preferences...'), 'preferences-desktop'); + item.connect('activate', Lang.bind(this, this._onPreferencesActivate)); + this._menu.append(item); + item.show(); + + item = new Gtk.SeparatorMenuItem(); + this._menu.append(item); + item.show(); + + item = this._createImageMenuItem(_('Lock Screen'), 'system-lock-screen'); + item.connect('activate', Lang.bind(this, this._onLockScreenActivate)); + this._menu.append(item); + item.show(); + + item = this._createImageMenuItem(_('Switch User'), 'system-users'); + item.connect('activate', Lang.bind(this, this._onLoginScreenActivate)); + this._menu.append(item); + item.show(); + this._loginScreenItem = item; + + item = this._createImageMenuItem(_('Log Out...'), 'system-log-out'); + item.connect('activate', Lang.bind(this, this._onQuitSessionActivate)); + this._menu.append(item); + item.show(); + + item = this._createImageMenuItem(_('Shut Down...'), 'system-shutdown'); + item.connect('activate', Lang.bind(this, this._onShutDownActivate)); + this._menu.append(item); + item.show(); + }, + + _onAccountInformationActivate: function() { + this._spawn(['gnome-about-me']); + }, + + _onPreferencesActivate: function() { + this._spawn(['gnome-control-center']); + }, + + _onLockScreenActivate: function() { + this._spawn(['gnome-screensaver-command', '--lock']); + }, + + _onLoginScreenActivate: function() { + this._gdm.goto_login_session(); + this._onLockScreenActivate(); + }, + + _onQuitSessionActivate: function() { + this._spawn(['gnome-session-save', '--logout-dialog']); + }, + + _onShutDownActivate: function() { + this._spawn(['gnome-session-save', '--shutdown-dialog']); + }, + + _spawn: function(args) { + // FIXME: once Shell.Process gets support for signalling + // errors we should pop up an error dialog or something here + // on failure + let p = new Shell.Process({'args' : args}); + p.run(); + }, + + // shell_status_menu_toggle: + // @event: event causing the toggle + // + // If the menu is not currently up, pops it up. Otherwise, hides it. + // Popping up may fail if another grab is already active; check with + // isActive(). + toggle: function(event) { + if (this._menu.visible) + this._menu.popdown(); + else { + // We don't want to overgrab a Mutter grab with the grab + // that GTK+ uses on menus. + if (global.display_is_grabbed()) + return; + + let [menuWidth, menuHeight] = this._menu.get_size_request (); + + let panel; + for (panel = this.actor; panel; panel = panel.get_parent()) { + if (panel._delegate instanceof Panel.Panel) + break; + } + + let [panelX, panelY] = panel.get_transformed_position(); + let [panelWidth, panelHeight] = panel.get_transformed_size(); + + let menuX = Math.round(panelX + panelWidth - menuWidth); + let menuY = Math.round(panelY + panelHeight); + + Shell.popup_menu(this._menu, event.get_button(), event.get_time(), + menuX, menuY); + } + }, + + // isActive: + // + // Gets whether the menu is currently popped up + // + // Return value: %true if the menu is currently popped up + isActive: function() { + return this._menu.visible; + } +}; +Signals.addSignalMethods(StatusMenu.prototype); diff --git a/src/Makefile.am b/src/Makefile.am index 1970e85f3..4b11e83f3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -87,8 +87,6 @@ libgnome_shell_la_SOURCES = \ shell-global.c \ shell-global.h \ shell-global-private.h \ - shell-status-menu.c \ - shell-status-menu.h \ shell-stack.c \ shell-stack.h \ shell-tray-manager.c \ diff --git a/src/shell-global.c b/src/shell-global.c index b07d0905f..5bb7e69d4 100644 --- a/src/shell-global.c +++ b/src/shell-global.c @@ -1026,3 +1026,36 @@ shell_get_event_state (ClutterEvent *event) ClutterModifierType state = clutter_event_get_state (event); return state & CLUTTER_MODIFIER_MASK; } + +static void +shell_popup_menu_position_func (GtkMenu *menu, + int *x, + int *y, + gboolean *push_in, + gpointer user_data) +{ + *x = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menu), "shell-menu-x")); + *y = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menu), "shell-menu-y")); +} + +/** + * shell_popup_menu: + * @menu: a #GtkMenu + * @button: mouse button that triggered the menu + * @time: timestamp of event that triggered the menu + * @menu_x: x coordinate to display the menu at + * @menu_y: y coordinate to display the menu at + * + * Wraps gtk_menu_popup(), but using @menu_x, @menu_y for the location + * rather than needing a callback. + **/ +void +shell_popup_menu (GtkMenu *menu, int button, guint32 time, + int menu_x, int menu_y) +{ + g_object_set_data (G_OBJECT (menu), "shell-menu-x", GINT_TO_POINTER (menu_x)); + g_object_set_data (G_OBJECT (menu), "shell-menu-y", GINT_TO_POINTER (menu_y)); + + gtk_menu_popup (menu, NULL, NULL, shell_popup_menu_position_func, NULL, + button, time); +} diff --git a/src/shell-global.h b/src/shell-global.h index 55844a3a4..60b9cb552 100644 --- a/src/shell-global.h +++ b/src/shell-global.h @@ -79,6 +79,10 @@ GdkModifierType shell_global_get_modifier_keys (ShellGlobal *global); ClutterModifierType shell_get_event_state (ClutterEvent *event); +void shell_popup_menu (GtkMenu *menu, int button, guint32 time, + int menu_x, int menu_y); + + G_END_DECLS #endif /* __SHELL_GLOBAL_H__ */ diff --git a/src/shell-status-menu.c b/src/shell-status-menu.c deleted file mode 100644 index 4018faf3c..000000000 --- a/src/shell-status-menu.c +++ /dev/null @@ -1,732 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* Adapted from gdm/gui/user-switch-applet/applet.c */ -/* - * - * Copyright (C) 2004-2005 James M. Cape . - * Copyright (C) 2008,2009 Red Hat, Inc. - * - * 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 "shell-status-menu.h" - -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include - -#define GDMUSER_I_KNOW_THIS_IS_UNSTABLE -#include - -#include "shell-global.h" -#include "shell-gconf.h" - -#define LOCKDOWN_DIR "/desktop/gnome/lockdown" -#define LOCKDOWN_KEY LOCKDOWN_DIR "/disable_user_switching" - -#define SIDEBAR_VISIBLE_KEY SHELL_GCONF_DIR "/sidebar/visible" - -struct _ShellStatusMenuPrivate { - GConfClient *client; - GdmUserManager *manager; - GdmUser *user; - - ClutterTexture *user_icon; - BigBox *name_box; - ClutterText *name; - - GtkWidget *menu; - GtkWidget *account_item; - GtkWidget *sidebar_item; - GtkWidget *control_panel_item; - GtkWidget *lock_screen_item; - GtkWidget *login_screen_item; - GtkWidget *quit_session_item; - GtkWidget *shut_down_item; - - guint client_notify_lockdown_id; - - guint current_status_state; - - guint user_icon_changed_id; - guint user_notify_id; - - gboolean has_other_users; - - GtkIconSize icon_size; - guint pixel_size; -}; - -enum { - PROP_0 -}; - -G_DEFINE_TYPE(ShellStatusMenu, shell_status_menu, BIG_TYPE_BOX); - -/* Signals */ -enum -{ - DEACTIVATED, - LAST_SIGNAL -}; - -static guint shell_status_menu_signals [LAST_SIGNAL] = { 0 }; - -static void -reset_icon (ShellStatusMenu *status) -{ - ShellStatusMenuPrivate *priv = status->priv; - GdkPixbuf *pixbuf; - - if (priv->user == NULL) - return; - - if (priv->user_icon != NULL) - { - pixbuf = gdm_user_render_icon (priv->user, 24); - - if (pixbuf == NULL) - return; - - shell_clutter_texture_set_from_pixbuf (priv->user_icon, pixbuf); - - g_object_unref (pixbuf); - } -} - -static void -update_name_text (ShellStatusMenu *status) -{ - ShellStatusMenuPrivate *priv = status->priv; - - clutter_text_set_text (priv->name, - gdm_user_get_real_name (GDM_USER (priv->user))); -} - -static void -on_user_icon_changed (GdmUser *user, - ShellStatusMenu *status) -{ - g_debug ("User icon changed"); - reset_icon (status); -} - -static void -user_notify_display_name_cb (GObject *object, - GParamSpec *pspec, - ShellStatusMenu *status) -{ - update_name_text (status); -} - -static void -setup_current_user (ShellStatusMenu *status) -{ - ShellStatusMenuPrivate *priv = status->priv; - const char *name; - - priv->user = gdm_user_manager_get_user_by_uid (priv->manager, getuid ()); - if (priv->user != NULL) - { - g_object_ref (priv->user); - name = gdm_user_get_real_name (priv->user); - } - else - { - name = _("Unknown"); - } - - update_name_text (status); - - if (priv->user != NULL) - { - reset_icon (status); - - priv->user_icon_changed_id = - g_signal_connect (priv->user, - "icon-changed", - G_CALLBACK (on_user_icon_changed), - status); - priv->user_notify_id = - g_signal_connect (priv->user, - "notify::display-name", - G_CALLBACK (user_notify_display_name_cb), - status); - } -} - -static void -maybe_lock_screen (ShellStatusMenu *status) -{ - char *args[3]; - GError *err; - GdkScreen *screen; - gboolean use_gscreensaver = TRUE; - gboolean res; - - g_debug ("Attempting to lock screen"); - - args[0] = g_find_program_in_path ("gnome-screensaver-command"); - if (args[0] == NULL) - { - args[0] = g_find_program_in_path ("xscreensaver-command"); - use_gscreensaver = FALSE; - } - - if (args[0] == NULL) - return; - - if (use_gscreensaver) - args[1] = "--lock"; - else - args[1] = "-lock"; - args[2] = NULL; - - screen = gdk_screen_get_default (); - - err = NULL; - res = gdk_spawn_on_screen (screen, g_get_home_dir (), args, NULL, 0, NULL, - NULL, NULL, &err); - if (!res) - { - g_warning (_("Can't lock screen: %s"), err->message); - g_error_free (err); - } - - if (use_gscreensaver) - args[1] = "--throttle"; - else - args[1] = "-throttle"; - - err = NULL; - res = gdk_spawn_on_screen (screen, g_get_home_dir (), args, NULL, - (G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_STDOUT_TO_DEV_NULL), NULL, NULL, - NULL, &err); - if (!res) - { - g_warning (_("Can't temporarily set screensaver to blank screen: %s"), - err->message); - g_error_free (err); - } - - g_free (args[0]); -} - -static void -on_lock_screen_activate (GtkMenuItem *item, - ShellStatusMenu *status) -{ - maybe_lock_screen (status); -} - -static void -do_switch (ShellStatusMenu *status, - GdmUser *user) -{ - ShellStatusMenuPrivate *priv = status->priv; - guint num_sessions; - - g_debug ("Do user switch"); - - if (user == NULL) - { - gdm_user_manager_goto_login_session (priv->manager); - goto out; - } - - num_sessions = gdm_user_get_num_sessions (user); - if (num_sessions > 0) - gdm_user_manager_activate_user_session (priv->manager, user); - else - gdm_user_manager_goto_login_session (priv->manager); -out: - maybe_lock_screen (status); -} - -static void -on_login_screen_activate (GtkMenuItem *item, - ShellStatusMenu *status) -{ - GdmUser *user; - - user = NULL; - - do_switch (status, user); -} - -static void -spawn_external (ShellStatusMenu *status, const char *program) -{ - char *args[2]; - GError *error; - GdkScreen *screen; - gboolean res; - - args[0] = g_find_program_in_path (program); - if (args[0] == NULL) - return; - args[1] = NULL; - - screen = gdk_screen_get_default (); - - error = NULL; - res = gdk_spawn_on_screen (screen, g_get_home_dir (), args, NULL, 0, NULL, - NULL, NULL, &error); - if (!res) - { - g_warning ("Failed to exec %s: %s", program, error->message); - g_clear_error (&error); - } - - g_free (args[0]); - -} - -static void -on_control_panel_activate (GtkMenuItem *item, - ShellStatusMenu *status) -{ - spawn_external (status, "gnome-control-center"); -} - -static void -on_account_activate (GtkMenuItem *item, - ShellStatusMenu *status) -{ - spawn_external (status, "gnome-about-me"); -} - -static void -on_sidebar_toggled (GtkCheckMenuItem *item, - ShellStatusMenu *status) -{ - gconf_client_set_bool (status->priv->client, SIDEBAR_VISIBLE_KEY, - gtk_check_menu_item_get_active (item), NULL); -} - - -/* Calls 'gnome-session-save arg' */ -static void -gnome_session_save_command (const char *arg) -{ - char *args[3]; - GError *error; - GdkScreen *screen; - gboolean res; - - args[0] = g_find_program_in_path ("gnome-session-save"); - if (args[0] == NULL) - return; - - args[1] = (char *)arg; - args[2] = NULL; - - screen = gdk_screen_get_default (); - - error = NULL; - res = gdk_spawn_on_screen (screen, g_get_home_dir (), args, NULL, 0, NULL, - NULL, NULL, &error); - if (!res) - { - g_warning (_("Can't logout: %s"), error->message); - g_error_free (error); - } - - g_free (args[0]); -} - - -static void -on_quit_session_activate (GtkMenuItem *item, - ShellStatusMenu *status) -{ - gnome_session_save_command ("--logout-dialog"); -} - -static void -on_shut_down_activate (GtkMenuItem *item, - ShellStatusMenu *status) -{ - gnome_session_save_command ("--shutdown-dialog"); -} - -static void -update_switch_user (ShellStatusMenu *status) -{ - ShellStatusMenuPrivate *priv = status->priv; - GSList *users; - - users = gdm_user_manager_list_users (priv->manager); - priv->has_other_users = FALSE; - if (users != NULL) - priv->has_other_users = g_slist_length (users) > 1; - g_slist_free (users); - - if (priv->has_other_users) - gtk_widget_show (priv->login_screen_item); - else - gtk_widget_hide (priv->login_screen_item); -} - -static void -on_manager_user_added (GdmUserManager *manager, - GdmUser *user, - ShellStatusMenu *status) -{ - update_switch_user (status); -} - -static void -on_manager_user_removed (GdmUserManager *manager, - GdmUser *user, - ShellStatusMenu *status) -{ - update_switch_user (status); -} - -static void -on_manager_users_loaded (GdmUserManager *manager, - ShellStatusMenu *status) -{ - update_switch_user (status); -} - -static void -menu_style_set_cb (GtkWidget *menu, GtkStyle *old_style, - ShellStatusMenu *status) -{ - ShellStatusMenuPrivate *priv = status->priv; - GtkSettings *settings; - int width; - int height; - - priv->icon_size = gtk_icon_size_from_name ("panel-menu"); - if (priv->icon_size == GTK_ICON_SIZE_INVALID) - priv->icon_size = gtk_icon_size_register ("panel-menu", 24, 24); - - if (gtk_widget_has_screen (menu)) - settings = gtk_settings_get_for_screen (gtk_widget_get_screen (menu)); - else - settings = gtk_settings_get_default (); - - if (!gtk_icon_size_lookup_for_settings (settings, priv->icon_size, &width, - &height)) - priv->pixel_size = -1; - else - priv->pixel_size = MAX(width, height); -} - -static void -menuitem_style_set_cb (GtkWidget *menuitem, - GtkStyle *old_style, - ShellStatusMenu *status) -{ - GtkWidget *image; - const char *icon_name; - ShellStatusMenuPrivate *priv = status->priv; - - if (menuitem == priv->login_screen_item) - icon_name = "system-users"; - else if (menuitem == priv->lock_screen_item) - icon_name = "system-lock-screen"; - else if (menuitem == priv->quit_session_item) - icon_name = "system-log-out"; - else if (menuitem == priv->account_item) - icon_name = "user-info"; - else if (menuitem == priv->control_panel_item) - icon_name = "preferences-desktop"; - else if (menuitem == priv->shut_down_item) - icon_name = "system-shutdown"; - else - icon_name = GTK_STOCK_MISSING_IMAGE; - - image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (menuitem)); - gtk_image_set_pixel_size (GTK_IMAGE (image), priv->pixel_size); - gtk_image_set_from_icon_name (GTK_IMAGE (image), icon_name, priv->icon_size); -} - -static void -on_deactivate (GtkMenuShell *menushell, gpointer user_data) -{ - ShellStatusMenu *status = SHELL_STATUS_MENU (user_data); - g_signal_emit (G_OBJECT (status), shell_status_menu_signals[DEACTIVATED], 0); -} - -static void -create_sub_menu (ShellStatusMenu *status) -{ - ShellStatusMenuPrivate *priv = status->priv; - GtkWidget *item; - - priv->menu = gtk_menu_new (); - g_signal_connect (priv->menu, "style-set", G_CALLBACK (menu_style_set_cb), - status); - - g_signal_connect (priv->manager, "users-loaded", - G_CALLBACK (on_manager_users_loaded), status); - g_signal_connect (priv->manager, "user-added", - G_CALLBACK (on_manager_user_added), status); - g_signal_connect (priv->manager, "user-removed", - G_CALLBACK (on_manager_user_removed), status); - - priv->account_item = gtk_image_menu_item_new_with_label (_("Account Information...")); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (priv->account_item), - gtk_image_new ()); - gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), priv->account_item); - g_signal_connect (priv->account_item, "style-set", - G_CALLBACK (menuitem_style_set_cb), status); - g_signal_connect (priv->account_item, "activate", - G_CALLBACK (on_account_activate), status); - gtk_widget_show (priv->account_item); - - priv->sidebar_item = gtk_check_menu_item_new_with_label (_("Sidebar")); - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (priv->sidebar_item), - gconf_client_get_bool (priv->client, SIDEBAR_VISIBLE_KEY, NULL)); - gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), priv->sidebar_item); - g_signal_connect (priv->sidebar_item, "toggled", - G_CALLBACK (on_sidebar_toggled), status); - gtk_widget_show (priv->sidebar_item); - - priv->control_panel_item = gtk_image_menu_item_new_with_label (_("System Preferences...")); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (priv->control_panel_item), - gtk_image_new ()); - gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), priv->control_panel_item); - g_signal_connect (priv->control_panel_item, "style-set", - G_CALLBACK (menuitem_style_set_cb), status); - g_signal_connect (priv->control_panel_item, "activate", - G_CALLBACK (on_control_panel_activate), status); - gtk_widget_show (priv->control_panel_item); - - item = gtk_separator_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), item); - gtk_widget_show (item); - - priv->lock_screen_item - = gtk_image_menu_item_new_with_label (_("Lock Screen")); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (priv->lock_screen_item), - gtk_image_new ()); - gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), priv->lock_screen_item); - g_signal_connect (priv->lock_screen_item, "style-set", - G_CALLBACK (menuitem_style_set_cb), status); - g_signal_connect (priv->lock_screen_item, "activate", - G_CALLBACK (on_lock_screen_activate), status); - gtk_widget_show (priv->lock_screen_item); - - priv->login_screen_item = gtk_image_menu_item_new_with_label (_("Switch User")); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (priv->login_screen_item), - gtk_image_new ()); - gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), priv->login_screen_item); - g_signal_connect (priv->login_screen_item, "style-set", - G_CALLBACK (menuitem_style_set_cb), status); - g_signal_connect (priv->login_screen_item, "activate", - G_CALLBACK (on_login_screen_activate), status); - /* Only show switch user if there are other users */ - - /* Log Out */ - priv->quit_session_item = gtk_image_menu_item_new_with_label (_("Log Out...")); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (priv->quit_session_item), - gtk_image_new ()); - gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), priv->quit_session_item); - g_signal_connect (priv->quit_session_item, "style-set", - G_CALLBACK (menuitem_style_set_cb), status); - g_signal_connect (priv->quit_session_item, "activate", - G_CALLBACK (on_quit_session_activate), status); - gtk_widget_show (priv->quit_session_item); - - /* Shut down */ - priv->shut_down_item = gtk_image_menu_item_new_with_label (_("Shut Down...")); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (priv->shut_down_item), - gtk_image_new ()); - gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), priv->shut_down_item); - g_signal_connect (priv->shut_down_item, "style-set", - G_CALLBACK (menuitem_style_set_cb), status); - g_signal_connect (priv->shut_down_item, "activate", - G_CALLBACK (on_shut_down_activate), status); - gtk_widget_show (priv->shut_down_item); - - g_signal_connect (G_OBJECT (priv->menu), "deactivate", - G_CALLBACK (on_deactivate), status); -} - -static void -shell_status_menu_init (ShellStatusMenu *status) -{ - ShellStatusMenuPrivate *priv; - - status->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (status, SHELL_TYPE_STATUS_MENU, - ShellStatusMenuPrivate); - - g_object_set (G_OBJECT (status), - "orientation", BIG_BOX_ORIENTATION_HORIZONTAL, - NULL); - priv->client = gconf_client_get_default (); - - priv->user_icon = CLUTTER_TEXTURE (clutter_texture_new ()); - big_box_append (BIG_BOX (status), CLUTTER_ACTOR (status->priv->user_icon), 0); - - priv->name_box = BIG_BOX (big_box_new (BIG_BOX_ORIENTATION_VERTICAL)); - g_object_set (G_OBJECT (priv->name_box), "y-align", BIG_BOX_ALIGNMENT_CENTER, NULL); - big_box_append (BIG_BOX (status), CLUTTER_ACTOR (priv->name_box), BIG_BOX_PACK_EXPAND); - priv->name = CLUTTER_TEXT (clutter_text_new ()); - big_box_append (BIG_BOX (priv->name_box), CLUTTER_ACTOR (priv->name), BIG_BOX_PACK_EXPAND); - - priv->manager = gdm_user_manager_ref_default (); - setup_current_user (status); - - create_sub_menu (status); -} - -static void -shell_status_menu_finalize (GObject *object) -{ - ShellStatusMenu *status = SHELL_STATUS_MENU (object); - ShellStatusMenuPrivate *priv = status->priv; - - gconf_client_notify_remove (priv->client, priv->client_notify_lockdown_id); - - g_signal_handler_disconnect (priv->user, priv->user_notify_id); - g_signal_handler_disconnect (priv->user, priv->user_icon_changed_id); - - if (priv->user != NULL) { - g_object_unref (priv->user); - } - g_object_unref (priv->client); - g_object_unref (priv->manager); - - G_OBJECT_CLASS (shell_status_menu_parent_class)->finalize (object); -} - -static void -shell_status_menu_class_init (ShellStatusMenuClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (ShellStatusMenuPrivate)); - - gobject_class->finalize = shell_status_menu_finalize; - - shell_status_menu_signals[DEACTIVATED] = - g_signal_new ("deactivated", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ShellStatusMenuClass, deactivated), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); -} - -static void -position_menu (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data) -{ - ShellStatusMenu *status = SHELL_STATUS_MENU (user_data); - ClutterActor *parent; - float src_x, src_y; - float width, height; - int menu_width; - - gtk_widget_get_size_request (GTK_WIDGET (menu), &menu_width, NULL); - - /* Encapsulation breakage: it looks better if the menu is - * aligned with the bottom of the actor's grandparent - the - * panel, rather than with the bottom of the actor. We just - * assume what the hierarchy is and where we are positioned - * in the panel. - */ - parent = clutter_actor_get_parent (CLUTTER_ACTOR (status)); - parent = clutter_actor_get_parent (parent); - clutter_actor_get_transformed_position (parent, &src_x, &src_y); - clutter_actor_get_transformed_size (parent, &width, &height); - *x = (gint)(0.5 + src_x + width - menu_width); - *y = (gint)(0.5 + src_y + height); -} - -/** - * shell_status_menu_toggle: - * @menu: a #ShellStatusMenu - * - * If the menu is not currently up, pops it up. Otherwise, hides it. - * Popping up may fail if another grab is already active; check with - * shell_status_menu_is_active(). - */ -void -shell_status_menu_toggle (ShellStatusMenu *status, ClutterEvent *event) -{ - ShellStatusMenuPrivate *priv = status->priv; - - if (GTK_WIDGET_VISIBLE (priv->menu)) - { - gtk_menu_popdown (GTK_MENU (priv->menu)); - } - else - { - /* We don't want to overgrab a Mutter grab with the grab that GTK+ - * uses on menus. - */ - ShellGlobal *global = shell_global_get (); - if (shell_global_display_is_grabbed (global)) - return; - - gtk_menu_popup (GTK_MENU (priv->menu), NULL, NULL, position_menu, - status, 1, event->button.time); - } -} - -/** - * shell_status_menu_is_active: - * @menu: a #ShellStatusMenu - * - * Gets whether the menu is currently popped up - * - * Return value: %TRUE if the menu is currently popped up - */ -gboolean -shell_status_menu_is_active (ShellStatusMenu *status) -{ - ShellStatusMenuPrivate *priv = status->priv; - - return GTK_WIDGET_VISIBLE (priv->menu); -} - -/** - * shell_status_menu_get_name: - * @menu: a #ShellStatusMenu - * - * Return value: (transfer none): the #ClutterText actor with the user's name. - */ -ClutterText * -shell_status_menu_get_name (ShellStatusMenu *menu) -{ - return menu->priv->name; -} - -/** - * shell_status_menu_get_icon: - * @menu: a #ShellStatusMenu - * - * Return value: (transfer none): the #ClutterTexture actor with the user icon. - */ -ClutterTexture * -shell_status_menu_get_icon (ShellStatusMenu *menu) -{ - return menu->priv->user_icon; -} diff --git a/src/shell-status-menu.h b/src/shell-status-menu.h deleted file mode 100644 index 9a7c2969f..000000000 --- a/src/shell-status-menu.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -#ifndef __SHELL_STATUS_MENU_H__ -#define __SHELL_STATUS_MENU_H__ - -#include -#include "big/box.h" - -G_BEGIN_DECLS - -#define SHELL_TYPE_STATUS_MENU (shell_status_menu_get_type ()) -#define SHELL_STATUS_MENU(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHELL_TYPE_STATUS_MENU, ShellStatusMenu)) -#define SHELL_STATUS_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_STATUS_MENU, ShellStatusMenuClass)) -#define SHELL_IS_STATUS_MENU(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SHELL_TYPE_STATUS_MENU)) -#define SHELL_IS_STATUS_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_STATUS_MENU)) -#define SHELL_STATUS_MENU_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_STATUS_MENU, ShellStatusMenuClass)) - -typedef struct _ShellStatusMenu ShellStatusMenu; -typedef struct _ShellStatusMenuPrivate ShellStatusMenuPrivate; -typedef struct _ShellStatusMenuClass ShellStatusMenuClass; - -struct _ShellStatusMenu -{ - BigBox parent_instance; - - ShellStatusMenuPrivate *priv; -}; - -struct _ShellStatusMenuClass -{ - BigBoxClass parent_class; - - void (*deactivated) (ShellStatusMenu *status, gpointer user_data); -}; - -GType shell_status_menu_get_type (void); - -void shell_status_menu_toggle (ShellStatusMenu *menu, ClutterEvent *event); -gboolean shell_status_menu_is_active (ShellStatusMenu *menu); -ClutterText *shell_status_menu_get_name (ShellStatusMenu *menu); -ClutterTexture *shell_status_menu_get_icon (ShellStatusMenu *menu); - -G_END_DECLS - -#endif /* __SHELL_STATUS_MENU_H__ */ From bb63d513fdad951292ab434cd159f5e061b54056 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 10 Nov 2009 16:34:13 -0500 Subject: [PATCH 39/51] Add Presence items to the status menu https://bugzilla.gnome.org/show_bug.cgi?id=601458 --- js/ui/statusMenu.js | 98 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 2 deletions(-) diff --git a/js/ui/statusMenu.js b/js/ui/statusMenu.js index a4de8bf92..7aa5f2884 100644 --- a/js/ui/statusMenu.js +++ b/js/ui/statusMenu.js @@ -1,5 +1,6 @@ /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ +const DBus = imports.dbus; const Gdm = imports.gi.Gdm; const GLib = imports.gi.GLib; const Gtk = imports.gi.Gtk; @@ -27,10 +28,24 @@ StatusMenu.prototype = { _init: function() { this._gdm = Gdm.UserManager.ref_default(); this._user = this._gdm.get_user(GLib.get_user_name()); + this._presence = new GnomeSessionPresence(); this.actor = new St.BoxLayout({ name: 'StatusMenu' }); this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); + this._iconBox = new St.Bin(); + this.actor.add(this._iconBox, { y_align: St.Align.MIDDLE }); + + let textureCache = Shell.TextureCache.get_default(); + // FIXME: these icons are all wrong (likewise in createSubMenu) + this._availableIcon = textureCache.load_icon_name('gtk-yes', 16); + this._busyIcon = textureCache.load_icon_name('gtk-no', 16); + this._invisibleIcon = textureCache.load_icon_name('gtk-close', 16); + this._idleIcon = textureCache.load_icon_name('gtk-media-pause', 16); + + this._presence.connect('StatusChanged', Lang.bind(this, this._updatePresenceIcon)); + this._presence.getStatus(Lang.bind(this, this._updatePresenceIcon)); + this._name = new St.Label({ text: this._user.get_real_name() }); this.actor.add(this._name, { expand: true, y_align: St.Align.MIDDLE }); this._userNameChangedId = this._user.connect('notify::display-name', Lang.bind(this, this._updateUserName)); @@ -57,12 +72,24 @@ StatusMenu.prototype = { this._loginScreenItem.hide(); }, + _updatePresenceIcon: function(presence, status) { + if (status == GnomeSessionPresenceStatus.AVAILABLE) + this._iconBox.child = this._availableIcon; + else if (status == GnomeSessionPresenceStatus.BUSY) + this._iconBox.child = this._busyIcon; + else if (status == GnomeSessionPresenceStatus.INVISIBLE) + this._iconBox.child = this._invisibleIcon; + else + this._iconBox.child = this._idleIcon; + }, + // The menu - _createImageMenuItem: function(label, iconName) { + _createImageMenuItem: function(label, iconName, forceIcon) { let image = new Gtk.Image(); let item = new Gtk.ImageMenuItem({ label: label, - image: image }); + image: image, + always_show_image: forceIcon == true }); item.connect('style-set', Lang.bind(this, function() { image.set_from_icon_name(iconName, Gtk.IconSize.MENU); @@ -77,6 +104,25 @@ StatusMenu.prototype = { let item; + item = this._createImageMenuItem(_('Available'), 'gtk-yes', true); + item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSessionPresenceStatus.AVAILABLE)); + this._menu.append(item); + item.show(); + + item = this._createImageMenuItem(_('Busy'), 'gtk-no', true); + item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSessionPresenceStatus.BUSY)); + this._menu.append(item); + item.show(); + + item = this._createImageMenuItem(_('Invisible'), 'gtk-close', true); + item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSessionPresenceStatus.INVISIBLE)); + this._menu.append(item); + item.show(); + + item = new Gtk.SeparatorMenuItem(); + this._menu.append(item); + item.show(); + item = this._createImageMenuItem(_('Account Information...'), 'user-info'); item.connect('activate', Lang.bind(this, this._onAccountInformationActivate)); this._menu.append(item); @@ -123,6 +169,10 @@ StatusMenu.prototype = { item.show(); }, + _setPresenceStatus: function(item, status) { + this._presence.setStatus(status); + }, + _onAccountInformationActivate: function() { this._spawn(['gnome-about-me']); }, @@ -200,3 +250,47 @@ StatusMenu.prototype = { } }; Signals.addSignalMethods(StatusMenu.prototype); + + +const GnomeSessionPresenceIface = { + name: 'org.gnome.SessionManager.Presence', + methods: [{ name: 'SetStatus', + inSignature: 'u' }], + properties: [{ name: 'status', + signature: 'u', + access: 'readwrite' }], + signals: [{ name: 'StatusChanged', + inSignature: 'u' }] +}; + +const GnomeSessionPresenceStatus = { + AVAILABLE: 0, + INVISIBLE: 1, + BUSY: 2, + IDLE: 3 +}; + +function GnomeSessionPresence() { + this._init(); +} + +GnomeSessionPresence.prototype = { + _init: function() { + DBus.session.proxifyObject(this, 'org.gnome.SessionManager', '/org/gnome/SessionManager/Presence', this); + this.connect('StatusChanged', Lang.bind(this, function (proxy, status) { this.status = status; })); + }, + + getStatus: function(callback) { + this.GetRemote('status', Lang.bind(this, + function(status, ex) { + if (!ex) + callback(this, status); + })); + }, + + setStatus: function(status) { + this.SetStatusRemote(status); + } +}; +DBus.proxifyPrototype(GnomeSessionPresence.prototype, GnomeSessionPresenceIface); + From 050e7107701fa3f3a27803e798877439125c28fc Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 12 Nov 2009 15:17:35 -0500 Subject: [PATCH 40/51] Use gnome-terminal rather than xterm+xeyes+xlogo in --xephyr mode https://bugzilla.gnome.org/show_bug.cgi?id=588056 --- src/gnome-shell.in | 4 +--- tools/build/gnome-shell-build-setup.sh | 16 +++++++--------- 2 files changed, 8 insertions(+), 12 deletions(-) mode change 100644 => 100755 src/gnome-shell.in diff --git a/src/gnome-shell.in b/src/gnome-shell.in old mode 100644 new mode 100755 index e5ef5095e..b009ec495 --- a/src/gnome-shell.in +++ b/src/gnome-shell.in @@ -53,9 +53,7 @@ def start_xephyr(): time.sleep(1) # Start some windows in our session. - subprocess.Popen(["xterm", "-geometry", "+30+30"]) - subprocess.Popen(["xlogo", "-geometry", "-0-0"]) - subprocess.Popen(["xeyes", "-geometry", "-0+30"]) + subprocess.Popen(["gnome-terminal"]) return xephyr; diff --git a/tools/build/gnome-shell-build-setup.sh b/tools/build/gnome-shell-build-setup.sh index 1f5ddd474..223500353 100755 --- a/tools/build/gnome-shell-build-setup.sh +++ b/tools/build/gnome-shell-build-setup.sh @@ -53,12 +53,10 @@ fi # # Non-devel packages needed by gnome-shell and its deps: # glxinfo, gstreamer-plugins-base, gstreamer-plugins-good, -# python, pygobject, gnome-python (gconf), -# Xephyr, xeyes*, xlogo*, xterm*, zenity +# python, pygobject, gnome-python (gconf), gnome-terminal* +# Xephyr*, zenity # -# (*)ed packages are only needed because gnome-shell launches them -# when running in Xephyr mode, and we should probably change it to use -# less lame things. +# (*) only needed for --xephyr # Can this be simplified? Obvious ways don't handle handle packages # that have been installed then removed. ('purged' status, e.g.) @@ -82,7 +80,7 @@ if test x$system = xUbuntu -o x$system = xDebian -o x$system = xLinuxMint ; then libdbus-glib-1-dev libgconf2-dev libgtk2.0-dev libffi-dev \ libgnome-menu-dev libgnome-desktop-dev librsvg2-dev libwnck-dev libgl1-mesa-dev \ libreadline5-dev mesa-common-dev mesa-utils python-dev python-gconf python-gobject \ - xulrunner-dev xserver-xephyr libcroco3-dev \ + xulrunner-dev xserver-xephyr gnome-terminal libcroco3-dev \ libgstreamer0.10-dev gstreamer0.10-plugins-base gstreamer0.10-plugins-good \ ; do if ! dpkg_is_installed $pkg; then @@ -106,7 +104,7 @@ if test x$system = xFedora ; then gnome-desktop-devel librsvg2-devel libwnck-devel mesa-libGL-devel python-devel pygobject2 \ readline-devel xulrunner-devel libXdamage-devel libcroco-devel \ gstreamer-devel gstreamer-plugins-base gstreamer-plugins-good \ - glx-utils xorg-x11-apps xorg-x11-server-Xephyr xterm zenity \ + glx-utils xorg-x11-server-Xephyr gnome-terminal zenity \ ; do if ! rpm -q $pkg > /dev/null 2>&1; then reqd="$pkg $reqd" @@ -124,7 +122,7 @@ if test x$system = xSUSE ; then bison flex gnome-doc-utils-devel \ gconf2-devel libffi-devel gnome-desktop-devel librsvg-devel libwnck-devel \ xorg-x11-proto-devel readline-devel mozilla-xulrunner190-devel \ - libcroco-devel xorg-x11-devel xterm xorg-x11 xorg-x11-server-extra \ + libcroco-devel xorg-x11-devel xorg-x11 xorg-x11-server-extra \ ; do if ! rpm -q $pkg > /dev/null 2>&1; then reqd="$pkg $reqd" @@ -144,7 +142,7 @@ if test x$system = xMandrivaLinux ; then bison flex gnome-common gnome-doc-utils gtk-doc intltool \ libGConf2-devel ffi5-devel libgnomeui2-devel librsvg2-devel \ libwnck-1-devel GL-devel readline-devel libxulrunner-devel \ - libxdamage-devel mesa-demos x11-server-xephyr x11-apps xterm zenity \ + libxdamage-devel mesa-demos x11-server-xephyr zenity \ libcroco0.6-devel \ ; do if ! rpm -q --whatprovides $pkg > /dev/null 2>&1; then From 21f15246a6cba287d1d1769607352eec5ef6d938 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 13 Nov 2009 14:27:25 -0500 Subject: [PATCH 41/51] [genericDisplay] Fix selection not being set correctly We need to check if the display actor is an instance of Shell.OverflowList or St.BoxLayout to use the appropriate function for getting its child with a given index. --- js/ui/genericDisplay.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/ui/genericDisplay.js b/js/ui/genericDisplay.js index 8ee03343b..d5c3e3f38 100644 --- a/js/ui/genericDisplay.js +++ b/js/ui/genericDisplay.js @@ -734,7 +734,11 @@ GenericDisplay.prototype = { // Returns a display item based on its index in the ordering of the // display children. _findDisplayedByIndex: function(index) { - let actor = this._list.get_children()[index]; + let actor; + if (this.actor instanceof Shell.OverflowList) + actor = this.actor.get_displayed_actor(index); + else + actor = this._list.get_children()[index]; return this._findDisplayedByActor(actor); }, From 8334b063f11a2032f1302a6d6eebcfe5da0ee1a2 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 13 Nov 2009 14:38:38 -0500 Subject: [PATCH 42/51] Deal with title-less windows https://bugzilla.gnome.org/show_bug.cgi?id=601290 --- js/ui/altTab.js | 13 ++++++++----- src/shell-app-system.c | 2 ++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/js/ui/altTab.js b/js/ui/altTab.js index a1a5f1612..dd7726631 100644 --- a/js/ui/altTab.js +++ b/js/ui/altTab.js @@ -751,11 +751,14 @@ ThumbnailList.prototype = { height: height * scale }); box.add_actor(clone); - let name = new St.Label({ text: windows[i].get_title() }); - // St.Label doesn't support text-align so use a Bin - let bin = new St.Bin({ x_align: St.Align.MIDDLE }); - bin.add_actor(name); - box.add_actor(bin); + let title = windows[i].get_title(); + if (title) { + let name = new St.Label({ text: title }); + // St.Label doesn't support text-align so use a Bin + let bin = new St.Bin({ x_align: St.Align.MIDDLE }); + bin.add_actor(name); + box.add_actor(bin); + } this.addItem(box); } diff --git a/src/shell-app-system.c b/src/shell-app-system.c index 898fd0f95..2ec877472 100644 --- a/src/shell-app-system.c +++ b/src/shell-app-system.c @@ -740,6 +740,8 @@ shell_app_info_get_name (ShellAppInfo *info) { char *title; g_object_get (info->window, "title", &title, NULL); + if (!title) + title = g_strdup (""); return title; } } From ab809faaf05cab63956998474f25da4444241e90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Urban=C4=8Di=C4=8D?= Date: Sat, 14 Nov 2009 11:18:02 +0100 Subject: [PATCH 43/51] Updated Slovenian translation --- po/sl.po | 63 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/po/sl.po b/po/sl.po index 6ae049c58..e55ddadff 100644 --- a/po/sl.po +++ b/po/sl.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: gnome-shell master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell&component=general\n" -"POT-Creation-Date: 2009-10-23 17:29+0000\n" -"PO-Revision-Date: 2009-10-26 07:29+0100\n" +"POT-Creation-Date: 2009-11-12 21:33+0000\n" +"PO-Revision-Date: 2009-11-14 10:19+0100\n" "Last-Translator: Matej Urbančič \n" "Language-Team: Slovenian GNOME Translation Team \n" "MIME-Version: 1.0\n" @@ -27,60 +27,53 @@ msgstr "Gnome lupina" msgid "Window management and application launching" msgstr "Upravljanje oken in zaganjanje programov" -#: ../js/ui/appDisplay.js:332 -msgid "Frequent" -msgstr "Pogosto" +#: ../js/ui/appDisplay.js:696 +msgid "Drag here to add favorites" +msgstr "S potegom na to mesto se izbor doda med priljubljene" -#: ../js/ui/appIcon.js:426 +#: ../js/ui/appIcon.js:425 msgid "New Window" msgstr "Novo okno" -#: ../js/ui/appIcon.js:430 +#: ../js/ui/appIcon.js:429 msgid "Remove from Favorites" msgstr "Odstrani iz priljubljenih" -#: ../js/ui/appIcon.js:431 +#: ../js/ui/appIcon.js:430 msgid "Add to Favorites" msgstr "Dodaj med priljubljene" -#: ../js/ui/dash.js:283 +#: ../js/ui/dash.js:237 msgid "Find..." msgstr "Poišči ..." -#: ../js/ui/dash.js:400 -msgid "More" -msgstr "Več" - -#: ../js/ui/dash.js:543 -msgid "(see all)" -msgstr "(poglej vse)" - #. **** Applications **** -#: ../js/ui/dash.js:725 -#: ../js/ui/dash.js:787 +#: ../js/ui/dash.js:656 +#: ../js/ui/dash.js:718 msgid "APPLICATIONS" msgstr "Programi" #. **** Places **** #. Translators: This is in the sense of locations for documents, #. network locations, etc. -#: ../js/ui/dash.js:745 +#: ../js/ui/dash.js:676 +#: ../js/ui/dash.js:733 msgid "PLACES" msgstr "Mesta" #. **** Documents **** -#: ../js/ui/dash.js:752 -#: ../js/ui/dash.js:797 +#: ../js/ui/dash.js:683 +#: ../js/ui/dash.js:728 msgid "RECENT DOCUMENTS" msgstr "Nedavni dokumenti" #. **** Search Results **** -#: ../js/ui/dash.js:777 -#: ../js/ui/dash.js:961 +#: ../js/ui/dash.js:708 +#: ../js/ui/dash.js:898 msgid "SEARCH RESULTS" msgstr "Rezultati iskanja" -#: ../js/ui/dash.js:792 +#: ../js/ui/dash.js:723 msgid "PREFERENCES" msgstr "Lastnosti" @@ -95,13 +88,13 @@ msgstr "Dejavnosti" msgid "%a %l:%M %p" msgstr "%a, %H:%M" -#: ../js/ui/places.js:178 +#: ../js/ui/placeDisplay.js:84 msgid "Connect to..." msgstr "Povezava z ..." #: ../js/ui/runDialog.js:96 msgid "Please enter a command:" -msgstr "Prosim, vnesite ukaz:" +msgstr "Vnos ukaza:" #: ../js/ui/runDialog.js:173 #, c-format @@ -121,11 +114,11 @@ msgstr "Programi" msgid "Recent Documents" msgstr "Nedavni dokumenti" -#: ../src/shell-global.c:812 +#: ../src/shell-global.c:821 msgid "Less than a minute ago" msgstr "Pred manj kot eno minuto" -#: ../src/shell-global.c:815 +#: ../src/shell-global.c:824 #, c-format msgid "%d minute ago" msgid_plural "%d minutes ago" @@ -134,7 +127,7 @@ msgstr[1] "Pred %d minuto" msgstr[2] "Pred %d minutama" msgstr[3] "Pred %d minutami" -#: ../src/shell-global.c:818 +#: ../src/shell-global.c:827 #, c-format msgid "%d hour ago" msgid_plural "%d hours ago" @@ -143,7 +136,7 @@ msgstr[1] "Pred %d uro" msgstr[2] "Pred %d urama" msgstr[3] "Pred %d urami" -#: ../src/shell-global.c:821 +#: ../src/shell-global.c:830 #, c-format msgid "%d day ago" msgid_plural "%d days ago" @@ -152,7 +145,7 @@ msgstr[1] "Pred %d dnevom" msgstr[2] "Pred %d dnevoma" msgstr[3] "Pred %d dnevi" -#: ../src/shell-global.c:824 +#: ../src/shell-global.c:833 #, c-format msgid "%d week ago" msgid_plural "%d weeks ago" @@ -235,6 +228,12 @@ msgstr "Iskanje" msgid "%1$s: %2$s" msgstr "%1$s: %2$s" +#~ msgid "Frequent" +#~ msgstr "Pogosto" +#~ msgid "More" +#~ msgstr "Več" +#~ msgid "(see all)" +#~ msgstr "(poglej vse)" #~ msgid "Browse" #~ msgstr "Prebrskaj" From 931cbc6ae3ccecff5f26e30f9e582c1a848a0494 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 14 Nov 2009 10:10:33 -0500 Subject: [PATCH 44/51] Fix sidebar enable/disable menu item https://bugzilla.gnome.org/show_bug.cgi?id=601875 --- js/ui/statusMenu.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/ui/statusMenu.js b/js/ui/statusMenu.js index 7aa5f2884..3486ca0bc 100644 --- a/js/ui/statusMenu.js +++ b/js/ui/statusMenu.js @@ -137,6 +137,7 @@ StatusMenu.prototype = { })); this._menu.append(item); item.show(); + this._sidebarItem = item; item = this._createImageMenuItem(_('System Preferences...'), 'preferences-desktop'); item.connect('activate', Lang.bind(this, this._onPreferencesActivate)); From cdd508e12d825f8b6c411448513c24fd17f862bb Mon Sep 17 00:00:00 2001 From: Florian Muellner Date: Sun, 15 Nov 2009 02:24:43 +0100 Subject: [PATCH 45/51] Darken workspace indicator when doing lightbox effect Adjust the opacity of the workspace indicator to not having it stand out too badly when in lightbox mode. https://bugzilla.gnome.org/show_bug.cgi?id=594556 --- js/ui/workspaces.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/ui/workspaces.js b/js/ui/workspaces.js index 1cde8acce..8e4a60d97 100644 --- a/js/ui/workspaces.js +++ b/js/ui/workspaces.js @@ -575,6 +575,9 @@ Workspace.prototype = { this._lightbox.destroy(); this._lightbox = null; } + if (this._frame) { + this._frame.set_opacity(showLightbox ? 150 : 255); + } }, /** From a5edc78fac9f2d1ddb8a91556d6cd02ec8911130 Mon Sep 17 00:00:00 2001 From: Abderrahim Kitouni Date: Sat, 14 Nov 2009 18:20:31 +0100 Subject: [PATCH 46/51] [StWidget] add API support for right-to-left UI https://bugzilla.gnome.org/show_bug.cgi?id=584662 --- src/st/st-widget.c | 36 ++++++++++++++++++++++++++++++++++++ src/st/st-widget.h | 11 +++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/st/st-widget.c b/src/st/st-widget.c index d606497d5..482d5c04a 100644 --- a/src/st/st-widget.c +++ b/src/st/st-widget.c @@ -66,6 +66,8 @@ struct _StWidgetPrivate gboolean draw_border_internal : 1; StTooltip *tooltip; + + StTextDirection direction; }; /** @@ -1272,6 +1274,40 @@ st_widget_ensure_style (StWidget *widget) st_widget_recompute_style (widget, NULL); } +static StTextDirection default_direction = ST_TEXT_DIRECTION_LTR; + +StTextDirection +st_widget_get_default_direction (void) +{ + return default_direction; +} + +void +st_widget_set_default_direction (StTextDirection dir) +{ + g_return_if_fail (dir != ST_TEXT_DIRECTION_NONE); + + default_direction = dir; +} + +StTextDirection +st_widget_get_direction (StWidget *self) +{ + g_return_val_if_fail (ST_IS_WIDGET (self), ST_TEXT_DIRECTION_LTR); + + if (self->priv->direction != ST_TEXT_DIRECTION_NONE) + return self->priv->direction; + else + return default_direction; +} + +void +st_widget_set_direction (StWidget *self, StTextDirection dir) +{ + g_return_if_fail (ST_IS_WIDGET (self)); + self->priv->direction = dir; +} + /** * st_widget_get_border_image: * @actor: A #StWidget diff --git a/src/st/st-widget.h b/src/st/st-widget.h index 66f7b0698..bebe28620 100644 --- a/src/st/st-widget.h +++ b/src/st/st-widget.h @@ -35,6 +35,12 @@ G_BEGIN_DECLS +typedef enum { + ST_TEXT_DIRECTION_NONE, + ST_TEXT_DIRECTION_LTR, + ST_TEXT_DIRECTION_RTL +} StTextDirection; + #define ST_TYPE_WIDGET (st_widget_get_type ()) #define ST_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_WIDGET, StWidget)) #define ST_IS_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_WIDGET)) @@ -103,6 +109,11 @@ void st_widget_hide_tooltip (StWidget *widget); void st_widget_ensure_style (StWidget *widget); +StTextDirection st_widget_get_default_direction (void); +void st_widget_set_default_direction (StTextDirection dir); + +StTextDirection st_widget_get_direction (StWidget *self); +void st_widget_set_direction (StWidget *self, StTextDirection dir); /* Only to be used by sub-classes of StWidget */ void st_widget_style_changed (StWidget *widget); From 4e8206d60ec448c04ad9c45665c4429651a35b08 Mon Sep 17 00:00:00 2001 From: Abderrahim Kitouni Date: Sat, 14 Nov 2009 18:22:36 +0100 Subject: [PATCH 47/51] [StBoxLayout] now RTL aware https://bugzilla.gnome.org/show_bug.cgi?id=584662 --- src/st/st-box-layout.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/st/st-box-layout.c b/src/st/st-box-layout.c index 90c7d71f6..88c2d9309 100644 --- a/src/st/st-box-layout.c +++ b/src/st/st-box-layout.c @@ -803,6 +803,8 @@ st_box_layout_allocate (ClutterActor *actor, gint n_expand_children = 0, i; gfloat expand_amount, shrink_amount; BoxChildShrink *shrinks = NULL; + gboolean flip = (st_widget_get_direction (ST_WIDGET (actor)) == ST_TEXT_DIRECTION_RTL) + && (!priv->is_vertical); CLUTTER_ACTOR_CLASS (st_box_layout_parent_class)->allocate (actor, box, flags); @@ -897,6 +899,8 @@ st_box_layout_allocate (ClutterActor *actor, if (priv->is_vertical) position = content_box.y1; + else if (flip) + position = content_box.x2; else position = content_box.x1; @@ -954,7 +958,10 @@ st_box_layout_allocate (ClutterActor *actor, else if (shrink_amount > 0) child_allocated -= shrinks[i].shrink_amount; - next_position = position + child_allocated; + if (flip) + next_position = position - child_allocated; + else + next_position = position + child_allocated; if (priv->is_vertical) { @@ -972,8 +979,17 @@ st_box_layout_allocate (ClutterActor *actor, } else { - child_box.x1 = (int)(0.5 + position); - child_box.x2 = (int)(0.5 + next_position); + if (flip) + { + child_box.x1 = (int)(0.5 + next_position); + child_box.x2 = (int)(0.5 + position); + } + else + { + child_box.x1 = (int)(0.5 + position); + child_box.x2 = (int)(0.5 + next_position); + } + child_box.y1 = content_box.y1; if (priv->vadjustment) child_box.y2 = content_box.y1 + MAX (avail_height, natural_height); @@ -984,7 +1000,10 @@ st_box_layout_allocate (ClutterActor *actor, clutter_actor_allocate (child, &child_box, flags); } - position = next_position + priv->spacing; + if (flip) + position = next_position - priv->spacing; + else + position = next_position + priv->spacing; next_child: if (priv->is_pack_start) From 3529b8c9150959454e68a02e76d0a3a0a4a7bbb7 Mon Sep 17 00:00:00 2001 From: Abderrahim Kitouni Date: Sat, 14 Nov 2009 18:23:56 +0100 Subject: [PATCH 48/51] [StTable] now RTL aware https://bugzilla.gnome.org/show_bug.cgi?id=584662 --- src/st/st-table.c | 77 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 15 deletions(-) diff --git a/src/st/st-table.c b/src/st/st-table.c index e844ff6fb..42723a36c 100644 --- a/src/st/st-table.c +++ b/src/st/st-table.c @@ -290,7 +290,8 @@ st_table_allocate_fill (ClutterActor *child, gdouble x_align, gdouble y_align, gboolean x_fill, - gboolean y_fill) + gboolean y_fill, + gboolean ltr) { gfloat natural_width, natural_height; gfloat min_width, min_height; @@ -310,8 +311,16 @@ st_table_allocate_fill (ClutterActor *child, if (x_fill) { - allocation.x1 = childbox->x1; - allocation.x2 = (int)(allocation.x1 + available_width); + if (ltr) + { + allocation.x1 = childbox->x1; + allocation.x2 = (int)(allocation.x1 + available_width); + } + else + { + allocation.x2 = childbox->x2; + allocation.x1 = (int)(allocation.x2 - available_width); + } } if (y_fill) @@ -361,8 +370,16 @@ st_table_allocate_fill (ClutterActor *child, if (!x_fill) { - allocation.x1 = childbox->x1 + (int)((available_width - child_width) * x_align); - allocation.x2 = allocation.x1 + (int) child_width; + if (ltr) + { + allocation.x1 = childbox->x1 + (int)((available_width - child_width) * x_align); + allocation.x2 = allocation.x1 + (int) child_width; + } + else + { + allocation.x2 = childbox->x2 - (int)((available_width - child_width) * x_align); + allocation.x1 = allocation.x2 - (int) child_width; + } } if (!y_fill) @@ -384,6 +401,7 @@ st_table_homogeneous_allocate (ClutterActor *self, gfloat col_width, row_height; gint row_spacing, col_spacing; StTablePrivate *priv = ST_TABLE (self)->priv; + gboolean ltr = st_widget_get_direction (ST_WIDGET (self)) == ST_TEXT_DIRECTION_LTR; col_spacing = priv->col_spacing; row_spacing = priv->row_spacing; @@ -421,13 +439,21 @@ st_table_homogeneous_allocate (ClutterActor *self, x_fill = meta->x_fill; y_fill = meta->y_fill; - childbox.x1 = content_box->x1 + (col_width + col_spacing) * col; - childbox.x2 = childbox.x1 + (col_width * col_span) + (col_spacing * (col_span - 1)); + if (ltr) + { + childbox.x1 = content_box->x1 + (col_width + col_spacing) * col; + childbox.x2 = childbox.x1 + (col_width * col_span) + (col_spacing * (col_span - 1)); + } + else + { + childbox.x2 = content_box->x2 - (col_width + col_spacing) * col; + childbox.x1 = childbox.x2 - (col_width * col_span) - (col_spacing * (col_span - 1)); + } childbox.y1 = content_box->y1 + (row_height + row_spacing) * row; childbox.y2 = childbox.y1 + (row_height * row_span) + (row_spacing * (row_span - 1)); - st_table_allocate_fill (child, &childbox, x_align, y_align, x_fill, y_fill); + st_table_allocate_fill (child, &childbox, x_align, y_align, x_fill, y_fill, ltr); clutter_actor_allocate (child, &childbox, flags); } @@ -725,6 +751,7 @@ st_table_preferred_allocate (ClutterActor *self, gint *col_widths, *row_heights; StTable *table; StTablePrivate *priv; + gboolean ltr; table = ST_TABLE (self); priv = ST_TABLE (self)->priv; @@ -741,6 +768,8 @@ st_table_preferred_allocate (ClutterActor *self, (int) (content_box->y2 - content_box->y1), col_widths); + ltr = (st_widget_get_direction (ST_WIDGET (self)) == ST_TEXT_DIRECTION_LTR); + for (list = priv->children; list; list = g_slist_next (list)) { @@ -808,10 +837,20 @@ st_table_preferred_allocate (ClutterActor *self, } /* calculate child x */ - child_x = (int) content_box->x1 - + col_spacing * col; - for (i = 0; i < col; i++) - child_x += col_widths[i]; + if (ltr) + { + child_x = (int) content_box->x1 + + col_spacing * col; + for (i = 0; i < col; i++) + child_x += col_widths[i]; + } + else + { + child_x = (int) content_box->x2 + - col_spacing * col; + for (i = 0; i < col; i++) + child_x -= col_widths[i]; + } /* calculate child y */ child_y = (int) content_box->y1 @@ -820,14 +859,22 @@ st_table_preferred_allocate (ClutterActor *self, child_y += row_heights[i]; /* set up childbox */ - childbox.x1 = (float) child_x; - childbox.x2 = (float) MAX (0, child_x + col_width); + if (ltr) + { + childbox.x1 = (float) child_x; + childbox.x2 = (float) MAX (0, child_x + col_width); + } + else + { + childbox.x2 = (float) child_x; + childbox.x1 = (float) MAX (0, child_x - col_width); + } childbox.y1 = (float) child_y; childbox.y2 = (float) MAX (0, child_y + row_height); - st_table_allocate_fill (child, &childbox, x_align, y_align, x_fill, y_fill); + st_table_allocate_fill (child, &childbox, x_align, y_align, x_fill, y_fill, ltr); clutter_actor_allocate (child, &childbox, flags); } From 9ba5ca019345aa62754a055afcca88a7a46a455f Mon Sep 17 00:00:00 2001 From: Abderrahim Kitouni Date: Sat, 14 Nov 2009 18:08:27 +0100 Subject: [PATCH 49/51] environment.js: set default direction for St widgets https://bugzilla.gnome.org/show_bug.cgi?id=584662 --- js/ui/environment.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/js/ui/environment.js b/js/ui/environment.js index 6d0bb4884..dbf816413 100644 --- a/js/ui/environment.js +++ b/js/ui/environment.js @@ -1,6 +1,7 @@ /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ const St = imports.gi.St; +const Gettext_gtk20 = imports.gettext.domain('gtk20'); const Tweener = imports.ui.tweener; @@ -33,4 +34,9 @@ _patchContainerClass(St.Table); function init() { Tweener.init(); String.prototype.format = Format.format; + + // Set the default direction for St widgets (this needs to be done before any use of St) + if (Gettext_gtk20.gettext("default:LTR") == "default:RTL") { + St.Widget.set_default_direction(St.TextDirection.RTL); + } } From 15265000790f63b27e4cb3899712b310041e494f Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 16 Nov 2009 14:10:13 -0500 Subject: [PATCH 50/51] [placeDisplay] Fix inverted logic for desktop-is-home case We only want to hide the Desktop link if it desktopIsHome, not if it isn't. --- js/ui/placeDisplay.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ui/placeDisplay.js b/js/ui/placeDisplay.js index aa5003eb4..f408fc978 100644 --- a/js/ui/placeDisplay.js +++ b/js/ui/placeDisplay.js @@ -284,7 +284,7 @@ PlacesManager.prototype = { getDefaultPlaces: function () { let places = [this._home]; - if (this._isDesktopHome) + if (!this._isDesktopHome) places.push(this._desktopMenu); if (this._network) From 2c914374e0ec88b199ed9472fc7e54ab87a121ea Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 13 Nov 2009 18:51:07 -0500 Subject: [PATCH 51/51] Integer align workspace and pane positioning We had previously been leaving the scaled workspace at a non-integral position which didn't look obviously ugly, but now that we're constraining the popup pane to the workspace size, we really need to ensure that we're using integral positions here. https://bugzilla.gnome.org/show_bug.cgi?id=601854 --- js/ui/overview.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/js/ui/overview.js b/js/ui/overview.js index e49119275..e217bfe1a 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -148,11 +148,11 @@ Overview.prototype = { // We divide the screen into an imaginary grid which helps us determine the layout of // different visual components. if (wideScreen) { - displayGridColumnWidth = primary.width / COLUMNS_WIDE_SCREEN; - displayGridRowHeight = primary.height / ROWS_WIDE_SCREEN; + displayGridColumnWidth = Math.floor(primary.width / COLUMNS_WIDE_SCREEN); + displayGridRowHeight = Math.floor(primary.height / ROWS_WIDE_SCREEN); } else { - displayGridColumnWidth = primary.width / COLUMNS_REGULAR_SCREEN; - displayGridRowHeight = primary.height / ROWS_REGULAR_SCREEN; + displayGridColumnWidth = Math.floor(primary.width / COLUMNS_REGULAR_SCREEN); + displayGridRowHeight = Math.floor(primary.height / ROWS_REGULAR_SCREEN); } }, @@ -174,11 +174,11 @@ Overview.prototype = { - WORKSPACE_GRID_PADDING * 2; // We scale the vertical padding by (primary.height / primary.width) // so that the workspace preserves its aspect ratio. - this._workspacesHeight = displayGridRowHeight * workspaceRowsUsed - - WORKSPACE_GRID_PADDING * (primary.height / primary.width) * 2; + this._workspacesHeight = Math.floor(displayGridRowHeight * workspaceRowsUsed + - WORKSPACE_GRID_PADDING * (primary.height / primary.width) * 2); this._workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING; - this._workspacesY = displayGridRowHeight + WORKSPACE_GRID_PADDING * (primary.height / primary.width); + this._workspacesY = Math.floor(displayGridRowHeight + WORKSPACE_GRID_PADDING * (primary.height / primary.width)); this._dash.actor.set_position(0, contentY); this._dash.actor.set_size(displayGridColumnWidth, contentHeight);