Compare commits

..

26 Commits

Author SHA1 Message Date
42619cdd3b Bump version to 3.12.2
Update NEWS.
2014-05-14 10:39:36 +02:00
76ea1f4dca search: Make sure to destroy old provider displays when we unregister
When we unregistered providers, like when we refreshed the list of
active remote providers, we would forget to destroy the old provider
display after the fact. This left an empty "skeleton" provider display
still in the search results that would never be filled in. Make sure
to destroy it properly.

https://bugzilla.gnome.org/show_bug.cgi?id=728597
2014-05-10 08:58:39 -05:00
e4e3252ffc [l10n] Updated Catalan (Valencian) translation 2014-05-09 00:03:24 +02:00
e9ae77186d system: Keep key focus when switching between alternatives
When switching between alternatives in AltSwitcher, the currently
visible child is replaced with the alternative. If the original
child has the key focus when it is removed from the stage, the
focus is lost. Detect this case and manually move the focus to
the new child.

https://bugzilla.gnome.org/show_bug.cgi?id=727259
2014-05-06 14:29:28 +02:00
a0c146bbfd Fix Italian translation
- "Aereo" is the thing that flies, "Aero" is the Windows 7 theme.
- "Abilita", not "Abilitato", for the Enable action.
2014-05-04 15:23:25 +02:00
6d679148b6 Updated Belarusian translation. 2014-05-03 14:46:52 +02:00
07198c5890 rfkill: make the Airplane mode menu insensitive in the lock screen
Like we do for the bluetooth and wifi menus

https://bugzilla.gnome.org/show_bug.cgi?id=729224
2014-04-30 22:00:00 +02:00
4720bc3412 workspaceThumbnails: Fix removal of multiple workspaces
When workspaces have been removed, we need to remove the corresponding
thumbnails as well; the number of thumbnails that need removing is
the difference between the old number of workspaces and the new one.
Currently we assume that the old number of workspaces corresponds to
the number of existing thumbnails, but that may actually be wrong:
A thumbnail will still be animated out after its workspace has been
removed. As a result, we end up removing too many thumbnails when a
workspace is removed while a thumbnail of a previously removed workspace
is still animating out. Fix this by basing the old number of workspaces
only on thumbnails that have not been removed previously.

https://bugzilla.gnome.org/show_bug.cgi?id=728820
2014-04-26 17:51:42 +02:00
7113821964 osdWindow: Fix setting a zero-level in osdWindow
Commit 7101cc3170 caused a small
regression insomuch that it checks for a valid "level" but simply using
"if (level)" which will be false if level is undefined and if
level == 0.

Check for not undefined instead.

https://bugzilla.gnome.org/show_bug.cgi?id=727384
2014-04-25 15:19:32 +02:00
c2ae98209d networkAgent: Handle empty vpn 'keyfiles'
Passing back no data is valid in case both secrets (group and user passwords)
are stored.

Just confirm the request in that case.

https://bugzilla.gnome.org/show_bug.cgi?id=728681
2014-04-23 13:10:37 +02:00
21f0e422c0 Updated Ukrainian translation 2014-04-22 23:08:29 +03:00
eb0f2b8b34 rfkill: fix turning off airplane mode from the menu
The menu does not have a proxy anymore, it needs to go through
the manager.

https://bugzilla.gnome.org/show_bug.cgi?id=728512
2014-04-21 19:14:08 +02:00
65e781a973 Updated Dutch translation 2014-04-18 20:16:28 +02:00
4590903159 Bump version to 3.12.1
Update NEWS.
2014-04-15 23:37:57 +02:00
8b6fcbea50 layout: Don't always extend struts to the screen edge
NetWM struts are defined in terms of screen edges (rather than monitor
edges), which works poorly with vertical monitor layouts (as it renders
entire monitors unusable). Don't extend struts in those cases.

https://bugzilla.gnome.org/show_bug.cgi?id=663690
2014-04-15 23:36:33 +02:00
c6067ffa1d extension-prefs: Force linking with libgnome-shell-js
Use the same hack we use for the main executable to fool the linker
when using --as-needed.

https://bugzilla.gnome.org/show_bug.cgi?id=727948
2014-04-15 23:36:33 +02:00
7b4254da4e Revert "global: Run maybe_gc at leisure again"
It's causing segfaults so let's back it out for 3.12.1

This reverts commit 2f576e3076.
2014-04-15 14:14:47 +02:00
2f576e3076 global: Run maybe_gc at leisure again
The deadlocks are now fixed this should keep memory usage low,
avoid memory fragmentation and prevent the gc from running at
inconvient times.
2014-04-14 23:11:30 +02:00
60d7c3ad86 Updated Serbian translation 2014-04-14 19:33:40 +02:00
43fdc15ac0 l10n: Update Japanese translation 2014-04-15 00:36:18 +09:00
f082a58071 Updated Danish translation 2014-04-13 21:58:56 +02:00
ae5dfb5740 Updated Hungarian translation 2014-04-13 15:42:58 +02:00
e8fdba4f66 Updated Latvian translation 2014-04-12 12:36:23 +03:00
1030cdfe8a layout: Change setDummyCursorPosition to also set the size
If we are being used to follow a text entry cursor we also need to set
the size so that the popup menu avoids covering it.

https://bugzilla.gnome.org/show_bug.cgi?id=727579
2014-04-11 16:51:31 +02:00
ca2d626b59 Added Khmer translation 2014-04-10 23:35:19 +02:00
2b4eaf6b3f Updated Indonesian translation 2014-04-10 23:35:11 +02:00
211 changed files with 33514 additions and 46819 deletions

7
.gitignore vendored
View File

@ -24,13 +24,10 @@ data/gnome-shell-wayland.desktop.in
data/gnome-shell-extension-prefs.desktop data/gnome-shell-extension-prefs.desktop
data/gnome-shell-extension-prefs.desktop.in data/gnome-shell-extension-prefs.desktop.in
data/gschemas.compiled data/gschemas.compiled
data/perf-background.xml
data/org.gnome.shell.gschema.xml data/org.gnome.shell.gschema.xml
data/org.gnome.shell.gschema.valid data/org.gnome.shell.gschema.valid
data/org.gnome.shell.evolution.calendar.gschema.xml data/org.gnome.shell.evolution.calendar.gschema.xml
data/org.gnome.shell.evolution.calendar.gschema.valid data/org.gnome.shell.evolution.calendar.gschema.valid
data/org.gnome.Shell.PortalHelper.desktop
data/org.gnome.Shell.PortalHelper.service
docs/reference/*/*.args docs/reference/*/*.args
docs/reference/*/*.bak docs/reference/*/*.bak
docs/reference/*/*.hierarchy docs/reference/*/*.hierarchy
@ -81,9 +78,11 @@ src/gnome-shell-calendar-server
src/gnome-shell-extension-prefs src/gnome-shell-extension-prefs
src/gnome-shell-extension-tool src/gnome-shell-extension-tool
src/gnome-shell-hotplug-sniffer src/gnome-shell-hotplug-sniffer
src/gnome-shell-jhbuild
src/gnome-shell-perf-helper src/gnome-shell-perf-helper
src/gnome-shell-perf-tool src/gnome-shell-perf-tool
src/gnome-shell-portal-helper src/gnome-shell-real
src/gnome-shell-wayland
src/hotplug-sniffer/org.gnome.Shell.HotplugSniffer.service src/hotplug-sniffer/org.gnome.Shell.HotplugSniffer.service
src/run-js-test src/run-js-test
src/test-recorder src/test-recorder

253
NEWS
View File

@ -1,229 +1,22 @@
3.14.2 3.12.2
======
* Do not hard-depend on latest NetworkManager [Florian; #738485]
* Fix check for isToday in calendar [Darcy; #738725]
* Fix workspace changes from app picker [Yuki; #737534]
* Misc. bug fixes [Yuki; #739497]
Contributors:
Darcy, Florian Müllner, Yuki
3.14.1.5
========
* Fix handing of SystemBackground [Owen; #738652]
* Summarize queued up notifications [Devyani; #702460]
* Plug an animation object leak [Rui; #739252]
* Improve handling of multi-day events [Andreas; #727302]
Contributors:
Andreas Brauchli, Devyani Kota, Rui Matos, Owen W. Taylor
3.14.1
======
* Fix pulse animation for scrolled app folders [Florian; #736885]
* Fix updating background on file changes [Owen; #710756]
* Obtain keyboard variant from IBus [Jinkyu; #735066]
* Implement Ctrl-u / Ctrl-k keybindings in entries [Florian; #737346]
* Pass VPN hints to auth dialog [Dan; #737592]
* Only allow one screenshot request at a time [Adel; #737456]
* Respect disable-save-to-disc lockdown setting [Florian; #737846]
* Respect scaling-factor for profile pictures [Darcy; #735419]
* Focus login screen after lifting the lock screen shield [Ray; #708105]
* Speed up pulse animation for few items [Carlos S.; #737017]
* Fix gap between workspace switcher and screen edge [Florian; #728899]
* Disable unredirection during recordings [Adel; #738226]
* Ensure there's always at least one input source [Rui; #738303]
* Restrict width of dash icons' context menus [Adel; #738054]
* Misc. bug fixes [Jasper, Florian, Carlos G., Owen; #736999, #737382, #737001,
#738314, #738256, #738147]
Contributors:
Darcy Beurle, Cosimo Cecchi, Adel Gadllah, Carlos Garnacho, Rui Matos,
Florian Müllner, Carlos Soriano, Jasper St. Pierre, Ray Strode, Patrick Ward,
Dan Williams, Owen W. Taylor, Jinkyu Yi
Translations:
Мирослав Николић po/sr, sr@latin.po, Fran Diéguez [gl], Marek Černocký [cs],
Saibal Ray [bn_IN], Rajesh Ranjan [hi], Friedel Wolff [af],
Zhou Fang [zh_CN], Krishnababu Krothapalli [te], Kjartan Maraas [nb],
Rūdolfs Mazurs [lv], Sweta Kothari [gu], Christian Kirbach [de],
Cheng-Chia Tseng [zh_TW], Pedro Albuquerque [pt], Daniel Mustieles [es],
Luca Ferretti [it], Baurzhan Muftakhidinov [kk], Arash Mousavi [fa],
Milo Casagrande [it]
3.14.0
======
* Fix exposure of the accessible tree [Alejandro; #736821]
* Hide empty app folders in app picker [Florian; #736910]
Contributors:
Florian Müllner, Alejandro Piñeiro
Translations:
Yuri Myasoedov [ru], Pawan Chitrakar [ne], Manoj Kumar Giri [or],
Daniel Mustieles [es], GNOME Translation Robot [de], Rajesh Ranjan [hi],
Shankar Prasad [kn], Kenneth Nielsen [da], Daniel Korostil [uk],
Changwoo Ryu [ko], A S Alam [pa], Tom Tryfonidis [el], Petr Kovar [cs]
3.13.92
=======
* Fix submenu arrow animations [Hashem; #728927]
* Always initialize clutter accessibility [Alejandro; #735908]
* Adapt to mutter background changes [Owen; #735638]
* Improve handling of outOfDate extensions in prefs [Florian; #736185]
* Port offline updates to PackageKit's DBus interface [Kalev; #736337]
* location: Translate accuracy levels for geoclue [Zeeshan; #736479]
* Implement input source switching [Rui; #736435]
* Fix crash when dragging window from workspace switcher [Carlos G.; #735972]
* Clean out list of default favorites [Elad; #735682]
* Add settings link to location submenu [Florian; #736542]
* Fix keynav of message tray menu button [Florian; #707799]
* Misc. bug fixes [Carlos G., Florian, Rui; #736110, #736329, #736343,
#735927, #735976]
Contributors:
Elad Alfassa, Zeeshan Ali (Khattak), Michael Catanzaro, Adel Gadllah,
Carlos Garnacho, Kalev Lember, Rui Matos, Florian Müllner, Hashem Nasarat,
Alejandro Piñeiro, Carlos Soriano, Jasper St. Pierre, Owen W. Taylor
Translations:
Piotr Drąg [pl], Changwoo Ryu [ko], Yuri Myasoedov [ru], Zhou Fang [ja],
Peter Mráz [sk], Ville-Pekka Vainio [fi], Sweta Kothari [gu],
Marek Černocký [cs], A S Alam [pa], Christian Kirbach [de],
Alexandre Franke [fr], Aurimas Černius [lt], Khaled Hosny [ar],
Enrico Nicoletto [pt_BR], Andika Triwidada [id], Shantha kumar [ta],
Matej Urbančič [sl], Pawan Chitrakar [ne], Yosef Or Boczko [he],
Balázs Úr [hu], Dušan Kazik [sk], Gil Forcada [ca],
Carles Ferrando [ca@valencia], Nilamdyuti Goswami [as], Ivaylo Valkov [bg],
Sandeep Sheshrao Shedmake [mr], Umarzuki Bin Mochlis Moktar [ms],
Muhammet Kara [tr], Jiro Matsuzawa [ja], Kris Thomsen [da],
Mattias Eriksson [sv]
3.13.91
=======
* Fix keynav into session menu on login screen [Florian; #735614]
* Add gesture to summon message tray [Carlos G.; #735625]
* Accept scrolls/swipes either way on the screen shield [Jasper; #734874]
* Animate opening the app picker and improve app folder animations
[Carlos S.; #734726]
* Animate app icons on launching a new window [Carlos S., Florian; #734726]
* Show the on-screen keyboard when touch input is being used [David; #702015]
* Misc. bug fixes [Bastien, Owen, Florian, Carlos G.; #735190, #735385,
#735608, #735681]
Contributors:
Carlos Garnacho, David King, Kalev Lember, Florian Müllner, Bastien Nocera,
Carlos Soriano, Jasper St. Pierre, Owen W. Taylor
Translations:
Fran Diéguez [gl], Sweta Kothari [gu], Manoj Kumar Giri [or],
Alain Lojewski [fr], Praveen Illa [te], Arash Mousavi [fa],
Andika Triwidada [id]
3.13.90
=======
* Make use of GLSL optional [Adel; #733623]
* Update on-screen-keyboard position on monitor changes [Cosimo; #733790]
* Improve window manager animations [Giovanni; #732857]
* Handle touch events [Carlos G.; #733633]
* Try to not show "New Window" action for single-window apps
[Giovanni; #722554]
* Fix overview exceeding screen size with many apps installed
[Carlos S.; #723496]
* Add Software to default favorites [Mathieu; #734406]
* Improve app picker <-> desktop transition [Carlos S.; #732901]
* Remove <shift>-magic for switcher popups [Christophe; #732296]
* Add a special background to use for performance testing [Owen; #734610]
* Add support for default disabled search providers [Giovanni; #734110]
* Fix portals that don't redirect properly [Giovanni; #733848]
* Fix history trimming in chat notifications [Giovanni; #733899]
* Try to use default calendar application [Florian; #722333]
* Only show location menu when geolocation is in use [Zeeshan; #731122]
* Misc. bug fixes and cleanups [Giovanni, Carlos G., Zeeshan, Carlos S.,
Cosimo; #711682, #733840, #734483, #734680, #733813, #735062]
Contributors:
Zeeshan Ali (Khattak), Mathieu Bridon, Giovanni Campagna, Cosimo Cecchi,
Piotr Drąg, Christophe Fergeau, Adel Gadllah, Carlos Garnacho,
Florian Müllner, Carlos Soriano, Jasper St. Pierre, Olav Vitters,
Owen W. Taylor
Translations:
Aurimas Černius [lt], MarMav [el], Inaki Larranaga Murgoitio [eu],
Reinout van Schouwen [nl], ngoswami [as], Fabio Tomat [fur],
Chao-Hsiung Liao [zh_HK, zh_TW]
3.13.4
======
* Handle portal login requests [Giovanni; #704416]
* Scale fonts on wayland on hiDPI devices [Adel; #732537]
* Fix default ibus candidate index labels [Rui; #702944]
* Add gestures for various system actions [Carlos G.]
* Add performance test script for the perf.gnome.org [Owen; #732350]
* Use new restart framework to improve restart visuals [Owen; #733026]
* Improve keynav in app folder popups [Carlos S.; #731477]
* Fix truncation of app search results [Carlos S.; #732416]
* Automatically update renamed desktop files in favorites [Kalev; #729429]
* Misc. bug fixes and cleanups [Giovanni, Yosef, Owen, Bastien, Javier;
#729823, #726401, #732301, #732348, #732349, #733498, #733540]
Contributors:
Giovanni Campagna, Adel Gadllah, Carlos Garnacho, Javier Hernández,
Kalev Lember, Rui Matos, Florian Müllner, Bastien Nocera, Yosef Or Boczko,
Carlos Soriano, Jasper St. Pierre, Owen W. Taylor
Translations:
Yuri Myasoedov [ru], Daniel Mustieles [es], Fran Diéguez [gl],
Cheng-Chia Tseng [zh_TW], A S Alam [pa], Benjamin Steinwender [de],
Enrico Nicoletto [pt_BR], MarMav [el], Yosef Or Boczko [he],
Kjartan Maraas [nb]
3.13.3
======
* Don't allow closing windows with attached modals [Florian; #729886]
* Fix self-restarting on OpenBSD [Antoine; #727763]
* Improve behavior of window buttons with compositor menus [Florian; #731058]
* Work around atspi-related performance regression [Alejandro; #730118]
* Misc bug fixes and cleanups [Florian, Lan, Jasper, Christophe, Debarshi,
Zeeshan; #728271, #726460, #703833, #731118, #731220, #695487, #730527,
#728170, #731619, #731738, #731882, #731923]
Contributors:
Zeeshan Ali (Khattak), Christophe Fergeau, Adel Gadllah, Antoine Jacoutot,
Ting-Wei Lan, Florian Müllner, Alejandro Piñeiro, Debarshi Ray,
Carlos Soriano, Jasper St. Pierre, Wim Taymans, Rico Tzschichholz
Translations:
Philip Withnall [en_GB], Milo Casagrande [it], Aurimas Černius [lt],
Enrico Nicoletto [pt_BR], Kjartan Maraas [nb], Balázs Meskó [hu],
Muhammet Kara [tr], Daniel Mustieles [es], Yosef Or Boczko [he],
Matej Urbančič [sl], Mattias Eriksson [sv]
3.13.2
====== ======
* Fix turning off airplane mode [Giovanni; #728512]
* Handle empty VPN keyfiles [Adel; #728681]
* Fix setting zero-level in osdWindow [Bastien; #727384]
* Fix removal of multiple workspace thumbnails at once [Florian; #728820]
* Make airplane mode menu insensitive in lock screen [Giovanni; #729224] * Make airplane mode menu insensitive in lock screen [Giovanni; #729224]
* Don't always extend struts to the screen edge [Florian; #683819]
* Fix keynav for alternatives in AltSwitcher [Florian; #727259] * Fix keynav for alternatives in AltSwitcher [Florian; #727259]
* Implement window menus in the shell [Jasper; #726352] * Fix zombie search providers showing up [Jasper; #728597]
* Support resource:/// URLs in GNOME_SHELL_JS envvar [Owen; #730409]
* Fix switcher popups with keybindings containing Escape [Rui; #730739]
* Update extension-prefs UI to follow GNOME 3 patterns [Florian; #730829]
* Add support for fallback app menu in window decorations [Florian; #730752]
* Fix keynav escaping open app folders [Florian; #726760]
* Misc. bug fixes [Kalev, Florian, Owen; #729429, #728449, #730408, #730753,
#730653]
Contributors: Contributors:
Giovanni Campagna, Piotr Drąg, Kalev Lember, Rui Matos, Florian Müllner, Giovanni Campagna, Adel Gadllah, Florian Müllner, Bastien Nocera,
Vadim Rutkovsky, Carlos Soriano, Jasper St. Pierre, Owen W. Taylor Jasper St. Pierre
Translations: Translations:
Ihar Hrachyshka [be], Giovanni Campagna [it], Carles Ferrando [ca@valencia], Wouter Bolsterlee [nl], Daniel Korostil [uk], Ihar Hrachyshka [be],
Daniel Mustieles [es], Aurimas Černius [lt], Enrico Nicoletto [pt_BR], Giovanni Campagna [it], Carles Ferrando [ca@valencia]
Yosef Or Boczko [he], Marek Černocký [cs], Muhammet Kara [tr],
Georges Neto [pt_BR], Andika Triwidada [id]
3.13.1 3.12.1
====== ======
* Ensure the currently focused app icon is viewable [Rui; #726759] * Ensure the currently focused app icon is viewable [Rui; #726759]
* Improve language in location menu [Zeeshan; #726498] * Improve language in location menu [Zeeshan; #726498]
@ -232,27 +25,12 @@ Translations:
* Fix bad antialiasing on panel menu buttons [Carlos; #727336] * Fix bad antialiasing on panel menu buttons [Carlos; #727336]
* Don't hide location menu [Zeeshan; #727398] * Don't hide location menu [Zeeshan; #727398]
* Fix IM candidate window obscuring current text [Rui; #727579] * Fix IM candidate window obscuring current text [Rui; #727579]
* Fix extension-prefs tool when linked with --as-needed [Florian; #727948]
* Don't always extend struts to the screen edge [Florian; #663690] * Don't always extend struts to the screen edge [Florian; #663690]
* Add shortcuts for switching to the last workspace [Elad; #659288]
* Show OSD window on all monitors [Adel; #722684]
* Improve consistency of labels in network menu [Paul; #727163]
* Fix zombie search providers showing up [Jasper; #728597]
* Remove ConsoleKit support [Florian; #686626]
* Fix region screenshots with open shell menus [Florian; #709126]
* Support <shift>insert in text entries [Florian; #648318]
* Improve app picker scrolling on touch [Jasper; #729064]
* Don't make date button clickable when on current date [Carlos; #726724]
* Tweak heuristic for hiding workspace switcher [Florian; #662457]
* Add option to show in Software to app context menu [Matthias; #643043]
* Misc. bug fixes and cleanups [Bastien, Florian, Giovanni, Adel, Vadim,
Carlos; #727983, #727948, #728512, #728681, #728897, #727384, #728820,
#715042, #728449, #728343]
Contributors: Contributors:
Elad Alfassa, Zeeshan Ali (Khattak), Giovanni Campagna, Cosimo Cecchi, Zeeshan Ali (Khattak), Cosimo Cecchi, Piotr Drąg, Rui Matos, Simon McVittie,
Matthias Clasen, Piotr Drąg, Adel Gadllah, Paul Lange, Rui Matos, Florian Müllner, Alejandro Piñeiro, Carlos Soriano
Simon McVittie, Florian Müllner, Bastien Nocera, Alejandro Piñeiro,
Vadim Rutkovsky, Carlos Soriano, Jasper St. Pierre
Translations: Translations:
Khaled Hosny [ar], Piotr Drąg [pl], Yosef Or Boczko [he], Khaled Hosny [ar], Piotr Drąg [pl], Yosef Or Boczko [he],
@ -264,8 +42,7 @@ Translations:
Fran Diéguez [gl], Pau Iranzo [ca], Luca Ferretti [it], Milo Casagrande [it], Fran Diéguez [gl], Pau Iranzo [ca], Luca Ferretti [it], Milo Casagrande [it],
Tiago S [pt], Victor Ibragimov [tg], Dirgita [id], Khoem Sokhem [km], Tiago S [pt], Victor Ibragimov [tg], Dirgita [id], Khoem Sokhem [km],
Rūdolfs Mazurs [lv], Balázs Úr [hu], Ask H. Larsen [da], Ikuya Awashiro [ja], Rūdolfs Mazurs [lv], Balázs Úr [hu], Ask H. Larsen [da], Ikuya Awashiro [ja],
Wouter Bolsterlee [nl], Daniel Korostil [uk], Daniel Șerbănescu [ro], Мирослав Николић [sr, sr@latin]
Enrico Nicoletto [pt_BR]
3.12.0 3.12.0
====== ======

View File

@ -1,5 +1,5 @@
AC_PREREQ(2.63) AC_PREREQ(2.63)
AC_INIT([gnome-shell],[3.14.2],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell]) AC_INIT([gnome-shell],[3.12.2],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c]) AC_CONFIG_SRCDIR([src/shell-global.c])
@ -76,8 +76,8 @@ AC_MSG_RESULT($enable_systemd)
CLUTTER_MIN_VERSION=1.15.90 CLUTTER_MIN_VERSION=1.15.90
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1 GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=1.39.0 GJS_MIN_VERSION=1.39.0
MUTTER_MIN_VERSION=3.14.2 MUTTER_MIN_VERSION=3.12.1
GTK_MIN_VERSION=3.13.2 GTK_MIN_VERSION=3.7.9
GIO_MIN_VERSION=2.37.0 GIO_MIN_VERSION=2.37.0
LIBECAL_MIN_VERSION=3.5.3 LIBECAL_MIN_VERSION=3.5.3
LIBEDATASERVER_MIN_VERSION=3.5.3 LIBEDATASERVER_MIN_VERSION=3.5.3
@ -112,6 +112,13 @@ fi
PKG_CHECK_MODULES(GNOME_SHELL, $SHARED_PCS) PKG_CHECK_MODULES(GNOME_SHELL, $SHARED_PCS)
PKG_CHECK_MODULES(MUTTER, libmutter >= $MUTTER_MIN_VERSION) PKG_CHECK_MODULES(MUTTER, libmutter >= $MUTTER_MIN_VERSION)
PKG_CHECK_MODULES(MUTTER_WAYLAND, [libmutter-wayland >= $MUTTER_MIN_VERSION],
[MUTTER_WAYLAND_TYPELIB_DIR=`$PKG_CONFIG --variable=typelibdir libmutter-wayland`
AC_SUBST(MUTTER_WAYLAND_TYPELIB_DIR)
have_mutter_wayland=yes],
[have_mutter_wayland=no])
AM_CONDITIONAL(HAVE_MUTTER_WAYLAND, test $have_mutter_wayland != no)
PKG_CHECK_MODULES(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION) PKG_CHECK_MODULES(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION)
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11) PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11)
@ -223,14 +230,6 @@ fi
AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no) AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no)
GNOME_COMPILE_WARNINGS([error]) GNOME_COMPILE_WARNINGS([error])
case "$WARN_CFLAGS" in
*-Werror*)
WARN_CFLAGS="$WARN_CFLAGS -Wno-error=deprecated-declarations"
;;
esac
AM_CFLAGS="$AM_CFLAGS $WARN_CFLAGS"
AC_SUBST(AM_CFLAGS)
BROWSER_PLUGIN_DIR="${BROWSER_PLUGIN_DIR:-"\${libdir}/mozilla/plugins"}" BROWSER_PLUGIN_DIR="${BROWSER_PLUGIN_DIR:-"\${libdir}/mozilla/plugins"}"
AC_ARG_VAR([BROWSER_PLUGIN_DIR],[Where to install the plugin to]) AC_ARG_VAR([BROWSER_PLUGIN_DIR],[Where to install the plugin to])

View File

@ -1,23 +1,9 @@
CLEANFILES =
desktopdir=$(datadir)/applications desktopdir=$(datadir)/applications
desktop_DATA = gnome-shell.desktop gnome-shell-wayland.desktop gnome-shell-extension-prefs.desktop desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop
if HAVE_MUTTER_WAYLAND
desktop_DATA += gnome-shell-wayland.desktop
endif HAVE_MUTTER_WAYLAND
if HAVE_NETWORKMANAGER
desktop_DATA += org.gnome.Shell.PortalHelper.desktop
servicedir = $(datadir)/dbus-1/services
service_DATA = org.gnome.Shell.PortalHelper.service
CLEANFILES += \
org.gnome.Shell.PortalHelper.service \
org.gnome.Shell.PortalHelper.desktop
endif
%.service: %.service.in
$(AM_V_GEN) sed -e "s|@libexecdir[@]|$(libexecdir)|" \
$< > $@ || rm $@
# We substitute in bindir so it works as an autostart # We substitute in bindir so it works as an autostart
# file when built in a non-system prefix # file when built in a non-system prefix
@ -53,6 +39,7 @@ dist_theme_DATA = \
theme/filter-selected-rtl.svg \ theme/filter-selected-rtl.svg \
theme/gnome-shell.css \ theme/gnome-shell.css \
theme/logged-in-indicator.svg \ theme/logged-in-indicator.svg \
theme/menu-arrow-symbolic.svg \
theme/message-tray-background.png \ theme/message-tray-background.png \
theme/more-results.svg \ theme/more-results.svg \
theme/noise-texture.png \ theme/noise-texture.png \
@ -74,13 +61,6 @@ dist_theme_DATA = \
theme/ws-switch-arrow-up.png \ theme/ws-switch-arrow-up.png \
theme/ws-switch-arrow-down.png theme/ws-switch-arrow-down.png
backgrounddir = $(pkgdatadir)
background_DATA = perf-background.xml
perf-background.xml: perf-background.xml.in
$(AM_V_GEN) sed -e "s|@datadir[@]|$(datadir)|" \
$< > $@ || rm $@
keysdir = @GNOME_KEYBINDINGS_KEYSDIR@ keysdir = @GNOME_KEYBINDINGS_KEYSDIR@
keys_in_files = 50-gnome-shell-system.xml.in keys_in_files = 50-gnome-shell-system.xml.in
keys_DATA = $(keys_in_files:.xml.in=.xml) keys_DATA = $(keys_in_files:.xml.in=.xml)
@ -113,19 +93,15 @@ EXTRA_DIST = \
$(menu_DATA) \ $(menu_DATA) \
$(convert_DATA) \ $(convert_DATA) \
$(keys_in_files) \ $(keys_in_files) \
perf-background.xml.in \
org.gnome.Shell.PortalHelper.desktop.in \
org.gnome.Shell.PortalHelper.service.in \
org.gnome.shell.gschema.xml.in.in org.gnome.shell.gschema.xml.in.in
CLEANFILES += \ CLEANFILES = \
gnome-shell.desktop.in \ gnome-shell.desktop.in \
gnome-shell-wayland.desktop.in \ gnome-shell-wayland.desktop.in \
gnome-shell-extension-prefs.in \ gnome-shell-extension-prefs.in \
$(desktop_DATA) \ $(desktop_DATA) \
$(keys_DATA) \ $(keys_DATA) \
$(gsettings_SCHEMAS) \ $(gsettings_SCHEMAS) \
perf-background.xml \
gschemas.compiled \ gschemas.compiled \
org.gnome.shell.gschema.valid \ org.gnome.shell.gschema.valid \
org.gnome.shell.gschema.xml.in org.gnome.shell.gschema.xml.in

View File

@ -1,4 +1,5 @@
[org.gnome.shell.overrides] [org.gnome.shell.overrides]
attach-modal-dialogs = /desktop/gnome/shell/windows/attach_modal_dialogs attach-modal-dialogs = /desktop/gnome/shell/windows/attach_modal_dialogs
button-layout = /desktop/gnome/shell/windows/button_layout
edge-tiling = /desktop/gnome/shell/windows/edge_tiling edge-tiling = /desktop/gnome/shell/windows/edge_tiling
workspaces-only-on-primary = /desktop/gnome/shell/windows/workspaces_only_on_primary workspaces-only-on-primary = /desktop/gnome/shell/windows/workspaces_only_on_primary

View File

@ -2,7 +2,7 @@
Type=Application Type=Application
_Name=GNOME Shell (wayland compositor) _Name=GNOME Shell (wayland compositor)
_Comment=Window management and application launching _Comment=Window management and application launching
Exec=@bindir@/gnome-shell --wayland --display-server Exec=@bindir@/mutter-launch -- gnome-shell-wayland --wayland --display-server
X-GNOME-Bugzilla-Bugzilla=GNOME X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-shell X-GNOME-Bugzilla-Product=gnome-shell
X-GNOME-Bugzilla-Component=general X-GNOME-Bugzilla-Component=general

View File

@ -1,9 +0,0 @@
[Desktop Entry]
_Name=Captive Portal
Type=Application
Exec=gapplication launch org.gnome.Shell.PortalHelper
DBusActivatable=true
NoDisplay=true
Icon=network-workgroup
StartupNotify=true
OnlyShowIn=GNOME;

View File

@ -1,3 +0,0 @@
[D-BUS Service]
Name=org.gnome.Shell.PortalHelper
Exec=@libexecdir@/gnome-shell-portal-helper

View File

@ -38,6 +38,7 @@
<method name="Screencast"> <method name="Screencast">
<arg type="s" direction="in" name="file_template"/> <arg type="s" direction="in" name="file_template"/>
<arg type="a{sv}" direction="in" name="options"/> <arg type="a{sv}" direction="in" name="options"/>
<arg type="b" direction="in" name="flash"/>
<arg type="b" direction="out" name="success"/> <arg type="b" direction="out" name="success"/>
<arg type="s" direction="out" name="filename_used"/> <arg type="s" direction="out" name="filename_used"/>
</method> </method>

View File

@ -31,7 +31,7 @@
</_description> </_description>
</key> </key>
<key name="favorite-apps" type="as"> <key name="favorite-apps" type="as">
<default>[ 'epiphany.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ]</default> <default>[ 'epiphany.desktop', 'evolution.desktop', 'empathy.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'libreoffice-writer.desktop', 'nautilus.desktop', 'gnome-documents.desktop' ]</default>
<_summary>List of desktop file IDs for favorite applications</_summary> <_summary>List of desktop file IDs for favorite applications</_summary>
<_description> <_description>
The applications corresponding to these identifiers The applications corresponding to these identifiers
@ -40,10 +40,10 @@
</key> </key>
<key name="app-picker-view" type="u"> <key name="app-picker-view" type="u">
<default>0</default> <default>0</default>
<_summary>App Picker View</_summary> <summary>App Picker View</summary>
<_description> <description>
Index of the currently selected view in the application picker. Index of the currently selected view in the application picker.
</_description> </description>
</key> </key>
<key name="command-history" type="as"> <key name="command-history" type="as">
<default>[]</default> <default>[]</default>
@ -74,6 +74,7 @@
<child name="calendar" schema="org.gnome.shell.calendar"/> <child name="calendar" schema="org.gnome.shell.calendar"/>
<child name="keybindings" schema="org.gnome.shell.keybindings"/> <child name="keybindings" schema="org.gnome.shell.keybindings"/>
<child name="keyboard" schema="org.gnome.shell.keyboard"/> <child name="keyboard" schema="org.gnome.shell.keyboard"/>
<child name="location" schema="org.gnome.shell.location"/>
</schema> </schema>
<schema id="org.gnome.shell.calendar" path="/org/gnome/shell/calendar/" <schema id="org.gnome.shell.calendar" path="/org/gnome/shell/calendar/"
@ -127,8 +128,8 @@
</key> </key>
<key name="pause-resume-tweens" type="as"> <key name="pause-resume-tweens" type="as">
<default>[]</default> <default>[]</default>
<_summary>Keybinding that pauses and resumes all running tweens, for debugging purposes</_summary> <summary>Keybinding that pauses and resumes all running tweens, for debugging purposes</summary>
<_description></_description> <description></description>
</key> </key>
</schema> </schema>
@ -143,16 +144,42 @@
</key> </key>
</schema> </schema>
<enum id="org.gnome.shell.geoclue.AccuracyLevel">
<value value="0" nick="off"/>
<value value="1" nick="country"/>
<value value="4" nick="city"/>
<value value="5" nick="neighborhood"/>
<value value="6" nick="street"/>
<value value="8" nick="exact"/>
</enum>
<schema id="org.gnome.shell.location"
path="/org/gnome/shell/location/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="max-accuracy-level" enum="org.gnome.shell.geoclue.AccuracyLevel">
<default>'exact'</default>
<_summary>The maximum accuracy level of location.</_summary>
<_description>
Configures the maximum level of location accuracy applications are
allowed to see. Valid options are 'off' (disable location tracking),
'country', 'city', 'neighborhood', 'street', and 'exact' (typically
requires GPS receiver). Please keep in mind that this only controls
what GeoClue will allow applications to see and they can find user's
location on their own using network resources (albeit with street-level
accuracy at best).
</_description>
</key>
</schema>
<schema id="org.gnome.shell.app-switcher" <schema id="org.gnome.shell.app-switcher"
path="/org/gnome/shell/app-switcher/" path="/org/gnome/shell/app-switcher/"
gettext-domain="@GETTEXT_PACKAGE@"> gettext-domain="@GETTEXT_PACKAGE@">
<key type="b" name="current-workspace-only"> <key type="b" name="current-workspace-only">
<default>false</default> <default>false</default>
<_summary>Limit switcher to current workspace.</_summary> <summary>Limit switcher to current workspace.</summary>
<_description> <description>
If true, only applications that have windows on the current workspace are shown in the switcher. If true, only applications that have windows on the current workspace are shown in the switcher.
Otherwise, all applications are included. Otherwise, all applications are included.
</_description> </description>
</key> </key>
</schema> </schema>
@ -175,11 +202,11 @@
</key> </key>
<key type="b" name="current-workspace-only"> <key type="b" name="current-workspace-only">
<default>true</default> <default>true</default>
<_summary>Limit switcher to current workspace.</_summary> <summary>Limit switcher to current workspace.</summary>
<_description> <description>
If true, only windows from the current workspace are shown in the switcher. If true, only windows from the current workspace are shown in the switcher.
Otherwise, all windows are included. Otherwise, all windows are included.
</_description> </description>
</key> </key>
</schema> </schema>
@ -194,6 +221,15 @@
</_description> </_description>
</key> </key>
<key name="button-layout" type="s">
<default>":close"</default>
<_summary>Arrangement of buttons on the titlebar</_summary>
<_description>
This key overrides the key in org.gnome.desktop.wm.preferences when
running GNOME Shell.
</_description>
</key>
<key name="edge-tiling" type="b"> <key name="edge-tiling" type="b">
<default>true</default> <default>true</default>
<_summary>Enable edge tiling when dropping windows on screen edges</_summary> <_summary>Enable edge tiling when dropping windows on screen edges</_summary>

View File

@ -1,31 +0,0 @@
<!-- With an animated background, performance will differ depending on whether
one layer or two layers are being blended together. This messes up our
benchmarks. We could just benchmark a single image, but since blended
images are present for much of the day with the GNOME default background,
we want to make sure that also performs well; for that reason we ship
an "animated" background that animates super-slowly to use during
performance tests; it will be in the blended state until 2030. -->
<background>
<starttime>
<year>1990</year>
<month>1</month>
<day>1</day>
<hour>0</hour>
<minute>00</minute>
<second>00</second>
</starttime>
<!-- One transition that takes 40 years -->
<transition type="overlay">
<duration>1261440000.0</duration>
<from>@datadir@/backgrounds/gnome/adwaita-morning.jpg</from>
<to>@datadir@/backgrounds/gnome/adwaita-day.jpg</to>
</transition>
<!-- A single slide doesn't work, so another slide for 1 minute after 40 years -->
<static>
<duration>60</duration>
<file>/usr/share/backgrounds/gnome/Sandstone.jpg</file>
</static>
</background>

View File

@ -153,21 +153,6 @@ StScrollBar StButton#vhandle:active {
-arrow-rise: 11px; -arrow-rise: 11px;
} }
.popup-menu-boxpointer.fallback-app-menu {
-arrow-border-radius: 4px;
-arrow-background-color: #ededed;
-arrow-border-width: 1px;
-arrow-border-color: #a6a6a6;
-arrow-base: 24px;
-arrow-rise: 11px;
}
.popup-menu-boxpointer.fallback-app-menu.dark {
-arrow-background-color: #3f4747;
-arrow-border-color: #282b2b;
}
.popup-menu { .popup-menu {
min-width: 200px; min-width: 200px;
} }
@ -181,15 +166,6 @@ StScrollBar StButton#vhandle:active {
background-color: #333333; background-color: #333333;
} }
.fallback-app-menu .popup-submenu-menu-item:open {
background-color: #888888;
color: white;
}
.fallback-app-menu.dark .popup-submenu-menu-item:open {
background-color: #333333;
}
.popup-sub-menu { .popup-sub-menu {
background-gradient-start: rgba(80,80,80,0.3); background-gradient-start: rgba(80,80,80,0.3);
background-gradient-end: rgba(80,80,80,0.4); background-gradient-end: rgba(80,80,80,0.4);
@ -197,20 +173,6 @@ StScrollBar StButton#vhandle:active {
box-shadow: inset 0px 2px 4px rgba(0,0,0,0.9); box-shadow: inset 0px 2px 4px rgba(0,0,0,0.9);
} }
.fallback-app-menu .popup-sub-menu {
background-gradient-start: #dddddd;
background-gradient-end: #dfdfdf;
background-gradient-direction: vertical;
box-shadow: inset 0px 2px 4px rgba(0,0,0,0.4);
}
.fallback-app-menu.dark .popup-sub-menu {
background-gradient-start: #474747;
background-gradient-end: #4b4b4b;
background-gradient-direction: vertical;
box-shadow: inset 0px 2px 4px rgba(0,0,0,0.9);
}
.popup-sub-menu:scrolled .popup-menu-item:ltr { .popup-sub-menu:scrolled .popup-menu-item:ltr {
padding-right: 0em; padding-right: 0em;
} }
@ -232,10 +194,6 @@ StScrollBar StButton#vhandle:active {
border-width: 0px; border-width: 0px;
} }
.app-well-menu {
max-width: 400px;
}
/* The remaining popup-menu sizing is all done in ems, so that if you /* The remaining popup-menu sizing is all done in ems, so that if you
* override .popup-menu.font-size, everything else will scale with it. * override .popup-menu.font-size, everything else will scale with it.
*/ */
@ -263,29 +221,7 @@ StScrollBar StButton#vhandle:active {
color: #9f9f9f; color: #9f9f9f;
} }
.fallback-app-menu .popup-menu-item { .popup-image-menu-item {
color: #43484a;
}
.fallback-app-menu .popup-menu-item:active {
color: white;
background-color: #4689cd;
}
.fallback-app-menu .popup-menu-item:insensitive {
color: gray;
}
.fallback-app-menu.dark .popup-menu-item {
color: white;
}
.fallback-app-menu.dark .popup-menu-item:active {
background-color: #445f7d;
}
.fallback-app-menu.dark .popup-menu-item:insensitive {
color: #9f9f9f;
} }
.popup-separator-menu-item { .popup-separator-menu-item {
@ -297,15 +233,8 @@ StScrollBar StButton#vhandle:active {
padding: 8px 0px; padding: 8px 0px;
} }
.fallback-app-menu .popup-separator-menu-item { .popup-alternating-menu-item:alternate {
-gradient-start: #a0a2a3; font-weight: bold;
-gradient-end: #a0a2a3;
-margin-horizontal: 0;
}
.fallback-app-menu.dark .popup-separator-menu-item {
-gradient-start: #818584;
-gradient-end: #818584;
} }
.popup-status-menu-item { .popup-status-menu-item {
@ -407,14 +336,6 @@ StScrollBar StButton#vhandle:active {
icon-size: 16px; icon-size: 16px;
} }
.no-networks-label {
color: #999999;
}
.no-networks-box {
spacing: 12px;
}
/* Buttons */ /* Buttons */
.candidate-page-button, .candidate-page-button,
@ -482,7 +403,7 @@ StScrollBar StButton#vhandle:active {
/* Common radii */ /* Common radii */
.search-entry, #searchEntry,
.modal-dialog-button, .modal-dialog-button,
.notification-button, .notification-button,
.hotplug-notification-item, .hotplug-notification-item,
@ -504,7 +425,7 @@ StScrollBar StButton#vhandle:active {
/* Entries */ /* Entries */
.search-entry, #searchEntry,
.login-dialog StEntry, .login-dialog StEntry,
.notification StEntry, .notification StEntry,
.modal-dialog StEntry { .modal-dialog StEntry {
@ -516,7 +437,7 @@ StScrollBar StButton#vhandle:active {
padding: 4px 12px; padding: 4px 12px;
} }
.search-entry, #searchEntry,
.login-dialog StEntry, .login-dialog StEntry,
.run-dialog-entry, .run-dialog-entry,
.notification StEntry { .notification StEntry {
@ -528,8 +449,8 @@ StScrollBar StButton#vhandle:active {
box-shadow: inset 0px 2px 4px rgba(0,0,0,0.6); box-shadow: inset 0px 2px 4px rgba(0,0,0,0.6);
} }
.search-entry:focus, #searchEntry:focus,
.search-entry:hover, #searchEntry:hover,
.login-dialog StEntry:focus, .login-dialog StEntry:focus,
.notification StEntry:focus, .notification StEntry:focus,
.modal-dialog StEntry { .modal-dialog StEntry {
@ -546,18 +467,18 @@ StScrollBar StButton#vhandle:active {
border: 2px solid #3465a4; border: 2px solid #3465a4;
} }
.search-entry { #searchEntry {
border-color: rgba(245,245,245,0.3); border-color: rgba(245,245,245,0.3);
color: rgb(192, 192, 192); color: rgb(192, 192, 192);
caret-color: rgb(192, 192, 192); caret-color: rgb(192, 192, 192);
} }
.search-entry:hover { #searchEntry:hover {
color: rgb(128, 128, 128); color: rgb(128, 128, 128);
caret-color: rgb(128, 128, 128); caret-color: rgb(128, 128, 128);
} }
.search-entry:focus { #searchEntry:focus {
color: rgb(64, 64, 64); color: rgb(64, 64, 64);
caret-color: rgb(64, 64, 64); caret-color: rgb(64, 64, 64);
font-weight: bold; font-weight: bold;
@ -661,6 +582,11 @@ StScrollBar StButton#vhandle:active {
app-icon-bottom-clip: 2px; app-icon-bottom-clip: 2px;
} }
.app-menu-icon {
width: 24px;
height: 24px;
}
.panel-button { .panel-button {
-natural-hpadding: 12px; -natural-hpadding: 12px;
-minimum-hpadding: 6px; -minimum-hpadding: 6px;
@ -921,7 +847,7 @@ StScrollBar StButton#vhandle:active {
/* Search Box */ /* Search Box */
.search-entry { #searchEntry {
width: 320px; width: 320px;
} }
@ -930,8 +856,8 @@ StScrollBar StButton#vhandle:active {
color: #c0c0c0; color: #c0c0c0;
} }
.search-entry:hover .search-entry-icon, #searchEntry:hover .search-entry-icon,
.search-entry:focus .search-entry-icon { #searchEntry:focus .search-entry-icon {
color: #8d8f8a; color: #8d8f8a;
} }
@ -1163,7 +1089,6 @@ StScrollBar StButton#vhandle:active {
.show-apps:checked > .overview-icon, .show-apps:checked > .overview-icon,
.show-apps:active > .overview-icon, .show-apps:active > .overview-icon,
.search-provider-icon:active, .search-provider-icon:active,
.grid-search-result:active .overview-icon,
.list-search-result:active { .list-search-result:active {
background-gradient-start: rgba(255, 255, 255, .05); background-gradient-start: rgba(255, 255, 255, .05);
background-gradient-end: rgba(255, 255, 255, .15); background-gradient-end: rgba(255, 255, 255, .15);
@ -1232,6 +1157,11 @@ StScrollBar StButton#vhandle:active {
text-shadow: black 0px 2px 2px; text-shadow: black 0px 2px 2px;
} }
#LookingGlassDialog .lg-inspector-title {
font-weight: bold;
padding-bottom: 8px;
}
.lg-dialog StEntry { .lg-dialog StEntry {
selection-background-color: #bbbbbb; selection-background-color: #bbbbbb;
selected-color: #333333; selected-color: #333333;
@ -1311,8 +1241,14 @@ StScrollBar StButton#vhandle:active {
width: 0.3em; width: 0.3em;
} }
#calendarPopup .calendar {
padding: 10px;
}
.calendar { .calendar {
padding: .4em 1.75em .8em 1.75em; padding: .4em 1.75em .8em 1.75em;
spacing-rows: 0px;
spacing-columns: 0px;
} }
.calendar-month-label { .calendar-month-label {
@ -1494,10 +1430,6 @@ StScrollBar StButton#vhandle:active {
text-align: right; text-align: right;
} }
.events-day-time-ellipses {
color: rgba(153, 153, 153, 1.0);
}
.events-day-time:rtl { .events-day-time:rtl {
text-align: left; text-align: left;
} }
@ -1512,8 +1444,11 @@ StScrollBar StButton#vhandle:active {
padding-right: 8pt; padding-right: 8pt;
} }
/* Message Tray */ .url-highlighter {
link-color: #ccccff;
}
/* Message Tray */
#message-tray { #message-tray {
background: #2e3436 url(message-tray-background.png); background: #2e3436 url(message-tray-background.png);
background-repeat: repeat; background-repeat: repeat;
@ -1536,12 +1471,13 @@ StScrollBar StButton#vhandle:active {
color: #eeeeee; color: #eeeeee;
} }
.url-highlighter { .no-messages-label,
link-color: #ccccff; .no-networks-label {
color: #999999;
} }
.no-messages-label { .no-networks-box {
color: #999999; spacing: 12px;
} }
.notification { .notification {
@ -1837,6 +1773,26 @@ StScrollBar StButton#vhandle:active {
spacing: 8px; spacing: 8px;
} }
.thumbnail-scroll-gradient-left {
background-gradient-direction: horizontal;
background-gradient-start: rgba(51, 51, 51, 1.0);
background-gradient-end: rgba(51, 51, 51, 0);
border-radius: 24px;
border-radius-topright: 0px;
border-radius-bottomright: 0px;
width: 60px;
}
.thumbnail-scroll-gradient-right {
background-gradient-direction: horizontal;
background-gradient-start: rgba(51, 51, 51, 0);
background-gradient-end: rgba(51, 51, 51, 1.0);
border-radius: 24px;
border-radius-topleft: 0px;
border-radius-bottomleft: 0px;
width: 60px;
}
.switcher-list .item-box { .switcher-list .item-box {
padding: 8px; padding: 8px;
border-radius: 8px; border-radius: 8px;
@ -2101,16 +2057,15 @@ StScrollBar StButton#vhandle:active {
font-size: 10pt; font-size: 10pt;
} }
/* Restart message */
.restart-message {
font-size: 14pt;
}
/* ShellMountOperation Dialogs */ /* ShellMountOperation Dialogs */
.shell-mount-operation-icon { .shell-mount-operation-icon {
icon-size: 48px; icon-size: 48px;
} }
.mount-password-reask {
color: red;
}
.show-processes-dialog, .show-processes-dialog,
.mount-question-dialog { .mount-question-dialog {
spacing: 24px; spacing: 24px;
@ -2406,6 +2361,13 @@ StScrollBar StButton#vhandle:active {
padding-bottom: 1em; padding-bottom: 1em;
} }
.login-dialog-title {
font-size: 14pt;
font-weight: bold;
color: #666666;
padding-bottom: 2em;
}
.login-dialog { .login-dialog {
/* Reset border and background */ /* Reset border and background */
border: none; border: none;
@ -2454,6 +2416,10 @@ StScrollBar StButton#vhandle:active {
background-size: contain; background-size: contain;
} }
.login-dialog-user-list-item-text-box {
padding: 0 0.5em;
}
.login-dialog-user-list-item .login-dialog-timed-login-indicator { .login-dialog-user-list-item .login-dialog-timed-login-indicator {
background-color: rgba(0,0,0,0.0); background-color: rgba(0,0,0,0.0);
height: 2px; height: 2px;

View File

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg3863"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="menu-arrow.svg">
<defs
id="defs3865" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="15.836083"
inkscape:cx="-3.1641676"
inkscape:cy="11.823817"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1366"
inkscape:window-height="702"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-bbox="true">
<sodipodi:guide
orientation="1,0"
position="15.996443,16.922964"
id="guide3873" />
<sodipodi:guide
orientation="0,1"
position="28.041217,3.1256134"
id="guide3875" />
<sodipodi:guide
orientation="0,1"
position="-0.80372916,24.469088"
id="guide3877" />
<sodipodi:guide
orientation="1,0"
position="3.0363102,34.649657"
id="guide3879" />
<sodipodi:guide
orientation="1,0"
position="29.023553,28.577037"
id="guide3881" />
<inkscape:grid
type="xygrid"
id="grid2988" />
</sodipodi:namedview>
<metadata
id="metadata3868">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,-16)">
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 4,23 8,0 -4,5 z"
id="path3883"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -66,7 +66,6 @@ IGNORE_HFILES= \
gactionmuxer.h \ gactionmuxer.h \
gactionobservable.h \ gactionobservable.h \
gactionobserver.h \ gactionobserver.h \
shell-network-agent.h \
shell-recorder-src.h shell-recorder-src.h
if !BUILD_RECORDER if !BUILD_RECORDER

View File

@ -50,6 +50,7 @@
<xi:include href="xml/shell-wm.xml"/> <xi:include href="xml/shell-wm.xml"/>
<xi:include href="xml/shell-util.xml"/> <xi:include href="xml/shell-util.xml"/>
<xi:include href="xml/shell-mount-operation.xml"/> <xi:include href="xml/shell-mount-operation.xml"/>
<xi:include href="xml/shell-network-agent.xml"/>
<xi:include href="xml/shell-polkit-authentication-agent.xml"/> <xi:include href="xml/shell-polkit-authentication-agent.xml"/>
<xi:include href="xml/shell-tp-client.xml"/> <xi:include href="xml/shell-tp-client.xml"/>
</chapter> </chapter>

View File

@ -27,9 +27,7 @@ its dependencies to build from tarballs.</description>
<download-page rdf:resource="http://download.gnome.org/sources/gnome-shell/" /> <download-page rdf:resource="http://download.gnome.org/sources/gnome-shell/" />
<bug-database rdf:resource="https://bugzilla.gnome.org/browse.cgi?product=gnome-shell" /> <bug-database rdf:resource="https://bugzilla.gnome.org/browse.cgi?product=gnome-shell" />
<category rdf:resource="http://api.gnome.org/doap-extensions#core" /> <category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
<programming-language>JavaScript</programming-language>
<programming-language>C</programming-language>
<maintainer> <maintainer>
<foaf:Person> <foaf:Person>

View File

@ -13,7 +13,7 @@ misc/config.js: misc/config.js.in Makefile
-e "s|[@]sysconfdir@|$(sysconfdir)|g" \ -e "s|[@]sysconfdir@|$(sysconfdir)|g" \
$< > $@ $< > $@
js_resource_files = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --sourcedir=$(builddir) --generate-dependencies $(srcdir)/js-resources.gresource.xml) js_resource_files = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/js-resources.gresource.xml)
js-resources.h: js-resources.gresource.xml $(js_resource_files) misc/config.js js-resources.h: js-resources.gresource.xml $(js_resource_files) misc/config.js
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --sourcedir=$(builddir) --generate --c-name shell_js_resources $< $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --sourcedir=$(builddir) --generate --c-name shell_js_resources $<
js-resources.c: js-resources.gresource.xml $(js_resource_files) misc/config.js js-resources.c: js-resources.gresource.xml $(js_resource_files) misc/config.js

View File

@ -23,11 +23,6 @@ const GnomeShellIface = '<node> \
</interface> \ </interface> \
</node>'; </node>';
const customCss = '.prefs-button { \
padding: 8px; \
border-radius: 20px; \
}';
const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface); const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface);
function stripPrefix(string, prefix) { function stripPrefix(string, prefix) {
@ -51,10 +46,13 @@ const Application = new Lang.Class({
this._extensionPrefsModules = {}; this._extensionPrefsModules = {};
this._extensionIters = {};
this._startupUuid = null; this._startupUuid = null;
this._loaded = false; },
this._skipMainWindow = false;
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' }); _buildModel: function() {
this._model = new Gtk.ListStore();
this._model.set_column_types([GObject.TYPE_STRING, GObject.TYPE_STRING]);
}, },
_extensionAvailable: function(uuid) { _extensionAvailable: function(uuid) {
@ -63,12 +61,20 @@ const Application = new Lang.Class({
if (!extension) if (!extension)
return false; return false;
if (ExtensionUtils.isOutOfDate(extension))
return false;
if (!extension.dir.get_child('prefs.js').query_exists(null)) if (!extension.dir.get_child('prefs.js').query_exists(null))
return false; return false;
return true; return true;
}, },
_setExtensionInsensitive: function(layout, cell, model, iter, data) {
let uuid = model.get_value(iter, 0);
cell.set_sensitive(this._extensionAvailable(uuid));
},
_getExtensionPrefsModule: function(extension) { _getExtensionPrefsModule: function(extension) {
let uuid = extension.metadata.uuid; let uuid = extension.metadata.uuid;
@ -98,23 +104,21 @@ const Application = new Lang.Class({
widget = this._buildErrorUI(extension, e); widget = this._buildErrorUI(extension, e);
} }
let dialog = new Gtk.Dialog({ use_header_bar: true, // Destroy the current prefs widget, if it exists
modal: true, if (this._extensionPrefsBin.get_child())
title: extension.metadata.name }); this._extensionPrefsBin.get_child().destroy();
if (this._skipMainWindow) { this._extensionPrefsBin.add(widget);
this.application.add_window(dialog); this._extensionSelector.set_active_iter(this._extensionIters[uuid]);
if (this._window) },
this._window.destroy();
this._window = dialog;
this._window.window_position = Gtk.WindowPosition.CENTER;
} else {
dialog.transient_for = this._window;
}
dialog.set_default_size(600, 400); _extensionSelected: function() {
dialog.get_content_area().add(widget); let [success, iter] = this._extensionSelector.get_active_iter();
dialog.show(); if (!success)
return;
let uuid = this._model.get_value(iter, 0);
this._selectExtension(uuid);
}, },
_buildErrorUI: function(extension, exc) { _buildErrorUI: function(extension, exc) {
@ -147,26 +151,48 @@ const Application = new Lang.Class({
_buildUI: function(app) { _buildUI: function(app) {
this._window = new Gtk.ApplicationWindow({ application: app, this._window = new Gtk.ApplicationWindow({ application: app,
window_position: Gtk.WindowPosition.CENTER }); window_position: Gtk.WindowPosition.CENTER,
title: _("GNOME Shell Extension Preferences") });
this._window.set_size_request(800, 500); this._window.set_size_request(600, 400);
this._titlebar = new Gtk.HeaderBar({ show_close_button: true, let vbox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
title: _("GNOME Shell Extensions") }); this._window.add(vbox);
this._window.set_titlebar(this._titlebar);
let scroll = new Gtk.ScrolledWindow({ hscrollbar_policy: Gtk.PolicyType.NEVER, let toolbar = new Gtk.Toolbar();
shadow_type: Gtk.ShadowType.IN, toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR);
halign: Gtk.Align.CENTER, vbox.add(toolbar);
margin: 18 }); let toolitem;
this._window.add(scroll);
this._extensionSelector = new Gtk.ListBox({ selection_mode: Gtk.SelectionMode.NONE }); let label = new Gtk.Label({ label: '<b>' + _("Extension") + '</b>',
this._extensionSelector.set_sort_func(Lang.bind(this, this._sortList)); use_markup: true });
this._extensionSelector.set_header_func(Lang.bind(this, this._updateHeader)); toolitem = new Gtk.ToolItem({ child: label });
toolbar.add(toolitem);
scroll.add(this._extensionSelector); this._extensionSelector = new Gtk.ComboBox({ model: this._model,
margin_left: 8,
hexpand: true });
this._extensionSelector.get_style_context().add_class(Gtk.STYLE_CLASS_RAISED);
let renderer = new Gtk.CellRendererText();
this._extensionSelector.pack_start(renderer, true);
this._extensionSelector.add_attribute(renderer, 'text', 1);
this._extensionSelector.set_cell_data_func(renderer, Lang.bind(this, this._setExtensionInsensitive));
this._extensionSelector.connect('changed', Lang.bind(this, this._extensionSelected));
toolitem = new Gtk.ToolItem({ child: this._extensionSelector });
toolitem.set_expand(true);
toolbar.add(toolitem);
this._extensionPrefsBin = new Gtk.Frame();
vbox.add(this._extensionPrefsBin);
let label = new Gtk.Label({
label: _("Select an extension to configure using the combobox above."),
vexpand: true
});
this._extensionPrefsBin.add(label);
this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell'); this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell');
this._shellProxy.connectSignal('ExtensionStatusChanged', Lang.bind(this, function(proxy, senderName, [uuid, state, error]) { this._shellProxy.connectSignal('ExtensionStatusChanged', Lang.bind(this, function(proxy, senderName, [uuid, state, error]) {
@ -177,35 +203,6 @@ const Application = new Lang.Class({
this._window.show_all(); this._window.show_all();
}, },
_addCustomStyle: function() {
let provider = new Gtk.CssProvider();
try {
provider.load_from_data(customCss, -1);
} catch(e) {
log('Failed to add application style');
return;
}
let screen = this._window.window.get_screen();
let priority = Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION;
Gtk.StyleContext.add_provider_for_screen(screen, provider, priority);
},
_sortList: function(row1, row2) {
let name1 = ExtensionUtils.extensions[row1.uuid].metadata.name;
let name2 = ExtensionUtils.extensions[row2.uuid].metadata.name;
return name1.localeCompare(name2);
},
_updateHeader: function(row, before) {
if (!before || row.get_header())
return;
let sep = new Gtk.Separator({ orientation: Gtk.Orientation.HORIZONTAL });
row.set_header(sep);
},
_scanExtensions: function() { _scanExtensions: function() {
let finder = new ExtensionUtils.ExtensionFinder(); let finder = new ExtensionUtils.ExtensionFinder();
finder.connect('extension-found', Lang.bind(this, this._extensionFound)); finder.connect('extension-found', Lang.bind(this, this._extensionFound));
@ -214,24 +211,15 @@ const Application = new Lang.Class({
}, },
_extensionFound: function(finder, extension) { _extensionFound: function(finder, extension) {
let row = new ExtensionRow(extension.uuid); let iter = this._model.append();
this._model.set(iter, [0, 1], [extension.uuid, extension.metadata.name]);
row.prefsButton.visible = this._extensionAvailable(row.uuid); this._extensionIters[extension.uuid] = iter;
row.prefsButton.connect('clicked', Lang.bind(this,
function() {
this._selectExtension(row.uuid);
}));
row.show_all();
this._extensionSelector.add(row);
}, },
_extensionsLoaded: function() { _extensionsLoaded: function() {
if (this._startupUuid && this._extensionAvailable(this._startupUuid)) if (this._startupUuid && this._extensionAvailable(this._startupUuid))
this._selectExtension(this._startupUuid); this._selectExtension(this._startupUuid);
this._startupUuid = null; this._startupUuid = null;
this._skipMainWindow = false;
this._loaded = true;
}, },
_onActivate: function() { _onActivate: function() {
@ -239,137 +227,29 @@ const Application = new Lang.Class({
}, },
_onStartup: function(app) { _onStartup: function(app) {
this._buildModel();
this._buildUI(app); this._buildUI(app);
this._addCustomStyle();
this._scanExtensions(); this._scanExtensions();
}, },
_onCommandLine: function(app, commandLine) { _onCommandLine: function(app, commandLine) {
app.activate(); app.activate();
let args = commandLine.get_arguments(); let args = commandLine.get_arguments();
if (args.length) { if (args.length) {
let uuid = args[0]; let uuid = args[0];
this._skipMainWindow = true;
// Strip off "extension:///" prefix which fakes a URI, if it exists // Strip off "extension:///" prefix which fakes a URI, if it exists
uuid = stripPrefix(uuid, "extension:///"); uuid = stripPrefix(uuid, "extension:///");
if (this._extensionAvailable(uuid)) if (this._extensionAvailable(uuid))
this._selectExtension(uuid); this._selectExtension(uuid);
else if (!this._loaded)
this._startupUuid = uuid;
else else
this._skipMainWindow = false; this._startupUuid = uuid;
} }
return 0; return 0;
} }
}); });
const ExtensionRow = new Lang.Class({
Name: 'ExtensionRow',
Extends: Gtk.ListBoxRow,
_init: function(uuid) {
this.parent();
this.uuid = uuid;
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' });
this._settings.connect('changed::enabled-extensions', Lang.bind(this,
function() {
this._switch.state = this._isEnabled();
}));
this._settings.connect('changed::disable-extension-version-validation',
Lang.bind(this, function() {
this._switch.sensitive = this._canEnable();
}));
this._buildUI();
},
_buildUI: function() {
let extension = ExtensionUtils.extensions[this.uuid];
let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL,
hexpand: true, margin: 12, spacing: 6 });
this.add(hbox);
let vbox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL,
spacing: 6, hexpand: true });
hbox.add(vbox);
let name = GLib.markup_escape_text(extension.metadata.name, -1);
let label = new Gtk.Label({ label: '<b>' + name + '</b>',
use_markup: true,
halign: Gtk.Align.START });
vbox.add(label);
let desc = extension.metadata.description.split('\n')[0];
label = new Gtk.Label({ label: desc,
ellipsize: Pango.EllipsizeMode.END,
halign: Gtk.Align.START });
vbox.add(label);
let button = new Gtk.Button({ valign: Gtk.Align.CENTER,
no_show_all: true });
button.add(new Gtk.Image({ icon_name: 'emblem-system-symbolic',
icon_size: Gtk.IconSize.BUTTON,
visible: true }));
button.get_style_context().add_class('prefs-button');
hbox.add(button);
this.prefsButton = button;
this._switch = new Gtk.Switch({ valign: Gtk.Align.CENTER,
sensitive: this._canEnable(),
state: this._isEnabled() });
this._switch.connect('notify::active', Lang.bind(this,
function() {
if (this._switch.active)
this._enable();
else
this._disable();
}));
this._switch.connect('state-set', function() { return true; });
hbox.add(this._switch);
},
_canEnable: function() {
let extension = ExtensionUtils.extensions[this.uuid];
let checkVersion = !this._settings.get_boolean('disable-extension-version-validation');
return !(checkVersion && ExtensionUtils.isOutOfDate(extension));
},
_isEnabled: function() {
let extensions = this._settings.get_strv('enabled-extensions');
return extensions.indexOf(this.uuid) != -1;
},
_enable: function() {
let extensions = this._settings.get_strv('enabled-extensions');
if (extensions.indexOf(this.uuid) != -1)
return;
extensions.push(this.uuid);
this._settings.set_strv('enabled-extensions', extensions);
},
_disable: function() {
let extensions = this._settings.get_strv('enabled-extensions');
let pos = extensions.indexOf(this.uuid);
if (pos == -1)
return;
do {
extensions.splice(pos, 1);
pos = extensions.indexOf(this.uuid);
} while (pos != -1);
this._settings.set_strv('enabled-extensions', extensions);
}
});
function initEnvironment() { function initEnvironment() {
// Monkey-patch in a "global" object that fakes some Shell utilities // Monkey-patch in a "global" object that fakes some Shell utilities
// that ExtensionUtils depends on. // that ExtensionUtils depends on.

View File

@ -134,7 +134,8 @@ const AuthPrompt = new Lang.Class({
}, },
_onDestroy: function() { _onDestroy: function() {
this._userVerifier.destroy(); this._userVerifier.clear();
this._userVerifier.disconnectAll();
this._userVerifier = null; this._userVerifier = null;
}, },
@ -418,13 +419,11 @@ const AuthPrompt = new Lang.Class({
}, },
setUser: function(user) { setUser: function(user) {
let oldChild = this._userWell.get_child();
if (oldChild)
oldChild.destroy();
if (user) { if (user) {
let userWidget = new UserWidget.UserWidget(user); let userWidget = new UserWidget.UserWidget(user);
this._userWell.set_child(userWidget.actor); this._userWell.set_child(userWidget.actor);
} else {
this._userWell.set_child(null);
} }
}, },

View File

@ -48,6 +48,8 @@ const _SCROLL_ANIMATION_TIME = 0.5;
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0; const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
const _LOGO_ICON_HEIGHT = 48; const _LOGO_ICON_HEIGHT = 48;
let _loginDialog = null;
const UserListItem = new Lang.Class({ const UserListItem = new Lang.Class({
Name: 'UserListItem', Name: 'UserListItem',
@ -64,8 +66,6 @@ const UserListItem = new Lang.Class({
reactive: true, reactive: true,
x_align: St.Align.START, x_align: St.Align.START,
x_fill: true }); x_fill: true });
this.actor.connect('destroy',
Lang.bind(this, this._onDestroy));
this._userWidget = new UserWidget.UserWidget(this.user); this._userWidget = new UserWidget.UserWidget(this.user);
layout.add(this._userWidget.actor); layout.add(this._userWidget.actor);
@ -89,10 +89,6 @@ const UserListItem = new Lang.Class({
this.actor.remove_style_pseudo_class('logged-in'); this.actor.remove_style_pseudo_class('logged-in');
}, },
_onDestroy: function() {
this._user.disconnect(this._userChangedId);
},
_onClicked: function() { _onClicked: function() {
this.emit('activate'); this.emit('activate');
}, },
@ -379,15 +375,16 @@ const LoginDialog = new Lang.Class({
if (GLib.getenv('GDM_GREETER_TEST') != '1') { if (GLib.getenv('GDM_GREETER_TEST') != '1') {
this._greeter = gdmClient.get_greeter_sync(null); this._greeter = gdmClient.get_greeter_sync(null);
this._defaultSessionChangedId = this._greeter.connect('default-session-name-changed', this._greeter.connect('default-session-name-changed',
Lang.bind(this, this._onDefaultSessionChanged)); Lang.bind(this, this._onDefaultSessionChanged));
this._sessionOpenedId = this._greeter.connect('session-opened',
Lang.bind(this, this._onSessionOpened)); this._greeter.connect('session-opened',
this._timedLoginRequestedId = this._greeter.connect('timed-login-requested', Lang.bind(this, this._onSessionOpened));
Lang.bind(this, this._onTimedLoginRequested)); this._greeter.connect('timed-login-requested',
Lang.bind(this, this._onTimedLoginRequested));
} }
this._settings = new Gio.Settings({ schema_id: GdmUtil.LOGIN_SCREEN_SCHEMA }); this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA });
this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_KEY, this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_KEY,
Lang.bind(this, this._updateBanner)); Lang.bind(this, this._updateBanner));
@ -399,8 +396,8 @@ const LoginDialog = new Lang.Class({
Lang.bind(this, this._updateLogo)); Lang.bind(this, this._updateLogo));
this._textureCache = St.TextureCache.get_default(); this._textureCache = St.TextureCache.get_default();
this._updateLogoTextureId = this._textureCache.connect('texture-file-changed', this._textureCache.connect('texture-file-changed',
Lang.bind(this, this._updateLogoTexture)); Lang.bind(this, this._updateLogoTexture));
this._userSelectionBox = new St.BoxLayout({ style_class: 'login-dialog-user-selection-box', this._userSelectionBox = new St.BoxLayout({ style_class: 'login-dialog-user-selection-box',
x_align: Clutter.ActorAlign.CENTER, x_align: Clutter.ActorAlign.CENTER,
@ -481,12 +478,12 @@ const LoginDialog = new Lang.Class({
// If the user list is enabled, it should take key focus; make sure the // If the user list is enabled, it should take key focus; make sure the
// screen shield is initialized first to prevent it from stealing the // screen shield is initialized first to prevent it from stealing the
// focus later // focus later
this._startupCompleteId = Main.layoutManager.connect('startup-complete', Main.layoutManager.connect('startup-complete',
Lang.bind(this, this._updateDisableUserList)); Lang.bind(this, this._updateDisableUserList));
}, },
_ensureUserListLoaded: function() { _ensureUserListLoaded: function() {
if (!this._userManager.is_loaded) { if (!this._userManager.is_loaded)
this._userManagerLoadedId = this._userManager.connect('notify::is-loaded', this._userManagerLoadedId = this._userManager.connect('notify::is-loaded',
Lang.bind(this, function() { Lang.bind(this, function() {
if (this._userManager.is_loaded) { if (this._userManager.is_loaded) {
@ -495,10 +492,8 @@ const LoginDialog = new Lang.Class({
this._userManagerLoadedId = 0; this._userManagerLoadedId = 0;
} }
})); }));
} else { else
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, this._loadUserList)); GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, this._loadUserList));
GLib.Source.set_name_by_id(id, '[gnome-shell] _loadUserList');
}
}, },
_updateDisableUserList: function() { _updateDisableUserList: function() {
@ -670,12 +665,10 @@ const LoginDialog = new Lang.Class({
}, },
_gotGreeterSessionProxy: function(proxy) { _gotGreeterSessionProxy: function(proxy) {
this._greeterSessionProxy = proxy; proxy.connect('g-properties-changed', Lang.bind(this, function() {
this._greeterSessionProxyChangedId = if (proxy.Active)
proxy.connect('g-properties-changed', Lang.bind(this, function() { this._loginScreenSessionActivated();
if (proxy.Active) }));
this._loginScreenSessionActivated();
}));
}, },
_startSession: function(serviceName) { _startSession: function(serviceName) {
@ -693,11 +686,10 @@ const LoginDialog = new Lang.Class({
}, },
onUpdateScope: this, onUpdateScope: this,
onComplete: function() { onComplete: function() {
let id = Mainloop.idle_add(Lang.bind(this, function() { Mainloop.idle_add(Lang.bind(this, function() {
this._greeter.call_start_session_when_ready_sync(serviceName, true, null); this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(id, '[gnome-shell] this._greeter.call_start_session_when_ready_sync');
}, },
onCompleteScope: this }); onCompleteScope: this });
}, },
@ -753,7 +745,6 @@ const LoginDialog = new Lang.Class({
hold.release(); hold.release();
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
GLib.Source.set_name_by_id(this._timedLoginIdleTimeOutId, '[gnome-shell] this._timedLoginAnimationTime');
return hold; return hold;
}, },
@ -897,30 +888,6 @@ const LoginDialog = new Lang.Class({
this._userManager.disconnect(this._userManagerLoadedId); this._userManager.disconnect(this._userManagerLoadedId);
this._userManagerLoadedId = 0; this._userManagerLoadedId = 0;
} }
if (this._userAddedId) {
this._userManager.disconnect(this._userAddedId);
this._userAddedId = 0;
}
if (this._userRemovedId) {
this._userManager.disconnect(this._userRemovedId);
this._userRemovedId = 0;
}
this._textureCache.disconnect(this._updateLogoTextureId);
Main.layoutManager.disconnect(this._startupCompleteId);
if (this._settings) {
this._settings.run_dispose();
this._settings = null;
}
if (this._greeter) {
this._greeter.disconnect(this._defaultSessionChangedId);
this._greeter.disconnect(this._sessionOpenedId);
this._greeter.disconnect(this._timedLoginRequestedId);
this._greeter = null;
}
if (this._greeterSessionProxy) {
this._greeterSessionProxy.disconnect(this._greeterSessionProxyChangedId);
this._greeterSessionProxy = null;
}
}, },
_loadUserList: function() { _loadUserList: function() {
@ -935,15 +902,15 @@ const LoginDialog = new Lang.Class({
this._userList.addUser(users[i]); this._userList.addUser(users[i]);
} }
this._userAddedId = this._userManager.connect('user-added', this._userManager.connect('user-added',
Lang.bind(this, function(userManager, user) { Lang.bind(this, function(userManager, user) {
this._userList.addUser(user); this._userList.addUser(user);
})); }));
this._userRemovedId = this._userManager.connect('user-removed', this._userManager.connect('user-removed',
Lang.bind(this, function(userManager, user) { Lang.bind(this, function(userManager, user) {
this._userList.removeUser(user); this._userList.removeUser(user);
})); }));
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}, },
@ -957,8 +924,6 @@ const LoginDialog = new Lang.Class({
this.actor.show(); this.actor.show();
this.actor.opacity = 0; this.actor.opacity = 0;
Main.pushModal(this.actor, { keybindingMode: Shell.KeyBindingMode.LOGIN_SCREEN });
Tweener.addTween(this.actor, Tweener.addTween(this.actor,
{ opacity: 255, { opacity: 255,
time: 1, time: 1,
@ -968,8 +933,7 @@ const LoginDialog = new Lang.Class({
}, },
close: function() { close: function() {
Main.popModal(this.actor); Main.ctrlAltTabManager.removeGroup(this.dialogLayout);
Main.ctrlAltTabManager.removeGroup(this.actor);
}, },
cancel: function() { cancel: function() {

View File

@ -128,7 +128,7 @@ const ShellUserVerifier = new Lang.Class({
this._client = client; this._client = client;
this._settings = new Gio.Settings({ schema_id: LOGIN_SCREEN_SCHEMA }); this._settings = new Gio.Settings({ schema: LOGIN_SCREEN_SCHEMA });
this._settings.connect('changed', this._settings.connect('changed',
Lang.bind(this, this._updateDefaultService)); Lang.bind(this, this._updateDefaultService));
this._updateDefaultService(); this._updateDefaultService();
@ -142,10 +142,10 @@ const ShellUserVerifier = new Lang.Class({
// after a user has been picked. // after a user has been picked.
this._checkForSmartcard(); this._checkForSmartcard();
this._smartcardInsertedId = this._smartcardManager.connect('smartcard-inserted', this._smartcardManager.connect('smartcard-inserted',
Lang.bind(this, this._checkForSmartcard)); Lang.bind(this, this._checkForSmartcard));
this._smartcardRemovedId = this._smartcardManager.connect('smartcard-removed', this._smartcardManager.connect('smartcard-removed',
Lang.bind(this, this._checkForSmartcard)); Lang.bind(this, this._checkForSmartcard));
this._messageQueue = []; this._messageQueue = [];
this._messageQueueTimeoutId = 0; this._messageQueueTimeoutId = 0;
@ -159,8 +159,8 @@ const ShellUserVerifier = new Lang.Class({
if (this._oVirtCredentialsManager.hasToken()) if (this._oVirtCredentialsManager.hasToken())
this._oVirtUserAuthenticated(this._oVirtCredentialsManager.getToken()); this._oVirtUserAuthenticated(this._oVirtCredentialsManager.getToken());
this._oVirtUserAuthenticatedId = this._oVirtCredentialsManager.connect('user-authenticated', this._oVirtCredentialsManager.connect('user-authenticated',
Lang.bind(this, this._oVirtUserAuthenticated)); Lang.bind(this, this._oVirtUserAuthenticated));
}, },
begin: function(userName, hold) { begin: function(userName, hold) {
@ -191,37 +191,20 @@ const ShellUserVerifier = new Lang.Class({
} }
}, },
_clearUserVerifier: function() {
if (this._userVerifier) {
this._userVerifier.run_dispose();
this._userVerifier = null;
}
},
clear: function() { clear: function() {
if (this._cancellable) { if (this._cancellable) {
this._cancellable.cancel(); this._cancellable.cancel();
this._cancellable = null; this._cancellable = null;
} }
this._clearUserVerifier(); if (this._userVerifier) {
this._userVerifier.run_dispose();
this._userVerifier = null;
}
this._clearMessageQueue(); this._clearMessageQueue();
}, },
destroy: function() {
this.clear();
this._settings.run_dispose();
this._settings = null;
this._smartcardManager.disconnect(this._smartcardInsertedId);
this._smartcardManager.disconnect(this._smartcardRemovedId);
this._smartcardManager = null;
this._oVirtCredentialsManager.disconnect(this._oVirtUserAuthenticatedId);
this._oVirtCredentialsManager = null;
},
answerQuery: function(serviceName, answer) { answerQuery: function(serviceName, answer) {
if (!this.hasPendingMessages) { if (!this.hasPendingMessages) {
this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null); this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null);
@ -269,7 +252,6 @@ const ShellUserVerifier = new Lang.Class({
this._queueMessageTimeout(); this._queueMessageTimeout();
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(this._messageQueueTimeoutId, '[gnome-shell] this._queueMessageTimeout');
}, },
_queueMessage: function(message, messageType) { _queueMessage: function(message, messageType) {
@ -300,10 +282,9 @@ const ShellUserVerifier = new Lang.Class({
this._fprintManager.GetDefaultDeviceRemote(Gio.DBusCallFlags.NONE, this._cancellable, Lang.bind(this, this._fprintManager.GetDefaultDeviceRemote(Gio.DBusCallFlags.NONE, this._cancellable, Lang.bind(this,
function(device, error) { function(device, error) {
if (!error && device) { if (!error && device)
this._haveFingerprintReader = true; this._haveFingerprintReader = true;
this._updateDefaultService(); this._updateDefaultService();
}
})); }));
}, },
@ -344,7 +325,6 @@ const ShellUserVerifier = new Lang.Class({
_reauthenticationChannelOpened: function(client, result) { _reauthenticationChannelOpened: function(client, result) {
try { try {
this._clearUserVerifier();
this._userVerifier = client.open_reauthentication_channel_finish(result); this._userVerifier = client.open_reauthentication_channel_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { } catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return; return;
@ -368,7 +348,6 @@ const ShellUserVerifier = new Lang.Class({
_userVerifierGot: function(client, result) { _userVerifierGot: function(client, result) {
try { try {
this._clearUserVerifier();
this._userVerifier = client.get_user_verifier_finish(result); this._userVerifier = client.get_user_verifier_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { } catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return; return;

View File

@ -16,9 +16,7 @@
<file>misc/fileUtils.js</file> <file>misc/fileUtils.js</file>
<file>misc/gnomeSession.js</file> <file>misc/gnomeSession.js</file>
<file>misc/history.js</file> <file>misc/history.js</file>
<file>misc/ibusManager.js</file>
<file>misc/jsParse.js</file> <file>misc/jsParse.js</file>
<file>misc/keyboardManager.js</file>
<file>misc/loginManager.js</file> <file>misc/loginManager.js</file>
<file>misc/modemManager.js</file> <file>misc/modemManager.js</file>
<file>misc/objectManager.js</file> <file>misc/objectManager.js</file>
@ -27,9 +25,6 @@
<file>misc/util.js</file> <file>misc/util.js</file>
<file>perf/core.js</file> <file>perf/core.js</file>
<file>perf/hwtest.js</file>
<file>portalHelper/main.js</file>
<file>ui/altTab.js</file> <file>ui/altTab.js</file>
<file>ui/animation.js</file> <file>ui/animation.js</file>
@ -44,7 +39,6 @@
<file>ui/dash.js</file> <file>ui/dash.js</file>
<file>ui/dateMenu.js</file> <file>ui/dateMenu.js</file>
<file>ui/dnd.js</file> <file>ui/dnd.js</file>
<file>ui/edgeDragAction.js</file>
<file>ui/endSessionDialog.js</file> <file>ui/endSessionDialog.js</file>
<file>ui/environment.js</file> <file>ui/environment.js</file>
<file>ui/extensionDownloader.js</file> <file>ui/extensionDownloader.js</file>
@ -90,7 +84,6 @@
<file>ui/userWidget.js</file> <file>ui/userWidget.js</file>
<file>ui/viewSelector.js</file> <file>ui/viewSelector.js</file>
<file>ui/windowAttentionHandler.js</file> <file>ui/windowAttentionHandler.js</file>
<file>ui/windowMenu.js</file>
<file>ui/windowManager.js</file> <file>ui/windowManager.js</file>
<file>ui/workspace.js</file> <file>ui/workspace.js</file>
<file>ui/workspaceSwitcherPopup.js</file> <file>ui/workspaceSwitcherPopup.js</file>

View File

@ -1,180 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Signals = imports.signals;
try {
var IBus = imports.gi.IBus;
if (!('new_async' in IBus.Bus))
throw "IBus version is too old";
const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
} catch (e) {
var IBus = null;
log(e);
}
let _ibusManager = null;
function getIBusManager() {
if (_ibusManager == null)
_ibusManager = new IBusManager();
return _ibusManager;
}
const IBusManager = new Lang.Class({
Name: 'IBusManager',
// This is the longest we'll keep the keyboard frozen until an input
// source is active.
_MAX_INPUT_SOURCE_ACTIVATION_TIME: 4000, // ms
_init: function() {
if (!IBus)
return;
IBus.init();
this._candidatePopup = new IBusCandidatePopup.CandidatePopup();
this._panelService = null;
this._engines = {};
this._ready = false;
this._registerPropertiesId = 0;
this._currentEngineName = null;
this._ibus = IBus.Bus.new_async();
this._ibus.connect('connected', Lang.bind(this, this._onConnected));
this._ibus.connect('disconnected', Lang.bind(this, this._clear));
// Need to set this to get 'global-engine-changed' emitions
this._ibus.set_watch_ibus_signal(true);
this._ibus.connect('global-engine-changed', Lang.bind(this, this._engineChanged));
this._spawn();
},
_spawn: function() {
try {
Gio.Subprocess.new(['ibus-daemon', '--xim', '--panel', 'disable'],
Gio.SubprocessFlags.NONE);
} catch(e) {
log('Failed to launch ibus-daemon: ' + e.message);
}
},
_clear: function() {
if (this._panelService)
this._panelService.destroy();
this._panelService = null;
this._candidatePopup.setPanelService(null);
this._engines = {};
this._ready = false;
this._registerPropertiesId = 0;
this._currentEngineName = null;
this.emit('ready', false);
this._spawn();
},
_onConnected: function() {
this._ibus.list_engines_async(-1, null, Lang.bind(this, this._initEngines));
this._ibus.request_name_async(IBus.SERVICE_PANEL,
IBus.BusNameFlag.REPLACE_EXISTING,
-1, null,
Lang.bind(this, this._initPanelService));
},
_initEngines: function(ibus, result) {
let enginesList = this._ibus.list_engines_async_finish(result);
if (enginesList) {
for (let i = 0; i < enginesList.length; ++i) {
let name = enginesList[i].get_name();
this._engines[name] = enginesList[i];
}
this._updateReadiness();
} else {
this._clear();
}
},
_initPanelService: function(ibus, result) {
let success = this._ibus.request_name_async_finish(result);
if (success) {
this._panelService = new IBus.PanelService({ connection: this._ibus.get_connection(),
object_path: IBus.PATH_PANEL });
this._candidatePopup.setPanelService(this._panelService);
this._panelService.connect('update-property', Lang.bind(this, this._updateProperty));
// If an engine is already active we need to get its properties
this._ibus.get_global_engine_async(-1, null, Lang.bind(this, function(i, result) {
let engine;
try {
engine = this._ibus.get_global_engine_async_finish(result);
if (!engine)
return;
} catch(e) {
return;
}
this._engineChanged(this._ibus, engine.get_name());
}));
this._updateReadiness();
} else {
this._clear();
}
},
_updateReadiness: function() {
this._ready = (Object.keys(this._engines).length > 0 &&
this._panelService != null);
this.emit('ready', this._ready);
},
_engineChanged: function(bus, engineName) {
if (!this._ready)
return;
this._currentEngineName = engineName;
if (this._registerPropertiesId != 0)
return;
this._registerPropertiesId =
this._panelService.connect('register-properties', Lang.bind(this, function(p, props) {
if (!props.get(0))
return;
this._panelService.disconnect(this._registerPropertiesId);
this._registerPropertiesId = 0;
this.emit('properties-registered', this._currentEngineName, props);
}));
},
_updateProperty: function(panel, prop) {
this.emit('property-updated', this._currentEngineName, prop);
},
activateProperty: function(key, state) {
this._panelService.property_activate(key, state);
},
getEngineDesc: function(id) {
if (!IBus || !this._ready)
return null;
return this._engines[id];
},
setEngine: function(id, callback) {
if (!IBus || !this._ready || id == this._currentEngineName) {
if (callback)
callback();
return;
}
this._ibus.set_global_engine_async(id, this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
null, callback);
},
});
Signals.addSignalMethods(IBusManager.prototype);

View File

@ -1,153 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const GLib = imports.gi.GLib;
const GnomeDesktop = imports.gi.GnomeDesktop;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Main = imports.ui.main;
const DEFAULT_LOCALE = 'en_US';
const DEFAULT_LAYOUT = 'us';
const DEFAULT_VARIANT = '';
let _xkbInfo = null;
function getXkbInfo() {
if (_xkbInfo == null)
_xkbInfo = new GnomeDesktop.XkbInfo();
return _xkbInfo;
}
let _keyboardManager = null;
function getKeyboardManager() {
if (_keyboardManager == null)
_keyboardManager = new KeyboardManager();
return _keyboardManager;
}
function releaseKeyboard() {
if (Main.modalCount > 0)
global.display.unfreeze_keyboard(global.get_current_time());
else
global.display.ungrab_keyboard(global.get_current_time());
}
function holdKeyboard() {
global.freeze_keyboard(global.get_current_time());
}
const KeyboardManager = new Lang.Class({
Name: 'KeyboardManager',
// The XKB protocol doesn't allow for more that 4 layouts in a
// keymap. Wayland doesn't impose this limit and libxkbcommon can
// handle up to 32 layouts but since we need to support X clients
// even as a Wayland compositor, we can't bump this.
MAX_LAYOUTS_PER_GROUP: 4,
_init: function() {
this._xkbInfo = getXkbInfo();
this._current = null;
this._localeLayoutInfo = this._getLocaleLayout();
this._layoutInfos = {};
},
_applyLayoutGroup: function(group) {
let options = this._buildOptionsString();
let [layouts, variants] = this._buildGroupStrings(group);
Meta.get_backend().set_keymap(layouts, variants, options);
},
_applyLayoutGroupIndex: function(idx) {
Meta.get_backend().lock_layout_group(idx);
},
apply: function(id) {
let info = this._layoutInfos[id];
if (!info)
return;
if (this._current && this._current.group == info.group) {
if (this._current.groupIndex != info.groupIndex)
this._applyLayoutGroupIndex(info.groupIndex);
} else {
this._applyLayoutGroup(info.group);
this._applyLayoutGroupIndex(info.groupIndex);
}
this._current = info;
},
reapply: function() {
if (!this._current)
return;
this._applyLayoutGroup(this._current.group);
this._applyLayoutGroupIndex(this._current.groupIndex);
},
setUserLayouts: function(ids) {
this._current = null;
this._layoutInfos = {};
for (let i = 0; i < ids.length; ++i) {
let [found, , , _layout, _variant] = this._xkbInfo.get_layout_info(ids[i]);
if (found)
this._layoutInfos[ids[i]] = { id: ids[i], layout: _layout, variant: _variant };
}
let i = 0;
let group = [];
for (let id in this._layoutInfos) {
// We need to leave one slot on each group free so that we
// can add a layout containing the symbols for the
// language used in UI strings to ensure that toolkits can
// handle mnemonics like Alt+Ф even if the user is
// actually typing in a different layout.
let groupIndex = i % (this.MAX_LAYOUTS_PER_GROUP - 1);
if (groupIndex == 0)
group = [];
let info = this._layoutInfos[id];
group[groupIndex] = info;
info.group = group;
info.groupIndex = groupIndex;
i += 1;
}
},
_getLocaleLayout: function() {
let locale = GLib.get_language_names()[0];
if (locale.indexOf('_') == -1)
locale = DEFAULT_LOCALE;
let [found, , id] = GnomeDesktop.get_input_source_from_locale(locale);
if (!found)
[, , id] = GnomeDesktop.get_input_source_from_locale(DEFAULT_LOCALE);
let [found, , , _layout, _variant] = this._xkbInfo.get_layout_info(id);
if (found)
return { layout: _layout, variant: _variant };
else
return { layout: DEFAULT_LAYOUT, variant: DEFAULT_VARIANT };
},
_buildGroupStrings: function(_group) {
let group = _group.concat(this._localeLayoutInfo);
let layouts = group.map(function(g) { return g.layout; }).join(',');
let variants = group.map(function(g) { return g.variant; }).join(',');
return [layouts, variants];
},
setKeyboardOptions: function(options) {
this._xkbOptions = options;
},
_buildOptionsString: function() {
let options = this._xkbOptions.join(',');
return options;
}
});

View File

@ -46,6 +46,32 @@ const SystemdLoginSessionIface = '<node> \
const SystemdLoginManager = Gio.DBusProxy.makeProxyWrapper(SystemdLoginManagerIface); const SystemdLoginManager = Gio.DBusProxy.makeProxyWrapper(SystemdLoginManagerIface);
const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIface); const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIface);
const ConsoleKitManagerIface = '<node> \
<interface name="org.freedesktop.ConsoleKit.Manager"> \
<method name="CanRestart"> \
<arg type="b" direction="out"/> \
</method> \
<method name="CanStop"> \
<arg type="b" direction="out"/> \
</method> \
<method name="Restart" /> \
<method name="Stop" /> \
<method name="GetCurrentSession"> \
<arg type="o" direction="out" /> \
</method> \
</interface> \
</node>';
const ConsoleKitSessionIface = '<node> \
<interface name="org.freedesktop.ConsoleKit.Session"> \
<signal name="Lock" /> \
<signal name="Unlock" /> \
</interface> \
</node>';
const ConsoleKitSession = Gio.DBusProxy.makeProxyWrapper(ConsoleKitSessionIface);
const ConsoleKitManager = Gio.DBusProxy.makeProxyWrapper(ConsoleKitManagerIface);
function haveSystemd() { function haveSystemd() {
return GLib.access("/run/systemd/seats", 0) >= 0; return GLib.access("/run/systemd/seats", 0) >= 0;
} }
@ -75,7 +101,7 @@ function canLock() {
-1, null); -1, null);
let version = result.deep_unpack()[0].deep_unpack(); let version = result.deep_unpack()[0].deep_unpack();
return haveSystemd() && versionCompare('3.5.91', version); return versionCompare('3.5.91', version);
} catch(e) { } catch(e) {
return false; return false;
} }
@ -93,7 +119,7 @@ function getLoginManager() {
if (haveSystemd()) if (haveSystemd())
_loginManager = new LoginManagerSystemd(); _loginManager = new LoginManagerSystemd();
else else
_loginManager = new LoginManagerDummy(); _loginManager = new LoginManagerConsoleKit();
} }
return _loginManager; return _loginManager;
@ -110,6 +136,9 @@ const LoginManagerSystemd = new Lang.Class({
Lang.bind(this, this._prepareForSleep)); Lang.bind(this, this._prepareForSleep));
}, },
// Having this function is a bit of a hack since the Systemd and ConsoleKit
// session objects have different interfaces - but in both cases there are
// Lock/Unlock signals, and that's all we count upon at the moment.
getCurrentSessionProxy: function(callback) { getCurrentSessionProxy: function(callback) {
if (this._currentSession) { if (this._currentSession) {
callback (this._currentSession); callback (this._currentSession);
@ -162,7 +191,7 @@ const LoginManagerSystemd = new Lang.Class({
let fd = -1; let fd = -1;
try { try {
let [outVariant, fdList] = proxy.call_with_unix_fd_list_finish(result); let [outVariant, fdList] = proxy.call_with_unix_fd_list_finish(result);
fd = fdList.steal_fds()[0]; fd = fdList.steal_fds(outVariant.deep_unpack())[0];
callback(new Gio.UnixInputStream({ fd: fd })); callback(new Gio.UnixInputStream({ fd: fd }));
} catch(e) { } catch(e) {
logError(e, "Error getting systemd inhibitor"); logError(e, "Error getting systemd inhibitor");
@ -177,13 +206,35 @@ const LoginManagerSystemd = new Lang.Class({
}); });
Signals.addSignalMethods(LoginManagerSystemd.prototype); Signals.addSignalMethods(LoginManagerSystemd.prototype);
const LoginManagerDummy = new Lang.Class({ const LoginManagerConsoleKit = new Lang.Class({
Name: 'LoginManagerDummy', Name: 'LoginManagerConsoleKit',
_init: function() {
this._proxy = new ConsoleKitManager(Gio.DBus.system,
'org.freedesktop.ConsoleKit',
'/org/freedesktop/ConsoleKit/Manager');
},
// Having this function is a bit of a hack since the Systemd and ConsoleKit
// session objects have different interfaces - but in both cases there are
// Lock/Unlock signals, and that's all we count upon at the moment.
getCurrentSessionProxy: function(callback) { getCurrentSessionProxy: function(callback) {
// we could return a DummySession object that fakes whatever callers if (this._currentSession) {
// expect (at the time of writing: connect() and connectSignal() callback (this._currentSession);
// methods), but just never calling the callback should be safer return;
}
this._proxy.GetCurrentSessionRemote(Lang.bind(this,
function(result, error) {
if (error) {
logError(error, 'Could not get a proxy for the current session');
} else {
this._currentSession = new ConsoleKitSession(Gio.DBus.system,
'org.freedesktop.ConsoleKit',
result[0]);
callback(this._currentSession);
}
}));
}, },
canSuspend: function(asyncCallback) { canSuspend: function(asyncCallback) {
@ -203,4 +254,4 @@ const LoginManagerDummy = new Lang.Class({
callback(null); callback(null);
} }
}); });
Signals.addSignalMethods(LoginManagerDummy.prototype); Signals.addSignalMethods(LoginManagerConsoleKit.prototype);

View File

@ -129,7 +129,7 @@ function trySpawn(argv)
// Dummy child watch; we don't want to double-fork internally // Dummy child watch; we don't want to double-fork internally
// because then we lose the parent-child relationship, which // because then we lose the parent-child relationship, which
// can break polkit. See https://bugzilla.redhat.com//show_bug.cgi?id=819275 // can break polkit. See https://bugzilla.redhat.com//show_bug.cgi?id=819275
GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, function () {}); GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, function () {}, null);
} }
// trySpawnCommandLine: // trySpawnCommandLine:

View File

@ -72,9 +72,6 @@ function run() {
Scripting.defineScriptEvent("applicationsShowStart", "Starting to switch to applications view"); Scripting.defineScriptEvent("applicationsShowStart", "Starting to switch to applications view");
Scripting.defineScriptEvent("applicationsShowDone", "Done switching to applications view"); Scripting.defineScriptEvent("applicationsShowDone", "Done switching to applications view");
// Enable recording of timestamps for different points in the frame cycle
global.frame_timestamps = true;
Main.overview.connect('shown', function() { Main.overview.connect('shown', function() {
Scripting.scriptEvent('overviewShowDone'); Scripting.scriptEvent('overviewShowDone');
}); });
@ -90,10 +87,7 @@ function run() {
yield Scripting.destroyTestWindows(); yield Scripting.destroyTestWindows();
for (let k = 0; k < config.count; k++) for (let k = 0; k < config.count; k++)
yield Scripting.createTestWindow({ width: config.width, yield Scripting.createTestWindow(config.width, config.height, config.alpha, config.maximized);
height: config.height,
alpha: config.alpha,
maximized: config.maximized });
yield Scripting.waitTestWindows(); yield Scripting.waitTestWindows();
yield Scripting.sleep(1000); yield Scripting.sleep(1000);

View File

@ -1,308 +0,0 @@
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Meta = imports.gi.Meta;
const Main = imports.ui.main;
const Scripting = imports.ui.scripting;
const Shell = imports.gi.Shell;
let METRICS = {
timeToDesktop:
{ description: "Time from starting graphical.target to desktop showing",
units: "us" },
overviewShowTime:
{ description: "Time to switch to overview view, first time",
units: "us" },
applicationsShowTime:
{ description: "Time to switch to applications view, first time",
units: "us" },
mainViewRedrawTime:
{ description: "Time to redraw the main view, full screen",
units: "us" },
overviewRedrawTime:
{ description: "Time to redraw the overview, full screen, 5 windows",
units: "us" },
applicationRedrawTime:
{ description: "Time to redraw frame with a maximized application update",
units: "us" },
geditStartTime:
{ description: "Time from gedit launch to window drawn",
units: "us" },
}
function waitAndDraw(milliseconds) {
let cb;
let timeline = new Clutter.Timeline({ duration: milliseconds });
timeline.start();
timeline.connect('new-frame',
function(timeline, frame) {
global.stage.queue_redraw();
});
timeline.connect('completed',
function() {
timeline.stop();
if (cb)
cb();
});
return function(callback) {
cb = callback;
};
}
function waitSignal(object, signal) {
let cb;
let id = object.connect(signal, function() {
object.disconnect(id);
if (cb)
cb();
});
return function(callback) {
cb = callback;
};
}
function extractBootTimestamp() {
let sp = Gio.Subprocess.new(['journalctl', '-b',
'MESSAGE_ID=7d4958e842da4a758f6c1cdc7b36dcc5',
'UNIT=graphical.target',
'-o',
'json'],
Gio.SubprocessFlags.STDOUT_PIPE);
let result = null;
let datastream = Gio.DataInputStream.new(sp.get_stdout_pipe());
while (true) {
let [line, length] = datastream.read_line_utf8(null);
if (line === null)
break;
let fields = JSON.parse(line);
result = Number(fields['__MONOTONIC_TIMESTAMP']);
}
datastream.close(null);
return result;
}
function run() {
Scripting.defineScriptEvent("desktopShown", "Finished initial animation");
Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview");
Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing");
Scripting.defineScriptEvent("applicationsShowStart", "Starting to switch to applications view");
Scripting.defineScriptEvent("applicationsShowDone", "Done switching to applications view");
Scripting.defineScriptEvent("mainViewDrawStart", "Drawing main view");
Scripting.defineScriptEvent("mainViewDrawDone", "Ending timing main view drawing");
Scripting.defineScriptEvent("overviewDrawStart", "Drawing overview");
Scripting.defineScriptEvent("overviewDrawDone", "Ending timing overview drawing");
Scripting.defineScriptEvent("redrawTestStart", "Drawing application window");
Scripting.defineScriptEvent("redrawTestDone", "Ending timing application window drawing");
Scripting.defineScriptEvent("collectTimings", "Accumulate frame timings from redraw tests");
Scripting.defineScriptEvent("geditLaunch", "gedit application launch");
Scripting.defineScriptEvent("geditFirstFrame", "first frame of gedit window drawn");
yield Scripting.waitLeisure();
Scripting.scriptEvent('desktopShown');
Gtk.Settings.get_default().gtk_enable_animations = false;
Scripting.scriptEvent('overviewShowStart');
Main.overview.show();
yield Scripting.waitLeisure();
Scripting.scriptEvent('overviewShowDone');
yield Scripting.sleep(1000);
Scripting.scriptEvent('applicationsShowStart');
Main.overview._dash.showAppsButton.checked = true;
yield Scripting.waitLeisure();
Scripting.scriptEvent('applicationsShowDone');
yield Scripting.sleep(1000);
Main.overview.hide();
yield Scripting.waitLeisure();
////////////////////////////////////////
// Tests of redraw speed
////////////////////////////////////////
global.frame_timestamps = true;
global.frame_finish_timestamp = true;
for (let k = 0; k < 5; k++)
yield Scripting.createTestWindow(640, 480,
{ maximized: true });
yield Scripting.waitTestWindows();
yield Scripting.sleep(1000);
Scripting.scriptEvent('mainViewDrawStart');
yield waitAndDraw(1000);
Scripting.scriptEvent('mainViewDrawDone');
Main.overview.show();
Scripting.waitLeisure();
yield Scripting.sleep(1500);
Scripting.scriptEvent('overviewDrawStart');
yield waitAndDraw(1000);
Scripting.scriptEvent('overviewDrawDone');
yield Scripting.destroyTestWindows();
Main.overview.hide();
yield Scripting.createTestWindow(640, 480,
{ maximized: true,
redraws: true});
yield Scripting.waitTestWindows();
yield Scripting.sleep(1000);
Scripting.scriptEvent('redrawTestStart');
yield Scripting.sleep(1000);
Scripting.scriptEvent('redrawTestDone');
yield Scripting.sleep(1000);
Scripting.scriptEvent('collectTimings');
yield Scripting.destroyTestWindows();
global.frame_timestamps = false;
global.frame_finish_timestamp = false;
yield Scripting.sleep(1000);
////////////////////////////////////////
let appSys = Shell.AppSystem.get_default();
let app = appSys.lookup_app('org.gnome.gedit.desktop');
Scripting.scriptEvent('geditLaunch');
app.activate();
let windows = app.get_windows();
if (windows.length > 0)
throw new Error('gedit was already running');
while (windows.length == 0) {
yield waitSignal(global.display, 'window-created');
windows = app.get_windows();
}
let actor = windows[0].get_compositor_private();
yield waitSignal(actor, 'first-frame');
Scripting.scriptEvent('geditFirstFrame');
yield Scripting.sleep(1000);
windows[0].delete(global.get_current_time());
yield Scripting.sleep(1000);
Gtk.Settings.get_default().gtk_enable_animations = true;
}
let overviewShowStart;
let applicationsShowStart;
let stagePaintStart;
let redrawTiming;
let redrawTimes = {};
let geditLaunchTime;
function script_desktopShown(time) {
let bootTimestamp = extractBootTimestamp();
METRICS.timeToDesktop.value = time - bootTimestamp;
}
function script_overviewShowStart(time) {
overviewShowStart = time;
}
function script_overviewShowDone(time) {
METRICS.overviewShowTime.value = time - overviewShowStart;
}
function script_applicationsShowStart(time) {
applicationsShowStart = time;
}
function script_applicationsShowDone(time) {
METRICS.applicationsShowTime.value = time - applicationsShowStart;
}
function script_mainViewDrawStart(time) {
redrawTiming = 'mainView';
}
function script_mainViewDrawDone(time) {
redrawTiming = null;
}
function script_overviewDrawStart(time) {
redrawTiming = 'overview';
}
function script_overviewDrawDone(time) {
redrawTiming = null;
}
function script_redrawTestStart(time) {
redrawTiming = 'application';
}
function script_redrawTestDone(time) {
redrawTiming = null;
}
function script_collectTimings(time) {
for (let timing in redrawTimes) {
let times = redrawTimes[timing];
times.sort(function(a, b) { return a - b });
let len = times.length;
let median;
if (len == 0)
median = -1;
else if (len % 2 == 1)
median = times[(len - 1)/ 2];
else
median = Math.round((times[len / 2 - 1] + times[len / 2]) / 2);
METRICS[timing + 'RedrawTime'].value = median;
}
}
function script_geditLaunch(time) {
geditLaunchTime = time;
}
function script_geditFirstFrame(time) {
METRICS.geditStartTime.value = time - geditLaunchTime;
}
function clutter_stagePaintStart(time) {
stagePaintStart = time;
}
function clutter_paintCompletedTimestamp(time) {
if (redrawTiming != null && stagePaintStart != null) {
if (!(redrawTiming in redrawTimes))
redrawTimes[redrawTiming] = [];
redrawTimes[redrawTiming].push(time - stagePaintStart);
}
stagePaintStart = null;
}

View File

@ -1,247 +0,0 @@
const Format = imports.format;
const Gettext = imports.gettext;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Pango = imports.gi.Pango;
const Soup = imports.gi.Soup;
const WebKit = imports.gi.WebKit2;
const _ = Gettext.gettext;
const Config = imports.misc.config;
const PortalHelperResult = {
CANCELLED: 0,
COMPLETED: 1,
RECHECK: 2
};
const INACTIVITY_TIMEOUT = 30000; //ms
const CONNECTIVITY_RECHECK_RATELIMIT_TIMEOUT = 30 * GLib.USEC_PER_SEC;
const HelperDBusInterface = '<node> \
<interface name="org.gnome.Shell.PortalHelper"> \
<method name="Authenticate"> \
<arg type="o" direction="in" name="connection" /> \
<arg type="s" direction="in" name="url" /> \
<arg type="u" direction="in" name="timestamp" /> \
</method> \
<method name="Close"> \
<arg type="o" direction="in" name="connection" /> \
</method> \
<method name="Refresh"> \
<arg type="o" direction="in" name="connection" /> \
</method> \
<signal name="Done"> \
<arg type="o" name="connection" /> \
<arg type="u" name="result" /> \
</signal> \
</interface> \
</node>';
const PortalWindow = new Lang.Class({
Name: 'PortalWindow',
Extends: Gtk.ApplicationWindow,
_init: function(application, url, timestamp, doneCallback) {
this.parent({ application: application });
if (!url) {
url = 'http://www.gnome.org';
this._originalUrlWasGnome = true;
} else {
this._originalUrlWasGnome = false;
}
this._uri = new Soup.URI(url);
this._everSeenRedirect = false;
this._originalUrl = url;
this._doneCallback = doneCallback;
this._lastRecheck = 0;
this._recheckAtExit = false;
this._webView = new WebKit.WebView();
this._webView.connect('decide-policy', Lang.bind(this, this._onDecidePolicy));
this._webView.load_uri(url);
this._webView.connect('notify::title', Lang.bind(this, this._syncTitle));
this._syncTitle();
this.add(this._webView);
this._webView.show();
this.maximize();
this.present_with_time(timestamp);
},
_syncTitle: function() {
let title = this._webView.title;
if (title) {
this.title = title;
} else {
// TRANSLATORS: this is the title of the wifi captive portal login
// window, until we know the title of the actual login page
this.title = _("Web Authentication Redirect");
}
},
refresh: function() {
this._everSeenRedirect = false;
this._webView.load_uri(this._originalUrl);
},
vfunc_delete_event: function(event) {
if (this._recheckAtExit)
this._doneCallback(PortalHelperResult.RECHECK);
else
this._doneCallback(PortalHelperResult.CANCELLED);
return false;
},
_onDecidePolicy: function(view, decision, type) {
if (type == WebKit.PolicyDecisionType.NEW_WINDOW_ACTION) {
decision.ignore();
return true;
}
if (type != WebKit.PolicyDecisionType.NAVIGATION_ACTION)
return false;
let request = decision.get_request();
let uri = new Soup.URI(request.get_uri());
if (!uri.host_equal(this._uri) && this._originalUrlWasGnome) {
if (uri.get_host() == 'www.gnome.org' && this._everSeenRedirect) {
// Yay, we got to gnome!
decision.ignore();
this._doneCallback(PortalHelperResult.COMPLETED);
return true;
} else if (uri.get_host() != 'www.gnome.org') {
this._everSeenRedirect = true;
}
}
// We *may* have finished here, but we don't know for
// sure. Tell gnome-shell to run another connectivity check
// (but ratelimit the checks, we don't want to spam
// nmcheck.gnome.org for portals that have 10 or more internal
// redirects - and unfortunately they exist)
// If we hit the rate limit, we also queue a recheck
// when the window is closed, just in case we miss the
// final check and don't realize we're connected
// This should not be a problem in the cancelled logic,
// because if the user doesn't want to start the login,
// we should not see any redirect at all, outside this._uri
let now = GLib.get_monotonic_time();
let shouldRecheck = (now - this._lastRecheck) >
CONNECTIVITY_RECHECK_RATELIMIT_TIMEOUT;
if (shouldRecheck) {
this._lastRecheck = now;
this._recheckAtExit = false;
this._doneCallback(PortalHelperResult.RECHECK);
} else {
this._recheckAtExit = true;
}
// Update the URI, in case of chained redirects, so we still
// think we're doing the login until gnome-shell kills us
this._uri = uri;
decision.use();
return true;
},
});
const WebPortalHelper = new Lang.Class({
Name: 'WebPortalHelper',
Extends: Gtk.Application,
_init: function() {
this.parent({ application_id: 'org.gnome.Shell.PortalHelper',
flags: Gio.ApplicationFlags.IS_SERVICE,
inactivity_timeout: 30000 });
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(HelperDBusInterface, this);
this._queue = [];
},
vfunc_dbus_register: function(connection, path) {
this._dbusImpl.export(connection, path);
this.parent(connection, path);
return true;
},
vfunc_dbus_unregister: function(connection, path) {
this._dbusImpl.unexport_from_connection(connection);
this.parent(connection, path);
},
vfunc_activate: function() {
// If launched manually (for example for testing), force a dummy authentication
// session with the default url
this.Authenticate('/org/gnome/dummy', '', 0);
},
Authenticate: function(connection, url, timestamp) {
this._queue.push({ connection: connection, url: url, timestamp: timestamp });
this._processQueue();
},
Close: function(connection) {
for (let i = 0; i < this._queue.length; i++) {
let obj = this._queue[i];
if (obj.connection == connection) {
if (obj.window)
obj.window.destroy();
this._queue.splice(i, 1);
break;
}
}
this._processQueue();
},
Refresh: function(connection) {
for (let i = 0; i < this._queue.length; i++) {
let obj = this._queue[i];
if (obj.connection == connection) {
if (obj.window)
obj.window.refresh();
break;
}
}
},
_processQueue: function() {
if (this._queue.length == 0)
return;
let top = this._queue[0];
if (top.window != null)
return;
top.window = new PortalWindow(this, top.uri, top.timestamp, Lang.bind(this, function(result) {
this._dbusImpl.emit_signal('Done', new GLib.Variant('(ou)', [top.connection, result]));
}));
},
});
function initEnvironment() {
String.prototype.format = Format.format;
}
function main(argv) {
initEnvironment();
Gettext.bindtextdomain(Config.GETTEXT_PACKAGE, Config.LOCALEDIR);
Gettext.textdomain(Config.GETTEXT_PACKAGE);
let app = new WebPortalHelper();
return app.run(argv);
}

View File

@ -58,14 +58,6 @@ const AppSwitcherPopup = new Lang.Class({
this._currentWindow = -1; this._currentWindow = -1;
this.thumbnailsVisible = false; this.thumbnailsVisible = false;
let apps = Shell.AppSystem.get_default().get_running ();
if (apps.length == 0)
return;
this._switcherList = new AppSwitcher(apps, this);
this._items = this._switcherList.icons;
}, },
_allocate: function (actor, box, flags) { _allocate: function (actor, box, flags) {
@ -107,6 +99,20 @@ const AppSwitcherPopup = new Lang.Class({
} }
}, },
_createSwitcher: function() {
let apps = Shell.AppSystem.get_default().get_running ();
if (apps.length == 0)
return false;
this._switcherList = new AppSwitcher(apps, this);
this._items = this._switcherList.icons;
if (this._items.length == 0)
return false;
return true;
},
_initialSelection: function(backward, binding) { _initialSelection: function(backward, binding) {
if (binding == 'switch-group') { if (binding == 'switch-group') {
if (backward) { if (backward) {
@ -145,13 +151,13 @@ const AppSwitcherPopup = new Lang.Class({
this._items[this._selectedIndex].cachedWindows.length); this._items[this._selectedIndex].cachedWindows.length);
}, },
_keyPressHandler: function(keysym, action) { _keyPressHandler: function(keysym, backwards, action) {
if (action == Meta.KeyBindingAction.SWITCH_GROUP) { if (action == Meta.KeyBindingAction.SWITCH_GROUP) {
this._select(this._selectedIndex, this._nextWindow()); this._select(this._selectedIndex, backwards ? this._previousWindow() : this._nextWindow());
} else if (action == Meta.KeyBindingAction.SWITCH_GROUP_BACKWARD) { } else if (action == Meta.KeyBindingAction.SWITCH_GROUP_BACKWARD) {
this._select(this._selectedIndex, this._previousWindow()); this._select(this._selectedIndex, this._previousWindow());
} else if (action == Meta.KeyBindingAction.SWITCH_APPLICATIONS) { } else if (action == Meta.KeyBindingAction.SWITCH_APPLICATIONS) {
this._select(this._next()); this._select(backwards ? this._previous() : this._next());
} else if (action == Meta.KeyBindingAction.SWITCH_APPLICATIONS_BACKWARD) { } else if (action == Meta.KeyBindingAction.SWITCH_APPLICATIONS_BACKWARD) {
this._select(this._previous()); this._select(this._previous());
} else if (this._thumbnailsFocused) { } else if (this._thumbnailsFocused) {
@ -161,8 +167,6 @@ const AppSwitcherPopup = new Lang.Class({
this._select(this._selectedIndex, this._nextWindow()); this._select(this._selectedIndex, this._nextWindow());
else if (keysym == Clutter.Up) else if (keysym == Clutter.Up)
this._select(this._selectedIndex, null, true); this._select(this._selectedIndex, null, true);
else
return Clutter.EVENT_PROPAGATE;
} else { } else {
if (keysym == Clutter.Left) if (keysym == Clutter.Left)
this._select(this._previous()); this._select(this._previous());
@ -170,11 +174,7 @@ const AppSwitcherPopup = new Lang.Class({
this._select(this._next()); this._select(this._next());
else if (keysym == Clutter.Down) else if (keysym == Clutter.Down)
this._select(this._selectedIndex, 0); this._select(this._selectedIndex, 0);
else
return Clutter.EVENT_PROPAGATE;
} }
return Clutter.EVENT_STOP;
}, },
_scrollHandler: function(direction) { _scrollHandler: function(direction) {
@ -305,7 +305,6 @@ const AppSwitcherPopup = new Lang.Class({
this._thumbnailTimeoutId = Mainloop.timeout_add ( this._thumbnailTimeoutId = Mainloop.timeout_add (
THUMBNAIL_POPUP_TIME, THUMBNAIL_POPUP_TIME,
Lang.bind(this, this._timeoutPopupThumbnails)); Lang.bind(this, this._timeoutPopupThumbnails));
GLib.Source.set_name_by_id(this._thumbnailTimeoutId, '[gnome-shell] this._timeoutPopupThumbnails');
} }
}, },
@ -359,28 +358,44 @@ const WindowSwitcherPopup = new Lang.Class({
Name: 'WindowSwitcherPopup', Name: 'WindowSwitcherPopup',
Extends: SwitcherPopup.SwitcherPopup, Extends: SwitcherPopup.SwitcherPopup,
_init: function() { _init: function(items) {
this.parent(); this.parent(items);
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' }); this._settings = new Gio.Settings({ schema: 'org.gnome.shell.window-switcher' });
let windows = this._getWindowList();
if (windows.length == 0)
return;
let mode = this._settings.get_enum('app-icon-mode');
this._switcherList = new WindowList(windows, mode);
this._items = this._switcherList.icons;
}, },
_getWindowList: function() { _getWindowList: function() {
let workspace = this._settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace() : null; let workspace = this._settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace() : null;
return global.display.get_tab_list(Meta.TabList.NORMAL, workspace); return global.display.get_tab_list(Meta.TabList.NORMAL, global.screen, workspace);
}, },
_keyPressHandler: function(keysym, action) { _createSwitcher: function() {
let windows = this._getWindowList();
if (windows.length == 0)
return false;
let mode = this._settings.get_enum('app-icon-mode');
this._switcherList = new WindowList(windows, mode);
this._items = this._switcherList.icons;
if (this._items.length == 0)
return false;
return true;
},
_initialSelection: function(backward, binding) {
if (binding == 'switch-windows-backward' || backward)
this._select(this._items.length - 1);
else if (this._items.length == 1)
this._select(0);
else
this._select(1);
},
_keyPressHandler: function(keysym, backwards, action) {
if (action == Meta.KeyBindingAction.SWITCH_WINDOWS) { if (action == Meta.KeyBindingAction.SWITCH_WINDOWS) {
this._select(this._next()); this._select(backwards ? this._previous() : this._next());
} else if (action == Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD) { } else if (action == Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD) {
this._select(this._previous()); this._select(this._previous());
} else { } else {
@ -388,11 +403,7 @@ const WindowSwitcherPopup = new Lang.Class({
this._select(this._previous()); this._select(this._previous());
else if (keysym == Clutter.Right) else if (keysym == Clutter.Right)
this._select(this._next()); this._select(this._next());
else
return Clutter.EVENT_PROPAGATE;
} }
return Clutter.EVENT_STOP;
}, },
_finish: function() { _finish: function() {
@ -434,10 +445,11 @@ const AppSwitcher = new Lang.Class({
this._arrows = []; this._arrows = [];
let windowTracker = Shell.WindowTracker.get_default(); let windowTracker = Shell.WindowTracker.get_default();
let settings = new Gio.Settings({ schema_id: 'org.gnome.shell.app-switcher' }); let settings = new Gio.Settings({ schema: 'org.gnome.shell.app-switcher' });
let workspace = settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace() let workspace = settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace()
: null; : null;
let allWindows = global.display.get_tab_list(Meta.TabList.NORMAL, workspace); let allWindows = global.display.get_tab_list(Meta.TabList.NORMAL,
global.screen, workspace);
// Construct the AppIcons, add to the popup // Construct the AppIcons, add to the popup
for (let i = 0; i < apps.length; i++) { for (let i = 0; i < apps.length; i++) {
@ -544,7 +556,6 @@ const AppSwitcher = new Lang.Class({
this._mouseTimeOutId = 0; this._mouseTimeOutId = 0;
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(this._mouseTimeOutId, '[gnome-shell] this._enterItem');
} else } else
this._itemEntered(index); this._itemEntered(index);
}, },

View File

@ -34,7 +34,6 @@ const Animation = new Lang.Class({
this._showFrame(0); this._showFrame(0);
this._timeoutId = Mainloop.timeout_add(this._speed, Lang.bind(this, this._update)); this._timeoutId = Mainloop.timeout_add(this._speed, Lang.bind(this, this._update));
GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] this._update');
} }
this._isPlaying = true; this._isPlaying = true;

View File

@ -16,7 +16,6 @@ const Atk = imports.gi.Atk;
const AppFavorites = imports.ui.appFavorites; const AppFavorites = imports.ui.appFavorites;
const BoxPointer = imports.ui.boxpointer; const BoxPointer = imports.ui.boxpointer;
const DND = imports.ui.dnd; const DND = imports.ui.dnd;
const GrabHelper = imports.ui.grabHelper;
const IconGrid = imports.ui.iconGrid; const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main; const Main = imports.ui.main;
const Overview = imports.ui.overview; const Overview = imports.ui.overview;
@ -34,9 +33,7 @@ const MIN_COLUMNS = 4;
const MIN_ROWS = 4; const MIN_ROWS = 4;
const INACTIVE_GRID_OPACITY = 77; const INACTIVE_GRID_OPACITY = 77;
// This time needs to be less than IconGrid.EXTRA_SPACE_ANIMATION_TIME const INACTIVE_GRID_OPACITY_ANIMATION_TIME = 0.40;
// to not clash with other animations
const INACTIVE_GRID_OPACITY_ANIMATION_TIME = 0.24;
const FOLDER_SUBICON_FRACTION = .4; const FOLDER_SUBICON_FRACTION = .4;
const MIN_FREQUENT_APPS_COUNT = 3; const MIN_FREQUENT_APPS_COUNT = 3;
@ -44,17 +41,9 @@ const MIN_FREQUENT_APPS_COUNT = 3;
const INDICATORS_BASE_TIME = 0.25; const INDICATORS_BASE_TIME = 0.25;
const INDICATORS_ANIMATION_DELAY = 0.125; const INDICATORS_ANIMATION_DELAY = 0.125;
const INDICATORS_ANIMATION_MAX_TIME = 0.75; const INDICATORS_ANIMATION_MAX_TIME = 0.75;
// Fraction of page height the finger or mouse must reach
// Follow iconGrid animations approach and divide by 2 to animate out to // to change page
// not annoy the user when the user wants to quit appDisplay. const PAGE_SWITCH_TRESHOLD = 0.2;
// Also, make sure we don't exceed iconGrid animation total time or
// views switch time.
const INDICATORS_BASE_TIME_OUT = 0.125;
const INDICATORS_ANIMATION_DELAY_OUT = 0.0625;
const INDICATORS_ANIMATION_MAX_TIME_OUT =
Math.min (VIEWS_SWITCH_TIME,
IconGrid.ANIMATION_TIME_OUT + IconGrid.ANIMATION_MAX_DELAY_OUT_FOR_ITEM);
const PAGE_SWITCH_TIME = 0.3; const PAGE_SWITCH_TIME = 0.3;
const VIEWS_SWITCH_TIME = 0.4; const VIEWS_SWITCH_TIME = 0.4;
@ -92,10 +81,6 @@ function _getFolderName(folder) {
return name; return name;
} }
function clamp(value, min, max) {
return Math.max(min, Math.min(max, value));
}
const BaseAppView = new Lang.Class({ const BaseAppView = new Lang.Class({
Name: 'BaseAppView', Name: 'BaseAppView',
Abstract: true, Abstract: true,
@ -189,98 +174,26 @@ const BaseAppView = new Lang.Class({
this.selectApp(id); this.selectApp(id);
})); }));
} }
},
_doSpringAnimation: function(animationDirection) {
this._grid.actor.opacity = 255;
this._grid.animateSpring(animationDirection,
Main.overview.getShowAppsButton());
},
animate: function(animationDirection, onComplete) {
if (animationDirection == IconGrid.AnimationDirection.IN) {
let toAnimate = this._grid.actor.connect('notify::allocation', Lang.bind(this,
function() {
this._grid.actor.disconnect(toAnimate);
// We need to hide the grid temporary to not flash it
// for a frame
this._grid.actor.opacity = 0;
Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
Lang.bind(this, function() {
this._doSpringAnimation(animationDirection)
}));
}));
} else {
this._doSpringAnimation(animationDirection);
}
if (onComplete) {
let animationDoneId = this._grid.connect('animation-done', Lang.bind(this,
function () {
this._grid.disconnect(animationDoneId);
onComplete();
}));
}
},
animateSwitch: function(animationDirection) {
Tweener.removeTweens(this.actor);
Tweener.removeTweens(this._grid.actor);
let params = { time: VIEWS_SWITCH_TIME,
transition: 'easeOutQuad' };
if (animationDirection == IconGrid.AnimationDirection.IN) {
this.actor.show();
params.opacity = 255;
params.delay = VIEWS_SWITCH_ANIMATION_DELAY;
} else {
params.opacity = 0;
params.delay = 0;
params.onComplete = Lang.bind(this, function() { this.actor.hide() });
}
Tweener.addTween(this._grid.actor, params);
} }
}); });
Signals.addSignalMethods(BaseAppView.prototype); Signals.addSignalMethods(BaseAppView.prototype);
const PageIndicatorsActor = new Lang.Class({
Name:'PageIndicatorsActor',
Extends: St.BoxLayout,
_init: function() {
this.parent({ style_class: 'page-indicators',
vertical: true,
x_expand: true, y_expand: true,
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.CENTER,
reactive: true,
clip_to_allocation: true });
},
vfunc_get_preferred_height: function(forWidth) {
// We want to request the natural height of all our children as our
// natural height, so we chain up to St.BoxLayout, but we only request 0
// as minimum height, since it's not that important if some indicators
// are not shown
let [, natHeight] = this.parent(forWidth);
return [0, natHeight];
}
});
const PageIndicators = new Lang.Class({ const PageIndicators = new Lang.Class({
Name:'PageIndicators', Name:'PageIndicators',
_init: function() { _init: function() {
this.actor = new PageIndicatorsActor(); this.actor = new St.BoxLayout({ style_class: 'page-indicators',
vertical: true,
x_expand: true, y_expand: true,
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.CENTER,
reactive: true });
this._nPages = 0; this._nPages = 0;
this._currentPage = undefined; this._currentPage = undefined;
this.actor.connect('notify::mapped', this.actor.connect('notify::mapped',
Lang.bind(this, function() { Lang.bind(this, this._animateIndicators));
this.animateIndicators(IconGrid.AnimationDirection.IN);
})
);
}, },
setNPages: function(nPages) { setNPages: function(nPages) {
@ -321,7 +234,7 @@ const PageIndicators = new Lang.Class({
children[i].set_checked(i == this._currentPage); children[i].set_checked(i == this._currentPage);
}, },
animateIndicators: function(animationDirection) { _animateIndicators: function() {
if (!this.actor.mapped) if (!this.actor.mapped)
return; return;
@ -329,32 +242,24 @@ const PageIndicators = new Lang.Class({
if (children.length == 0) if (children.length == 0)
return; return;
for (let i = 0; i < this._nPages; i++)
Tweener.removeTweens(children[i]);
let offset; let offset;
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL) if (this.actor.get_text_direction() == Clutter.TextDirection.RTL)
offset = -children[0].width; offset = -children[0].width;
else else
offset = children[0].width; offset = children[0].width;
let isAnimationIn = animationDirection == IconGrid.AnimationDirection.IN; let delay = INDICATORS_ANIMATION_DELAY;
let delay = isAnimationIn ? INDICATORS_ANIMATION_DELAY : let totalAnimationTime = INDICATORS_BASE_TIME + INDICATORS_ANIMATION_DELAY * this._nPages;
INDICATORS_ANIMATION_DELAY_OUT; if (totalAnimationTime > INDICATORS_ANIMATION_MAX_TIME)
let baseTime = isAnimationIn ? INDICATORS_BASE_TIME : INDICATORS_BASE_TIME_OUT; delay -= (totalAnimationTime - INDICATORS_ANIMATION_MAX_TIME) / this._nPages;
let totalAnimationTime = baseTime + delay * this._nPages;
let maxTime = isAnimationIn ? INDICATORS_ANIMATION_MAX_TIME :
INDICATORS_ANIMATION_MAX_TIME_OUT;
if (totalAnimationTime > maxTime)
delay -= (totalAnimationTime - maxTime) / this._nPages;
for (let i = 0; i < this._nPages; i++) { for (let i = 0; i < this._nPages; i++) {
children[i].translation_x = isAnimationIn ? offset : 0; children[i].translation_x = offset;
Tweener.addTween(children[i], Tweener.addTween(children[i],
{ translation_x: isAnimationIn ? 0 : offset, { translation_x: 0,
time: baseTime + delay * i, time: INDICATORS_BASE_TIME + delay * i,
transition: 'easeInOutQuad', transition: 'easeInOutQuad',
delay: isAnimationIn ? VIEWS_SWITCH_ANIMATION_DELAY : 0 delay: VIEWS_SWITCH_ANIMATION_DELAY
}); });
} }
} }
@ -397,7 +302,7 @@ const AllView = new Lang.Class({
this._stack = new St.Widget({ layout_manager: new Clutter.BinLayout() }); this._stack = new St.Widget({ layout_manager: new Clutter.BinLayout() });
let box = new St.BoxLayout({ vertical: true }); let box = new St.BoxLayout({ vertical: true });
this._grid.currentPage = 0; this._currentPage = 0;
this._stack.add_actor(this._grid.actor); this._stack.add_actor(this._grid.actor);
this._eventBlocker = new St.Widget({ x_expand: true, y_expand: true }); this._eventBlocker = new St.Widget({ x_expand: true, y_expand: true });
this._stack.add_actor(this._eventBlocker); this._stack.add_actor(this._eventBlocker);
@ -463,7 +368,7 @@ const AllView = new Lang.Class({
Shell.AppSystem.get_default().connect('installed-changed', Lang.bind(this, function() { Shell.AppSystem.get_default().connect('installed-changed', Lang.bind(this, function() {
Main.queueDeferredWork(this._redisplayWorkId); Main.queueDeferredWork(this._redisplayWorkId);
})); }));
this._folderSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.app-folders' }); this._folderSettings = new Gio.Settings({ schema: 'org.gnome.desktop.app-folders' });
this._folderSettings.connect('changed::folder-children', Lang.bind(this, function() { this._folderSettings.connect('changed::folder-children', Lang.bind(this, function() {
Main.queueDeferredWork(this._redisplayWorkId); Main.queueDeferredWork(this._redisplayWorkId);
})); }));
@ -529,52 +434,14 @@ const AllView = new Lang.Class({
this._refilterApps(); this._refilterApps();
}, },
// Overriden from BaseAppView
animate: function (animationDirection, onComplete) {
if (animationDirection == IconGrid.AnimationDirection.OUT &&
this._displayingPopup && this._currentPopup) {
this._currentPopup.popdown();
let spaceClosedId = this._grid.connect('space-closed', Lang.bind(this,
function() {
this._grid.disconnect(spaceClosedId);
// Given that we can't call this.parent() inside the
// signal handler, call again animate which will
// call the parent given that popup is already
// closed.
this.animate(animationDirection, onComplete);
}));
} else {
this.parent(animationDirection, onComplete);
if (animationDirection == IconGrid.AnimationDirection.OUT)
this._pageIndicators.animateIndicators(animationDirection);
}
},
animateSwitch: function(animationDirection) {
this.parent(animationDirection);
if (this._currentPopup && this._displayingPopup &&
animationDirection == IconGrid.AnimationDirection.OUT)
Tweener.addTween(this._currentPopup.actor,
{ time: VIEWS_SWITCH_TIME,
transition: 'easeOutQuad',
opacity: 0,
onComplete: function() {
this.opacity = 255;
} });
if (animationDirection == IconGrid.AnimationDirection.OUT)
this._pageIndicators.animateIndicators(animationDirection);
},
getCurrentPageY: function() { getCurrentPageY: function() {
return this._grid.getPageY(this._grid.currentPage); return this._grid.getPageY(this._currentPage);
}, },
goToPage: function(pageNumber) { goToPage: function(pageNumber) {
pageNumber = clamp(pageNumber, 0, this._grid.nPages() - 1); if(pageNumber < 0 || pageNumber > this._grid.nPages() - 1)
return;
if (this._grid.currentPage == pageNumber && this._displayingPopup && this._currentPopup) if (this._currentPage == pageNumber && this._displayingPopup && this._currentPopup)
return; return;
if (this._displayingPopup && this._currentPopup) if (this._displayingPopup && this._currentPopup)
this._currentPopup.popdown(); this._currentPopup.popdown();
@ -594,7 +461,7 @@ const AllView = new Lang.Class({
let time; let time;
// Only take the velocity into account on page changes, otherwise // Only take the velocity into account on page changes, otherwise
// return smoothly to the current page using the default velocity // return smoothly to the current page using the default velocity
if (this._grid.currentPage != pageNumber) { if (this._currentPage != pageNumber) {
let minVelocity = totalHeight / (PAGE_SWITCH_TIME * 1000); let minVelocity = totalHeight / (PAGE_SWITCH_TIME * 1000);
velocity = Math.max(minVelocity, velocity); velocity = Math.max(minVelocity, velocity);
time = (diffToPage / velocity) / 1000; time = (diffToPage / velocity) / 1000;
@ -605,12 +472,14 @@ const AllView = new Lang.Class({
// longer than PAGE_SWITCH_TIME // longer than PAGE_SWITCH_TIME
time = Math.min(time, PAGE_SWITCH_TIME); time = Math.min(time, PAGE_SWITCH_TIME);
this._grid.currentPage = pageNumber; if (pageNumber < this._grid.nPages() && pageNumber >= 0) {
Tweener.addTween(this._adjustment, this._currentPage = pageNumber;
{ value: this._grid.getPageY(this._grid.currentPage), Tweener.addTween(this._adjustment,
time: time, { value: this._grid.getPageY(this._currentPage),
transition: 'easeOutQuad' }); time: time,
this._pageIndicators.setCurrentPage(pageNumber); transition: 'easeOutQuad' });
this._pageIndicators.setCurrentPage(pageNumber);
}
}, },
_diffToPage: function (pageNumber) { _diffToPage: function (pageNumber) {
@ -636,9 +505,9 @@ const AllView = new Lang.Class({
let direction = event.get_scroll_direction(); let direction = event.get_scroll_direction();
if (direction == Clutter.ScrollDirection.UP) if (direction == Clutter.ScrollDirection.UP)
this.goToPage(this._grid.currentPage - 1); this.goToPage(this._currentPage - 1);
else if (direction == Clutter.ScrollDirection.DOWN) else if (direction == Clutter.ScrollDirection.DOWN)
this.goToPage(this._grid.currentPage + 1); this.goToPage(this._currentPage + 1);
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
}, },
@ -657,19 +526,15 @@ const AllView = new Lang.Class({
_onPanEnd: function(action) { _onPanEnd: function(action) {
if (this._displayingPopup) if (this._displayingPopup)
return; return;
let diffCurrentPage = this._diffToPage(this._currentPage);
let pageHeight = this._grid.getPageHeight(); if (diffCurrentPage > this._scrollView.height * PAGE_SWITCH_TRESHOLD) {
if (action.get_velocity(0)[2] > 0)
// Calculate the scroll value we'd be at, which is our current this.goToPage(this._currentPage - 1);
// scroll plus any velocity the user had when they released else
// their finger. this.goToPage(this._currentPage + 1);
} else {
let velocity = -action.get_velocity(0)[2]; this.goToPage(this._currentPage);
let endPanValue = this._adjustment.value + velocity; }
let closestPage = Math.round(endPanValue / pageHeight);
this.goToPage(closestPage);
this._panning = false; this._panning = false;
}, },
@ -678,10 +543,10 @@ const AllView = new Lang.Class({
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
if (event.get_key_symbol() == Clutter.Page_Up) { if (event.get_key_symbol() == Clutter.Page_Up) {
this.goToPage(this._grid.currentPage - 1); this.goToPage(this._currentPage - 1);
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} else if (event.get_key_symbol() == Clutter.Page_Down) { } else if (event.get_key_symbol() == Clutter.Page_Down) {
this.goToPage(this._grid.currentPage + 1); this.goToPage(this._currentPage + 1);
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
@ -742,7 +607,6 @@ const AllView = new Lang.Class({
if (this._availWidth != availWidth || this._availHeight != availHeight || oldNPages != this._grid.nPages()) { if (this._availWidth != availWidth || this._availHeight != availHeight || oldNPages != this._grid.nPages()) {
this._adjustment.value = 0; this._adjustment.value = 0;
this._grid.currentPage = 0;
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
function() { function() {
this._pageIndicators.setNPages(this._grid.nPages()); this._pageIndicators.setNPages(this._grid.nPages());
@ -872,7 +736,7 @@ const AppDisplay = new Lang.Class({
Name: 'AppDisplay', Name: 'AppDisplay',
_init: function() { _init: function() {
this._privacySettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.privacy' }); this._privacySettings = new Gio.Settings({ schema: 'org.gnome.desktop.privacy' });
this._privacySettings.connect('changed::remember-app-usage', this._privacySettings.connect('changed::remember-app-usage',
Lang.bind(this, this._updateFrequentVisibility)); Lang.bind(this, this._updateFrequentVisibility));
@ -900,23 +764,10 @@ const AppDisplay = new Lang.Class({
this._viewStack = new St.Widget({ x_expand: true, y_expand: true, this._viewStack = new St.Widget({ x_expand: true, y_expand: true,
layout_manager: this._viewStackLayout }); layout_manager: this._viewStackLayout });
this._viewStackLayout.connect('allocated-size-changed', Lang.bind(this, this._onAllocatedSizeChanged)); this._viewStackLayout.connect('allocated-size-changed', Lang.bind(this, this._onAllocatedSizeChanged));
this.actor.add_actor(this._viewStack); this.actor.add_actor(this._viewStack, { expand: true });
let layout = new ControlsBoxLayout({ homogeneous: true }); let layout = new ControlsBoxLayout({ homogeneous: true });
this._controls = new St.Widget({ style_class: 'app-view-controls', this._controls = new St.Widget({ style_class: 'app-view-controls',
layout_manager: layout }); layout_manager: layout });
this._controls.connect('notify::mapped', Lang.bind(this,
function() {
// controls are faded either with their parent or
// explicitly in animate(); we can't know how they'll be
// shown next, so make sure to restore their opacity
// when they are hidden
if (this._controls.mapped)
return;
Tweener.removeTweens(this._controls);
this._controls.opacity = 255;
}));
layout.hookup_style(this._controls); layout.hookup_style(this._controls);
this.actor.add_actor(new St.Bin({ child: this._controls })); this.actor.add_actor(new St.Bin({ child: this._controls }));
@ -940,39 +791,23 @@ const AppDisplay = new Lang.Class({
this._updateFrequentVisibility(); this._updateFrequentVisibility();
}, },
animate: function(animationDirection, onComplete) {
let currentView = this._views[global.settings.get_uint('app-picker-view')].view;
// Animate controls opacity using iconGrid animation time, since
// it will be the time the AllView or FrequentView takes to show
// it entirely.
let finalOpacity;
if (animationDirection == IconGrid.AnimationDirection.IN) {
this._controls.opacity = 0;
finalOpacity = 255;
} else {
finalOpacity = 0
}
Tweener.addTween(this._controls,
{ time: IconGrid.ANIMATION_TIME_IN,
transition: 'easeInOutQuad',
opacity: finalOpacity,
});
currentView.animate(animationDirection, onComplete);
},
_showView: function(activeIndex) { _showView: function(activeIndex) {
for (let i = 0; i < this._views.length; i++) { for (let i = 0; i < this._views.length; i++) {
let actor = this._views[i].view.actor;
let params = { time: VIEWS_SWITCH_TIME,
opacity: (i == activeIndex) ? 255 : 0,
delay: (i == activeIndex) ? VIEWS_SWITCH_ANIMATION_DELAY : 0 };
if (i == activeIndex)
actor.visible = true;
else
params.onComplete = function() { actor.hide(); };
Tweener.addTween(actor, params);
if (i == activeIndex) if (i == activeIndex)
this._views[i].control.add_style_pseudo_class('checked'); this._views[i].control.add_style_pseudo_class('checked');
else else
this._views[i].control.remove_style_pseudo_class('checked'); this._views[i].control.remove_style_pseudo_class('checked');
let animationDirection = i == activeIndex ? IconGrid.AnimationDirection.IN :
IconGrid.AnimationDirection.OUT;
this._views[i].view.animateSwitch(animationDirection);
} }
}, },
@ -1054,6 +889,26 @@ const AppSearchProvider = new Lang.Class({
this.getInitialResultSet(terms, callback, cancellable); this.getInitialResultSet(terms, callback, cancellable);
}, },
activateResult: function(result) {
let app = this._appSys.lookup_app(result);
let event = Clutter.get_current_event();
let modifiers = event ? event.get_state() : 0;
let openNewWindow = modifiers & Clutter.ModifierType.CONTROL_MASK;
if (openNewWindow)
app.open_new_window(-1);
else
app.activate();
},
dragActivateResult: function(id, params) {
params = Params.parse(params, { workspace: -1,
timestamp: 0 });
let app = this._appSys.lookup_app(id);
app.open_new_window(workspace);
},
createResultObject: function (resultMeta) { createResultObject: function (resultMeta) {
let app = this._appSys.lookup_app(resultMeta['id']); let app = this._appSys.lookup_app(resultMeta['id']);
return new AppIcon(app); return new AppIcon(app);
@ -1085,20 +940,14 @@ const FolderView = new Lang.Class({
Util.ensureActorVisibleInScrollView(this.actor, actor); Util.ensureActorVisibleInScrollView(this.actor, actor);
}, },
// Overriden from BaseAppView
animate: function(animationDirection) {
this._grid.animatePulse(animationDirection);
},
createFolderIcon: function(size) { createFolderIcon: function(size) {
let layout = new Clutter.GridLayout(); let layout = new Clutter.TableLayout();
let icon = new St.Widget({ layout_manager: layout, let icon = new St.Widget({ layout_manager: layout,
style_class: 'app-folder-icon' }); style_class: 'app-folder-icon' });
layout.hookup_style(icon); layout.hookup_style(icon);
let subSize = Math.floor(FOLDER_SUBICON_FRACTION * size); let subSize = Math.floor(FOLDER_SUBICON_FRACTION * size);
let numItems = this._allItems.length; let numItems = this._allItems.length;
let rtl = icon.get_text_direction() == Clutter.TextDirection.RTL;
for (let i = 0; i < 4; i++) { for (let i = 0; i < 4; i++) {
let bin; let bin;
if (i < numItems) { if (i < numItems) {
@ -1107,7 +956,7 @@ const FolderView = new Lang.Class({
} else { } else {
bin = new St.Bin({ width: subSize, height: subSize }); bin = new St.Bin({ width: subSize, height: subSize });
} }
layout.attach(bin, rtl ? (i + 1) % 2 : i % 2, Math.floor(i / 2), 1, 1); layout.pack(bin, i % 2, Math.floor(i / 2));
} }
return icon; return icon;
@ -1267,7 +1116,6 @@ const FolderIcon = new Lang.Class({
addAppId(appInfo.get_id()); addAppId(appInfo.get_id());
}); });
this.actor.visible = this.view.getAllItems().length > 0;
this.view.loadGrid(); this.view.loadGrid();
this.emit('apps-changed'); this.emit('apps-changed');
}, },
@ -1397,53 +1245,18 @@ const AppFolderPopup = new Lang.Class({
function() { function() {
this.actor.destroy(); this.actor.destroy();
})); }));
this._grabHelper = new GrabHelper.GrabHelper(this.actor);
this._grabHelper.addActor(Main.layoutManager.overviewGroup);
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPress)); this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPress));
}, },
_onKeyPress: function(actor, event) { _onKeyPress: function(actor, event) {
if (global.stage.get_key_focus() != actor) if (!this._isOpen)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
// Since we need to only grab focus on one item child when the user if (event.get_key_symbol() != Clutter.KEY_Escape)
// actually press a key we don't use navigate_focus when opening return Clutter.EVENT_PROPAGATE;
// the popup.
// Instead of that, grab the focus on the AppFolderPopup actor
// and actually moves the focus to a child only when the user
// actually press a key.
// It should work with just grab_key_focus on the AppFolderPopup
// actor, but since the arrow keys are not wrapping_around the focus
// is not grabbed by a child when the widget that has the current focus
// is the same that is requesting focus, so to make it works with arrow
// keys we need to connect to the key-press-event and navigate_focus
// when that happens using TAB_FORWARD or TAB_BACKWARD instead of arrow
// keys
// Use TAB_FORWARD for down key and right key this.popdown();
// and TAB_BACKWARD for up key and left key on ltr return Clutter.EVENT_STOP;
// languages
let direction;
let isLtr = Clutter.get_default_text_direction() == Clutter.TextDirection.LTR;
switch (event.get_key_symbol()) {
case Clutter.Down:
direction = Gtk.DirectionType.TAB_FORWARD;
break;
case Clutter.Right:
direction = isLtr ? Gtk.DirectionType.TAB_FORWARD :
Gtk.DirectionType.TAB_BACKWARD;
break;
case Clutter.Up:
direction = Gtk.DirectionType.TAB_BACKWARD;
break;
case Clutter.Left:
direction = isLtr ? Gtk.DirectionType.TAB_BACKWARD :
Gtk.DirectionType.TAB_FORWARD;
break;
default:
return Clutter.EVENT_PROPAGATE;
}
return actor.navigate_focus(null, direction, false);
}, },
toggle: function() { toggle: function() {
@ -1457,27 +1270,15 @@ const AppFolderPopup = new Lang.Class({
if (this._isOpen) if (this._isOpen)
return; return;
this._isOpen = this._grabHelper.grab({ actor: this.actor,
onUngrab: Lang.bind(this, this.popdown) });
if (!this._isOpen)
return;
this.actor.show(); this.actor.show();
this._boxPointer.setArrowActor(this._source.actor); this._boxPointer.setArrowActor(this._source.actor);
// We need to hide the icons of the view until the boxpointer animation
// is completed so we can animate the icons after as we like without
// showing them while boxpointer is animating.
this._view.actor.opacity = 0;
this._boxPointer.show(BoxPointer.PopupAnimation.FADE | this._boxPointer.show(BoxPointer.PopupAnimation.FADE |
BoxPointer.PopupAnimation.SLIDE, BoxPointer.PopupAnimation.SLIDE);
Lang.bind(this,
function() {
this._view.actor.opacity = 255;
this._view.animate(IconGrid.AnimationDirection.IN);
}));
this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
this._isOpen = true;
this.emit('open-state-changed', true); this.emit('open-state-changed', true);
}, },
@ -1485,8 +1286,6 @@ const AppFolderPopup = new Lang.Class({
if (!this._isOpen) if (!this._isOpen)
return; return;
this._grabHelper.ungrab({ actor: this.actor });
this._boxPointer.hide(BoxPointer.PopupAnimation.FADE | this._boxPointer.hide(BoxPointer.PopupAnimation.FADE |
BoxPointer.PopupAnimation.SLIDE); BoxPointer.PopupAnimation.SLIDE);
this._isOpen = false; this._isOpen = false;
@ -1537,9 +1336,7 @@ const AppIcon = new Lang.Class({
this.actor.label_actor = this.icon.label; this.actor.label_actor = this.icon.label;
this.actor.connect('leave-event', Lang.bind(this, this._onLeaveEvent));
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress)); this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
this.actor.connect('touch-event', Lang.bind(this, this._onTouchEvent));
this.actor.connect('clicked', Lang.bind(this, this._onClicked)); this.actor.connect('clicked', Lang.bind(this, this._onClicked));
this.actor.connect('popup-menu', Lang.bind(this, this._onKeyboardPopupMenu)); this.actor.connect('popup-menu', Lang.bind(this, this._onKeyboardPopupMenu));
@ -1564,11 +1361,10 @@ const AppIcon = new Lang.Class({
this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._menuTimeoutId = 0; this._menuTimeoutId = 0;
this._stateChangedId = this.app.connect('notify::state', Lang.bind(this, this._stateChangedId = this.app.connect('notify::state',
function () { Lang.bind(this,
this._updateRunningStyle(); this._onStateChanged));
})); this._onStateChanged();
this._updateRunningStyle();
}, },
_onDestroy: function() { _onDestroy: function() {
@ -1589,33 +1385,23 @@ const AppIcon = new Lang.Class({
} }
}, },
_updateRunningStyle: function() { _onStateChanged: function() {
if (this.app.state != Shell.AppState.STOPPED) if (this.app.state != Shell.AppState.STOPPED)
this.actor.add_style_class_name('running'); this.actor.add_style_class_name('running');
else else
this.actor.remove_style_class_name('running'); this.actor.remove_style_class_name('running');
}, },
_setPopupTimeout: function() {
this._removeMenuTimeout();
this._menuTimeoutId = Mainloop.timeout_add(MENU_POPUP_TIMEOUT,
Lang.bind(this, function() {
this._menuTimeoutId = 0;
this.popupMenu();
return GLib.SOURCE_REMOVE;
}));
GLib.Source.set_name_by_id(this._menuTimeoutId, '[gnome-shell] this.popupMenu');
},
_onLeaveEvent: function(actor, event) {
this.actor.fake_release();
this._removeMenuTimeout();
},
_onButtonPress: function(actor, event) { _onButtonPress: function(actor, event) {
let button = event.get_button(); let button = event.get_button();
if (button == 1) { if (button == 1) {
this._setPopupTimeout(); this._removeMenuTimeout();
this._menuTimeoutId = Mainloop.timeout_add(MENU_POPUP_TIMEOUT,
Lang.bind(this, function() {
this._menuTimeoutId = 0;
this.popupMenu();
return GLib.SOURCE_REMOVE;
}));
} else if (button == 3) { } else if (button == 3) {
this.popupMenu(); this.popupMenu();
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
@ -1623,16 +1409,16 @@ const AppIcon = new Lang.Class({
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
}, },
_onTouchEvent: function (actor, event) {
if (event.type() == Clutter.EventType.TOUCH_BEGIN)
this._setPopupTimeout();
return Clutter.EVENT_PROPAGATE;
},
_onClicked: function(actor, button) { _onClicked: function(actor, button) {
this._removeMenuTimeout(); this._removeMenuTimeout();
this.activate(button);
if (button == 1) {
this._onActivate(Clutter.get_current_event());
} else if (button == 2) {
this.app.open_new_window(-1);
Main.overview.hide();
}
return false;
}, },
_onKeyboardPopupMenu: function() { _onKeyboardPopupMenu: function() {
@ -1686,29 +1472,19 @@ const AppIcon = new Lang.Class({
this.emit('menu-state-changed', false); this.emit('menu-state-changed', false);
}, },
activate: function (button) { _onActivate: function (event) {
let event = Clutter.get_current_event(); let modifiers = event.get_state();
let modifiers = event ? event.get_state() : 0;
let openNewWindow = this.app.can_open_new_window () &&
modifiers & Clutter.ModifierType.CONTROL_MASK &&
this.app.state == Shell.AppState.RUNNING ||
button && button == 2;
if (this.app.state == Shell.AppState.STOPPED || openNewWindow) if (modifiers & Clutter.ModifierType.CONTROL_MASK
this.animateLaunch(); && this.app.state == Shell.AppState.RUNNING) {
if (openNewWindow)
this.app.open_new_window(-1); this.app.open_new_window(-1);
else } else {
this.app.activate(); this.app.activate();
}
Main.overview.hide(); Main.overview.hide();
}, },
animateLaunch: function() {
this.icon.animateZoomOut();
},
shellWorkspaceLaunch : function(params) { shellWorkspaceLaunch : function(params) {
params = Params.parse(params, { workspace: -1, params = Params.parse(params, { workspace: -1,
timestamp: 0 }); timestamp: 0 });
@ -1787,17 +1563,12 @@ const AppIconMenu = new Lang.Class({
if (!this._source.app.is_window_backed()) { if (!this._source.app.is_window_backed()) {
this._appendSeparator(); this._appendSeparator();
if (this._source.app.can_open_new_window()) { this._newWindowMenuItem = this._appendMenuItem(_("New Window"));
this._newWindowMenuItem = this._appendMenuItem(_("New Window")); this._newWindowMenuItem.connect('activate', Lang.bind(this, function() {
this._newWindowMenuItem.connect('activate', Lang.bind(this, function() { this._source.app.open_new_window(-1);
if (this._source.app.state == Shell.AppState.STOPPED) this.emit('activate-window', null);
this._source.animateLaunch(); }));
this._appendSeparator();
this._source.app.open_new_window(-1);
this.emit('activate-window', null);
}));
this._appendSeparator();
}
let appInfo = this._source.app.get_app_info(); let appInfo = this._source.app.get_app_info();
let actions = appInfo.list_actions(); let actions = appInfo.list_actions();
@ -1826,26 +1597,6 @@ const AppIconMenu = new Lang.Class({
favs.addFavorite(this._source.app.get_id()); favs.addFavorite(this._source.app.get_id());
})); }));
} }
if (Shell.AppSystem.get_default().lookup_app('org.gnome.Software.desktop')) {
this._appendSeparator();
let item = this._appendMenuItem(_("Show Details"));
item.connect('activate', Lang.bind(this, function() {
let id = this._source.app.get_id();
let args = GLib.Variant.new('(ss)', [id, '']);
Gio.DBus.get(Gio.BusType.SESSION, null,
function(o, res) {
let bus = Gio.DBus.get_finish(res);
bus.call('org.gnome.Software',
'/org/gnome/Software',
'org.gtk.Actions', 'Activate',
GLib.Variant.new('(sava{sv})',
['details', [args], null]),
null, 0, -1, null, null);
Main.overview.hide();
});
}));
}
} }
}, },

View File

@ -6,36 +6,6 @@ const Signals = imports.signals;
const Main = imports.ui.main; const Main = imports.ui.main;
const RENAMED_DESKTOP_IDS = {
'baobab.desktop': 'org.gnome.baobab.desktop',
'cheese.desktop': 'org.gnome.Cheese.desktop',
'dconf-editor.desktop': 'ca.desrt.dconf-editor.desktop',
'file-roller.desktop': 'org.gnome.FileRoller.desktop',
'gcalctool.desktop': 'gnome-calculator.desktop',
'gedit.desktop': 'org.gnome.gedit.desktop',
'glchess.desktop': 'gnome-chess.desktop',
'glines.desktop': 'five-or-more.desktop',
'gnect.desktop': 'four-in-a-row.desktop',
'gnibbles.desktop': 'gnome-nibbles.desktop',
'gnobots2.desktop': 'gnome-robots.desktop',
'gnome-boxes.desktop': 'org.gnome.Boxes.desktop',
'gnome-clocks.desktop': 'org.gnome.clocks.desktop',
'gnome-contacts.desktop': 'org.gnome.Contacts.desktop',
'gnome-documents.desktop': 'org.gnome.Documents.desktop',
'gnome-font-viewer.desktop': 'org.gnome.font-viewer.desktop',
'gnome-photos.desktop': 'org.gnome.Photos.desktop',
'gnome-screenshot.desktop': 'org.gnome.Screenshot.desktop',
'gnome-software.desktop': 'org.gnome.Software.desktop',
'gnome-weather.desktop': 'org.gnome.Weather.Application.desktop',
'gnomine.desktop': 'gnome-mines.desktop',
'gnotravex.desktop': 'gnome-tetravex.desktop',
'gnotski.desktop': 'gnome-klotski.desktop',
'gtali.desktop': 'tali.desktop',
'nautilus.desktop': 'org.gnome.Nautilus.desktop',
'polari.desktop': 'org.gnome.Polari.desktop',
'totem.desktop': 'org.gnome.Totem.desktop',
};
const AppFavorites = new Lang.Class({ const AppFavorites = new Lang.Class({
Name: 'AppFavorites', Name: 'AppFavorites',
@ -54,21 +24,6 @@ const AppFavorites = new Lang.Class({
reload: function() { reload: function() {
let ids = global.settings.get_strv(this.FAVORITE_APPS_KEY); let ids = global.settings.get_strv(this.FAVORITE_APPS_KEY);
// Map old desktop file names to the current ones
let updated = false;
ids = ids.map(function (id) {
let newId = RENAMED_DESKTOP_IDS[id];
if (newId !== undefined) {
updated = true;
return newId;
}
return id;
});
// ... and write back the updated desktop file names
if (updated)
global.settings.set_strv(this.FAVORITE_APPS_KEY, ids);
let appSys = Shell.AppSystem.get_default(); let appSys = Shell.AppSystem.get_default();
let apps = ids.map(function (id) { let apps = ids.map(function (id) {
return appSys.lookup_app(id); return appSys.lookup_app(id);

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,8 @@ function addBackgroundMenu(actor, layoutManager) {
actor._backgroundManager = new PopupMenu.PopupMenuManager({ actor: actor }); actor._backgroundManager = new PopupMenu.PopupMenuManager({ actor: actor });
actor._backgroundManager.addMenu(actor._backgroundMenu); actor._backgroundManager.addMenu(actor._backgroundMenu);
function openMenu(x, y) { function openMenu() {
let [x, y] = global.get_pointer();
Main.layoutManager.setDummyCursorGeometry(x, y, 0, 0); Main.layoutManager.setDummyCursorGeometry(x, y, 0, 0);
actor._backgroundMenu.open(BoxPointer.PopupAnimation.NONE); actor._backgroundMenu.open(BoxPointer.PopupAnimation.NONE);
} }
@ -41,32 +42,22 @@ function addBackgroundMenu(actor, layoutManager) {
let clickAction = new Clutter.ClickAction(); let clickAction = new Clutter.ClickAction();
clickAction.connect('long-press', function(action, actor, state) { clickAction.connect('long-press', function(action, actor, state) {
if (state == Clutter.LongPressState.QUERY) if (state == Clutter.LongPressState.QUERY)
return ((action.get_button() == 0 || return action.get_button() == 1 && !actor._backgroundMenu.isOpen;
action.get_button() == 1) &&
!actor._backgroundMenu.isOpen);
if (state == Clutter.LongPressState.ACTIVATE) { if (state == Clutter.LongPressState.ACTIVATE) {
let [x, y] = action.get_coords(); openMenu();
openMenu(x, y);
actor._backgroundManager.ignoreRelease(); actor._backgroundManager.ignoreRelease();
} }
return true; return true;
}); });
clickAction.connect('clicked', function(action) { clickAction.connect('clicked', function(action) {
if (action.get_button() == 3) { if (action.get_button() == 3)
let [x, y] = action.get_coords(); openMenu();
openMenu(x, y);
}
}); });
actor.add_action(clickAction); actor.add_action(clickAction);
let grabOpBeginId = global.display.connect('grab-op-begin', function () {
clickAction.release();
});
actor.connect('destroy', function() { actor.connect('destroy', function() {
actor._backgroundMenu.destroy(); actor._backgroundMenu.destroy();
actor._backgroundMenu = null; actor._backgroundMenu = null;
actor._backgroundManager = null; actor._backgroundManager = null;
global.display.disconnect(grabOpBeginId);
}); });
} }

View File

@ -13,10 +13,6 @@ const Shell = imports.gi.Shell;
const MSECS_IN_DAY = 24 * 60 * 60 * 1000; const MSECS_IN_DAY = 24 * 60 * 60 * 1000;
const SHOW_WEEKDATE_KEY = 'show-weekdate'; const SHOW_WEEKDATE_KEY = 'show-weekdate';
const ELLIPSIS_CHAR = '\u2026';
// alias to prevent xgettext from picking up strings translated in GTK+
const gtk30_ = Gettext_gtk30.gettext;
// in org.gnome.desktop.interface // in org.gnome.desktop.interface
const CLOCK_FORMAT_KEY = 'clock-format'; const CLOCK_FORMAT_KEY = 'clock-format';
@ -59,21 +55,19 @@ function _getEndOfDay(date) {
return ret; return ret;
} }
function _formatEventTime(event, clockFormat, periodBegin, periodEnd) { function _formatEventTime(event, clockFormat) {
let ret; let ret;
let allDay = (event.allDay || (event.date <= periodBegin && event.end >= periodEnd)); if (event.allDay) {
if (allDay) {
/* Translators: Shown in calendar event list for all day events /* Translators: Shown in calendar event list for all day events
* Keep it short, best if you can use less then 10 characters * Keep it short, best if you can use less then 10 characters
*/ */
ret = C_("event list time", "All Day"); ret = C_("event list time", "All Day");
} else { } else {
let date = event.date >= periodBegin ? event.date : event.end;
switch (clockFormat) { switch (clockFormat) {
case '24h': case '24h':
/* Translators: Shown in calendar event list, if 24h format, /* Translators: Shown in calendar event list, if 24h format,
\u2236 is a ratio character, similar to : */ \u2236 is a ratio character, similar to : */
ret = date.toLocaleFormat(C_("event list time", "%H\u2236%M")); ret = event.date.toLocaleFormat(C_("event list time", "%H\u2236%M"));
break; break;
default: default:
@ -82,7 +76,7 @@ function _formatEventTime(event, clockFormat, periodBegin, periodEnd) {
/* Translators: Shown in calendar event list, if 12h format, /* Translators: Shown in calendar event list, if 12h format,
\u2236 is a ratio character, similar to : and \u2009 is \u2236 is a ratio character, similar to : and \u2009 is
a thin space */ a thin space */
ret = date.toLocaleFormat(C_("event list time", "%l\u2236%M\u2009%p")); ret = event.date.toLocaleFormat(C_("event list time", "%l\u2236%M\u2009%p"));
break; break;
} }
} }
@ -364,12 +358,6 @@ const DBusEventSource = new Lang.Class({
result.push(event); result.push(event);
} }
} }
result.sort(function(event1, event2) {
// sort events by end time on ending day
let d1 = event1.date < begin && event1.end <= end ? event1.end : event1.date;
let d2 = event2.date < begin && event2.end <= end ? event2.end : event2.date;
return d1.getTime() - d2.getTime();
});
return result; return result;
}, },
@ -392,14 +380,14 @@ const Calendar = new Lang.Class({
_init: function() { _init: function() {
this._weekStart = Shell.util_get_week_start(); this._weekStart = Shell.util_get_week_start();
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.calendar' }); this._settings = new Gio.Settings({ schema: 'org.gnome.shell.calendar' });
this._settings.connect('changed::' + SHOW_WEEKDATE_KEY, Lang.bind(this, this._onSettingsChange)); this._settings.connect('changed::' + SHOW_WEEKDATE_KEY, Lang.bind(this, this._onSettingsChange));
this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY); this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY);
// Find the ordering for month/year in the calendar heading // Find the ordering for month/year in the calendar heading
this._headerFormatWithoutYear = '%B'; this._headerFormatWithoutYear = '%B';
switch (gtk30_('calendar:MY')) { switch (Gettext_gtk30.gettext('calendar:MY')) {
case 'calendar:MY': case 'calendar:MY':
this._headerFormat = '%B %Y'; this._headerFormat = '%B %Y';
break; break;
@ -417,9 +405,9 @@ const Calendar = new Lang.Class({
this._shouldDateGrabFocus = false; this._shouldDateGrabFocus = false;
this.actor = new St.Widget({ style_class: 'calendar', this.actor = new St.Table({ homogeneous: false,
layout_manager: new Clutter.GridLayout(), style_class: 'calendar',
reactive: true }); reactive: true });
this.actor.connect('scroll-event', this.actor.connect('scroll-event',
Lang.bind(this, this._onScroll)); Lang.bind(this, this._onScroll));
@ -450,13 +438,13 @@ const Calendar = new Lang.Class({
}, },
_buildHeader: function() { _buildHeader: function() {
let layout = this.actor.layout_manager;
let offsetCols = this._useWeekdate ? 1 : 0; let offsetCols = this._useWeekdate ? 1 : 0;
this.actor.destroy_all_children(); this.actor.destroy_all_children();
// Top line of the calendar '<| September 2009 |>' // Top line of the calendar '<| September 2009 |>'
this._topBox = new St.BoxLayout(); this._topBox = new St.BoxLayout();
layout.attach(this._topBox, 0, 0, offsetCols + 7, 1); this.actor.add(this._topBox,
{ row: 0, col: 0, col_span: offsetCols + 7 });
this._backButton = new St.Button({ style_class: 'calendar-change-month-back', this._backButton = new St.Button({ style_class: 'calendar-change-month-back',
accessible_name: _("Previous month"), accessible_name: _("Previous month"),
@ -488,12 +476,10 @@ const Calendar = new Lang.Class({
let customDayAbbrev = _getCalendarDayAbbreviation(iter.getDay()); let customDayAbbrev = _getCalendarDayAbbreviation(iter.getDay());
let label = new St.Label({ style_class: 'calendar-day-base calendar-day-heading', let label = new St.Label({ style_class: 'calendar-day-base calendar-day-heading',
text: customDayAbbrev }); text: customDayAbbrev });
let col; this.actor.add(label,
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL) { row: 1,
col = 6 - (7 + iter.getDay() - this._weekStart) % 7; col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7,
else x_fill: false, x_align: St.Align.MIDDLE });
col = offsetCols + (7 + iter.getDay() - this._weekStart) % 7;
layout.attach(label, col, 1, 1, 1);
iter.setTime(iter.getTime() + MSECS_IN_DAY); iter.setTime(iter.getTime() + MSECS_IN_DAY);
} }
@ -612,7 +598,6 @@ const Calendar = new Lang.Class({
beginDate.setTime(beginDate.getTime() - (weekPadding + daysToWeekStart) * MSECS_IN_DAY); beginDate.setTime(beginDate.getTime() - (weekPadding + daysToWeekStart) * MSECS_IN_DAY);
let layout = this.actor.layout_manager;
let iter = new Date(beginDate); let iter = new Date(beginDate);
let row = 2; let row = 2;
// nRows here means 6 weeks + one header + one navbar // nRows here means 6 weeks + one header + one navbar
@ -660,19 +645,16 @@ const Calendar = new Lang.Class({
button.style_class = styleClass; button.style_class = styleClass;
let offsetCols = this._useWeekdate ? 1 : 0; let offsetCols = this._useWeekdate ? 1 : 0;
let col; this.actor.add(button,
if (rtl) { row: row, col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7 });
col = 6 - (7 + iter.getDay() - this._weekStart) % 7;
else
col = offsetCols + (7 + iter.getDay() - this._weekStart) % 7;
layout.attach(button, col, row, 1, 1);
this._buttons.push(button); this._buttons.push(button);
if (this._useWeekdate && iter.getDay() == 4) { if (this._useWeekdate && iter.getDay() == 4) {
let label = new St.Label({ text: _getCalendarWeekForDate(iter).toString(), let label = new St.Label({ text: _getCalendarWeekForDate(iter).toString(),
style_class: 'calendar-day-base calendar-week-number'}); style_class: 'calendar-day-base calendar-week-number'});
layout.attach(label, rtl ? 7 : 0, row, 1, 1); this.actor.add(label,
{ row: row, col: 0, y_align: St.Align.MIDDLE });
} }
iter.setTime(iter.getTime() + MSECS_IN_DAY); iter.setTime(iter.getTime() + MSECS_IN_DAY);
@ -715,12 +697,9 @@ const EventsList = new Lang.Class({
Name: 'EventsList', Name: 'EventsList',
_init: function() { _init: function() {
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL }); this.actor = new St.Table({ style_class: 'events-table' });
this.actor = new St.Widget({ style_class: 'events-table',
layout_manager: layout });
layout.hookup_style(this.actor);
this._date = new Date(); this._date = new Date();
this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' }); this._desktopSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
this._desktopSettings.connect('changed', Lang.bind(this, this._update)); this._desktopSettings.connect('changed', Lang.bind(this, this._update));
this._weekStart = Shell.util_get_week_start(); this._weekStart = Shell.util_get_week_start();
}, },
@ -730,82 +709,68 @@ const EventsList = new Lang.Class({
this._eventSource.connect('changed', Lang.bind(this, this._update)); this._eventSource.connect('changed', Lang.bind(this, this._update));
}, },
_addEvent: function(event, index, includeDayName, periodBegin, periodEnd) { _addEvent: function(event, index, includeDayName) {
let dayString; let dayString;
if (includeDayName) { if (includeDayName)
if (event.date >= periodBegin) dayString = _getEventDayAbbreviation(event.date.getDay());
dayString = _getEventDayAbbreviation(event.date.getDay()); else
else /* show event end day if it began earlier */
dayString = _getEventDayAbbreviation(event.end.getDay());
} else {
dayString = ''; dayString = '';
}
let dayLabel = new St.Label({ style_class: 'events-day-dayname', let dayLabel = new St.Label({ style_class: 'events-day-dayname',
text: dayString, text: dayString });
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.START });
dayLabel.clutter_text.line_wrap = false; dayLabel.clutter_text.line_wrap = false;
dayLabel.clutter_text.ellipsize = false; dayLabel.clutter_text.ellipsize = false;
let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL; this.actor.add(dayLabel, { row: index, col: 0,
x_expand: false, x_align: St.Align.END,
y_fill: false, y_align: St.Align.START });
let layout = this.actor.layout_manager;
layout.attach(dayLabel, rtl ? 2 : 0, index, 1, 1);
let clockFormat = this._desktopSettings.get_string(CLOCK_FORMAT_KEY); let clockFormat = this._desktopSettings.get_string(CLOCK_FORMAT_KEY);
let timeString = _formatEventTime(event, clockFormat, periodBegin, periodEnd); let timeString = _formatEventTime(event, clockFormat);
let timeLabel = new St.Label({ style_class: 'events-day-time', let timeLabel = new St.Label({ style_class: 'events-day-time',
text: timeString, text: timeString });
y_align: Clutter.ActorAlign.START });
timeLabel.clutter_text.line_wrap = false; timeLabel.clutter_text.line_wrap = false;
timeLabel.clutter_text.ellipsize = false; timeLabel.clutter_text.ellipsize = false;
let preEllipsisLabel = new St.Label({ style_class: 'events-day-time-ellipses', this.actor.add(timeLabel, { row: index, col: 1,
text: ELLIPSIS_CHAR, x_expand: false, x_align: St.Align.MIDDLE,
y_align: Clutter.ActorAlign.START }); y_fill: false, y_align: St.Align.START });
let postEllipsisLabel = new St.Label({ style_class: 'events-day-time-ellipses',
text: ELLIPSIS_CHAR,
y_align: Clutter.ActorAlign.START });
if (event.allDay || event.date >= periodBegin)
preEllipsisLabel.opacity = 0;
if (event.allDay || event.end <= periodEnd)
postEllipsisLabel.opacity = 0;
let timeLabelBoxLayout = new St.BoxLayout();
timeLabelBoxLayout.add(preEllipsisLabel);
timeLabelBoxLayout.add(timeLabel);
timeLabelBoxLayout.add(postEllipsisLabel);
layout.attach(timeLabelBoxLayout, 1, index, 1, 1);
let titleLabel = new St.Label({ style_class: 'events-day-task', let titleLabel = new St.Label({ style_class: 'events-day-task',
text: event.summary, text: event.summary });
x_expand: true });
titleLabel.clutter_text.line_wrap = true; titleLabel.clutter_text.line_wrap = true;
titleLabel.clutter_text.ellipsize = false; titleLabel.clutter_text.ellipsize = false;
layout.attach(titleLabel, rtl ? 0 : 2, index, 1, 1); this.actor.add(titleLabel, { row: index, col: 2,
x_expand: true, x_align: St.Align.START,
y_fill: false, y_align: St.Align.START });
}, },
_addPeriod: function(header, index, periodBegin, periodEnd, includeDayName, showNothingScheduled) { _addPeriod: function(header, index, begin, end, includeDayName, showNothingScheduled) {
let events = this._eventSource.getEvents(periodBegin, periodEnd); let events = this._eventSource.getEvents(begin, end);
if (events.length == 0 && !showNothingScheduled) if (events.length == 0 && !showNothingScheduled)
return index; return index;
let label = new St.Label({ style_class: 'events-day-header', text: header }); this.actor.add(new St.Label({ style_class: 'events-day-header', text: header }),
let layout = this.actor.layout_manager; { row: index, col: 0, col_span: 3,
layout.attach(label, 0, index, 3, 1); // In theory, x_expand should be true here, but x_expand
// is a property of the column for StTable, ie all day cells
// get it too
x_expand: false, x_align: St.Align.START,
y_fill: false, y_align: St.Align.START });
index++; index++;
for (let n = 0; n < events.length; n++) { for (let n = 0; n < events.length; n++) {
this._addEvent(events[n], index, includeDayName, periodBegin, periodEnd); this._addEvent(events[n], index, includeDayName);
index++; index++;
} }
if (events.length == 0 && showNothingScheduled) { if (events.length == 0 && showNothingScheduled) {
let now = new Date();
/* Translators: Text to show if there are no events */ /* Translators: Text to show if there are no events */
let nothingEvent = new CalendarEvent(periodBegin, periodBegin, _("Nothing Scheduled"), true); let nothingEvent = new CalendarEvent(now, now, _("Nothing Scheduled"), true);
this._addEvent(nothingEvent, index, false, periodBegin, periodEnd); this._addEvent(nothingEvent, index, false);
index++; index++;
} }

View File

@ -23,7 +23,7 @@ const AutomountManager = new Lang.Class({
Name: 'AutomountManager', Name: 'AutomountManager',
_init: function() { _init: function() {
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA }); this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
this._volumeQueue = []; this._volumeQueue = [];
this._session = new GnomeSession.SessionManager(); this._session = new GnomeSession.SessionManager();
this._session.connectSignal('InhibitorAdded', this._session.connectSignal('InhibitorAdded',
@ -43,7 +43,6 @@ const AutomountManager = new Lang.Class({
this._driveEjectButtonId = this._volumeMonitor.connect('drive-eject-button', Lang.bind(this, this._onDriveEjectButton)); this._driveEjectButtonId = this._volumeMonitor.connect('drive-eject-button', Lang.bind(this, this._onDriveEjectButton));
this._mountAllId = Mainloop.idle_add(Lang.bind(this, this._startupMountAll)); this._mountAllId = Mainloop.idle_add(Lang.bind(this, this._startupMountAll));
GLib.Source.set_name_by_id(this._mountAllId, '[gnome-shell] this._startupMountAll');
}, },
disable: function() { disable: function() {
@ -235,11 +234,10 @@ const AutomountManager = new Lang.Class({
}, },
_allowAutorunExpire: function(volume) { _allowAutorunExpire: function(volume) {
let id = Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, function() { Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, function() {
volume.allowAutorun = false; volume.allowAutorun = false;
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
GLib.Source.set_name_by_id(id, '[gnome-shell] volume.allowAutorun');
} }
}); });
const Component = AutomountManager; const Component = AutomountManager;

View File

@ -96,7 +96,7 @@ const ContentTypeDiscoverer = new Lang.Class({
_init: function(callback) { _init: function(callback) {
this._callback = callback; this._callback = callback;
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA }); this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
}, },
guessContentTypes: function(mount) { guessContentTypes: function(mount) {
@ -441,7 +441,7 @@ const AutorunTransientDispatcher = new Lang.Class({
_init: function(manager) { _init: function(manager) {
this._manager = manager; this._manager = manager;
this._sources = []; this._sources = [];
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA }); this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
}, },
_getAutorunSettingForType: function(contentType) { _getAutorunSettingForType: function(contentType) {

View File

@ -80,58 +80,44 @@ const KeyringDialog = new Lang.Class({
}, },
_buildControlTable: function() { _buildControlTable: function() {
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL }); let layout = new Clutter.TableLayout();
let table = new St.Widget({ style_class: 'keyring-dialog-control-table', let table = new St.Widget({ style_class: 'keyring-dialog-control-table',
layout_manager: layout }); layout_manager: layout });
layout.hookup_style(table); layout.hookup_style(table);
let rtl = table.get_text_direction() == Clutter.TextDirection.RTL;
let row = 0; let row = 0;
if (this.prompt.password_visible) { if (this.prompt.password_visible) {
let label = new St.Label({ style_class: 'prompt-dialog-password-label', let label = new St.Label({ style_class: 'prompt-dialog-password-label' });
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.CENTER });
label.set_text(_("Password:")); label.set_text(_("Password:"));
label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
layout.pack(label, 0, row);
layout.child_set(label, { x_expand: false, y_fill: false,
x_align: Clutter.TableAlignment.START });
this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry', this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: '', text: '',
can_focus: true, can_focus: true });
x_expand: true });
this._passwordEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE this._passwordEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true }); ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
this._passwordEntry.clutter_text.connect('activate', Lang.bind(this, this._onPasswordActivate)); this._passwordEntry.clutter_text.connect('activate', Lang.bind(this, this._onPasswordActivate));
layout.pack(this._passwordEntry, 1, row);
if (rtl) {
layout.attach(this._passwordEntry, 0, row, 1, 1);
layout.attach(label, 1, row, 1, 1);
} else {
layout.attach(label, 0, row, 1, 1);
layout.attach(this._passwordEntry, 1, row, 1, 1);
}
row++; row++;
} else { } else {
this._passwordEntry = null; this._passwordEntry = null;
} }
if (this.prompt.confirm_visible) { if (this.prompt.confirm_visible) {
var label = new St.Label(({ style_class: 'prompt-dialog-password-label', var label = new St.Label(({ style_class: 'prompt-dialog-password-label' }));
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.CENTER }));
label.set_text(_("Type again:")); label.set_text(_("Type again:"));
layout.pack(label, 0, row);
layout.child_set(label, { x_expand: false, y_fill: false,
x_align: Clutter.TableAlignment.START });
this._confirmEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry', this._confirmEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: '', text: '',
can_focus: true, can_focus: true });
x_expand: true });
this._confirmEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE this._confirmEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
ShellEntry.addContextMenu(this._confirmEntry, { isPassword: true }); ShellEntry.addContextMenu(this._confirmEntry, { isPassword: true });
this._confirmEntry.clutter_text.connect('activate', Lang.bind(this, this._onConfirmActivate)); this._confirmEntry.clutter_text.connect('activate', Lang.bind(this, this._onConfirmActivate));
if (rtl) { layout.pack(this._confirmEntry, 1, row);
layout.attach(this._confirmEntry, 0, row, 1, 1);
layout.attach(label, 1, row, 1, 1);
} else {
layout.attach(label, 0, row, 1, 1);
layout.attach(this._confirmEntry, 1, row, 1, 1);
}
row++; row++;
} else { } else {
this._confirmEntry = null; this._confirmEntry = null;
@ -144,15 +130,15 @@ const KeyringDialog = new Lang.Class({
let choice = new CheckBox.CheckBox(); let choice = new CheckBox.CheckBox();
this.prompt.bind_property('choice-label', choice.getLabelActor(), 'text', GObject.BindingFlags.SYNC_CREATE); this.prompt.bind_property('choice-label', choice.getLabelActor(), 'text', GObject.BindingFlags.SYNC_CREATE);
this.prompt.bind_property('choice-chosen', choice.actor, 'checked', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL); this.prompt.bind_property('choice-chosen', choice.actor, 'checked', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL);
layout.attach(choice.actor, rtl ? 0 : 1, row, 1, 1); layout.pack(choice.actor, 1, row);
row++; row++;
} }
let warning = new St.Label({ style_class: 'prompt-dialog-error-label', let warning = new St.Label({ style_class: 'prompt-dialog-error-label' });
x_align: Clutter.ActorAlign.START });
warning.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; warning.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
warning.clutter_text.line_wrap = true; warning.clutter_text.line_wrap = true;
layout.attach(warning, rtl ? 0 : 1, row, 1, 1); layout.pack(warning, 1, row);
layout.child_set(warning, { x_fill: false, x_align: Clutter.TableAlignment.START });
this.prompt.bind_property('warning-visible', warning, 'visible', GObject.BindingFlags.SYNC_CREATE); this.prompt.bind_property('warning-visible', warning, 'visible', GObject.BindingFlags.SYNC_CREATE);
this.prompt.bind_property('warning', warning, 'text', GObject.BindingFlags.SYNC_CREATE); this.prompt.bind_property('warning', warning, 'text', GObject.BindingFlags.SYNC_CREATE);

View File

@ -72,28 +72,24 @@ const NetworkSecretDialog = new Lang.Class({
expand: true }); expand: true });
} }
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL }); let layout = new Clutter.TableLayout();
let secretTable = new St.Widget({ style_class: 'network-dialog-secret-table', let secretTable = new St.Widget({ style_class: 'network-dialog-secret-table',
layout_manager: layout }); layout_manager: layout });
layout.hookup_style(secretTable); layout.hookup_style(secretTable);
let rtl = secretTable.get_text_direction() == Clutter.TextDirection.RTL;
let initialFocusSet = false; let initialFocusSet = false;
let pos = 0; let pos = 0;
for (let i = 0; i < this._content.secrets.length; i++) { for (let i = 0; i < this._content.secrets.length; i++) {
let secret = this._content.secrets[i]; let secret = this._content.secrets[i];
let label = new St.Label({ style_class: 'prompt-dialog-password-label', let label = new St.Label({ style_class: 'prompt-dialog-password-label',
text: secret.label, text: secret.label });
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.CENTER });
label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
let reactive = secret.key != null; let reactive = secret.key != null;
secret.entry = new St.Entry({ style_class: 'prompt-dialog-password-entry', secret.entry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: secret.value, can_focus: reactive, text: secret.value, can_focus: reactive,
reactive: reactive, reactive: reactive });
x_expand: true });
ShellEntry.addContextMenu(secret.entry, ShellEntry.addContextMenu(secret.entry,
{ isPassword: secret.password }); { isPassword: secret.password });
@ -120,13 +116,10 @@ const NetworkSecretDialog = new Lang.Class({
} else } else
secret.valid = true; secret.valid = true;
if (rtl) { layout.pack(label, 0, pos);
layout.attach(secret.entry, 0, pos, 1, 1); layout.child_set(label, { x_expand: false, y_fill: false,
layout.attach(label, 1, pos, 1, 1); x_align: Clutter.TableAlignment.START });
} else { layout.pack(secret.entry, 1, pos);
layout.attach(label, 0, pos, 1, 1);
layout.attach(secret.entry, 1, pos, 1, 1);
}
pos++; pos++;
if (secret.password) if (secret.password)
@ -380,12 +373,6 @@ const VPNRequestHandler = new Lang.Class({
argv.push('-i'); argv.push('-i');
if (flags & NMClient.SecretAgentGetSecretsFlags.REQUEST_NEW) if (flags & NMClient.SecretAgentGetSecretsFlags.REQUEST_NEW)
argv.push('-r'); argv.push('-r');
if (authHelper.supportsHints) {
for (let i = 0; i < hints.length; i++) {
argv.push('-t');
argv.push(hints[i]);
}
}
this._newStylePlugin = authHelper.externalUIMode; this._newStylePlugin = authHelper.externalUIMode;
@ -604,15 +591,7 @@ const NetworkAgent = new Lang.Class({
Name: 'NetworkAgent', Name: 'NetworkAgent',
_init: function() { _init: function() {
try { this._native = new Shell.NetworkAgent({ identifier: 'org.gnome.Shell.NetworkAgent' });
this._native = new Shell.NetworkAgent({ identifier: 'org.gnome.Shell.NetworkAgent',
capabilities: NMClient.SecretAgentCapabilities.VPN_HINTS
});
} catch(e) {
// Support older versions without NetworkAgent:capabilities
this._native = new Shell.NetworkAgent({ identifier: 'org.gnome.Shell.NetworkAgent'
});
}
this._dialogs = { }; this._dialogs = { };
this._vpnRequests = { }; this._vpnRequests = { };
@ -712,23 +691,16 @@ const NetworkAgent = new Lang.Class({
let service = keyfile.get_string('VPN Connection', 'service'); let service = keyfile.get_string('VPN Connection', 'service');
let binary = keyfile.get_string('GNOME', 'auth-dialog'); let binary = keyfile.get_string('GNOME', 'auth-dialog');
let externalUIMode = false; let externalUIMode = false;
let hints = false;
try { try {
externalUIMode = keyfile.get_boolean('GNOME', 'supports-external-ui-mode'); externalUIMode = keyfile.get_boolean('GNOME', 'supports-external-ui-mode');
} catch(e) { } // ignore errors if key does not exist } catch(e) { } // ignore errors if key does not exist
try {
hints = keyfile.get_boolean('GNOME', 'supports-hints');
} catch(e) { } // ignore errors if key does not exist
let path = binary; let path = binary;
if (!GLib.path_is_absolute(path)) { if (!GLib.path_is_absolute(path)) {
path = GLib.build_filenamev([Config.LIBEXECDIR, path]); path = GLib.build_filenamev([Config.LIBEXECDIR, path]);
} }
if (GLib.file_test(path, GLib.FileTest.IS_EXECUTABLE)) if (GLib.file_test(path, GLib.FileTest.IS_EXECUTABLE))
this._vpnBinaries[service] = { fileName: path, externalUIMode: externalUIMode, supportsHints: hints }; this._vpnBinaries[service] = { fileName: path, externalUIMode: externalUIMode };
else else
throw new Error('VPN plugin at %s is not executable'.format(path)); throw new Error('VPN plugin at %s is not executable'.format(path));
} catch(e) { } catch(e) {

View File

@ -681,7 +681,6 @@ const ChatSource = new Lang.Class({
Mainloop.source_remove(this._notifyTimeoutId); Mainloop.source_remove(this._notifyTimeoutId);
this._notifyTimeoutId = Mainloop.timeout_add(500, this._notifyTimeoutId = Mainloop.timeout_add(500,
Lang.bind(this, this._notifyTimeout)); Lang.bind(this, this._notifyTimeout));
GLib.Source.set_name_by_id(this._notifyTimeoutId, '[gnome-shell] this._notifyTimeout');
}, },
_notifyTimeout: function() { _notifyTimeout: function() {
@ -783,6 +782,7 @@ const ChatNotification = new Lang.Class({
this._createScrollArea(); this._createScrollArea();
this._lastGroup = null; this._lastGroup = null;
this._lastGroupActor = null;
// Keep track of the bottom position for the current adjustment and // Keep track of the bottom position for the current adjustment and
// force a scroll to the bottom if things change while we were at the // force a scroll to the bottom if things change while we were at the
@ -863,6 +863,13 @@ const ChatNotification = new Lang.Class({
for (let i = 0; i < expired.length; i++) for (let i = 0; i < expired.length; i++)
expired[i].actor.destroy(); expired[i].actor.destroy();
} }
let groups = this._contentArea.get_children();
for (let i = 0; i < groups.length; i++) {
let group = groups[i];
if (group.get_n_children() == 0)
group.destroy();
}
}, },
/** /**
@ -904,32 +911,27 @@ const ChatNotification = new Lang.Class({
this._lastGroup = group; this._lastGroup = group;
let emptyLine = new St.Label({ style_class: 'chat-empty-line' }); let emptyLine = new St.Label({ style_class: 'chat-empty-line' });
this.addActor(emptyLine); this.addActor(emptyLine);
this._history.unshift({ actor: emptyLine, time: timestamp,
realMessage: false });
} }
let lineBox = new St.BoxLayout({ vertical: false }); this._lastMessageBox = new St.BoxLayout({ vertical: false });
lineBox.add(body, props.childProps); this._lastMessageBox.add(body, props.childProps);
this.addActor(lineBox); this.addActor(this._lastMessageBox);
this._lastMessageBox = lineBox;
this.updated(); this.updated();
let timestamp = props.timestamp; let timestamp = props.timestamp;
this._history.unshift({ actor: lineBox, time: timestamp, this._history.unshift({ actor: body, time: timestamp,
realMessage: group != 'meta' }); realMessage: group != 'meta' });
if (!props.noTimestamp) { if (!props.noTimestamp) {
if (timestamp < currentTime - SCROLLBACK_IMMEDIATE_TIME) { if (timestamp < currentTime - SCROLLBACK_IMMEDIATE_TIME)
this.appendTimestamp(); this.appendTimestamp();
} else { else
// Schedule a new timestamp in SCROLLBACK_IMMEDIATE_TIME // Schedule a new timestamp in SCROLLBACK_IMMEDIATE_TIME
// from the timestamp of the message. // from the timestamp of the message.
this._timestampTimeoutId = Mainloop.timeout_add_seconds( this._timestampTimeoutId = Mainloop.timeout_add_seconds(
SCROLLBACK_IMMEDIATE_TIME - (currentTime - timestamp), SCROLLBACK_IMMEDIATE_TIME - (currentTime - timestamp),
Lang.bind(this, this.appendTimestamp)); Lang.bind(this, this.appendTimestamp));
GLib.Source.set_name_by_id(this._timestampTimeoutId, '[gnome-shell] this.appendTimestamp');
}
} }
this._filterMessages(); this._filterMessages();
@ -942,76 +944,80 @@ const ChatNotification = new Lang.Class({
let format; let format;
let desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' }); let desktopSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
let clockFormat = desktopSettings.get_string(CLOCK_FORMAT_KEY); let clockFormat = desktopSettings.get_string(CLOCK_FORMAT_KEY);
let hasAmPm = date.toLocaleFormat('%p') != '';
if (clockFormat == '24h' || !hasAmPm) { switch (clockFormat) {
// Show only the time if date is on today case '24h':
if(daysAgo < 1){ // Show only the time if date is on today
/* Translators: Time in 24h format */ if(daysAgo < 1){
format = _("%H\u2236%M"); /* Translators: Time in 24h format */
} format = _("%H\u2236%M");
// Show the word "Yesterday" and time if date is on yesterday }
else if(daysAgo <2){ // Show the word "Yesterday" and time if date is on yesterday
/* Translators: this is the word "Yesterday" followed by a else if(daysAgo <2){
time string in 24h format. i.e. "Yesterday, 14:30" */ /* Translators: this is the word "Yesterday" followed by a
// xgettext:no-c-format time string in 24h format. i.e. "Yesterday, 14:30" */
format = _("Yesterday, %H\u2236%M"); // xgettext:no-c-format
} format = _("Yesterday, %H\u2236%M");
// Show a week day and time if date is in the last week }
else if (daysAgo < 7) { // Show a week day and time if date is in the last week
/* Translators: this is the week day name followed by a time else if (daysAgo < 7) {
string in 24h format. i.e. "Monday, 14:30" */ /* Translators: this is the week day name followed by a time
// xgettext:no-c-format string in 24h format. i.e. "Monday, 14:30" */
format = _("%A, %H\u2236%M"); // xgettext:no-c-format
format = _("%A, %H\u2236%M");
} else if (date.getYear() == now.getYear()) { } else if (date.getYear() == now.getYear()) {
/* Translators: this is the month name and day number /* Translators: this is the month name and day number
followed by a time string in 24h format. followed by a time string in 24h format.
i.e. "May 25, 14:30" */ i.e. "May 25, 14:30" */
// xgettext:no-c-format // xgettext:no-c-format
format = _("%B %d, %H\u2236%M"); format = _("%B %d, %H\u2236%M");
} else { } else {
/* Translators: this is the month name, day number, year /* Translators: this is the month name, day number, year
number followed by a time string in 24h format. number followed by a time string in 24h format.
i.e. "May 25 2012, 14:30" */ i.e. "May 25 2012, 14:30" */
// xgettext:no-c-format // xgettext:no-c-format
format = _("%B %d %Y, %H\u2236%M"); format = _("%B %d %Y, %H\u2236%M");
} }
} else { break;
// Show only the time if date is on today default:
if(daysAgo < 1){ /* explicit fall-through */
/* Translators: Time in 24h format */ case '12h':
format = _("%l\u2236%M %p"); // Show only the time if date is on today
} if(daysAgo < 1){
// Show the word "Yesterday" and time if date is on yesterday /* Translators: Time in 24h format */
else if(daysAgo <2){ format = _("%l\u2236%M %p");
/* Translators: this is the word "Yesterday" followed by a }
time string in 12h format. i.e. "Yesterday, 2:30 pm" */ // Show the word "Yesterday" and time if date is on yesterday
// xgettext:no-c-format else if(daysAgo <2){
format = _("Yesterday, %l\u2236%M %p"); /* Translators: this is the word "Yesterday" followed by a
} time string in 12h format. i.e. "Yesterday, 2:30 pm" */
// Show a week day and time if date is in the last week // xgettext:no-c-format
else if (daysAgo < 7) { format = _("Yesterday, %l\u2236%M %p");
/* Translators: this is the week day name followed by a time }
string in 12h format. i.e. "Monday, 2:30 pm" */ // Show a week day and time if date is in the last week
// xgettext:no-c-format else if (daysAgo < 7) {
format = _("%A, %l\u2236%M %p"); /* Translators: this is the week day name followed by a time
string in 12h format. i.e. "Monday, 2:30 pm" */
// xgettext:no-c-format
format = _("%A, %l\u2236%M %p");
} else if (date.getYear() == now.getYear()) { } else if (date.getYear() == now.getYear()) {
/* Translators: this is the month name and day number /* Translators: this is the month name and day number
followed by a time string in 12h format. followed by a time string in 12h format.
i.e. "May 25, 2:30 pm" */ i.e. "May 25, 2:30 pm" */
// xgettext:no-c-format // xgettext:no-c-format
format = _("%B %d, %l\u2236%M %p"); format = _("%B %d, %l\u2236%M %p");
} else { } else {
/* Translators: this is the month name, day number, year /* Translators: this is the month name, day number, year
number followed by a time string in 12h format. number followed by a time string in 12h format.
i.e. "May 25 2012, 2:30 pm"*/ i.e. "May 25 2012, 2:30 pm"*/
// xgettext:no-c-format // xgettext:no-c-format
format = _("%B %d %Y, %l\u2236%M %p"); format = _("%B %d %Y, %l\u2236%M %p");
} }
break;
} }
return date.toLocaleFormat(format); return date.toLocaleFormat(format);
}, },
@ -1094,7 +1100,6 @@ const ChatNotification = new Lang.Class({
this._composingTimeoutId = Mainloop.timeout_add_seconds( this._composingTimeoutId = Mainloop.timeout_add_seconds(
COMPOSING_STOP_TIMEOUT, COMPOSING_STOP_TIMEOUT,
Lang.bind(this, this._composingStopTimeout)); Lang.bind(this, this._composingStopTimeout));
GLib.Source.set_name_by_id(this._composingTimeoutId, '[gnome-shell] this._composingStopTimeout');
} else { } else {
this.source.setChatState(Tp.ChannelChatState.ACTIVE); this.source.setChatState(Tp.ChannelChatState.ACTIVE);
} }

View File

@ -87,7 +87,7 @@ const CtrlAltTabManager = new Lang.Class({
if (Main.sessionMode.hasWindows && !Main.overview.visible) { if (Main.sessionMode.hasWindows && !Main.overview.visible) {
let screen = global.screen; let screen = global.screen;
let display = screen.get_display(); let display = screen.get_display();
let windows = display.get_tab_list(Meta.TabList.DOCKS, screen.get_active_workspace ()); let windows = display.get_tab_list(Meta.TabList.DOCKS, screen, screen.get_active_workspace ());
let windowTracker = Shell.WindowTracker.get_default(); let windowTracker = Shell.WindowTracker.get_default();
let textureCache = St.TextureCache.get_default(); let textureCache = St.TextureCache.get_default();
for (let i = 0; i < windows.length; i++) { for (let i = 0; i < windows.length; i++) {
@ -140,25 +140,31 @@ const CtrlAltTabPopup = new Lang.Class({
Name: 'CtrlAltTabPopup', Name: 'CtrlAltTabPopup',
Extends: SwitcherPopup.SwitcherPopup, Extends: SwitcherPopup.SwitcherPopup,
_init: function(items) { _createSwitcher: function() {
this.parent(items);
this._switcherList = new CtrlAltTabSwitcher(this._items); this._switcherList = new CtrlAltTabSwitcher(this._items);
return true;
}, },
_keyPressHandler: function(keysym, action) { _initialSelection: function(backward, binding) {
if (binding == 'switch-panels') {
if (backward)
this._selectedIndex = this._items.length - 1;
} else if (binding == 'switch-panels-backward') {
if (!backward)
this._selectedIndex = this._items.length - 1;
}
this._select(this._selectedIndex);
},
_keyPressHandler: function(keysym, backwards, action) {
if (action == Meta.KeyBindingAction.SWITCH_PANELS) if (action == Meta.KeyBindingAction.SWITCH_PANELS)
this._select(this._next()); this._select(backwards ? this._previous() : this._next());
else if (action == Meta.KeyBindingAction.SWITCH_PANELS_BACKWARD) else if (action == Meta.KeyBindingAction.SWITCH_PANELS_BACKWARD)
this._select(this._previous()); this._select(backwards ? this._next() : this._previous());
else if (keysym == Clutter.Left) else if (keysym == Clutter.Left)
this._select(this._previous()); this._select(this._previous());
else if (keysym == Clutter.Right) else if (keysym == Clutter.Right)
this._select(this._next()); this._select(this._next());
else
return Clutter.EVENT_PROPAGATE;
return Clutter.EVENT_STOP;
}, },
_finish : function(time) { _finish : function(time) {

View File

@ -582,7 +582,6 @@ const Dash = new Lang.Class({
this._showLabelTimeoutId = 0; this._showLabelTimeoutId = 0;
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(this._showLabelTimeoutId, '[gnome-shell] item.showLabel');
if (this._resetHoverTimeoutId > 0) { if (this._resetHoverTimeoutId > 0) {
Mainloop.source_remove(this._resetHoverTimeoutId); Mainloop.source_remove(this._resetHoverTimeoutId);
this._resetHoverTimeoutId = 0; this._resetHoverTimeoutId = 0;
@ -600,7 +599,6 @@ const Dash = new Lang.Class({
this._resetHoverTimeoutId = 0; this._resetHoverTimeoutId = 0;
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(this._resetHoverTimeoutId, '[gnome-shell] this._labelShowing');
} }
} }
}, },

View File

@ -3,7 +3,6 @@
const GLib = imports.gi.GLib; const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const GnomeDesktop = imports.gi.GnomeDesktop; const GnomeDesktop = imports.gi.GnomeDesktop;
const GObject = imports.gi.GObject;
const Lang = imports.lang; const Lang = imports.lang;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
const Cairo = imports.cairo; const Cairo = imports.cairo;
@ -19,7 +18,8 @@ const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
const Calendar = imports.ui.calendar; const Calendar = imports.ui.calendar;
function _onVertSepRepaint(area) { function _onVertSepRepaint (area)
{
let cr = area.get_context(); let cr = area.get_context();
let themeNode = area.get_theme_node(); let themeNode = area.get_theme_node();
let [width, height] = area.get_surface_size(); let [width, height] = area.get_surface_size();
@ -33,7 +33,7 @@ function _onVertSepRepaint(area) {
cr.setLineWidth(stippleWidth); cr.setLineWidth(stippleWidth);
cr.stroke(); cr.stroke();
cr.$dispose(); cr.$dispose();
} };
const DateMenuButton = new Lang.Class({ const DateMenuButton = new Lang.Class({
Name: 'DateMenuButton', Name: 'DateMenuButton',
@ -63,11 +63,8 @@ const DateMenuButton = new Lang.Class({
hbox.add(vbox); hbox.add(vbox);
// Date // Date
// Having the ability to go to the current date if the user is already
// on the current date can be confusing. So don't make the button reactive
// until the selected date changes.
this._date = new St.Button({ style_class: 'datemenu-date-label', this._date = new St.Button({ style_class: 'datemenu-date-label',
reactive: false can_focus: true,
}); });
this._date.connect('clicked', this._date.connect('clicked',
Lang.bind(this, function() { Lang.bind(this, function() {
@ -85,9 +82,6 @@ const DateMenuButton = new Lang.Class({
// and the calender makes those dates unclickable when instantiated with // and the calender makes those dates unclickable when instantiated with
// a null event source // a null event source
this._eventList.setDate(date); this._eventList.setDate(date);
// Make the button reactive only if the selected date is not the current date.
this._date.can_focus = this._date.reactive = !this._isToday(date)
})); }));
vbox.add(this._calendar.actor); vbox.add(this._calendar.actor);
@ -125,31 +119,19 @@ const DateMenuButton = new Lang.Class({
if (isOpen) { if (isOpen) {
let now = new Date(); let now = new Date();
this._calendar.setDate(now); this._calendar.setDate(now);
/* Translators: This is the date format to use when the calendar popup is
* shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
*/
let dateFormat = _("%A %B %e, %Y");
this._date.set_label(now.toLocaleFormat(dateFormat));
} }
})); }));
// Done with hbox for calendar and event list // Done with hbox for calendar and event list
this._clock = new GnomeDesktop.WallClock(); this._clock = new GnomeDesktop.WallClock();
this._clock.bind_property('clock', this._clockDisplay, 'text', GObject.BindingFlags.SYNC_CREATE); this._clock.connect('notify::clock', Lang.bind(this, this._updateClockAndDate));
this._updateClockAndDate();
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated)); Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
this._sessionUpdated(); this._sessionUpdated();
}, },
_isToday: function(date) {
let now = new Date();
return now.getYear() == date.getYear() &&
now.getMonth() == date.getMonth() &&
now.getDate() == date.getDate();
},
_appInstalledChanged: function() { _appInstalledChanged: function() {
this._calendarApp = undefined; this._calendarApp = undefined;
this._updateEventsVisibility(); this._updateEventsVisibility();
@ -202,18 +184,25 @@ const DateMenuButton = new Lang.Class({
this._dateAndTimeSeparator.actor.visible = Main.sessionMode.allowSettings; this._dateAndTimeSeparator.actor.visible = Main.sessionMode.allowSettings;
}, },
_updateClockAndDate: function() {
this._clockDisplay.set_text(this._clock.clock);
/* Translators: This is the date format to use when the calendar popup is
* shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
*/
let dateFormat = _("%A %B %e, %Y");
let displayDate = new Date();
this._date.set_label(displayDate.toLocaleFormat(dateFormat));
},
_getCalendarApp: function() { _getCalendarApp: function() {
if (this._calendarApp !== undefined) if (this._calendarApp !== undefined)
return this._calendarApp; return this._calendarApp;
let apps = Gio.AppInfo.get_recommended_for_type('text/calendar'); let apps = Gio.AppInfo.get_recommended_for_type('text/calendar');
if (apps && (apps.length > 0)) { if (apps && (apps.length > 0))
let app = Gio.AppInfo.get_default_for_type('text/calendar', false); this._calendarApp = apps[0];
let defaultInRecommended = apps.some(function(a) { return a.equal(app); }); else
this._calendarApp = defaultInRecommended ? app : apps[0];
} else {
this._calendarApp = null; this._calendarApp = null;
}
return this._calendarApp; return this._calendarApp;
}, },

View File

@ -395,7 +395,6 @@ const _Draggable = new Lang.Class({
this._updateHoverId = GLib.idle_add(GLib.PRIORITY_DEFAULT, this._updateHoverId = GLib.idle_add(GLib.PRIORITY_DEFAULT,
Lang.bind(this, this._updateDragHover)); Lang.bind(this, this._updateDragHover));
GLib.Source.set_name_by_id(this._updateHoverId, '[gnome-shell] this._updateDragHover');
}, },
_updateDragPosition : function (event) { _updateDragPosition : function (event) {

View File

@ -1,78 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Signals = imports.signals;
const Meta = imports.gi.Meta;
const Clutter = imports.gi.Clutter;
const St = imports.gi.St;
const EDGE_THRESHOLD = 20;
const DRAG_DISTANCE = 80;
const EdgeDragAction = new Lang.Class({
Name: 'EdgeDragAction',
Extends: Clutter.GestureAction,
_init : function(side) {
this.parent();
this._side = side;
this.set_n_touch_points(1);
global.display.connect('grab-op-begin', Lang.bind(this, function() {
this.cancel();
}));
},
_getMonitorRect : function (x, y) {
let rect = new Meta.Rectangle({ x: x - 1, y: y - 1, width: 1, height: 1 });
let monitorIndex = global.screen.get_monitor_index_for_rect(rect);
return global.screen.get_monitor_geometry(monitorIndex);
},
vfunc_gesture_prepare : function(action, actor) {
if (this.get_n_current_points() == 0)
return false;
let [x, y] = this.get_press_coords(0);
let monitorRect = this._getMonitorRect(x, y);
return ((this._side == St.Side.LEFT && x < monitorRect.x + EDGE_THRESHOLD) ||
(this._side == St.Side.RIGHT && x > monitorRect.x + monitorRect.width - EDGE_THRESHOLD) ||
(this._side == St.Side.TOP && y < monitorRect.y + EDGE_THRESHOLD) ||
(this._side == St.Side.BOTTOM && y > monitorRect.y + monitorRect.height - EDGE_THRESHOLD));
},
vfunc_gesture_progress : function (action, actor) {
let [startX, startY] = this.get_press_coords(0);
let [x, y] = this.get_motion_coords(0);
let offsetX = Math.abs (x - startX);
let offsetY = Math.abs (y - startY);
if (offsetX < EDGE_THRESHOLD && offsetY < EDGE_THRESHOLD)
return true;
if ((offsetX > offsetY &&
(this._side == St.Side.TOP || this._side == St.Side.BOTTOM)) ||
(offsetY > offsetX &&
(this._side == St.Side.LEFT || this._side == St.Side.RIGHT))) {
this.cancel();
return false;
}
return true;
},
vfunc_gesture_end : function (action, actor) {
let [startX, startY] = this.get_press_coords(0);
let [x, y] = this.get_motion_coords(0);
let monitorRect = this._getMonitorRect(startX, startY);
if ((this._side == St.Side.TOP && y > monitorRect.y + DRAG_DISTANCE) ||
(this._side == St.Side.BOTTOM && y < monitorRect.y + monitorRect.height - DRAG_DISTANCE) ||
(this._side == St.Side.LEFT && x > monitorRect.x + DRAG_DISTANCE) ||
(this._side == St.Side.RIGHT && x < monitorRect.x + monitorRect.width - DRAG_DISTANCE))
this.emit('activated');
}
});
Signals.addSignalMethods(EdgeDragAction.prototype);

View File

@ -38,6 +38,8 @@ const UserWidget = imports.ui.userWidget;
let _endSessionDialog = null; let _endSessionDialog = null;
const TRIGGER_OFFLINE_UPDATE = '/usr/libexec/pk-trigger-offline-update';
const _ITEM_ICON_SIZE = 48; const _ITEM_ICON_SIZE = 48;
const _DIALOG_ICON_SIZE = 48; const _DIALOG_ICON_SIZE = 48;
@ -132,18 +134,11 @@ const restartInstallDialogContent = {
showOtherSessions: true, showOtherSessions: true,
}; };
const DialogType = {
LOGOUT: 0 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_LOGOUT */,
SHUTDOWN: 1 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_SHUTDOWN */,
RESTART: 2 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_RESTART */,
UPDATE_RESTART: 3
};
const DialogContent = { const DialogContent = {
0 /* DialogType.LOGOUT */: logoutDialogContent, 0 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_LOGOUT */: logoutDialogContent,
1 /* DialogType.SHUTDOWN */: shutdownDialogContent, 1 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_SHUTDOWN */: shutdownDialogContent,
2 /* DialogType.RESTART */: restartDialogContent, 2 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_RESTART */: restartDialogContent,
3 /* DialogType.UPDATE_RESTART */: restartInstallDialogContent 3: restartInstallDialogContent
}; };
const MAX_USERS_IN_SESSION_DIALOG = 5; const MAX_USERS_IN_SESSION_DIALOG = 5;
@ -160,19 +155,6 @@ const LogindSessionIface = '<node> \
const LogindSession = Gio.DBusProxy.makeProxyWrapper(LogindSessionIface); const LogindSession = Gio.DBusProxy.makeProxyWrapper(LogindSessionIface);
const PkOfflineIface = '<node> \
<interface name="org.freedesktop.PackageKit.Offline"> \
<property name="UpdatePrepared" type="b" access="read"/> \
<property name="TriggerAction" type="s" access="read"/> \
<method name="Trigger"> \
<arg type="s" name="action" direction="in"/> \
</method> \
<method name="Cancel"/> \
</interface> \
</node>';
const PkOfflineProxy = Gio.DBusProxy.makeProxyWrapper(PkOfflineIface);
const UPowerIface = '<node> \ const UPowerIface = '<node> \
<interface name="org.freedesktop.UPower"> \ <interface name="org.freedesktop.UPower"> \
<property name="OnBattery" type="b" access="read"/> \ <property name="OnBattery" type="b" access="read"/> \
@ -263,14 +245,9 @@ const EndSessionDialog = new Lang.Class({
this._loginManager = LoginManager.getLoginManager(); this._loginManager = LoginManager.getLoginManager();
this._userManager = AccountsService.UserManager.get_default(); this._userManager = AccountsService.UserManager.get_default();
this._user = this._userManager.get_user(GLib.get_user_name()); this._user = this._userManager.get_user(GLib.get_user_name());
this._updatesFile = Gio.File.new_for_path('/system-update');
this._preparedUpdateFile = Gio.File.new_for_path('/var/lib/PackageKit/prepared-update');
this._pkOfflineProxy = new PkOfflineProxy(Gio.DBus.system,
'org.freedesktop.PackageKit',
'/org/freedesktop/PackageKit',
Lang.bind(this, function(proxy, error) {
if (error)
log(error.message);
}));
this._powerProxy = new UPowerProxy(Gio.DBus.system, this._powerProxy = new UPowerProxy(Gio.DBus.system,
'org.freedesktop.UPower', 'org.freedesktop.UPower',
'/org/freedesktop/UPower', '/org/freedesktop/UPower',
@ -522,29 +499,31 @@ const EndSessionDialog = new Lang.Class({
}, },
_triggerOfflineUpdateReboot: function(callback) { _triggerOfflineUpdateReboot: function(callback) {
this._pkOfflineProxy.TriggerRemote('reboot', this._pkexecSpawn([TRIGGER_OFFLINE_UPDATE, 'reboot'], callback);
function (result, error) {
if (error)
log(error.message);
callback();
});
}, },
_triggerOfflineUpdateShutdown: function(callback) { _triggerOfflineUpdateShutdown: function(callback) {
this._pkOfflineProxy.TriggerRemote('power-off', this._pkexecSpawn([TRIGGER_OFFLINE_UPDATE, 'power-off'], callback);
function (result, error) {
if (error)
log(error.message);
callback();
});
}, },
_triggerOfflineUpdateCancel: function(callback) { _triggerOfflineUpdateCancel: function(callback) {
this._pkOfflineProxy.CancelRemote(function (result, error) { this._pkexecSpawn([TRIGGER_OFFLINE_UPDATE, '--cancel'], callback);
if (error) },
log(error.message);
_pkexecSpawn: function(argv, callback) {
let ret, pid;
try {
[ret, pid] = GLib.spawn_async(null, ['pkexec'].concat(argv), null,
GLib.SpawnFlags.DO_NOT_REAP_CHILD | GLib.SpawnFlags.SEARCH_PATH,
null);
} catch (e) {
log('Error spawning "pkexec %s": %s'.format(argv.join(' '), e.toString()));
callback();
return;
}
GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, function(pid, status) {
GLib.spawn_close_pid(pid);
callback(); callback();
}); });
@ -572,7 +551,6 @@ const EndSessionDialog = new Lang.Class({
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(this._timerId, '[gnome-shell] this._confirm');
}, },
_stopTimer: function() { _stopTimer: function() {
@ -698,9 +676,8 @@ const EndSessionDialog = new Lang.Class({
this._totalSecondsToStayOpen = totalSecondsToStayOpen; this._totalSecondsToStayOpen = totalSecondsToStayOpen;
this._type = type; this._type = type;
if (this._type == DialogType.RESTART && if (this._type == 2 && this._updatesFile.query_exists(null))
this._pkOfflineProxy.TriggerAction == 'reboot') this._type = 3;
this._type = DialogType.UPDATE_RESTART;
this._applications = []; this._applications = [];
this._applicationList.destroy_all_children(); this._applicationList.destroy_all_children();
@ -727,19 +704,19 @@ const EndSessionDialog = new Lang.Class({
if (dialogContent.showOtherSessions) if (dialogContent.showOtherSessions)
this._loadSessions(); this._loadSessions();
let updateAlreadyTriggered = this._pkOfflineProxy.TriggerAction == 'power-off' || this._pkOfflineProxy.TriggerAction == 'reboot'; let preparedUpdate = this._preparedUpdateFile.query_exists(null);
let updatePrepared = this._pkOfflineProxy.UpdatePrepared; let updateAlreadyTriggered = this._updatesFile.query_exists(null);
let updatesAllowed = this._updatesPermission && this._updatesPermission.allowed; let updatesAllowed = this._updatesPermission && this._updatesPermission.allowed;
_setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText); _setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText);
this._checkBox.actor.visible = (dialogContent.checkBoxText && updatePrepared && updatesAllowed); this._checkBox.actor.visible = (dialogContent.checkBoxText && preparedUpdate && updatesAllowed);
this._checkBox.actor.checked = (updatePrepared && updateAlreadyTriggered); this._checkBox.actor.checked = (preparedUpdate && updateAlreadyTriggered);
// We show the warning either together with the checkbox, or when // We show the warning either together with the checkbox, or when
// updates have already been triggered, but the user doesn't have // updates have already been triggered, but the user doesn't have
// enough permissions to cancel them. // enough permissions to cancel them.
this._batteryWarning.visible = (dialogContent.showBatteryWarning && this._batteryWarning.visible = (dialogContent.showBatteryWarning &&
(this._checkBox.actor.visible || updatePrepared && updateAlreadyTriggered && !updatesAllowed)); (this._checkBox.actor.visible || preparedUpdate && updateAlreadyTriggered && !updatesAllowed));
this._updateButtons(); this._updateButtons();

View File

@ -47,11 +47,8 @@ function _patchLayoutClass(layoutClass, styleProps) {
layoutClass.prototype.hookup_style = function(container) { layoutClass.prototype.hookup_style = function(container) {
container.connect('style-changed', Lang.bind(this, function() { container.connect('style-changed', Lang.bind(this, function() {
let node = container.get_theme_node(); let node = container.get_theme_node();
for (let prop in styleProps) { for (let prop in styleProps)
let [found, length] = node.lookup_length(styleProps[prop], false); this[prop] = node.get_length(styleProps[prop]);
if (found)
this[prop] = length;
}
})); }));
}; };
layoutClass.prototype.child_set = function(actor, props) { layoutClass.prototype.child_set = function(actor, props) {

View File

@ -271,17 +271,10 @@ function onEnabledExtensionsChanged() {
} }
function _onVersionValidationChanged() { function _onVersionValidationChanged() {
// we want to reload all extensions, but only enable
// extensions when allowed by the sessionMode, so
// temporarily disable them all
enabledExtensions = [];
for (let uuid in ExtensionUtils.extensions)
reloadExtension(ExtensionUtils.extensions[uuid]);
enabledExtensions = getEnabledExtensions();
if (Main.sessionMode.allowExtensions) { if (Main.sessionMode.allowExtensions) {
enabledExtensions.forEach(function(uuid) { enabledExtensions.forEach(function(uuid) {
enableExtension(uuid); if (ExtensionUtils.extensions[uuid])
reloadExtension(ExtensionUtils.extensions[uuid]);
}); });
} }
} }

View File

@ -32,9 +32,11 @@ const FocusCaretTracker = new Lang.Class({
Name: 'FocusCaretTracker', Name: 'FocusCaretTracker',
_init: function() { _init: function() {
Atspi.init();
Atspi.set_timeout(250, 250);
this._atspiListener = Atspi.EventListener.new(Lang.bind(this, this._onChanged)); this._atspiListener = Atspi.EventListener.new(Lang.bind(this, this._onChanged));
this._atspiInited = false;
this._focusListenerRegistered = false; this._focusListenerRegistered = false;
this._caretListenerRegistered = false; this._caretListenerRegistered = false;
}, },
@ -46,20 +48,12 @@ const FocusCaretTracker = new Lang.Class({
this.emit('caret-moved', event); this.emit('caret-moved', event);
}, },
_initAtspi: function() {
if (!this._atspiInited) {
Atspi.init();
Atspi.set_timeout(250, 250);
this._atspiInited = true;
}
},
registerFocusListener: function() { registerFocusListener: function() {
if (this._focusListenerRegistered) if (this._focusListenerRegistered)
return; return;
this._initAtspi(); // Ignore the return value, we get an exception if they fail
// And they should never fail
this._atspiListener.register(STATECHANGED + ':focused'); this._atspiListener.register(STATECHANGED + ':focused');
this._atspiListener.register(STATECHANGED + ':selected'); this._atspiListener.register(STATECHANGED + ':selected');
this._focusListenerRegistered = true; this._focusListenerRegistered = true;
@ -69,8 +63,6 @@ const FocusCaretTracker = new Lang.Class({
if (this._caretListenerRegistered) if (this._caretListenerRegistered)
return; return;
this._initAtspi();
this._atspiListener.register(CARETMOVED); this._atspiListener.register(CARETMOVED);
this._caretListenerRegistered = true; this._caretListenerRegistered = true;
}, },

View File

@ -56,7 +56,7 @@ const GrabHelper = new Lang.Class({
this._grabStack = []; this._grabStack = [];
this._actors = []; this._actors = [];
this._ignoreUntilRelease = false; this._ignoreRelease = false;
this._modalCount = 0; this._modalCount = 0;
}, },
@ -215,7 +215,7 @@ const GrabHelper = new Lang.Class({
_popGrabHelper(this); _popGrabHelper(this);
this._ignoreUntilRelease = false; this._ignoreRelease = false;
Main.popModal(this._owner); Main.popModal(this._owner);
global.sync_pointer(); global.sync_pointer();
@ -228,7 +228,7 @@ const GrabHelper = new Lang.Class({
// like the ComboBoxMenu that go away on press, but need to eat // like the ComboBoxMenu that go away on press, but need to eat
// the next release event. // the next release event.
ignoreRelease: function() { ignoreRelease: function() {
this._ignoreUntilRelease = true; this._ignoreRelease = true;
}, },
// ungrab: // ungrab:
@ -283,22 +283,12 @@ const GrabHelper = new Lang.Class({
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
let motion = type == Clutter.EventType.MOTION;
let press = type == Clutter.EventType.BUTTON_PRESS; let press = type == Clutter.EventType.BUTTON_PRESS;
let release = type == Clutter.EventType.BUTTON_RELEASE; let release = type == Clutter.EventType.BUTTON_RELEASE;
let button = press || release; let button = press || release;
let touchUpdate = type == Clutter.EventType.TOUCH_UPDATE; if (release && this._ignoreRelease) {
let touchBegin = type == Clutter.EventType.TOUCH_BEGIN; this._ignoreRelease = false;
let touchEnd = type == Clutter.EventType.TOUCH_END;
let touch = touchUpdate || touchBegin || touchEnd;
if (touch && !global.display.is_pointer_emulating_sequence (event.get_event_sequence()))
return Clutter.EVENT_PROPAGATE;
if (this._ignoreUntilRelease && (motion || release || touch)) {
if (release || touchEnd)
this._ignoreUntilRelease = false;
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
@ -308,12 +298,11 @@ const GrabHelper = new Lang.Class({
if (Main.keyboard.shouldTakeEvent(event)) if (Main.keyboard.shouldTakeEvent(event))
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
if (button || touchBegin) { if (button) {
// If we have a press event, ignore the next // If we have a press event, ignore the next event,
// motion/release events. // which should be a release event.
if (press || touchBegin) if (press)
this._ignoreUntilRelease = true; this._ignoreRelease = true;
let i = this._actorInGrabStack(event.get_source()) + 1; let i = this._actorInGrabStack(event.get_source()) + 1;
this.ungrab({ actor: this._grabStack[i].actor, isUser: true }); this.ungrab({ actor: this._grabStack[i].actor, isUser: true });
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;

View File

@ -11,9 +11,6 @@ const Main = imports.ui.main;
const MAX_CANDIDATES_PER_PAGE = 16; const MAX_CANDIDATES_PER_PAGE = 16;
const DEFAULT_INDEX_LABELS = [ '1', '2', '3', '4', '5', '6', '7', '8',
'9', '0', 'a', 'b', 'c', 'd', 'e', 'f' ];
const CandidateArea = new Lang.Class({ const CandidateArea = new Lang.Class({
Name: 'CandidateArea', Name: 'CandidateArea',
@ -92,7 +89,7 @@ const CandidateArea = new Lang.Class({
if (!visible) if (!visible)
continue; continue;
box._indexLabel.text = ((indexes && indexes[i]) ? indexes[i] : DEFAULT_INDEX_LABELS[i]); box._indexLabel.text = ((indexes && indexes[i]) ? indexes[i] : '%x'.format(i + 1));
box._candidateLabel.text = candidates[i]; box._candidateLabel.text = candidates[i];
} }

View File

@ -10,30 +10,12 @@ const St = imports.gi.St;
const Lang = imports.lang; const Lang = imports.lang;
const Params = imports.misc.params; const Params = imports.misc.params;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const Main = imports.ui.main;
const ICON_SIZE = 96; const ICON_SIZE = 96;
const MIN_ICON_SIZE = 16; const MIN_ICON_SIZE = 16;
const EXTRA_SPACE_ANIMATION_TIME = 0.25; const EXTRA_SPACE_ANIMATION_TIME = 0.25;
const ANIMATION_TIME_IN = 0.350;
const ANIMATION_TIME_OUT = 1/2 * ANIMATION_TIME_IN;
const ANIMATION_MAX_DELAY_FOR_ITEM = 2/3 * ANIMATION_TIME_IN;
const ANIMATION_BASE_DELAY_FOR_ITEM = 1/4 * ANIMATION_MAX_DELAY_FOR_ITEM;
const ANIMATION_MAX_DELAY_OUT_FOR_ITEM = 2/3 * ANIMATION_TIME_OUT;
const ANIMATION_FADE_IN_TIME_FOR_ITEM = 1/4 * ANIMATION_TIME_IN;
const ANIMATION_BOUNCE_ICON_SCALE = 1.1;
const AnimationDirection = {
IN: 0,
OUT: 1
};
const APPICON_ANIMATION_OUT_SCALE = 3;
const APPICON_ANIMATION_OUT_TIME = 0.25;
const BaseIcon = new Lang.Class({ const BaseIcon = new Lang.Class({
Name: 'BaseIcon', Name: 'BaseIcon',
@ -191,55 +173,9 @@ const BaseIcon = new Lang.Class({
_onIconThemeChanged: function() { _onIconThemeChanged: function() {
this._createIconTexture(this.iconSize); this._createIconTexture(this.iconSize);
},
animateZoomOut: function() {
// Animate only the child instead of the entire actor, so the
// styles like hover and running are not applied while
// animating.
zoomOutActor(this.actor.child);
} }
}); });
function clamp(value, min, max) {
return Math.max(Math.min(value, max), min);
};
function zoomOutActor(actor) {
let actorClone = new Clutter.Clone({ source: actor,
reactive: false });
let [width, height] = actor.get_transformed_size();
let [x, y] = actor.get_transformed_position();
actorClone.set_size(width, height);
actorClone.set_position(x, y);
actorClone.opacity = 255;
actorClone.set_pivot_point(0.5, 0.5);
Main.uiGroup.add_actor(actorClone);
// Avoid monitor edges to not zoom outside the current monitor
let monitor = Main.layoutManager.findMonitorForActor(actor);
let scaledWidth = width * APPICON_ANIMATION_OUT_SCALE;
let scaledHeight = height * APPICON_ANIMATION_OUT_SCALE;
let scaledX = x - (scaledWidth - width) / 2;
let scaledY = y - (scaledHeight - height) / 2;
let containedX = clamp(scaledX, monitor.x, monitor.x + monitor.width - scaledWidth);
let containedY = clamp(scaledY, monitor.y, monitor.y + monitor.height - scaledHeight);
Tweener.addTween(actorClone,
{ time: APPICON_ANIMATION_OUT_TIME,
scale_x: APPICON_ANIMATION_OUT_SCALE,
scale_y: APPICON_ANIMATION_OUT_SCALE,
translation_x: containedX - scaledX,
translation_y: containedY - scaledY,
opacity: 0,
transition: 'easeOutQuad',
onComplete: function() {
actorClone.destroy();
}
});
}
const IconGrid = new Lang.Class({ const IconGrid = new Lang.Class({
Name: 'IconGrid', Name: 'IconGrid',
@ -402,202 +338,15 @@ const IconGrid = new Lang.Class({
} }
}, },
/**
* Intended to be override by subclasses if they need a different
* set of items to be animated.
*/
_getChildrenToAnimate: function() {
return this._getVisibleChildren();
},
_animationDone: function() {
this._animating = false;
this.emit('animation-done');
},
animatePulse: function(animationDirection) {
if (animationDirection != AnimationDirection.IN)
throw new Error("Pulse animation only implements 'in' animation direction");
if (this._animating)
return;
this._animating = true;
let actors = this._getChildrenToAnimate();
if (actors.length == 0) {
this._animationDone();
return;
}
// For few items the animation can be slow, so use a smaller
// delay when there are less than 4 items
// (ANIMATION_BASE_DELAY_FOR_ITEM = 1/4 *
// ANIMATION_MAX_DELAY_FOR_ITEM)
let maxDelay = Math.min(ANIMATION_BASE_DELAY_FOR_ITEM * actors.length,
ANIMATION_MAX_DELAY_FOR_ITEM);
for (let index = 0; index < actors.length; index++) {
let actor = actors[index];
actor.reactive = false;
actor.set_scale(0, 0);
actor.set_pivot_point(0.5, 0.5);
let delay = index / actors.length * maxDelay;
let bounceUpTime = ANIMATION_TIME_IN / 4;
let isLastItem = index == actors.length - 1;
Tweener.addTween(actor,
{ time: bounceUpTime,
transition: 'easeInOutQuad',
delay: delay,
scale_x: ANIMATION_BOUNCE_ICON_SCALE,
scale_y: ANIMATION_BOUNCE_ICON_SCALE,
onComplete: Lang.bind(this, function() {
Tweener.addTween(actor,
{ time: ANIMATION_TIME_IN - bounceUpTime,
transition: 'easeInOutQuad',
scale_x: 1,
scale_y: 1,
onComplete: Lang.bind(this, function() {
if (isLastItem)
this._animationDone();
actor.reactive = true;
})
});
})
});
}
},
animateSpring: function(animationDirection, sourceActor) {
if (this._animating)
return;
this._animating = true;
let actors = this._getChildrenToAnimate();
if (actors.length == 0) {
this._animationDone();
return;
}
let [sourceX, sourceY] = sourceActor.get_transformed_position();
let [sourceWidth, sourceHeight] = sourceActor.get_size();
// Get the center
let [sourceCenterX, sourceCenterY] = [sourceX + sourceWidth / 2, sourceY + sourceHeight / 2];
// Design decision, 1/2 of the source actor size.
let [sourceScaledWidth, sourceScaledHeight] = [sourceWidth / 2, sourceHeight / 2];
actors.forEach(function(actor) {
let [actorX, actorY] = actor._transformedPosition = actor.get_transformed_position();
let [x, y] = [actorX - sourceX, actorY - sourceY];
actor._distance = Math.sqrt(x * x + y * y);
});
let maxDist = actors.reduce(function(prev, cur) {
return Math.max(prev, cur._distance);
}, 0);
let minDist = actors.reduce(function(prev, cur) {
return Math.min(prev, cur._distance);
}, Infinity);
let normalization = maxDist - minDist;
for (let index = 0; index < actors.length; index++) {
let actor = actors[index];
actor.opacity = 0;
actor.reactive = false;
let actorClone = new Clutter.Clone({ source: actor });
Main.uiGroup.add_actor(actorClone);
let [width, height,,] = this._getAllocatedChildSizeAndSpacing(actor);
actorClone.set_size(width, height);
let scaleX = sourceScaledWidth / width;
let scaleY = sourceScaledHeight / height;
let [adjustedSourcePositionX, adjustedSourcePositionY] = [sourceCenterX - sourceScaledWidth / 2, sourceCenterY - sourceScaledHeight / 2];
let movementParams, fadeParams;
if (animationDirection == AnimationDirection.IN) {
let isLastItem = actor._distance == minDist;
actorClone.opacity = 0;
actorClone.set_scale(scaleX, scaleY);
actorClone.set_position(adjustedSourcePositionX, adjustedSourcePositionY);
let delay = (1 - (actor._distance - minDist) / normalization) * ANIMATION_MAX_DELAY_FOR_ITEM;
let [finalX, finalY] = actor._transformedPosition;
movementParams = { time: ANIMATION_TIME_IN,
transition: 'easeInOutQuad',
delay: delay,
x: finalX,
y: finalY,
scale_x: 1,
scale_y: 1,
onComplete: Lang.bind(this, function() {
if (isLastItem)
this._animationDone();
actor.opacity = 255;
actor.reactive = true;
actorClone.destroy();
})};
fadeParams = { time: ANIMATION_FADE_IN_TIME_FOR_ITEM,
transition: 'easeInOutQuad',
delay: delay,
opacity: 255 };
} else {
let isLastItem = actor._distance == maxDist;
let [startX, startY] = actor._transformedPosition;
actorClone.set_position(startX, startY);
let delay = (actor._distance - minDist) / normalization * ANIMATION_MAX_DELAY_OUT_FOR_ITEM;
movementParams = { time: ANIMATION_TIME_OUT,
transition: 'easeInOutQuad',
delay: delay,
x: adjustedSourcePositionX,
y: adjustedSourcePositionY,
scale_x: scaleX,
scale_y: scaleY,
onComplete: Lang.bind(this, function() {
if (isLastItem) {
this._animationDone();
this._restoreItemsOpacity();
}
actor.reactive = true;
actorClone.destroy();
})};
fadeParams = { time: ANIMATION_FADE_IN_TIME_FOR_ITEM,
transition: 'easeInOutQuad',
delay: ANIMATION_TIME_OUT + delay - ANIMATION_FADE_IN_TIME_FOR_ITEM,
opacity: 0 };
}
Tweener.addTween(actorClone, movementParams);
Tweener.addTween(actorClone, fadeParams);
}
},
_restoreItemsOpacity: function() {
for (let index = 0; index < this._items.length; index++) {
this._items[index].actor.opacity = 255;
}
},
_getAllocatedChildSizeAndSpacing: function(child) {
let [,, natWidth, natHeight] = child.get_preferred_size();
let width = Math.min(this._getHItemSize(), natWidth);
let xSpacing = Math.max(0, width - natWidth) / 2;
let height = Math.min(this._getVItemSize(), natHeight);
let ySpacing = Math.max(0, height - natHeight) / 2;
return [width, height, xSpacing, ySpacing];
},
_calculateChildBox: function(child, x, y, box) { _calculateChildBox: function(child, x, y, box) {
let [childMinWidth, childMinHeight, childNaturalWidth, childNaturalHeight] =
child.get_preferred_size();
/* Center the item in its allocation horizontally */ /* Center the item in its allocation horizontally */
let [width, height, childXSpacing, childYSpacing] = let width = Math.min(this._getHItemSize(), childNaturalWidth);
this._getAllocatedChildSizeAndSpacing(child); let childXSpacing = Math.max(0, width - childNaturalWidth) / 2;
let height = Math.min(this._getVItemSize(), childNaturalHeight);
let childYSpacing = Math.max(0, height - childNaturalHeight) / 2;
let childBox = new Clutter.ActorBox(); let childBox = new Clutter.ActorBox();
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) { if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) {
@ -773,17 +522,21 @@ const IconGrid = new Lang.Class({
this._fixedHItemSize = Math.max(this._hItemSize - neededSpacePerItem, MIN_ICON_SIZE); this._fixedHItemSize = Math.max(this._hItemSize - neededSpacePerItem, MIN_ICON_SIZE);
this._fixedVItemSize = Math.max(this._vItemSize - neededSpacePerItem, MIN_ICON_SIZE); this._fixedVItemSize = Math.max(this._vItemSize - neededSpacePerItem, MIN_ICON_SIZE);
if (this._fixedHItemSize < MIN_ICON_SIZE)
this._fixedHItemSize = MIN_ICON_SIZE;
if (this._fixedVItemSize < MIN_ICON_SIZE)
this._fixedVItemSize = MIN_ICON_SIZE;
this._updateSpacingForSize(availWidth, availHeight); this._updateSpacingForSize(availWidth, availHeight);
} }
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, let scale = Math.min(this._fixedHItemSize, this._fixedVItemSize) / Math.max(this._hItemSize, this._vItemSize);
Lang.bind(this, this._updateIconSizes)); Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { this._updateChildrenScale(scale); }));
}, },
// Note that this is ICON_SIZE as used by BaseIcon, not elsewhere in IconGrid; it's a bit messed up // Note that this is ICON_SIZE as used by BaseIcon, not elsewhere in IconGrid; it's a bit messed up
_updateIconSizes: function() { _updateChildrenScale: function(scale) {
let scale = Math.min(this._fixedHItemSize, this._fixedVItemSize) / Math.max(this._hItemSize, this._vItemSize);
let newIconSize = Math.floor(ICON_SIZE * scale);
for (let i in this._items) { for (let i in this._items) {
let newIconSize = Math.floor(ICON_SIZE * scale);
this._items[i].icon.setIconSize(newIconSize); this._items[i].icon.setIconSize(newIconSize);
} }
} }
@ -797,7 +550,6 @@ const PaginatedIconGrid = new Lang.Class({
_init: function(params) { _init: function(params) {
this.parent(params); this.parent(params);
this._nPages = 0; this._nPages = 0;
this.currentPage = 0;
this._rowsPerPage = 0; this._rowsPerPage = 0;
this._spaceBetweenPages = 0; this._spaceBetweenPages = 0;
this._childrenPerPage = 0; this._childrenPerPage = 0;
@ -861,15 +613,6 @@ const PaginatedIconGrid = new Lang.Class({
} }
}, },
// Overriden from IconGrid
_getChildrenToAnimate: function() {
let children = this._getVisibleChildren();
let firstIndex = this._childrenPerPage * this.currentPage;
let lastIndex = firstIndex + this._childrenPerPage;
return children.slice(firstIndex, lastIndex);
},
_computePages: function (availWidthPerPage, availHeightPerPage) { _computePages: function (availWidthPerPage, availHeightPerPage) {
let [nColumns, usedWidth] = this._computeLayout(availWidthPerPage); let [nColumns, usedWidth] = this._computeLayout(availWidthPerPage);
let nRows; let nRows;
@ -902,10 +645,6 @@ const PaginatedIconGrid = new Lang.Class({
return this._nPages; return this._nPages;
}, },
getPageHeight: function() {
return this._availableHeightPerPageForItems();
},
getPageY: function(pageNumber) { getPageY: function(pageNumber) {
if (!this._nPages) if (!this._nPages)
return 0; return 0;

View File

@ -23,12 +23,6 @@ const KEYBOARD_TYPE = 'keyboard-type';
const A11Y_APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications'; const A11Y_APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications';
const SHOW_KEYBOARD = 'screen-keyboard-enabled'; const SHOW_KEYBOARD = 'screen-keyboard-enabled';
const CURSOR_BUS_NAME = 'org.gnome.SettingsDaemon.Cursor';
const CURSOR_OBJECT_PATH = '/org/gnome/SettingsDaemon/Cursor';
const CARIBOU_BUS_NAME = 'org.gnome.Caribou.Daemon';
const CARIBOU_OBJECT_PATH = '/org/gnome/Caribou/Daemon';
const CaribouKeyboardIface = '<node> \ const CaribouKeyboardIface = '<node> \
<interface name="org.gnome.Caribou.Keyboard"> \ <interface name="org.gnome.Caribou.Keyboard"> \
<method name="Show"> \ <method name="Show"> \
@ -53,29 +47,13 @@ const CaribouKeyboardIface = '<node> \
</interface> \ </interface> \
</node>'; </node>';
const CaribouDaemonIface = '<node> \
<interface name="org.gnome.Caribou.Daemon"> \
<method name="Run" /> \
<method name="Quit" /> \
</interface> \
</node>';
const CursorManagerIface = '<node> \
<interface name="org.gnome.SettingsDaemon.Cursor"> \
<property name="ShowOSK" type="b" access="read" /> \
</interface> \
</node>';
const CaribouDaemonProxy = Gio.DBusProxy.makeProxyWrapper(CaribouDaemonIface);
const CursorManagerProxy = Gio.DBusProxy.makeProxyWrapper(CursorManagerIface);
const Key = new Lang.Class({ const Key = new Lang.Class({
Name: 'Key', Name: 'Key',
_init : function(key) { _init : function(key) {
this._key = key; this._key = key;
this.actor = this._makeKey(key, GLib.markup_escape_text(key.label, -1));
this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); this.actor = this._makeKey();
this._extended_keys = this._key.get_extended_keys(); this._extended_keys = this._key.get_extended_keys();
this._extended_keyboard = null; this._extended_keyboard = null;
@ -98,26 +76,20 @@ const Key = new Lang.Class({
} }
}, },
_onDestroy: function() { _makeKey: function () {
if (this._boxPointer) { let label = GLib.markup_escape_text(this._key.label, -1);
this._boxPointer.actor.destroy();
this._boxPointer = null;
}
},
_makeKey: function (key, label) {
let button = new St.Button ({ label: label, let button = new St.Button ({ label: label,
style_class: 'keyboard-key' }); style_class: 'keyboard-key' });
button.key_width = this._key.width; button.key_width = this._key.width;
button.connect('button-press-event', Lang.bind(this, button.connect('button-press-event', Lang.bind(this,
function () { function () {
key.press(); this._key.press();
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
})); }));
button.connect('button-release-event', Lang.bind(this, button.connect('button-release-event', Lang.bind(this,
function () { function () {
key.release(); this._key.release();
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
})); }));
@ -140,9 +112,18 @@ const Key = new Lang.Class({
for (let i = 0; i < this._extended_keys.length; ++i) { for (let i = 0; i < this._extended_keys.length; ++i) {
let extended_key = this._extended_keys[i]; let extended_key = this._extended_keys[i];
let label = this._getUnichar(extended_key); let label = this._getUnichar(extended_key);
let key = this._makeKey(extended_key, label); let key = new St.Button({ label: label, style_class: 'keyboard-key' });
key.extended_key = extended_key; key.extended_key = extended_key;
key.connect('button-press-event', Lang.bind(this,
function () {
extended_key.press();
return Clutter.EVENT_PROPAGATE;
}));
key.connect('button-release-event', Lang.bind(this,
function () {
extended_key.release();
return Clutter.EVENT_PROPAGATE;
}));
this._extended_keyboard.add(key); this._extended_keyboard.add(key);
} }
this._boxPointer.bin.add_actor(this._extended_keyboard); this._boxPointer.bin.add_actor(this._extended_keyboard);
@ -180,33 +161,11 @@ const Keyboard = new Lang.Class({
this._timestamp = global.display.get_current_time_roundtrip(); this._timestamp = global.display.get_current_time_roundtrip();
this._keyboardSettings = new Gio.Settings({ schema_id: KEYBOARD_SCHEMA }); this._keyboardSettings = new Gio.Settings({ schema: KEYBOARD_SCHEMA });
this._keyboardSettings.connect('changed', Lang.bind(this, this._sync)); this._keyboardSettings.connect('changed', Lang.bind(this, this._settingsChanged));
this._a11yApplicationsSettings = new Gio.Settings({ schema_id: A11Y_APPLICATIONS_SCHEMA }); this._a11yApplicationsSettings = new Gio.Settings({ schema: A11Y_APPLICATIONS_SCHEMA });
this._a11yApplicationsSettings.connect('changed', Lang.bind(this, this._sync)); this._a11yApplicationsSettings.connect('changed', Lang.bind(this, this._settingsChanged));
this._watchNameId = Gio.bus_watch_name(Gio.BusType.SESSION, CURSOR_BUS_NAME, 0, this._settingsChanged();
Lang.bind(this, this._sync),
Lang.bind(this, this._sync));
this._daemonProxy = new CaribouDaemonProxy(Gio.DBus.session, CARIBOU_BUS_NAME,
CARIBOU_OBJECT_PATH,
Lang.bind(this, function(proxy, error) {
if (error) {
log(error.message);
return;
}
}));
this._cursorProxy = new CursorManagerProxy(Gio.DBus.session, CURSOR_BUS_NAME,
CURSOR_OBJECT_PATH,
Lang.bind(this, function(proxy, error) {
if (error) {
log(error.message);
return;
}
this._cursorProxy.connect('g-properties-changed',
Lang.bind(this, this._sync));
this._sync();
}));
this._sync();
this._showIdleId = 0; this._showIdleId = 0;
this._subkeysBoxPointer = null; this._subkeysBoxPointer = null;
@ -224,9 +183,8 @@ const Keyboard = new Lang.Class({
this._redraw(); this._redraw();
}, },
_sync: function () { _settingsChanged: function (settings, key) {
this._enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD) || this._enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD);
this._cursorProxy.ShowOSK;
if (!this._enableKeyboard && !this._keyboard) if (!this._enableKeyboard && !this._keyboard)
return; return;
if (this._enableKeyboard && this._keyboard && if (this._enableKeyboard && this._keyboard &&
@ -256,22 +214,9 @@ const Keyboard = new Lang.Class({
this.actor = null; this.actor = null;
this._destroySource(); this._destroySource();
this._daemonProxy.QuitRemote(function (result, error) {
if (error) {
log(error.message);
return;
}
});
}, },
_setupKeyboard: function() { _setupKeyboard: function() {
this._daemonProxy.RunRemote(function (result, error) {
if (error) {
log(error.message);
return;
}
});
this.actor = new St.BoxLayout({ name: 'keyboard', vertical: true, reactive: true }); this.actor = new St.BoxLayout({ name: 'keyboard', vertical: true, reactive: true });
Main.layoutManager.keyboardBox.add_actor(this.actor); Main.layoutManager.keyboardBox.add_actor(this.actor);
Main.layoutManager.trackChrome(this.actor); Main.layoutManager.trackChrome(this.actor);
@ -321,14 +266,12 @@ const Keyboard = new Lang.Class({
return; return;
} }
if (!this._showIdleId) { if (!this._showIdleId)
this._showIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, this._showIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE,
Lang.bind(this, function() { Lang.bind(this, function() {
this.Show(time); this.Show(time);
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(this._showIdleId, '[gnome-shell] this.Show');
}
}, },
_createLayersForGroup: function (gname) { _createLayersForGroup: function (gname) {
@ -557,7 +500,6 @@ const Keyboard = new Lang.Class({
this._show(monitor); this._show(monitor);
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(this._keyboardRestingId, '[gnome-shell] this._clearKeyboardRestTimer');
}, },
_show: function(monitor) { _show: function(monitor) {
@ -584,7 +526,6 @@ const Keyboard = new Lang.Class({
this._hide(); this._hide();
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(this._keyboardRestingId, '[gnome-shell] this._clearKeyboardRestTimer');
}, },
_hide: function() { _hide: function() {
@ -610,7 +551,7 @@ const Keyboard = new Lang.Class({
_moveTemporarily: function () { _moveTemporarily: function () {
let currentWindow = global.screen.get_display().focus_window; let currentWindow = global.screen.get_display().focus_window;
let rect = currentWindow.get_frame_rect(); let rect = currentWindow.get_outer_rect();
let newX = rect.x; let newX = rect.x;
let newY = 3 * this.actor.height / 2; let newY = 3 * this.actor.height / 2;

View File

@ -20,6 +20,7 @@ const Tweener = imports.ui.tweener;
const STARTUP_ANIMATION_TIME = 0.5; const STARTUP_ANIMATION_TIME = 0.5;
const KEYBOARD_ANIMATION_TIME = 0.15; const KEYBOARD_ANIMATION_TIME = 0.15;
const BACKGROUND_FADE_ANIMATION_TIME = 1.0; const BACKGROUND_FADE_ANIMATION_TIME = 1.0;
const DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff);
// The message tray takes this much pressure // The message tray takes this much pressure
// in the pressure barrier at once to release it. // in the pressure barrier at once to release it.
@ -159,10 +160,10 @@ const LayoutManager = new Lang.Class({
this._isPopupWindowVisible = false; this._isPopupWindowVisible = false;
this._startingUp = true; this._startingUp = true;
// We don't want to paint the stage background color because either // Normally, the stage is always covered so Clutter doesn't need to clear
// the SystemBackground we create or the MetaBackgroundActor inside // it; however it becomes visible during the startup animation
// global.window_group covers the entirety of the screen. // See the comment below for a longer explanation
global.stage.no_clear_hint = true; global.stage.color = DEFAULT_BACKGROUND_COLOR;
// Set up stage hierarchy to group all UI actors under one container. // Set up stage hierarchy to group all UI actors under one container.
this.uiGroup = new Shell.GenericContainer({ name: 'uiGroup' }); this.uiGroup = new Shell.GenericContainer({ name: 'uiGroup' });
@ -223,16 +224,12 @@ const LayoutManager = new Lang.Class({
// A dummy actor that tracks the mouse or text cursor, based on the // A dummy actor that tracks the mouse or text cursor, based on the
// position and size set in setDummyCursorGeometry. // position and size set in setDummyCursorGeometry.
this.dummyCursor = new St.Widget({ width: 0, height: 0, visible: false }); this.dummyCursor = new St.Widget({ width: 0, height: 0 });
this.uiGroup.add_actor(this.dummyCursor); this.uiGroup.add_actor(this.dummyCursor);
global.stage.remove_actor(global.top_window_group); global.stage.remove_actor(global.top_window_group);
this.uiGroup.add_actor(global.top_window_group); this.uiGroup.add_actor(global.top_window_group);
let feedbackGroup = Meta.get_feedback_group_for_screen(global.screen);
global.stage.remove_actor(feedbackGroup);
this.uiGroup.add_actor(feedbackGroup);
this._backgroundGroup = new Meta.BackgroundGroup(); this._backgroundGroup = new Meta.BackgroundGroup();
global.window_group.add_child(this._backgroundGroup); global.window_group.add_child(this._backgroundGroup);
this._backgroundGroup.lower_bottom(); this._backgroundGroup.lower_bottom();
@ -262,6 +259,7 @@ const LayoutManager = new Lang.Class({
this._inOverview = true; this._inOverview = true;
this._updateVisibility(); this._updateVisibility();
this._updateRegions();
}, },
hideOverview: function() { hideOverview: function() {
@ -269,6 +267,7 @@ const LayoutManager = new Lang.Class({
this._inOverview = false; this._inOverview = false;
this._updateVisibility(); this._updateVisibility();
this._queueUpdateRegions();
}, },
_sessionUpdated: function() { _sessionUpdated: function() {
@ -362,7 +361,7 @@ const LayoutManager = new Lang.Class({
}, },
_addBackgroundMenu: function(bgManager) { _addBackgroundMenu: function(bgManager) {
BackgroundMenu.addBackgroundMenu(bgManager.backgroundActor, this); BackgroundMenu.addBackgroundMenu(bgManager.background.actor, this);
}, },
_createBackgroundManager: function(monitorIndex) { _createBackgroundManager: function(monitorIndex) {
@ -379,10 +378,10 @@ const LayoutManager = new Lang.Class({
_showSecondaryBackgrounds: function() { _showSecondaryBackgrounds: function() {
for (let i = 0; i < this.monitors.length; i++) { for (let i = 0; i < this.monitors.length; i++) {
if (i != this.primaryIndex) { if (i != this.primaryIndex) {
let backgroundActor = this._bgManagers[i].backgroundActor; let background = this._bgManagers[i].background;
backgroundActor.show(); background.actor.show();
backgroundActor.opacity = 0; background.actor.opacity = 0;
Tweener.addTween(backgroundActor, Tweener.addTween(background.actor,
{ opacity: 255, { opacity: 255,
time: BACKGROUND_FADE_ANIMATION_TIME, time: BACKGROUND_FADE_ANIMATION_TIME,
transition: 'easeOutQuad' }); transition: 'easeOutQuad' });
@ -405,16 +404,10 @@ const LayoutManager = new Lang.Class({
this._bgManagers.push(bgManager); this._bgManagers.push(bgManager);
if (i != this.primaryIndex && this._startingUp) if (i != this.primaryIndex && this._startingUp)
bgManager.backgroundActor.hide(); bgManager.background.actor.hide();
} }
}, },
_updateKeyboardBox: function() {
this.keyboardBox.set_position(this.keyboardMonitor.x,
this.keyboardMonitor.y + this.keyboardMonitor.height);
this.keyboardBox.set_size(this.keyboardMonitor.width, -1);
},
_updateBoxes: function() { _updateBoxes: function() {
this.screenShieldGroup.set_position(0, 0); this.screenShieldGroup.set_position(0, 0);
this.screenShieldGroup.set_size(global.screen_width, global.screen_height); this.screenShieldGroup.set_size(global.screen_width, global.screen_height);
@ -424,8 +417,6 @@ const LayoutManager = new Lang.Class({
if (this.keyboardIndex < 0) if (this.keyboardIndex < 0)
this.keyboardIndex = this.primaryIndex; this.keyboardIndex = this.primaryIndex;
else
this._updateKeyboardBox();
this.trayBox.set_position(this.bottomMonitor.x, this.trayBox.set_position(this.bottomMonitor.x,
this.bottomMonitor.y + this.bottomMonitor.height); this.bottomMonitor.y + this.bottomMonitor.height);
@ -550,7 +541,9 @@ const LayoutManager = new Lang.Class({
set keyboardIndex(v) { set keyboardIndex(v) {
this._keyboardIndex = v; this._keyboardIndex = v;
this._updateKeyboardBox(); this.keyboardBox.set_position(this.keyboardMonitor.x,
this.keyboardMonitor.y + this.keyboardMonitor.height);
this.keyboardBox.set_size(this.keyboardMonitor.width, -1);
}, },
get keyboardIndex() { get keyboardIndex() {
@ -590,6 +583,10 @@ const LayoutManager = new Lang.Class({
// //
// When starting a normal user session, we want to grow it out of the middle // When starting a normal user session, we want to grow it out of the middle
// of the screen. // of the screen.
//
// Usually, we don't want to paint the stage background color because the
// MetaBackgroundActor inside global.window_group covers the entirety of the
// screen. So, we set no_clear_hint at the end of the animation.
_prepareStartupAnimation: function() { _prepareStartupAnimation: function() {
// During the initial transition, add a simple actor to block all events, // During the initial transition, add a simple actor to block all events,
@ -600,15 +597,13 @@ const LayoutManager = new Lang.Class({
reactive: true }); reactive: true });
this.addChrome(this._coverPane); this.addChrome(this._coverPane);
if (Meta.is_restart()) { if (Main.sessionMode.isGreeter) {
// On restart, we don't do an animation
} else if (Main.sessionMode.isGreeter) {
this.panelBox.translation_y = -this.panelBox.height; this.panelBox.translation_y = -this.panelBox.height;
} else { } else {
this._updateBackgrounds(); this._updateBackgrounds();
// We need to force an update of the regions now before we scale // We need to force an update of the regions now before we scale
// the UI group to get the correct allocation for the struts. // the UI group to get the coorect allocation for the struts.
this._updateRegions(); this._updateRegions();
this.trayBox.hide(); this.trayBox.hide();
@ -633,17 +628,14 @@ const LayoutManager = new Lang.Class({
// until the event loop is uncontended and idle. // until the event loop is uncontended and idle.
// This helps to prevent us from running the animation // This helps to prevent us from running the animation
// when the system is bogged down // when the system is bogged down
let id = GLib.idle_add(GLib.PRIORITY_LOW, Lang.bind(this, function() { GLib.idle_add(GLib.PRIORITY_LOW, Lang.bind(this, function() {
this._startupAnimation(); this._startupAnimation();
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(id, '[gnome-shell] this._startupAnimation');
}, },
_startupAnimation: function() { _startupAnimation: function() {
if (Meta.is_restart()) if (Main.sessionMode.isGreeter)
this._startupAnimationComplete();
else if (Main.sessionMode.isGreeter)
this._startupAnimationGreeter(); this._startupAnimationGreeter();
else else
this._startupAnimationSession(); this._startupAnimationSession();
@ -670,6 +662,10 @@ const LayoutManager = new Lang.Class({
}, },
_startupAnimationComplete: function() { _startupAnimationComplete: function() {
// At this point, the UI group is covering everything, so
// we no longer need to clear the stage
global.stage.no_clear_hint = true;
this._coverPane.destroy(); this._coverPane.destroy();
this._coverPane = null; this._coverPane = null;
@ -908,6 +904,9 @@ const LayoutManager = new Lang.Class({
}, },
_queueUpdateRegions: function() { _queueUpdateRegions: function() {
if (Main.sessionMode.isGreeter)
return;
if (this._startingUp) if (this._startingUp)
return; return;
@ -941,16 +940,13 @@ const LayoutManager = new Lang.Class({
}, },
_updateRegions: function() { _updateRegions: function() {
let rects = [], struts = [], i;
if (this._updateRegionIdle) { if (this._updateRegionIdle) {
Meta.later_remove(this._updateRegionIdle); Meta.later_remove(this._updateRegionIdle);
delete this._updateRegionIdle; delete this._updateRegionIdle;
} }
// No need to update when we have a modal.
if (Main.modalCount > 0)
return GLib.SOURCE_REMOVE;
let rects = [], struts = [], i;
let isPopupMenuVisible = global.top_window_group.get_children().some(isPopupMetaWindow); let isPopupMenuVisible = global.top_window_group.get_children().some(isPopupMetaWindow);
let wantsInputRegion = !isPopupMenuVisible; let wantsInputRegion = !isPopupMenuVisible;
@ -1020,6 +1016,43 @@ const LayoutManager = new Lang.Class({
else else
continue; continue;
// Ensure that the strut rects goes all the way to the screen edge,
// as this really what mutter expects. However skip this step
// in cases where this would render an entire monitor unusable.
switch (side) {
case Meta.Side.TOP:
let hasMonitorsAbove = this.monitors.some(Lang.bind(this,
function(mon) {
return this._isAboveOrBelowPrimary(mon) &&
mon.y < primary.y;
}));
if (!hasMonitorsAbove)
y1 = 0;
break;
case Meta.Side.BOTTOM:
if (this.primaryIndex == this.bottomIndex)
y2 = global.screen_height;
break;
case Meta.Side.LEFT:
let hasMonitorsLeft = this.monitors.some(Lang.bind(this,
function(mon) {
return !this._isAboveOrBelowPrimary(mon) &&
mon.x < primary.x;
}));
if (!hasMonitorsLeft)
x1 = 0;
break;
case Meta.Side.RIGHT:
let hasMonitorsRight = this.monitors.some(Lang.bind(this,
function(mon) {
return !this._isAboveOrBelowPrimary(mon) &&
mon.x > primary.x;
}));
if (!hasMonitorsRight)
x2 = global.screen_width;
break;
}
let strutRect = new Meta.Rectangle({ x: x1, y: y1, width: x2 - x1, height: y2 - y1}); let strutRect = new Meta.Rectangle({ x: x1, y: y1, width: x2 - x1, height: y2 - y1});
let strut = new Meta.Strut({ rect: strutRect, side: side }); let strut = new Meta.Strut({ rect: strutRect, side: side });
struts.push(strut); struts.push(strut);
@ -1036,13 +1069,7 @@ const LayoutManager = new Lang.Class({
} }
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}, }
modalEnded: function() {
// We don't update the stage input region while in a modal,
// so queue an update now.
this._queueUpdateRegions();
},
}); });
Signals.addSignalMethods(LayoutManager.prototype); Signals.addSignalMethods(LayoutManager.prototype);

View File

@ -105,8 +105,8 @@ const Lightbox = new Lang.Class({
this._container = container; this._container = container;
this._children = container.get_children(); this._children = container.get_children();
this._fadeFactor = params.fadeFactor; this._fadeFactor = params.fadeFactor;
this._radialEffect = Clutter.feature_available(Clutter.FeatureFlags.SHADERS_GLSL) && params.radialEffect; this._radialEffect = params.radialEffect;
if (this._radialEffect) if (params.radialEffect)
this.actor = new RadialShaderQuad({ x: 0, this.actor = new RadialShaderQuad({ x: 0,
y: 0, y: 0,
reactive: params.inhibitEvents }); reactive: params.inhibitEvents });

View File

@ -797,7 +797,7 @@ const LookingGlass = new Lang.Class({
reactive: true }); reactive: true });
this.actor.connect('key-press-event', Lang.bind(this, this._globalKeyPressEvent)); this.actor.connect('key-press-event', Lang.bind(this, this._globalKeyPressEvent));
this._interfaceSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' }); this._interfaceSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
this._interfaceSettings.connect('changed::monospace-font-name', this._interfaceSettings.connect('changed::monospace-font-name',
Lang.bind(this, this._updateFont)); Lang.bind(this, this._updateFont));
this._updateFont(); this._updateFont();
@ -843,10 +843,9 @@ const LookingGlass = new Lang.Class({
System.gc(); System.gc();
this._timeoutId = Mainloop.timeout_add(500, Lang.bind(this, function () { this._timeoutId = Mainloop.timeout_add(500, Lang.bind(this, function () {
gcIcon.icon_name = 'gnome-fs-trash-full'; gcIcon.icon_name = 'gnome-fs-trash-full';
this._timeoutId = 0; Mainloop.source_remove(this._timeoutId);
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] gcIcon.icon_name = \'gnome-fs-trash-full\'');
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
})); }));

View File

@ -441,8 +441,8 @@ const Magnifier = new Lang.Class({
}, },
_settingsInit: function(zoomRegion) { _settingsInit: function(zoomRegion) {
this._appSettings = new Gio.Settings({ schema_id: APPLICATIONS_SCHEMA }); this._appSettings = new Gio.Settings({ schema: APPLICATIONS_SCHEMA });
this._settings = new Gio.Settings({ schema_id: MAGNIFIER_SCHEMA }); this._settings = new Gio.Settings({ schema: MAGNIFIER_SCHEMA });
if (zoomRegion) { if (zoomRegion) {
// Mag factor is accurate to two decimal places. // Mag factor is accurate to two decimal places.
@ -1198,7 +1198,12 @@ const ZoomRegion = new Lang.Class({
// Add a background for when the magnified uiGroup is scrolled // Add a background for when the magnified uiGroup is scrolled
// out of view (don't want to see desktop showing through). // out of view (don't want to see desktop showing through).
this._background = (new Background.SystemBackground()).actor; this._background = new Clutter.Actor({ background_color: Main.DEFAULT_BACKGROUND_COLOR,
layout_manager: new Clutter.BinLayout(),
width: global.screen_width,
height: global.screen_height });
let noiseTexture = (new Background.SystemBackground()).actor;
this._background.add_actor(noiseTexture);
mainGroup.add_actor(this._background); mainGroup.add_actor(this._background);
// Clone the group that contains all of UI on the screen. This is the // Clone the group that contains all of UI on the screen. This is the

View File

@ -18,7 +18,6 @@ const ExtensionSystem = imports.ui.extensionSystem;
const ExtensionDownloader = imports.ui.extensionDownloader; const ExtensionDownloader = imports.ui.extensionDownloader;
const Keyboard = imports.ui.keyboard; const Keyboard = imports.ui.keyboard;
const MessageTray = imports.ui.messageTray; const MessageTray = imports.ui.messageTray;
const ModalDialog = imports.ui.modalDialog;
const OsdWindow = imports.ui.osdWindow; const OsdWindow = imports.ui.osdWindow;
const Overview = imports.ui.overview; const Overview = imports.ui.overview;
const Panel = imports.ui.panel; const Panel = imports.ui.panel;
@ -40,9 +39,10 @@ const Magnifier = imports.ui.magnifier;
const XdndHandler = imports.ui.xdndHandler; const XdndHandler = imports.ui.xdndHandler;
const Util = imports.misc.util; const Util = imports.misc.util;
const DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff);
const A11Y_SCHEMA = 'org.gnome.desktop.a11y.keyboard'; const A11Y_SCHEMA = 'org.gnome.desktop.a11y.keyboard';
const STICKY_KEYS_ENABLE = 'stickykeys-enable'; const STICKY_KEYS_ENABLE = 'stickykeys-enable';
const GNOMESHELL_STARTED_MESSAGE_ID = 'f3ea493c22934e26811cd62abe8e203a';
let componentManager = null; let componentManager = null;
let panel = null; let panel = null;
@ -55,7 +55,7 @@ let screenShield = null;
let notificationDaemon = null; let notificationDaemon = null;
let windowAttentionHandler = null; let windowAttentionHandler = null;
let ctrlAltTabManager = null; let ctrlAltTabManager = null;
let osdWindowManager = null; let osdWindow = null;
let sessionMode = null; let sessionMode = null;
let shellDBusService = null; let shellDBusService = null;
let shellMountOpDBusService = null; let shellMountOpDBusService = null;
@ -73,6 +73,7 @@ let _startDate;
let _defaultCssStylesheet = null; let _defaultCssStylesheet = null;
let _cssStylesheet = null; let _cssStylesheet = null;
let _a11ySettings = null; let _a11ySettings = null;
let dynamicWorkspacesSchema = null;
function _sessionUpdated() { function _sessionUpdated() {
_loadDefaultStylesheet(); _loadDefaultStylesheet();
@ -102,6 +103,9 @@ function start() {
global.logError = window.log; global.logError = window.log;
global.log = window.log; global.log = window.log;
if (!Meta.is_wayland_compositor)
Meta.is_wayland_compositor = function () { return false; };
// Chain up async errors reported from C // Chain up async errors reported from C
global.connect('notify-error', function (global, msg, detail) { notifyError(msg, detail); }); global.connect('notify-error', function (global, msg, detail) { notifyError(msg, detail); });
@ -109,6 +113,7 @@ function start() {
sessionMode = new SessionMode.SessionMode(); sessionMode = new SessionMode.SessionMode();
sessionMode.connect('updated', _sessionUpdated); sessionMode.connect('updated', _sessionUpdated);
_initializePrefs();
_initializeUI(); _initializeUI();
shellDBusService = new ShellDBus.GnomeShell(); shellDBusService = new ShellDBus.GnomeShell();
@ -117,6 +122,17 @@ function start() {
_sessionUpdated(); _sessionUpdated();
} }
function _initializePrefs() {
let keys = new Gio.Settings({ schema: sessionMode.overridesSchema }).list_keys();
for (let i = 0; i < keys.length; i++)
Meta.prefs_override_preference_schema(keys[i], sessionMode.overridesSchema);
if (keys.indexOf('dynamic-workspaces') > -1)
dynamicWorkspacesSchema = sessionMode.overridesSchema;
else
dynamicWorkspacesSchema = 'org.gnome.mutter';
}
function _initializeUI() { function _initializeUI() {
// Ensure ShellWindowTracker and ShellAppUsage are initialized; this will // Ensure ShellWindowTracker and ShellAppUsage are initialized; this will
// also initialize ShellAppSystem first. ShellAppSystem // also initialize ShellAppSystem first. ShellAppSystem
@ -142,7 +158,7 @@ function _initializeUI() {
screencastService = new Screencast.ScreencastService(); screencastService = new Screencast.ScreencastService();
xdndHandler = new XdndHandler.XdndHandler(); xdndHandler = new XdndHandler.XdndHandler();
ctrlAltTabManager = new CtrlAltTab.CtrlAltTabManager(); ctrlAltTabManager = new CtrlAltTab.CtrlAltTabManager();
osdWindowManager = new OsdWindow.OsdWindowManager(); osdWindow = new OsdWindow.OsdWindow();
overview = new Overview.Overview(); overview = new Overview.Overview();
wm = new WindowManager.WindowManager(); wm = new WindowManager.WindowManager();
magnifier = new Magnifier.Magnifier(); magnifier = new Magnifier.Magnifier();
@ -159,23 +175,13 @@ function _initializeUI() {
layoutManager.init(); layoutManager.init();
overview.init(); overview.init();
_a11ySettings = new Gio.Settings({ schema_id: A11Y_SCHEMA }); _a11ySettings = new Gio.Settings({ schema: A11Y_SCHEMA });
global.display.connect('overlay-key', Lang.bind(overview, function () { global.display.connect('overlay-key', Lang.bind(overview, function () {
if (!_a11ySettings.get_boolean (STICKY_KEYS_ENABLE)) if (!_a11ySettings.get_boolean (STICKY_KEYS_ENABLE))
overview.toggle(); overview.toggle();
})); }));
global.display.connect('show-restart-message', function(display, message) {
showRestartMessage(message);
return true;
});
global.display.connect('restart', function() {
global.reexec_self();
return true;
});
// Provide the bus object for gnome-session to // Provide the bus object for gnome-session to
// initiate logouts. // initiate logouts.
EndSessionDialog.init(); EndSessionDialog.init();
@ -185,6 +191,8 @@ function _initializeUI() {
_startDate = new Date(); _startDate = new Date();
log('GNOME Shell started at ' + _startDate);
let perfModuleName = GLib.getenv("SHELL_PERF_MODULE"); let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
if (perfModuleName) { if (perfModuleName) {
let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT"); let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT");
@ -202,24 +210,13 @@ function _initializeUI() {
} }
layoutManager.connect('startup-complete', function() { layoutManager.connect('startup-complete', function() {
if (keybindingMode == Shell.KeyBindingMode.NONE) { if (keybindingMode == Shell.KeyBindingMode.NONE) {
keybindingMode = Shell.KeyBindingMode.NORMAL; keybindingMode = Shell.KeyBindingMode.NORMAL;
} }
if (screenShield) { if (screenShield) {
screenShield.lockIfWasLocked(); screenShield.lockIfWasLocked();
} }
if (LoginManager.haveSystemd() && });
sessionMode.currentMode != 'gdm' &&
sessionMode.currentMode != 'initial-setup') {
// Do not import globally to not depend
// on systemd on non-systemd systems.
let GSystem = imports.gi.GSystem;
GSystem.log_structured_print('GNOME Shell started at ' + _startDate,
['MESSAGE_ID=' + GNOMESHELL_STARTED_MESSAGE_ID]);
} else {
log('GNOME Shell started at ' + _startDate);
}
});
} }
function _loadDefaultStylesheet() { function _loadDefaultStylesheet() {
@ -242,7 +239,8 @@ function _loadDefaultStylesheet() {
* Returns: A file path that contains the theme CSS, * Returns: A file path that contains the theme CSS,
* null if using the default * null if using the default
*/ */
function getThemeStylesheet() { function getThemeStylesheet()
{
return _cssStylesheet; return _cssStylesheet;
} }
@ -253,7 +251,8 @@ function getThemeStylesheet() {
* *
* Set the theme CSS file that the shell will load * Set the theme CSS file that the shell will load
*/ */
function setThemeStylesheet(cssStylesheet) { function setThemeStylesheet(cssStylesheet)
{
_cssStylesheet = cssStylesheet; _cssStylesheet = cssStylesheet;
} }
@ -452,7 +451,6 @@ function popModal(actor, timestamp) {
if (modalCount > 0) if (modalCount > 0)
return; return;
layoutManager.modalEnded();
global.end_modal(timestamp); global.end_modal(timestamp);
Meta.enable_unredirect_for_screen(global.screen); Meta.enable_unredirect_for_screen(global.screen);
keybindingMode = Shell.KeyBindingMode.NORMAL; keybindingMode = Shell.KeyBindingMode.NORMAL;
@ -613,31 +611,5 @@ function queueDeferredWork(workId) {
_deferredTimeoutId = 0; _deferredTimeoutId = 0;
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
GLib.Source.set_name_by_id(_deferredTimeoutId, '[gnome-shell] _runAllDeferredWork');
} }
} }
const RestartMessage = new Lang.Class({
Name: 'RestartMessage',
Extends: ModalDialog.ModalDialog,
_init : function(message) {
this.parent({ shellReactive: true,
styleClass: 'restart-message',
shouldFadeIn: false,
destroyOnClose: true });
let label = new St.Label({ text: message });
this.contentLayout.add(label, { x_fill: false,
y_fill: false,
x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE });
this.buttonLayout.hide();
}
});
function showRestartMessage(message) {
let restartMessage = new RestartMessage(message);
restartMessage.open();
}

View File

@ -15,7 +15,6 @@ const Signals = imports.signals;
const St = imports.gi.St; const St = imports.gi.St;
const Tp = imports.gi.TelepathyGLib; const Tp = imports.gi.TelepathyGLib;
const EdgeDragAction = imports.ui.edgeDragAction;
const BoxPointer = imports.ui.boxpointer; const BoxPointer = imports.ui.boxpointer;
const CtrlAltTab = imports.ui.ctrlAltTab; const CtrlAltTab = imports.ui.ctrlAltTab;
const GnomeSession = imports.misc.gnomeSession; const GnomeSession = imports.misc.gnomeSession;
@ -27,7 +26,6 @@ const PopupMenu = imports.ui.popupMenu;
const Params = imports.misc.params; const Params = imports.misc.params;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const Util = imports.misc.util; const Util = imports.misc.util;
const ViewSelector = imports.ui.viewSelector;
const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings'; const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
@ -113,6 +111,7 @@ const FocusGrabber = new Lang.Class({
if (this._focused) if (this._focused)
return; return;
this._prevFocusedWindow = global.display.focus_window;
this._prevKeyFocusActor = global.stage.get_key_focus(); this._prevKeyFocusActor = global.stage.get_key_focus();
this._focusActorChangedId = global.stage.connect('notify::key-focus', Lang.bind(this, this._focusActorChanged)); this._focusActorChangedId = global.stage.connect('notify::key-focus', Lang.bind(this, this._focusActorChanged));
@ -317,7 +316,7 @@ const NotificationGenericPolicy = new Lang.Class({
this.id = 'generic'; this.id = 'generic';
this._masterSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.notifications' }); this._masterSettings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications' });
this._masterSettings.connect('changed', Lang.bind(this, this._changed)); this._masterSettings.connect('changed', Lang.bind(this, this._changed));
}, },
@ -367,8 +366,8 @@ const NotificationApplicationPolicy = new Lang.Class({
this.id = id; this.id = id;
this._canonicalId = this._canonicalizeId(id); this._canonicalId = this._canonicalizeId(id);
this._masterSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.notifications' }); this._masterSettings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications' });
this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.notifications.application', this._settings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications.application',
path: '/org/gnome/desktop/notifications/application/' + this._canonicalId + '/' }); path: '/org/gnome/desktop/notifications/application/' + this._canonicalId + '/' });
this._masterSettings.connect('changed', Lang.bind(this, this._changed)); this._masterSettings.connect('changed', Lang.bind(this, this._changed));
@ -505,6 +504,7 @@ const Notification = new Lang.Class({
this.bannerBodyMarkup = false; this.bannerBodyMarkup = false;
this._bannerBodyAdded = false; this._bannerBodyAdded = false;
this._titleFitsInBannerMode = true; this._titleFitsInBannerMode = true;
this._titleDirection = Clutter.TextDirection.DEFAULT;
this._spacing = 0; this._spacing = 0;
this._scrollPolicy = Gtk.PolicyType.AUTOMATIC; this._scrollPolicy = Gtk.PolicyType.AUTOMATIC;
this._imageBin = null; this._imageBin = null;
@ -643,11 +643,10 @@ const Notification = new Lang.Class({
title = title ? _fixMarkup(title.replace(/\n/g, ' '), false) : ''; title = title ? _fixMarkup(title.replace(/\n/g, ' '), false) : '';
this._titleLabel.clutter_text.set_markup('<b>' + title + '</b>'); this._titleLabel.clutter_text.set_markup('<b>' + title + '</b>');
let titleDirection;
if (Pango.find_base_dir(title, -1) == Pango.Direction.RTL) if (Pango.find_base_dir(title, -1) == Pango.Direction.RTL)
titleDirection = Clutter.TextDirection.RTL; this._titleDirection = Clutter.TextDirection.RTL;
else else
titleDirection = Clutter.TextDirection.LTR; this._titleDirection = Clutter.TextDirection.LTR;
// Let the title's text direction control the overall direction // Let the title's text direction control the overall direction
// of the notification - in case where different scripts are used // of the notification - in case where different scripts are used
@ -655,7 +654,7 @@ const Notification = new Lang.Class({
// arguably for action buttons as well. Labels other than the title // arguably for action buttons as well. Labels other than the title
// will be allocated at the available width, so that their alignment // will be allocated at the available width, so that their alignment
// is done correctly automatically. // is done correctly automatically.
this._table.set_text_direction(titleDirection); this._table.set_text_direction(this._titleDirection);
// Unless the notification has custom content, we save this.bannerBodyText // Unless the notification has custom content, we save this.bannerBodyText
// to add it to the content of the notification if the notification is // to add it to the content of the notification if the notification is
@ -924,7 +923,7 @@ const Notification = new Lang.Class({
let [titleMinH, titleNatH] = this._titleLabel.get_preferred_height(availWidth); let [titleMinH, titleNatH] = this._titleLabel.get_preferred_height(availWidth);
let [bannerMinW, bannerNatW] = this._bannerLabel.get_preferred_width(availWidth); let [bannerMinW, bannerNatW] = this._bannerLabel.get_preferred_width(availWidth);
let rtl = (this._table.text_direction == Clutter.TextDirection.RTL); let rtl = (this._titleDirection == Clutter.TextDirection.RTL);
let x = rtl ? availWidth : 0; let x = rtl ? availWidth : 0;
if (this._secondaryIcon) { if (this._secondaryIcon) {
@ -1159,7 +1158,6 @@ const SourceActor = new Lang.Class({
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight)); this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this.actor.connect('allocate', Lang.bind(this, this._allocate)); this.actor.connect('allocate', Lang.bind(this, this._allocate));
this.actor.connect('destroy', Lang.bind(this, function() { this.actor.connect('destroy', Lang.bind(this, function() {
this._source.disconnect(this._iconUpdatedId);
this._actorDestroyed = true; this._actorDestroyed = true;
})); }));
this._actorDestroyed = false; this._actorDestroyed = false;
@ -1171,7 +1169,7 @@ const SourceActor = new Lang.Class({
this.actor.add_actor(this._iconBin); this.actor.add_actor(this._iconBin);
this._iconUpdatedId = this._source.connect('icon-updated', Lang.bind(this, this._updateIcon)); this._source.connect('icon-updated', Lang.bind(this, this._updateIcon));
this._updateIcon(); this._updateIcon();
}, },
@ -1229,12 +1227,8 @@ const SourceActorWithLabel = new Lang.Class({
this.actor.add_actor(this._counterBin); this.actor.add_actor(this._counterBin);
this._countUpdatedId = this._source.connect('count-updated', Lang.bind(this, this._updateCount)); this._source.connect('count-updated', Lang.bind(this, this._updateCount));
this._updateCount(); this._updateCount();
this.actor.connect('destroy', function() {
this._source.disconnect(this._countUpdatedId);
});
}, },
_allocate: function(actor, box, flags) { _allocate: function(actor, box, flags) {
@ -1817,13 +1811,6 @@ const MessageTray = new Lang.Class({
y_expand: true }); y_expand: true });
this.actor.add_actor(this._summary); this.actor.add_actor(this._summary);
this._focusTrap = new ViewSelector.FocusTrap({ can_focus: true });
this._focusTrap.connect('key-focus-in', Lang.bind(this,
function() {
this._messageTrayMenuButton.actor.grab_key_focus();
}));
this._summary.add_actor(this._focusTrap);
this._summaryMotionId = 0; this._summaryMotionId = 0;
this._summaryBoxPointer = new BoxPointer.BoxPointer(St.Side.BOTTOM, this._summaryBoxPointer = new BoxPointer.BoxPointer(St.Side.BOTTOM,
@ -1914,14 +1901,14 @@ const MessageTray = new Lang.Class({
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated)); Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
Main.wm.addKeybinding('toggle-message-tray', Main.wm.addKeybinding('toggle-message-tray',
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }), new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.NONE, Meta.KeyBindingFlags.NONE,
Shell.KeyBindingMode.NORMAL | Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.MESSAGE_TRAY | Shell.KeyBindingMode.MESSAGE_TRAY |
Shell.KeyBindingMode.OVERVIEW, Shell.KeyBindingMode.OVERVIEW,
Lang.bind(this, this.toggleAndNavigate)); Lang.bind(this, this.toggleAndNavigate));
Main.wm.addKeybinding('focus-active-notification', Main.wm.addKeybinding('focus-active-notification',
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }), new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.NONE, Meta.KeyBindingFlags.NONE,
Shell.KeyBindingMode.NORMAL | Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.MESSAGE_TRAY | Shell.KeyBindingMode.MESSAGE_TRAY |
@ -1947,13 +1934,6 @@ const MessageTray = new Lang.Class({
this._messageTrayMenuButton = new MessageTrayMenuButton(this); this._messageTrayMenuButton = new MessageTrayMenuButton(this);
this.actor.add_actor(this._messageTrayMenuButton.actor); this.actor.add_actor(this._messageTrayMenuButton.actor);
this._messageTrayMenuButton.actor.connect('key-press-event',
Lang.bind(this, this._onTrayButtonKeyPress));
let gesture = new EdgeDragAction.EdgeDragAction(St.Side.BOTTOM);
gesture.connect('activated', Lang.bind(this, this.toggle));
global.stage.add_action(gesture);
}, },
close: function() { close: function() {
@ -2007,7 +1987,6 @@ const MessageTray = new Lang.Class({
this._trayDwellTimeoutId = Mainloop.timeout_add(TRAY_DWELL_TIME, this._trayDwellTimeoutId = Mainloop.timeout_add(TRAY_DWELL_TIME,
Lang.bind(this, this._trayDwellTimeout)); Lang.bind(this, this._trayDwellTimeout));
GLib.Source.set_name_by_id(this._trayDwellTimeoutId, '[gnome-shell] this._trayDwellTimeout');
} }
this._trayDwelling = true; this._trayDwelling = true;
} else { } else {
@ -2046,16 +2025,6 @@ const MessageTray = new Lang.Class({
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}, },
_onTrayButtonKeyPress: function(actor, event) {
if (event.get_key_symbol() == Clutter.ISO_Left_Tab) {
this._focusTrap.can_focus = false;
this._summary.navigate_focus(null, Gtk.DirectionType.TAB_BACKWARD, false);
this._focusTrap.can_focus = true;
return Clutter.EVENT_STOP;
}
return Clutter.EVENT_PROPAGATE;
},
_onNotificationKeyRelease: function(actor, event) { _onNotificationKeyRelease: function(actor, event) {
if (event.get_key_symbol() == Clutter.KEY_Escape && event.get_state() == 0) { if (event.get_key_symbol() == Clutter.KEY_Escape && event.get_state() == 0) {
this._expireNotification(); this._expireNotification();
@ -2298,16 +2267,6 @@ const MessageTray = new Lang.Class({
this._grabHelper.addActor(corner.actor); this._grabHelper.addActor(corner.actor);
}, },
_resetNotificationLeftTimeout: function() {
this._useLongerNotificationLeftTimeout = false;
if (this._notificationLeftTimeoutId) {
Mainloop.source_remove(this._notificationLeftTimeoutId);
this._notificationLeftTimeoutId = 0;
this._notificationLeftMouseX = -1;
this._notificationLeftMouseY = -1;
}
},
_onNotificationHoverChanged: function() { _onNotificationHoverChanged: function() {
if (this._notificationWidget.hover == this._notificationHovered) if (this._notificationWidget.hover == this._notificationHovered)
return; return;
@ -2317,7 +2276,14 @@ const MessageTray = new Lang.Class({
// No dwell inside notifications at the bottom of the screen // No dwell inside notifications at the bottom of the screen
this._cancelTrayDwell(); this._cancelTrayDwell();
this._resetNotificationLeftTimeout(); this._useLongerNotificationLeftTimeout = false;
if (this._notificationLeftTimeoutId) {
Mainloop.source_remove(this._notificationLeftTimeoutId);
this._notificationLeftTimeoutId = 0;
this._notificationLeftMouseX = -1;
this._notificationLeftMouseY = -1;
return;
}
if (this._showNotificationMouseX >= 0) { if (this._showNotificationMouseX >= 0) {
let actorAtShowNotificationPosition = let actorAtShowNotificationPosition =
@ -2334,7 +2300,6 @@ const MessageTray = new Lang.Class({
return; return;
} }
} }
this._pointerInNotification = true; this._pointerInNotification = true;
this._updateState(); this._updateState();
} else { } else {
@ -2351,7 +2316,6 @@ const MessageTray = new Lang.Class({
// That gives the user more time to mouse away from the notification and mouse back in in order to expand it. // That gives the user more time to mouse away from the notification and mouse back in in order to expand it.
let timeout = this._useLongerNotificationLeftTimeout ? LONGER_HIDE_TIMEOUT * 1000 : HIDE_TIMEOUT * 1000; let timeout = this._useLongerNotificationLeftTimeout ? LONGER_HIDE_TIMEOUT * 1000 : HIDE_TIMEOUT * 1000;
this._notificationLeftTimeoutId = Mainloop.timeout_add(timeout, Lang.bind(this, this._onNotificationLeftTimeout)); this._notificationLeftTimeoutId = Mainloop.timeout_add(timeout, Lang.bind(this, this._onNotificationLeftTimeout));
GLib.Source.set_name_by_id(this._notificationLeftTimeoutId, '[gnome-shell] this._onNotificationLeftTimeout');
} }
}, },
@ -2387,7 +2351,6 @@ const MessageTray = new Lang.Class({
this._notificationLeftMouseX = -1; this._notificationLeftMouseX = -1;
this._notificationLeftTimeoutId = Mainloop.timeout_add(LONGER_HIDE_TIMEOUT * 1000, this._notificationLeftTimeoutId = Mainloop.timeout_add(LONGER_HIDE_TIMEOUT * 1000,
Lang.bind(this, this._onNotificationLeftTimeout)); Lang.bind(this, this._onNotificationLeftTimeout));
GLib.Source.set_name_by_id(this._notificationLeftTimeoutId, '[gnome-shell] this._onNotificationLeftTimeout');
} else { } else {
this._notificationLeftTimeoutId = 0; this._notificationLeftTimeoutId = 0;
this._useLongerNotificationLeftTimeout = false; this._useLongerNotificationLeftTimeout = false;
@ -2432,22 +2395,8 @@ const MessageTray = new Lang.Class({
if (shouldShowNotification && nextNotification) { if (shouldShowNotification && nextNotification) {
let limited = this._busy || Main.layoutManager.bottomMonitor.inFullscreen; let limited = this._busy || Main.layoutManager.bottomMonitor.inFullscreen;
let showNextNotification = (!limited || nextNotification.forFeedback || nextNotification.urgency == Urgency.CRITICAL); let showNextNotification = (!limited || nextNotification.forFeedback || nextNotification.urgency == Urgency.CRITICAL);
if (showNextNotification) { if (showNextNotification)
let len = this._notificationQueue.length; this._showNotification();
if (len > 1) {
this._notificationQueue.length = 0;
let source = new SystemNotificationSource();
this.add(source);
let notification = new Notification(source, ngettext("%d new message", "%d new messages", len).format(len));
notification.setTransient(true);
notification.connect('clicked', Lang.bind(this, function() {
this.openTray();
}));
source.notify(notification);
} else {
this._showNotification();
}
}
} }
} else if (this._notificationState == State.SHOWN) { } else if (this._notificationState == State.SHOWN) {
let expired = (this._userActiveWhileNotificationShown && let expired = (this._userActiveWhileNotificationShown &&
@ -2675,8 +2624,6 @@ const MessageTray = new Lang.Class({
// the mouse is moving towards it or within it. // the mouse is moving towards it or within it.
this._lastSeenMouseX = x; this._lastSeenMouseX = x;
this._lastSeenMouseY = y; this._lastSeenMouseY = y;
this._resetNotificationLeftTimeout();
}, },
_updateShowingNotification: function() { _updateShowingNotification: function() {
@ -2721,12 +2668,10 @@ const MessageTray = new Lang.Class({
Mainloop.source_remove(this._notificationTimeoutId); Mainloop.source_remove(this._notificationTimeoutId);
this._notificationTimeoutId = 0; this._notificationTimeoutId = 0;
} }
if (timeout > 0) { if (timeout > 0)
this._notificationTimeoutId = this._notificationTimeoutId =
Mainloop.timeout_add(timeout, Mainloop.timeout_add(timeout,
Lang.bind(this, this._notificationTimeout)); Lang.bind(this, this._notificationTimeout));
GLib.Source.set_name_by_id(this._notificationTimeoutId, '[gnome-shell] this._notificationTimeout');
}
}, },
_notificationTimeout: function() { _notificationTimeout: function() {
@ -2769,7 +2714,13 @@ const MessageTray = new Lang.Class({
this._notificationUnfocusedId = 0; this._notificationUnfocusedId = 0;
} }
this._resetNotificationLeftTimeout(); this._useLongerNotificationLeftTimeout = false;
if (this._notificationLeftTimeoutId) {
Mainloop.source_remove(this._notificationLeftTimeoutId);
this._notificationLeftTimeoutId = 0;
this._notificationLeftMouseX = -1;
this._notificationLeftMouseY = -1;
}
if (animate) { if (animate) {
this._tween(this._notificationWidget, '_notificationState', State.HIDDEN, this._tween(this._notificationWidget, '_notificationState', State.HIDDEN,

View File

@ -43,7 +43,6 @@ const ModalDialog = new Lang.Class({
styleClass: null, styleClass: null,
keybindingMode: Shell.KeyBindingMode.SYSTEM_MODAL, keybindingMode: Shell.KeyBindingMode.SYSTEM_MODAL,
shouldFadeIn: true, shouldFadeIn: true,
shouldFadeOut: true,
destroyOnClose: true }); destroyOnClose: true });
this.state = State.CLOSED; this.state = State.CLOSED;
@ -51,7 +50,6 @@ const ModalDialog = new Lang.Class({
this._keybindingMode = params.keybindingMode; this._keybindingMode = params.keybindingMode;
this._shellReactive = params.shellReactive; this._shellReactive = params.shellReactive;
this._shouldFadeIn = params.shouldFadeIn; this._shouldFadeIn = params.shouldFadeIn;
this._shouldFadeOut = params.shouldFadeOut;
this._destroyOnClose = params.destroyOnClose; this._destroyOnClose = params.destroyOnClose;
this._group = new St.Widget({ visible: false, this._group = new St.Widget({ visible: false,
@ -309,15 +307,6 @@ const ModalDialog = new Lang.Class({
return true; return true;
}, },
_closeComplete: function() {
this.state = State.CLOSED;
this._group.hide();
this.emit('closed');
if (this._destroyOnClose)
this.destroy();
},
close: function(timestamp) { close: function(timestamp) {
if (this.state == State.CLOSED || this.state == State.CLOSING) if (this.state == State.CLOSED || this.state == State.CLOSING)
return; return;
@ -326,16 +315,20 @@ const ModalDialog = new Lang.Class({
this.popModal(timestamp); this.popModal(timestamp);
this._savedKeyFocus = null; this._savedKeyFocus = null;
if (this._shouldFadeOut) Tweener.addTween(this._group,
Tweener.addTween(this._group, { opacity: 0,
{ opacity: 0, time: OPEN_AND_CLOSE_TIME,
time: OPEN_AND_CLOSE_TIME, transition: 'easeOutQuad',
transition: 'easeOutQuad', onComplete: Lang.bind(this,
onComplete: Lang.bind(this, function() {
this._closeComplete) this.state = State.CLOSED;
}) this._group.hide();
else this.emit('closed');
this._closeComplete();
if (this._destroyOnClose)
this.destroy();
})
});
}, },
// Drop modal status without closing the dialog; this makes the // Drop modal status without closing the dialog; this makes the

View File

@ -120,12 +120,15 @@ const FdoNotificationDaemon = new Lang.Class({
this._nextNotificationId = 1; this._nextNotificationId = 1;
Shell.WindowTracker.get_default().connect('notify::focus-app', Lang.bind(this, this._onFocusAppChanged));
Main.overview.connect('hidden', Lang.bind(this, this._onFocusAppChanged));
this._trayManager = new Shell.TrayManager(); this._trayManager = new Shell.TrayManager();
this._trayIconAddedId = this._trayManager.connect('tray-icon-added', Lang.bind(this, this._onTrayIconAdded)); this._trayIconAddedId = this._trayManager.connect('tray-icon-added', Lang.bind(this, this._onTrayIconAdded));
this._trayIconRemovedId = this._trayManager.connect('tray-icon-removed', Lang.bind(this, this._onTrayIconRemoved)); this._trayIconRemovedId = this._trayManager.connect('tray-icon-removed', Lang.bind(this, this._onTrayIconRemoved));
Shell.WindowTracker.get_default().connect('notify::focus-app',
Lang.bind(this, this._onFocusAppChanged));
Main.overview.connect('hidden',
Lang.bind(this, this._onFocusAppChanged));
this._trayManager.manage_screen(global.screen, Main.messageTray.actor); this._trayManager.manage_screen(global.screen, Main.messageTray.actor);
}, },
@ -241,12 +244,11 @@ const FdoNotificationDaemon = new Lang.Class({
// Ignore replacesId since we already sent back a // Ignore replacesId since we already sent back a
// NotificationClosed for that id. // NotificationClosed for that id.
id = this._nextNotificationId++; id = this._nextNotificationId++;
let idle_id = Mainloop.idle_add(Lang.bind(this, Mainloop.idle_add(Lang.bind(this,
function () { function () {
this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED); this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(idle_id, '[gnome-shell] this._emitNotificationClosed');
return invocation.return_value(GLib.Variant.new('(u)', [id])); return invocation.return_value(GLib.Variant.new('(u)', [id]));
} }
@ -689,12 +691,6 @@ const FdoNotificationDaemonSource = new Lang.Class({
} }
}); });
const PRIORITY_URGENCY_MAP = {
low: MessageTray.Urgency.LOW,
normal: MessageTray.Urgency.NORMAL,
high: MessageTray.Urgency.HIGH,
urgent: MessageTray.Urgency.CRITICAL
};
const GtkNotificationDaemonNotification = new Lang.Class({ const GtkNotificationDaemonNotification = new Lang.Class({
Name: 'GtkNotificationDaemonNotification', Name: 'GtkNotificationDaemonNotification',
@ -708,20 +704,12 @@ const GtkNotificationDaemonNotification = new Lang.Class({
"body": body, "body": body,
"icon": gicon, "icon": gicon,
"urgent": urgent, "urgent": urgent,
"priority": priority,
"buttons": buttons, "buttons": buttons,
"default-action": defaultAction, "default-action": defaultAction,
"default-action-target": defaultActionTarget } = notification; "default-action-target": defaultActionTarget } = notification;
if (priority) { this.setUrgency(urgent.unpack() ? MessageTray.Urgency.CRITICAL
let urgency = PRIORITY_URGENCY_MAP[priority.unpack()]; : MessageTray.Urgency.NORMAL);
this.setUrgency(urgency != undefined ? urgency : MessageTray.Urgency.NORMAL);
} else if (urgent) {
this.setUrgency(urgent.unpack() ? MessageTray.Urgency.CRITICAL
: MessageTray.Urgency.NORMAL);
} else {
this.setUrgency(MessageTray.Urgency.NORMAL);
}
if (buttons) { if (buttons) {
buttons.deep_unpack().forEach(Lang.bind(this, function(button) { buttons.deep_unpack().forEach(Lang.bind(this, function(button) {

View File

@ -73,17 +73,14 @@ const LevelBar = new Lang.Class({
const OsdWindow = new Lang.Class({ const OsdWindow = new Lang.Class({
Name: 'OsdWindow', Name: 'OsdWindow',
_init: function(monitorIndex) { _init: function() {
this._popupSize = 0; this._popupSize = 0;
this.actor = new St.Widget({ x_expand: true, this.actor = new St.Widget({ x_expand: true,
y_expand: true, y_expand: true,
x_align: Clutter.ActorAlign.CENTER, x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER }); y_align: Clutter.ActorAlign.CENTER });
this._currentMonitor = undefined;
this._monitorIndex = monitorIndex; this.setMonitor (-1);
let constraint = new Layout.MonitorConstraint({ index: monitorIndex });
this.actor.add_constraint(constraint);
this._box = new St.BoxLayout({ style_class: 'osd-window', this._box = new St.BoxLayout({ style_class: 'osd-window',
vertical: true }); vertical: true });
this.actor.add_actor(this._box); this.actor.add_actor(this._box);
@ -112,6 +109,7 @@ const OsdWindow = new Lang.Class({
Main.layoutManager.connect('monitors-changed', Main.layoutManager.connect('monitors-changed',
Lang.bind(this, this._monitorsChanged)); Lang.bind(this, this._monitorsChanged));
this._monitorsChanged(); this._monitorsChanged();
Main.uiGroup.add_child(this.actor); Main.uiGroup.add_child(this.actor);
}, },
@ -158,7 +156,6 @@ const OsdWindow = new Lang.Class({
Mainloop.source_remove(this._hideTimeoutId); Mainloop.source_remove(this._hideTimeoutId);
this._hideTimeoutId = Mainloop.timeout_add(HIDE_TIMEOUT, this._hideTimeoutId = Mainloop.timeout_add(HIDE_TIMEOUT,
Lang.bind(this, this._hide)); Lang.bind(this, this._hide));
GLib.Source.set_name_by_id(this._hideTimeoutId, '[gnome-shell] this._hide');
}, },
cancel: function() { cancel: function() {
@ -191,9 +188,12 @@ const OsdWindow = new Lang.Class({
_monitorsChanged: function() { _monitorsChanged: function() {
/* assume 110x110 on a 640x480 display and scale from there */ /* assume 110x110 on a 640x480 display and scale from there */
let monitor = Main.layoutManager.monitors[this._monitorIndex]; let monitor;
if (!monitor)
return; // we are about to be removed if (this._currentMonitor >= 0)
monitor = Main.layoutManager.monitors[this._currentMonitor];
else
monitor = Main.layoutManager.primaryMonitor;
let scalew = monitor.width / 640.0; let scalew = monitor.width / 640.0;
let scaleh = monitor.height / 480.0; let scaleh = monitor.height / 480.0;
@ -222,56 +222,23 @@ const OsdWindow = new Lang.Class({
// but the theme takes measures in unscaled dimensions // but the theme takes measures in unscaled dimensions
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._box.style = 'min-height: %dpx;'.format(Math.max(minWidth, minHeight) / scaleFactor); this._box.style = 'min-height: %dpx;'.format(Math.max(minWidth, minHeight) / scaleFactor);
} },
});
setMonitor: function(index) {
const OsdWindowManager = new Lang.Class({ let constraint;
Name: 'OsdWindowManager',
if (index < 0)
_init: function() { index = -1;
this._osdWindows = []; if (this._currentMonitor == index)
Main.layoutManager.connect('monitors-changed', return;
Lang.bind(this, this._monitorsChanged));
this._monitorsChanged(); if (index < 0)
}, constraint = new Layout.MonitorConstraint({ primary: true });
else
_monitorsChanged: function() { constraint = new Layout.MonitorConstraint({ index: index });
for (let i = 0; i < Main.layoutManager.monitors.length; i++) {
if (this._osdWindows[i] == undefined) this.actor.clear_constraints();
this._osdWindows[i] = new OsdWindow(i); this.actor.add_constraint(constraint);
} this._currentMonitor = index;
for (let i = Main.layoutManager.monitors.length; i < this._osdWindows.length; i++) {
this._osdWindows[i].actor.destroy();
this._osdWindows[i] = null;
}
this._osdWindows.length = Main.layoutManager.monitors.length;
},
_showOsdWindow: function(monitorIndex, icon, label, level) {
this._osdWindows[monitorIndex].setIcon(icon);
this._osdWindows[monitorIndex].setLabel(label);
this._osdWindows[monitorIndex].setLevel(level);
this._osdWindows[monitorIndex].show();
},
show: function(monitorIndex, icon, label, level) {
if (monitorIndex != -1) {
for (let i = 0; i < this._osdWindows.length; i++) {
if (i == monitorIndex)
this._showOsdWindow(i, icon, label, level);
else
this._osdWindows[i].cancel();
}
} else {
for (let i = 0; i < this._osdWindows.length; i++)
this._showOsdWindow(i, icon, label, level);
}
},
hideAll: function() {
for (let i = 0; i < this._osdWindows.length; i++)
this._osdWindows[i].cancel();
} }
}); });

View File

@ -185,7 +185,7 @@ const Overview = new Lang.Class({
for (let i = 0; i < Main.layoutManager.monitors.length; i++) { for (let i = 0; i < Main.layoutManager.monitors.length; i++) {
let bgManager = new Background.BackgroundManager({ container: this._backgroundGroup, let bgManager = new Background.BackgroundManager({ container: this._backgroundGroup,
monitorIndex: i, monitorIndex: i,
vignette: true }); effects: Meta.BackgroundEffects.VIGNETTE });
this._bgManagers.push(bgManager); this._bgManagers.push(bgManager);
} }
}, },
@ -193,9 +193,11 @@ const Overview = new Lang.Class({
_unshadeBackgrounds: function() { _unshadeBackgrounds: function() {
let backgrounds = this._backgroundGroup.get_children(); let backgrounds = this._backgroundGroup.get_children();
for (let i = 0; i < backgrounds.length; i++) { for (let i = 0; i < backgrounds.length; i++) {
Tweener.addTween(backgrounds[i], let background = backgrounds[i]._delegate;
Tweener.addTween(background,
{ brightness: 1.0, { brightness: 1.0,
vignette_sharpness: 0.0, vignetteSharpness: 0.0,
time: SHADE_ANIMATION_TIME, time: SHADE_ANIMATION_TIME,
transition: 'easeOutQuad' transition: 'easeOutQuad'
}); });
@ -205,9 +207,11 @@ const Overview = new Lang.Class({
_shadeBackgrounds: function() { _shadeBackgrounds: function() {
let backgrounds = this._backgroundGroup.get_children(); let backgrounds = this._backgroundGroup.get_children();
for (let i = 0; i < backgrounds.length; i++) { for (let i = 0; i < backgrounds.length; i++) {
Tweener.addTween(backgrounds[i], let background = backgrounds[i]._delegate;
Tweener.addTween(background,
{ brightness: Lightbox.VIGNETTE_BRIGHTNESS, { brightness: Lightbox.VIGNETTE_BRIGHTNESS,
vignette_sharpness: Lightbox.VIGNETTE_SHARPNESS, vignetteSharpness: Lightbox.VIGNETTE_SHARPNESS,
time: SHADE_ANIMATION_TIME, time: SHADE_ANIMATION_TIME,
transition: 'easeOutQuad' transition: 'easeOutQuad'
}); });
@ -238,7 +242,7 @@ const Overview = new Lang.Class({
opacity: 0 }); opacity: 0 });
this._overview.add_actor(this._panelGhost); this._overview.add_actor(this._panelGhost);
this._searchEntry = new St.Entry({ style_class: 'search-entry', this._searchEntry = new St.Entry({ name: 'searchEntry',
/* Translators: this is the text displayed /* Translators: this is the text displayed
in the search entry when no search is in the search entry when no search is
active; it should not exceed ~30 active; it should not exceed ~30
@ -361,7 +365,6 @@ const Overview = new Lang.Class({
this._lastHoveredWindow = null; this._lastHoveredWindow = null;
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(this._windowSwitchTimeoutId, '[gnome-shell] Main.activateWindow');
} }
return DND.DragMotionResult.CONTINUE; return DND.DragMotionResult.CONTINUE;
@ -421,6 +424,8 @@ const Overview = new Lang.Class({
this.emit('windows-restacked', stackIndices); this.emit('windows-restacked', stackIndices);
}, },
//// Public methods ////
beginItemDrag: function(source) { beginItemDrag: function(source) {
this.emit('item-drag-begin'); this.emit('item-drag-begin');
this._inDrag = true; this._inDrag = true;
@ -435,20 +440,37 @@ const Overview = new Lang.Class({
this._inDrag = false; this._inDrag = false;
}, },
beginWindowDrag: function(window) { beginWindowDrag: function(clone) {
this.emit('window-drag-begin', window); this.emit('window-drag-begin', clone);
this._inDrag = true; this._inDrag = true;
}, },
cancelledWindowDrag: function(window) { cancelledWindowDrag: function(clone) {
this.emit('window-drag-cancelled', window); this.emit('window-drag-cancelled', clone);
}, },
endWindowDrag: function(window) { endWindowDrag: function(clone) {
this.emit('window-drag-end', window); this.emit('window-drag-end', clone);
this._inDrag = false; this._inDrag = false;
}, },
// show:
//
// Animates the overview visible and grabs mouse and keyboard input
show: function() {
if (this.isDummy)
return;
if (this._shown)
return;
this._shown = true;
if (!this._syncGrab())
return;
Main.layoutManager.showOverview();
this._animateVisible();
},
focusSearch: function() { focusSearch: function() {
this.show(); this.show();
this._searchEntry.grab_key_focus(); this._searchEntry.grab_key_focus();
@ -481,6 +503,69 @@ const Overview = new Lang.Class({
}); });
}, },
_animateVisible: function() {
if (this.visible || this.animationInProgress)
return;
this.visible = true;
this.animationInProgress = true;
this.visibleTarget = true;
this._activationTime = Date.now() / 1000;
Meta.disable_unredirect_for_screen(global.screen);
this.viewSelector.show();
this._stack.opacity = 0;
Tweener.addTween(this._stack,
{ opacity: 255,
transition: 'easeOutQuad',
time: ANIMATION_TIME,
onComplete: this._showDone,
onCompleteScope: this
});
this._shadeBackgrounds();
this._coverPane.raise_top();
this._coverPane.show();
this.emit('showing');
},
// hide:
//
// Reverses the effect of show()
hide: function() {
if (this.isDummy)
return;
if (!this._shown)
return;
let event = Clutter.get_current_event();
if (event) {
let type = event.type();
let button = (type == Clutter.EventType.BUTTON_PRESS ||
type == Clutter.EventType.BUTTON_RELEASE);
let ctrl = (event.get_state() & Clutter.ModifierType.CONTROL_MASK) != 0;
if (button && ctrl)
return;
}
this._animateNotVisible();
this._shown = false;
this._syncGrab();
},
toggle: function() {
if (this.isDummy)
return;
if (this.visible)
this.hide();
else
this.show();
},
// Checks if the Activities button is currently sensitive to // Checks if the Activities button is currently sensitive to
// clicks. The first call to this function within the // clicks. The first call to this function within the
// OVERVIEW_ACTIVATION_TIMEOUT time of the hot corner being // OVERVIEW_ACTIVATION_TIMEOUT time of the hot corner being
@ -497,6 +582,8 @@ const Overview = new Lang.Class({
return false; return false;
}, },
//// Private methods ////
_syncGrab: function() { _syncGrab: function() {
// We delay grab changes during animation so that when removing the // We delay grab changes during animation so that when removing the
// overview we don't have a problem with the release of a press/release // overview we don't have a problem with the release of a press/release
@ -526,92 +613,6 @@ const Overview = new Lang.Class({
return true; return true;
}, },
// show:
//
// Animates the overview visible and grabs mouse and keyboard input
show: function() {
if (this.isDummy)
return;
if (this._shown)
return;
this._shown = true;
if (!this._syncGrab())
return;
Main.layoutManager.showOverview();
this._animateVisible();
},
_animateVisible: function() {
if (this.visible || this.animationInProgress)
return;
this.visible = true;
this.animationInProgress = true;
this.visibleTarget = true;
this._activationTime = Date.now() / 1000;
Meta.disable_unredirect_for_screen(global.screen);
this.viewSelector.show();
this._stack.opacity = 0;
Tweener.addTween(this._stack,
{ opacity: 255,
transition: 'easeOutQuad',
time: ANIMATION_TIME,
onComplete: this._showDone,
onCompleteScope: this
});
this._shadeBackgrounds();
this._coverPane.raise_top();
this._coverPane.show();
this.emit('showing');
},
_showDone: function() {
this.animationInProgress = false;
this._desktopFade.hide();
this._coverPane.hide();
this.emit('shown');
// Handle any calls to hide* while we were showing
if (!this._shown)
this._animateNotVisible();
this._syncGrab();
global.sync_pointer();
},
// hide:
//
// Reverses the effect of show()
hide: function() {
if (this.isDummy)
return;
if (!this._shown)
return;
let event = Clutter.get_current_event();
if (event) {
let type = event.type();
let button = (type == Clutter.EventType.BUTTON_PRESS ||
type == Clutter.EventType.BUTTON_RELEASE);
let ctrl = (event.get_state() & Clutter.ModifierType.CONTROL_MASK) != 0;
if (button && ctrl)
return;
}
this._animateNotVisible();
this._shown = false;
this._syncGrab();
},
_animateNotVisible: function() { _animateNotVisible: function() {
if (!this.visible || this.animationInProgress) if (!this.visible || this.animationInProgress)
return; return;
@ -619,7 +620,7 @@ const Overview = new Lang.Class({
this.animationInProgress = true; this.animationInProgress = true;
this.visibleTarget = false; this.visibleTarget = false;
this.viewSelector.animateFromOverview(); this.viewSelector.zoomFromOverview();
// Make other elements fade out. // Make other elements fade out.
Tweener.addTween(this._stack, Tweener.addTween(this._stack,
@ -636,6 +637,20 @@ const Overview = new Lang.Class({
this.emit('hiding'); this.emit('hiding');
}, },
_showDone: function() {
this.animationInProgress = false;
this._desktopFade.hide();
this._coverPane.hide();
this.emit('shown');
// Handle any calls to hide* while we were showing
if (!this._shown)
this._animateNotVisible();
this._syncGrab();
global.sync_pointer();
},
_hideDone: function() { _hideDone: function() {
// Re-enable unredirection // Re-enable unredirection
Meta.enable_unredirect_for_screen(global.screen); Meta.enable_unredirect_for_screen(global.screen);
@ -661,20 +676,6 @@ const Overview = new Lang.Class({
this._fakePointerEvent(); this._fakePointerEvent();
this._needsFakePointerEvent = false; this._needsFakePointerEvent = false;
} }
},
toggle: function() {
if (this.isDummy)
return;
if (this.visible)
this.hide();
else
this.show();
},
getShowAppsButton: function() {
return this._dash.showAppsButton;
} }
}); });
Signals.addSignalMethods(Overview.prototype); Signals.addSignalMethods(Overview.prototype);

View File

@ -36,7 +36,7 @@ const SlideLayout = new Lang.Class({
_init: function(params) { _init: function(params) {
this._slideX = 1; this._slideX = 1;
this._translationX = undefined; this._translationX = 0;
this._direction = SlideDirection.LEFT; this._direction = SlideDirection.LEFT;
this.parent(params); this.parent(params);
@ -64,8 +64,7 @@ const SlideLayout = new Lang.Class({
// flags only determine what to do if the allocated box is bigger // flags only determine what to do if the allocated box is bigger
// than the actor's box. // than the actor's box.
let realDirection = getRtlSlideDirection(this._direction, child); let realDirection = getRtlSlideDirection(this._direction, child);
let alignX = (realDirection == SlideDirection.LEFT) ? (availWidth - natWidth) let alignX = (realDirection == SlideDirection.LEFT) ? (availWidth - natWidth) : 0;
: (availWidth - natWidth * this._slideX);
let actorBox = new Clutter.ActorBox(); let actorBox = new Clutter.ActorBox();
actorBox.x1 = box.x1 + alignX + this._translationX; actorBox.x1 = box.x1 + alignX + this._translationX;
@ -119,6 +118,7 @@ const SlidingControl = new Lang.Class({
style_class: 'overview-controls', style_class: 'overview-controls',
clip_to_allocation: true }); clip_to_allocation: true });
Main.overview.connect('showing', Lang.bind(this, this._onOverviewShowing));
Main.overview.connect('hiding', Lang.bind(this, this._onOverviewHiding)); Main.overview.connect('hiding', Lang.bind(this, this._onOverviewHiding));
Main.overview.connect('item-drag-begin', Lang.bind(this, this._onDragBegin)); Main.overview.connect('item-drag-begin', Lang.bind(this, this._onDragBegin));
@ -162,8 +162,7 @@ const SlidingControl = new Lang.Class({
let translationEnd = 0; let translationEnd = 0;
let translation = this._getTranslation(); let translation = this._getTranslation();
let shouldShow = (this._getSlide() > 0); if (this._visible) {
if (shouldShow) {
translationStart = translation; translationStart = translation;
} else { } else {
translationEnd = translation; translationEnd = translation;
@ -178,9 +177,14 @@ const SlidingControl = new Lang.Class({
transition: 'easeOutQuad' }); transition: 'easeOutQuad' });
}, },
_onOverviewShowing: function() {
this._visible = true;
this.layout.slideX = this._getSlide();
this.layout.translationX = this._getTranslation();
this.slideIn();
},
_onOverviewHiding: function() { _onOverviewHiding: function() {
// We need to explicitly slideOut since showing pages
// doesn't imply sliding out, instead, hiding the overview does.
this.slideOut(); this.slideOut();
}, },
@ -194,7 +198,7 @@ const SlidingControl = new Lang.Class({
_onDragBegin: function() { _onDragBegin: function() {
this._inDrag = true; this._inDrag = true;
this._updateTranslation(); this.layout.translationX = 0;
this._updateSlide(); this._updateSlide();
}, },
@ -219,6 +223,7 @@ const SlidingControl = new Lang.Class({
slideIn: function() { slideIn: function() {
this._visible = true; this._visible = true;
this._updateTranslation();
// we will update slideX and the translation from pageEmpty // we will update slideX and the translation from pageEmpty
}, },
@ -254,18 +259,13 @@ const ThumbnailsSlider = new Lang.Class({
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._updateSlide)); Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._updateSlide));
this.actor.connect('notify::hover', Lang.bind(this, this._updateSlide)); this.actor.connect('notify::hover', Lang.bind(this, this._updateSlide));
global.window_manager.connect('switch-workspace', Lang.bind(this, this._updateSlide));
this._thumbnailsBox.actor.bind_property('visible', this.actor, 'visible', GObject.BindingFlags.SYNC_CREATE); this._thumbnailsBox.actor.bind_property('visible', this.actor, 'visible', GObject.BindingFlags.SYNC_CREATE);
}, },
_getAlwaysZoomOut: function() { _getAlwaysZoomOut: function() {
// Always show the pager when hover, during a drag, or if workspaces are // Always show the pager when hover, during a drag, or if workspaces are
// actually used, e.g. there are windows on any non-active workspace // actually used, e.g. there are windows on more than one
let alwaysZoomOut = this.actor.hover || let alwaysZoomOut = this.actor.hover || this._inDrag || !Meta.prefs_get_dynamic_workspaces() || global.screen.n_workspaces > 2;
this._inDrag ||
!Meta.prefs_get_dynamic_workspaces() ||
global.screen.n_workspaces > 2 ||
global.screen.get_active_workspace_index() != 0;
if (!alwaysZoomOut) { if (!alwaysZoomOut) {
let monitors = Main.layoutManager.monitors; let monitors = Main.layoutManager.monitors;

View File

@ -14,6 +14,7 @@ const St = imports.gi.St;
const Signals = imports.signals; const Signals = imports.signals;
const Atk = imports.gi.Atk; const Atk = imports.gi.Atk;
const Animation = imports.ui.animation; const Animation = imports.ui.animation;
const Config = imports.misc.config; const Config = imports.misc.config;
const CtrlAltTab = imports.ui.ctrlAltTab; const CtrlAltTab = imports.ui.ctrlAltTab;
@ -571,6 +572,7 @@ const ActivitiesButton = new Lang.Class({
this.actor.label_actor = this._label; this.actor.label_actor = this._label;
this.actor.connect('captured-event', Lang.bind(this, this._onCapturedEvent)); this.actor.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
this.actor.connect_after('button-release-event', Lang.bind(this, this._onButtonRelease));
this.actor.connect_after('key-release-event', Lang.bind(this, this._onKeyRelease)); this.actor.connect_after('key-release-event', Lang.bind(this, this._onKeyRelease));
Main.overview.connect('showing', Lang.bind(this, function() { Main.overview.connect('showing', Lang.bind(this, function() {
@ -593,27 +595,21 @@ const ActivitiesButton = new Lang.Class({
Mainloop.source_remove(this._xdndTimeOut); Mainloop.source_remove(this._xdndTimeOut);
this._xdndTimeOut = Mainloop.timeout_add(BUTTON_DND_ACTIVATION_TIMEOUT, this._xdndTimeOut = Mainloop.timeout_add(BUTTON_DND_ACTIVATION_TIMEOUT,
Lang.bind(this, this._xdndToggleOverview, actor)); Lang.bind(this, this._xdndToggleOverview, actor));
GLib.Source.set_name_by_id(this._xdndTimeOut, '[gnome-shell] this._xdndToggleOverview');
return DND.DragMotionResult.CONTINUE; return DND.DragMotionResult.CONTINUE;
}, },
_onCapturedEvent: function(actor, event) { _onCapturedEvent: function(actor, event) {
if (event.type() == Clutter.EventType.BUTTON_PRESS || if (event.type() == Clutter.EventType.BUTTON_PRESS) {
event.type() == Clutter.EventType.TOUCH_BEGIN) {
if (!Main.overview.shouldToggleByCornerOrButton()) if (!Main.overview.shouldToggleByCornerOrButton())
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
}, },
_onEvent: function(actor, event) { _onButtonRelease: function() {
this.parent(actor, event); Main.overview.toggle();
this.menu.close();
if (event.type() == Clutter.EventType.TOUCH_END ||
event.type() == Clutter.EventType.BUTTON_RELEASE)
Main.overview.toggle();
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
}, },
@ -1019,7 +1015,7 @@ const Panel = new Lang.Class({
if (!dragWindow) if (!dragWindow)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
let rect = dragWindow.get_frame_rect(); let rect = dragWindow.get_outer_rect();
let [stageX, stageY] = event.get_coords(); let [stageX, stageY] = event.get_coords();
let allowDrag = dragWindow.maximized_vertically && let allowDrag = dragWindow.maximized_vertically &&

View File

@ -41,7 +41,8 @@ const ButtonBox = new Lang.Class({
}, },
_getPreferredWidth: function(actor, forHeight, alloc) { _getPreferredWidth: function(actor, forHeight, alloc) {
let child = actor.get_first_child(); let children = actor.get_children();
let child = children.length > 0 ? children[0] : null;
if (child) { if (child) {
[alloc.min_size, alloc.natural_size] = child.get_preferred_width(-1); [alloc.min_size, alloc.natural_size] = child.get_preferred_width(-1);
@ -54,7 +55,8 @@ const ButtonBox = new Lang.Class({
}, },
_getPreferredHeight: function(actor, forWidth, alloc) { _getPreferredHeight: function(actor, forWidth, alloc) {
let child = actor.get_first_child(); let children = actor.get_children();
let child = children.length > 0 ? children[0] : null;
if (child) { if (child) {
[alloc.min_size, alloc.natural_size] = child.get_preferred_height(-1); [alloc.min_size, alloc.natural_size] = child.get_preferred_height(-1);
@ -64,11 +66,13 @@ const ButtonBox = new Lang.Class({
}, },
_allocate: function(actor, box, flags) { _allocate: function(actor, box, flags) {
let child = actor.get_first_child(); let children = actor.get_children();
if (!child) if (children.length == 0)
return; return;
let child = children[0];
let [minWidth, natWidth] = child.get_preferred_width(-1); let [minWidth, natWidth] = child.get_preferred_width(-1);
let [minHeight, natHeight] = child.get_preferred_height(-1);
let availWidth = box.x2 - box.x1; let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1; let availHeight = box.y2 - box.y1;
@ -100,7 +104,8 @@ const Button = new Lang.Class({
accessible_name: nameText ? nameText : "", accessible_name: nameText ? nameText : "",
accessible_role: Atk.Role.MENU }); accessible_role: Atk.Role.MENU });
this.actor.connect('event', Lang.bind(this, this._onEvent)); this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
this.actor.connect('key-press-event', Lang.bind(this, this._onSourceKeyPress));
this.actor.connect('notify::visible', Lang.bind(this, this._onVisibilityChanged)); this.actor.connect('notify::visible', Lang.bind(this, this._onVisibilityChanged));
if (dontCreateMenu) if (dontCreateMenu)
@ -130,15 +135,34 @@ const Button = new Lang.Class({
} }
}, },
_onEvent: function(actor, event) { _onButtonPress: function(actor, event) {
if (this.menu && if (!this.menu)
(event.type() == Clutter.EventType.TOUCH_BEGIN || return Clutter.EVENT_PROPAGATE;
event.type() == Clutter.EventType.BUTTON_PRESS))
this.menu.toggle();
this.menu.toggle();
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
}, },
_onSourceKeyPress: function(actor, event) {
if (!this.menu)
return Clutter.EVENT_PROPAGATE;
let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) {
this.menu.toggle();
return Clutter.EVENT_STOP;
} else if (symbol == Clutter.KEY_Escape && this.menu.isOpen) {
this.menu.close();
return Clutter.EVENT_STOP;
} else if (symbol == Clutter.KEY_Down) {
if (!this.menu.isOpen)
this.menu.toggle();
this.menu.actor.navigate_focus(this.actor, Gtk.DirectionType.DOWN, false);
return Clutter.EVENT_STOP;
} else
return Clutter.EVENT_PROPAGATE;
},
_onVisibilityChanged: function() { _onVisibilityChanged: function() {
if (!this.menu) if (!this.menu)
return; return;

View File

@ -107,7 +107,6 @@ const PointerWatcher = new Lang.Class({
this._timeoutId = Mainloop.timeout_add(minInterval, this._timeoutId = Mainloop.timeout_add(minInterval,
Lang.bind(this, this._onTimeout)); Lang.bind(this, this._onTimeout));
GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] this._onTimeout');
}, },
_onTimeout: function() { _onTimeout: function() {

View File

@ -1,7 +1,9 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk; const Gtk = imports.gi.Gtk;
const Gio = imports.gi.Gio;
const Lang = imports.lang; const Lang = imports.lang;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
@ -13,6 +15,7 @@ const GrabHelper = imports.ui.grabHelper;
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params; const Params = imports.misc.params;
const Separator = imports.ui.separator; const Separator = imports.ui.separator;
const Slider = imports.ui.slider;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const Ornament = { const Ornament = {
@ -21,6 +24,17 @@ const Ornament = {
CHECK: 2, CHECK: 2,
}; };
function _ensureStyle(actor) {
if (actor.get_children) {
let children = actor.get_children();
for (let i = 0; i < children.length; i++)
_ensureStyle(children[i]);
}
if (actor instanceof St.Widget)
actor.ensure_style();
}
function isPopupMenuItemVisible(child) { function isPopupMenuItemVisible(child) {
if (child._delegate instanceof PopupMenuSection) if (child._delegate instanceof PopupMenuSection)
if (child._delegate.isEmpty()) if (child._delegate.isEmpty())
@ -32,28 +46,33 @@ function isPopupMenuItemVisible(child) {
* @side Side to which the arrow points. * @side Side to which the arrow points.
*/ */
function arrowIcon(side) { function arrowIcon(side) {
let iconName; let rotation;
switch (side) { switch (side) {
case St.Side.TOP: case St.Side.TOP:
iconName = 'pan-up-symbolic'; rotation = 180;
break; break;
case St.Side.RIGHT: case St.Side.RIGHT:
iconName = 'pan-end-symbolic'; rotation = - 90;
break; break;
case St.Side.BOTTOM: case St.Side.BOTTOM:
iconName = 'pan-down-symbolic'; rotation = 0;
break; break;
case St.Side.LEFT: case St.Side.LEFT:
iconName = 'pan-start-symbolic'; rotation = 90;
break; break;
} }
let gicon = new Gio.FileIcon({ file: Gio.File.new_for_path(global.datadir +
'/theme/menu-arrow-symbolic.svg') });
let arrow = new St.Icon({ style_class: 'popup-menu-arrow', let arrow = new St.Icon({ style_class: 'popup-menu-arrow',
icon_name: iconName, gicon: gicon,
accessible_role: Atk.Role.ARROW, accessible_role: Atk.Role.ARROW,
y_expand: true, y_expand: true,
y_align: Clutter.ActorAlign.CENTER }); y_align: Clutter.ActorAlign.CENTER });
arrow.rotation_angle_z = rotation;
return arrow; return arrow;
} }
@ -92,7 +111,6 @@ const PopupBaseMenuItem = new Lang.Class({
if (this._activatable) { if (this._activatable) {
this.actor.connect('button-release-event', Lang.bind(this, this._onButtonReleaseEvent)); this.actor.connect('button-release-event', Lang.bind(this, this._onButtonReleaseEvent));
this.actor.connect('touch-event', Lang.bind(this, this._onTouchEvent));
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent)); this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
} }
if (params.reactive && params.hover) if (params.reactive && params.hover)
@ -119,14 +137,6 @@ const PopupBaseMenuItem = new Lang.Class({
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
}, },
_onTouchEvent: function (actor, event) {
if (event.type() == Clutter.EventType.TOUCH_END) {
this.activate(event);
return Clutter.EVENT_STOP;
}
return Clutter.EVENT_PROPAGATE;
},
_onKeyPressEvent: function (actor, event) { _onKeyPressEvent: function (actor, event) {
let symbol = event.get_key_symbol(); let symbol = event.get_key_symbol();
@ -241,16 +251,8 @@ const PopupSeparatorMenuItem = new Lang.Class({
this.actor.add(this.label); this.actor.add(this.label);
this.actor.label_actor = this.label; this.actor.label_actor = this.label;
this.label.connect('notify::text',
Lang.bind(this, this._syncVisibility));
this._syncVisibility();
this._separator = new Separator.HorizontalSeparator({ style_class: 'popup-separator-menu-item' }); this._separator = new Separator.HorizontalSeparator({ style_class: 'popup-separator-menu-item' });
this.actor.add(this._separator.actor, { expand: true }); this.actor.add(this._separator.actor, { expand: true });
},
_syncVisibility: function() {
this.label.visible = this.label.text != '';
} }
}); });
@ -373,9 +375,9 @@ const PopupImageMenuItem = new Lang.Class({
this.parent(params); this.parent(params);
this.label = new St.Label({ text: text }); this.label = new St.Label({ text: text });
this.actor.add_child(this.label); this.addActor(this.label);
this._icon = new St.Icon({ style_class: 'popup-menu-icon' }); this._icon = new St.Icon({ style_class: 'popup-menu-icon' });
this.actor.add_child(this._icon, { align: St.Align.END }); this.addActor(this._icon, { align: St.Align.END });
this.setIcon(iconName); this.setIcon(iconName);
}, },
@ -731,10 +733,6 @@ const PopupMenu = new Lang.Class({
global.focus_manager.add_group(this.actor); global.focus_manager.add_group(this.actor);
this.actor.reactive = true; this.actor.reactive = true;
if (this.sourceActor)
this._keyPressId = this.sourceActor.connect('key-press-event',
Lang.bind(this, this._onKeyPress));
this._openedSubMenu = null; this._openedSubMenu = null;
}, },
@ -745,40 +743,6 @@ const PopupMenu = new Lang.Class({
this._openedSubMenu = submenu; this._openedSubMenu = submenu;
}, },
_onKeyPress: function(actor, event) {
let navKey;
switch (this._boxPointer.arrowSide) {
case St.Side.TOP:
navKey = Clutter.KEY_Down;
break;
case St.Side.BOTTOM:
navKey = Clutter.KEY_Up;
break;
case St.Side.LEFT:
navKey = Clutter.KEY_Right;
break;
case St.Side.RIGHT:
navKey = Clutter.KEY_Left;
break;
}
let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) {
this.toggle();
return Clutter.EVENT_STOP;
} else if (symbol == Clutter.KEY_Escape && this.isOpen) {
this.close();
return Clutter.EVENT_STOP;
} else if (symbol == navKey) {
if (!this.isOpen)
this.toggle();
this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
return Clutter.EVENT_STOP;
} else
return Clutter.EVENT_PROPAGATE;
},
setArrowOrigin: function(origin) { setArrowOrigin: function(origin) {
this._boxPointer.setArrowOrigin(origin); this._boxPointer.setArrowOrigin(origin);
}, },
@ -819,12 +783,6 @@ const PopupMenu = new Lang.Class({
this.isOpen = false; this.isOpen = false;
this.emit('open-state-changed', false); this.emit('open-state-changed', false);
},
destroy: function() {
if (this._keyPressId)
this.sourceActor.disconnect(this._keyPressId);
this.parent();
} }
}); });
@ -918,14 +876,12 @@ const PopupSubMenu = new Lang.Class({
if (animate && needsScrollbar) if (animate && needsScrollbar)
animate = false; animate = false;
let targetAngle = this.actor.text_direction == Clutter.TextDirection.RTL ? -90 : 90;
if (animate) { if (animate) {
let [minHeight, naturalHeight] = this.actor.get_preferred_height(-1); let [minHeight, naturalHeight] = this.actor.get_preferred_height(-1);
this.actor.height = 0; this.actor.height = 0;
this.actor._arrowRotation = this._arrow.rotation_angle_z; this.actor._arrowRotation = this._arrow.rotation_angle_z;
Tweener.addTween(this.actor, Tweener.addTween(this.actor,
{ _arrowRotation: targetAngle, { _arrowRotation: this.actor._arrowRotation + 90,
height: naturalHeight, height: naturalHeight,
time: 0.25, time: 0.25,
onUpdateScope: this, onUpdateScope: this,
@ -938,7 +894,7 @@ const PopupSubMenu = new Lang.Class({
} }
}); });
} else { } else {
this._arrow.rotation_angle_z = targetAngle; this._arrow.rotation_angle_z = this.actor._arrowRotation + 90;
} }
}, },
@ -958,7 +914,7 @@ const PopupSubMenu = new Lang.Class({
if (animate) { if (animate) {
this.actor._arrowRotation = this._arrow.rotation_angle_z; this.actor._arrowRotation = this._arrow.rotation_angle_z;
Tweener.addTween(this.actor, Tweener.addTween(this.actor,
{ _arrowRotation: 0, { _arrowRotation: this.actor._arrowRotation - 90,
height: 0, height: 0,
time: 0.25, time: 0.25,
onUpdateScope: this, onUpdateScope: this,
@ -972,7 +928,7 @@ const PopupSubMenu = new Lang.Class({
}, },
}); });
} else { } else {
this._arrow.rotation_angle_z = 0; this._arrow.rotation_angle_z = this.actor._arrowRotation - 90;
this.actor.hide(); this.actor.hide();
} }
}, },
@ -1050,6 +1006,8 @@ const PopupSubMenuMenuItem = new Lang.Class({
this._triangleBin = new St.Widget({ y_expand: true, this._triangleBin = new St.Widget({ y_expand: true,
y_align: Clutter.ActorAlign.CENTER }); y_align: Clutter.ActorAlign.CENTER });
this._triangleBin.add_child(this._triangle); this._triangleBin.add_child(this._triangle);
if (this._triangleBin.get_text_direction() == Clutter.TextDirection.RTL)
this._triangleBin.set_scale(-1.0, 1.0);
this.actor.add_child(this._triangleBin); this.actor.add_child(this._triangleBin);
this.actor.add_accessible_state (Atk.StateType.EXPANDABLE); this.actor.add_accessible_state (Atk.StateType.EXPANDABLE);

View File

@ -110,13 +110,6 @@ function loadRemoteSearchProviders(callback) {
else else
remoteProvider = new RemoteSearchProvider(appInfo, busName, objectPath); remoteProvider = new RemoteSearchProvider(appInfo, busName, objectPath);
remoteProvider.defaultEnabled = true;
try {
remoteProvider.defaultEnabled = !keyfile.get_boolean(group, 'DefaultDisabled');
} catch(e) {
// ignore error
}
objectPaths[objectPath] = remoteProvider; objectPaths[objectPath] = remoteProvider;
loadedProviders.push(remoteProvider); loadedProviders.push(remoteProvider);
} catch(e) { } catch(e) {
@ -124,7 +117,7 @@ function loadRemoteSearchProviders(callback) {
} }
} }
let searchSettings = new Gio.Settings({ schema_id: Search.SEARCH_PROVIDERS_SCHEMA }); let searchSettings = new Gio.Settings({ schema: Search.SEARCH_PROVIDERS_SCHEMA });
if (searchSettings.get_boolean('disable-external')) { if (searchSettings.get_boolean('disable-external')) {
callback([]); callback([]);
return; return;
@ -139,14 +132,8 @@ function loadRemoteSearchProviders(callback) {
loadedProviders = loadedProviders.filter(function(provider) { loadedProviders = loadedProviders.filter(function(provider) {
let appId = provider.appInfo.get_id(); let appId = provider.appInfo.get_id();
let disabled = searchSettings.get_strv('disabled');
if (provider.defaultEnabled) { return disabled.indexOf(appId) == -1;
let disabled = searchSettings.get_strv('disabled');
return disabled.indexOf(appId) == -1;
} else {
let enabled = searchSettings.get_strv('enabled');
return enabled.indexOf(appId) != -1;
}
}); });
loadedProviders.sort(function(providerA, providerB) { loadedProviders.sort(function(providerA, providerB) {

View File

@ -38,8 +38,8 @@ const RunDialog = new Lang.Class({
this.parent({ styleClass: 'run-dialog', this.parent({ styleClass: 'run-dialog',
destroyOnClose: false }); destroyOnClose: false });
this._lockdownSettings = new Gio.Settings({ schema_id: LOCKDOWN_SCHEMA }); this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA });
this._terminalSettings = new Gio.Settings({ schema_id: TERMINAL_SCHEMA }); this._terminalSettings = new Gio.Settings({ schema: TERMINAL_SCHEMA });
global.settings.connect('changed::development-tools', Lang.bind(this, function () { global.settings.connect('changed::development-tools', Lang.bind(this, function () {
this._enableInternalCommands = global.settings.get_boolean('development-tools'); this._enableInternalCommands = global.settings.get_boolean('development-tools');
})); }));
@ -50,10 +50,14 @@ const RunDialog = new Lang.Class({
Main.createLookingGlass().open(); Main.createLookingGlass().open();
}), }),
'r': Lang.bind(this, this._restart), 'r': Lang.bind(this, function() {
global.reexec_self();
}),
// Developer brain backwards compatibility // Developer brain backwards compatibility
'restart': Lang.bind(this, this._restart), 'restart': Lang.bind(this, function() {
global.reexec_self();
}),
'debugexit': Lang.bind(this, function() { 'debugexit': Lang.bind(this, function() {
Meta.quit(Meta.ExitCode.ERROR); Meta.quit(Meta.ExitCode.ERROR);
@ -182,10 +186,6 @@ const RunDialog = new Lang.Class({
let results = someResults.reduce(function(a, b) { let results = someResults.reduce(function(a, b) {
return a.concat(b); return a.concat(b);
}, []); }, []);
if (!results.length)
return null;
let common = results.reduce(_getCommon, null); let common = results.reduce(_getCommon, null);
return common.substr(text.length); return common.substr(text.length);
}, },
@ -271,12 +271,6 @@ const RunDialog = new Lang.Class({
} }
}, },
_restart: function() {
this._shouldFadeOut = false;
this.close();
Meta.restart(_("Restarting…"));
},
open: function() { open: function() {
this._history.lastItem(); this._history.lastItem();
this._errorBox.hide(); this._errorBox.hide();

View File

@ -444,12 +444,14 @@ function clamp(value, min, max) {
} }
/** /**
* To test screen shield, make sure to kill gnome-screensaver.
*
* If you are setting org.gnome.desktop.session.idle-delay directly in dconf, * If you are setting org.gnome.desktop.session.idle-delay directly in dconf,
* rather than through System Settings, you also need to set * rather than through System Settings, you also need to set
* org.gnome.settings-daemon.plugins.power.sleep-display-ac and * org.gnome.settings-daemon.plugins.power.sleep-display-ac and
* org.gnome.settings-daemon.plugins.power.sleep-display-battery to the same value. * org.gnome.settings-daemon.plugins.power.sleep-display-battery to the same value.
* This will ensure that the screen blanks at the right time when it fades out. * This will ensure that the screen blanks at the right time when it fades out.
* https://bugzilla.gnome.org/show_bug.cgi?id=668703 explains the dependency. * https://bugzilla.gnome.org/show_bug.cgi?id=668703 explains the dependance.
*/ */
const ScreenShield = new Lang.Class({ const ScreenShield = new Lang.Class({
Name: 'ScreenShield', Name: 'ScreenShield',
@ -561,7 +563,7 @@ const ScreenShield = new Lang.Class({
this._loginSession.connectSignal('Unlock', Lang.bind(this, function() { this.deactivate(false); })); this._loginSession.connectSignal('Unlock', Lang.bind(this, function() { this.deactivate(false); }));
})); }));
this._settings = new Gio.Settings({ schema_id: SCREENSAVER_SCHEMA }); this._settings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA });
this._isModal = false; this._isModal = false;
this._hasLockScreen = false; this._hasLockScreen = false;
@ -687,10 +689,10 @@ const ScreenShield = new Lang.Class({
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
let delta = 0; let delta = 0;
if (event.get_scroll_direction() == Clutter.ScrollDirection.SMOOTH) if (event.get_scroll_direction() == Clutter.ScrollDirection.UP)
delta = Math.abs(event.get_scroll_delta()[0]);
else
delta = 5; delta = 5;
else if (event.get_scroll_direction() == Clutter.ScrollDirection.SMOOTH)
delta = Math.max(0, event.get_scroll_delta()[0]);
this._lockScreenScrollCounter += delta; this._lockScreenScrollCounter += delta;
@ -848,7 +850,6 @@ const ScreenShield = new Lang.Class({
this.lock(false); this.lock(false);
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(this._lockTimeoutId, '[gnome-shell] this.lock');
} }
this._activateFade(this._longLightbox, STANDARD_FADE_TIME); this._activateFade(this._longLightbox, STANDARD_FADE_TIME);
@ -900,11 +901,17 @@ const ScreenShield = new Lang.Class({
}, },
showDialog: function() { showDialog: function() {
if (!this._becomeModal()) { // Ensure that the stage window is mapped, before taking a grab
// In the login screen, this is a hard error. Fail-whale // otherwise X errors out
log('Could not acquire modal grab for the login screen. Aborting login process.'); Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
Meta.quit(Meta.ExitCode.ERROR); if (!this._becomeModal()) {
} // In the login screen, this is a hard error. Fail-whale
log('Could not acquire modal grab for the login screen. Aborting login process.');
Meta.quit(Meta.ExitCode.ERROR);
}
return false;
}));
this.actor.show(); this.actor.show();
this._isGreeter = Main.sessionMode.isGreeter; this._isGreeter = Main.sessionMode.isGreeter;
@ -919,11 +926,6 @@ const ScreenShield = new Lang.Class({
this._lockScreenState = MessageTray.State.HIDDEN; this._lockScreenState = MessageTray.State.HIDDEN;
this._lockScreenGroup.hide(); this._lockScreenGroup.hide();
if (this._dialog) {
this._dialog.actor.grab_key_focus();
this._dialog.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
}
}, },
_hideLockScreen: function(animate, velocity) { _hideLockScreen: function(animate, velocity) {
@ -1039,7 +1041,6 @@ const ScreenShield = new Lang.Class({
if (!this._arrowAnimationId) { if (!this._arrowAnimationId) {
this._arrowAnimationId = Mainloop.timeout_add(6000, Lang.bind(this, this._animateArrows)); this._arrowAnimationId = Mainloop.timeout_add(6000, Lang.bind(this, this._animateArrows));
GLib.Source.set_name_by_id(this._arrowAnimationId, '[gnome-shell] this._animateArrows');
this._animateArrows(); this._animateArrows();
} }
@ -1107,11 +1108,10 @@ const ScreenShield = new Lang.Class({
if (params.fadeToBlack && params.animateFade) { if (params.fadeToBlack && params.animateFade) {
// Take a beat // Take a beat
let id = Mainloop.timeout_add(1000 * MANUAL_FADE_TIME, Lang.bind(this, function() { Mainloop.timeout_add(1000 * MANUAL_FADE_TIME, Lang.bind(this, function() {
this._activateFade(this._shortLightbox, MANUAL_FADE_TIME); this._activateFade(this._shortLightbox, MANUAL_FADE_TIME);
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(id, '[gnome-shell] this._activateFade');
} else { } else {
if (params.fadeToBlack) if (params.fadeToBlack)
this._activateFade(this._shortLightbox, 0); this._activateFade(this._shortLightbox, 0);

View File

@ -43,8 +43,6 @@ const ScreencastService = new Lang.Class({
this._recorders = new Map(); this._recorders = new Map();
this._lockdownSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.lockdown' });
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated)); Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
}, },
@ -70,8 +68,8 @@ const ScreencastService = new Lang.Class({
if (Main.sessionMode.allowScreencast) if (Main.sessionMode.allowScreencast)
return; return;
for (let sender of this._recorders.keys()) this._recorders.clear();
this._stopRecordingForSender(sender); this.emit('updated');
}, },
_onNameVanished: function(connection, name) { _onNameVanished: function(connection, name) {
@ -105,8 +103,7 @@ const ScreencastService = new Lang.Class({
ScreencastAsync: function(params, invocation) { ScreencastAsync: function(params, invocation) {
let returnValue = [false, '']; let returnValue = [false, ''];
if (!Main.sessionMode.allowScreencast || if (!Main.sessionMode.allowScreencast) {
this._lockdownSettings.get_boolean('disable-save-to-disk')) {
invocation.return_value(GLib.Variant.new('(bs)', returnValue)); invocation.return_value(GLib.Variant.new('(bs)', returnValue));
return; return;
} }
@ -120,8 +117,6 @@ const ScreencastService = new Lang.Class({
this._applyOptionalParameters(recorder, options); this._applyOptionalParameters(recorder, options);
let [success, fileName] = recorder.record(); let [success, fileName] = recorder.record();
returnValue = [success, fileName ? fileName : '']; returnValue = [success, fileName ? fileName : ''];
if (!success)
this._stopRecordingForSender(sender);
} }
invocation.return_value(GLib.Variant.new('(bs)', returnValue)); invocation.return_value(GLib.Variant.new('(bs)', returnValue));
@ -129,8 +124,7 @@ const ScreencastService = new Lang.Class({
ScreencastAreaAsync: function(params, invocation) { ScreencastAreaAsync: function(params, invocation) {
let returnValue = [false, '']; let returnValue = [false, ''];
if (!Main.sessionMode.allowScreencast || if (!Main.sessionMode.allowScreencast) {
this._lockdownSettings.get_boolean('disable-save-to-disk')) {
invocation.return_value(GLib.Variant.new('(bs)', returnValue)); invocation.return_value(GLib.Variant.new('(bs)', returnValue));
return; return;
} }
@ -156,8 +150,6 @@ const ScreencastService = new Lang.Class({
this._applyOptionalParameters(recorder, options); this._applyOptionalParameters(recorder, options);
let [success, fileName] = recorder.record(); let [success, fileName] = recorder.record();
returnValue = [success, fileName ? fileName : '']; returnValue = [success, fileName ? fileName : ''];
if (!success)
this._stopRecordingForSender(sender);
} }
invocation.return_value(GLib.Variant.new('(bs)', returnValue)); invocation.return_value(GLib.Variant.new('(bs)', returnValue));

View File

@ -11,7 +11,6 @@ const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
const St = imports.gi.St; const St = imports.gi.St;
const GrabHelper = imports.ui.grabHelper;
const Lightbox = imports.ui.lightbox; const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main; const Main = imports.ui.main;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
@ -65,97 +64,29 @@ const ScreenshotService = new Lang.Class({
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ScreenshotIface, this); this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ScreenshotIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/Screenshot'); this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/Screenshot');
this._screenShooter = new Map();
this._lockdownSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.lockdown' });
Gio.DBus.session.own_name('org.gnome.Shell.Screenshot', Gio.BusNameOwnerFlags.REPLACE, null, null); Gio.DBus.session.own_name('org.gnome.Shell.Screenshot', Gio.BusNameOwnerFlags.REPLACE, null, null);
}, },
_createScreenshot: function(invocation) {
let sender = invocation.get_sender();
if (this._screenShooter.has(sender) ||
this._lockdownSettings.get_boolean('disable-save-to-disk')) {
invocation.return_value(GLib.Variant.new('(bs)', [false, '']));
return null;
}
let shooter = new Shell.Screenshot();
shooter._watchNameId =
Gio.bus_watch_name(Gio.BusType.SESSION, sender, 0, null,
Lang.bind(this, this._onNameVanished));
this._screenShooter.set(sender, shooter);
return shooter;
},
_onNameVanished: function(connection, name) {
this._removeShooterForSender(name);
},
_removeShooterForSender: function(sender) {
let shooter = this._screenShooter.get(sender);
if (!shooter)
return;
Gio.bus_unwatch_name(shooter._watchNameId);
this._screenShooter.delete(sender);
},
_checkArea: function(x, y, width, height) {
return x >= 0 && y >= 0 &&
width > 0 && height > 0 &&
x + width <= global.screen_width &&
y + height <= global.screen_height;
},
_onScreenshotComplete: function(obj, result, area, filenameUsed, flash, invocation) { _onScreenshotComplete: function(obj, result, area, filenameUsed, flash, invocation) {
if (result) { if (flash && result) {
if (flash) { let flashspot = new Flashspot(area);
let flashspot = new Flashspot(area); flashspot.fire();
flashspot.fire(Lang.bind(this, function() {
this._removeShooterForSender(invocation.get_sender());
}));
}
else
this._removeShooterForSender(invocation.get_sender());
} }
let retval = GLib.Variant.new('(bs)', [result, filenameUsed]); let retval = GLib.Variant.new('(bs)', [result, filenameUsed]);
invocation.return_value(retval); invocation.return_value(retval);
}, },
_scaleArea: function(x, y, width, height) {
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
x *= scaleFactor;
y *= scaleFactor;
width *= scaleFactor;
height *= scaleFactor;
return [x, y, width, height];
},
_unscaleArea: function(x, y, width, height) {
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
x /= scaleFactor;
y /= scaleFactor;
width /= scaleFactor;
height /= scaleFactor;
return [x, y, width, height];
},
ScreenshotAreaAsync : function (params, invocation) { ScreenshotAreaAsync : function (params, invocation) {
let [x, y, width, height, flash, filename, callback] = params; let [x, y, width, height, flash, filename, callback] = params;
[x, y, width, height] = this._scaleArea(x, y, width, height); if (x < 0 || y < 0 ||
if (!this._checkArea(x, y, width, height)) { width <= 0 || height <= 0 ||
invocation.return_error_literal(Gio.IOErrorEnum, x + width > global.screen_width || y + height > global.screen_height) {
Gio.IOErrorEnum.CANCELLED, invocation.return_error_literal(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED,
"Invalid params"); "Invalid params");
return; return;
} }
let screenshot = this._createScreenshot(invocation); let screenshot = new Shell.Screenshot();
if (!screenshot)
return;
screenshot.screenshot_area (x, y, width, height, filename, screenshot.screenshot_area (x, y, width, height, filename,
Lang.bind(this, this._onScreenshotComplete, Lang.bind(this, this._onScreenshotComplete,
flash, invocation)); flash, invocation));
@ -163,9 +94,7 @@ const ScreenshotService = new Lang.Class({
ScreenshotWindowAsync : function (params, invocation) { ScreenshotWindowAsync : function (params, invocation) {
let [include_frame, include_cursor, flash, filename] = params; let [include_frame, include_cursor, flash, filename] = params;
let screenshot = this._createScreenshot(invocation); let screenshot = new Shell.Screenshot();
if (!screenshot)
return;
screenshot.screenshot_window (include_frame, include_cursor, filename, screenshot.screenshot_window (include_frame, include_cursor, filename,
Lang.bind(this, this._onScreenshotComplete, Lang.bind(this, this._onScreenshotComplete,
flash, invocation)); flash, invocation));
@ -173,9 +102,7 @@ const ScreenshotService = new Lang.Class({
ScreenshotAsync : function (params, invocation) { ScreenshotAsync : function (params, invocation) {
let [include_cursor, flash, filename] = params; let [include_cursor, flash, filename] = params;
let screenshot = this._createScreenshot(invocation); let screenshot = new Shell.Screenshot();
if (!screenshot)
return;
screenshot.screenshot(include_cursor, filename, screenshot.screenshot(include_cursor, filename,
Lang.bind(this, this._onScreenshotComplete, Lang.bind(this, this._onScreenshotComplete,
flash, invocation)); flash, invocation));
@ -187,9 +114,9 @@ const ScreenshotService = new Lang.Class({
selectArea.connect('finished', Lang.bind(this, selectArea.connect('finished', Lang.bind(this,
function(selectArea, areaRectangle) { function(selectArea, areaRectangle) {
if (areaRectangle) { if (areaRectangle) {
let retRectangle = this._unscaleArea(areaRectangle.x, areaRectangle.y, let retval = GLib.Variant.new('(iiii)',
areaRectangle.width, areaRectangle.height); [areaRectangle.x, areaRectangle.y,
let retval = GLib.Variant.new('(iiii)', retRectangle); areaRectangle.width, areaRectangle.height]);
invocation.return_value(retval); invocation.return_value(retval);
} else { } else {
invocation.return_error_literal(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED, invocation.return_error_literal(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED,
@ -198,18 +125,9 @@ const ScreenshotService = new Lang.Class({
})); }));
}, },
FlashAreaAsync: function(params, invocation) { FlashArea: function(x, y, width, height) {
let [x, y, width, height] = params;
[x, y, width, height] = this._scaleArea(x, y, width, height);
if (!this._checkArea(x, y, width, height)) {
invocation.return_error_literal(Gio.IOErrorEnum,
Gio.IOErrorEnum.CANCELLED,
"Invalid params");
return;
}
let flashspot = new Flashspot({ x : x, y : y, width: width, height: height}); let flashspot = new Flashspot({ x : x, y : y, width: width, height: height});
flashspot.fire(); flashspot.fire();
invocation.return_value(null);
} }
}); });
@ -221,7 +139,6 @@ const SelectArea = new Lang.Class({
this._startY = -1; this._startY = -1;
this._lastX = 0; this._lastX = 0;
this._lastY = 0; this._lastY = 0;
this._result = null;
this._initRubberbandColors(); this._initRubberbandColors();
@ -231,12 +148,12 @@ const SelectArea = new Lang.Class({
y: 0 }); y: 0 });
Main.uiGroup.add_actor(this._group); Main.uiGroup.add_actor(this._group);
this._grabHelper = new GrabHelper.GrabHelper(this._group);
this._group.connect('button-press-event', this._group.connect('button-press-event',
Lang.bind(this, this._onButtonPress)); Lang.bind(this, this._onButtonPress));
this._group.connect('button-release-event', this._group.connect('button-release-event',
Lang.bind(this, this._onButtonRelease)); Lang.bind(this, this._onButtonRelease));
this._group.connect('key-press-event',
Lang.bind(this, this._onKeyPress));
this._group.connect('motion-event', this._group.connect('motion-event',
Lang.bind(this, this._onMotionEvent)); Lang.bind(this, this._onMotionEvent));
@ -252,12 +169,10 @@ const SelectArea = new Lang.Class({
}, },
show: function() { show: function() {
if (!this._grabHelper.grab({ actor: this._group, if (!Main.pushModal(this._group) || this._group.visible)
onUngrab: Lang.bind(this, this._onUngrab) }))
return; return;
global.screen.set_cursor(Meta.Cursor.CROSSHAIR); global.screen.set_cursor(Meta.Cursor.CROSSHAIR);
Main.uiGroup.set_child_above_sibling(this._group, null);
this._group.visible = true; this._group.visible = true;
}, },
@ -287,6 +202,13 @@ const SelectArea = new Lang.Class({
height: Math.abs(this._startY - this._lastY) }; height: Math.abs(this._startY - this._lastY) };
}, },
_onKeyPress: function(actor, event) {
if (event.get_key_symbol() == Clutter.Escape)
this._destroy(null, false);
return Clutter.EVENT_PROPAGATE;
},
_onMotionEvent: function(actor, event) { _onMotionEvent: function(actor, event) {
if (this._startX == -1 || this._startY == -1) if (this._startX == -1 || this._startY == -1)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
@ -308,28 +230,24 @@ const SelectArea = new Lang.Class({
}, },
_onButtonRelease: function(actor, event) { _onButtonRelease: function(actor, event) {
this._result = this._getGeometry(); this._destroy(this._getGeometry(), true);
Tweener.addTween(this._group,
{ opacity: 0,
time: 0.2,
transition: 'easeOutQuad',
onComplete: Lang.bind(this,
function() {
this._grabHelper.ungrab();
})
});
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
}, },
_onUngrab: function() { _destroy: function(geometry, fade) {
global.screen.set_cursor(Meta.Cursor.DEFAULT); Tweener.addTween(this._group,
this.emit('finished', this._result); { opacity: 0,
time: fade ? 0.2 : 0,
transition: 'easeOutQuad',
onComplete: Lang.bind(this,
function() {
Main.popModal(this._group);
this._group.destroy();
global.screen.set_cursor(Meta.Cursor.DEFAULT);
GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, this.emit('finished', geometry);
function() { })
this._group.destroy(); });
return GLib.SOURCE_REMOVE;
}));
} }
}); });
Signals.addSignalMethods(SelectArea.prototype); Signals.addSignalMethods(SelectArea.prototype);
@ -349,7 +267,7 @@ const Flashspot = new Lang.Class({
this.actor.set_position(area.x, area.y); this.actor.set_position(area.x, area.y);
}, },
fire: function(doneCallback) { fire: function() {
this.actor.show(); this.actor.show();
this.actor.opacity = 255; this.actor.opacity = 255;
Tweener.addTween(this.actor, Tweener.addTween(this.actor,
@ -357,8 +275,6 @@ const Flashspot = new Lang.Class({
time: FLASHSPOT_ANIMATION_OUT_TIME, time: FLASHSPOT_ANIMATION_OUT_TIME,
transition: 'easeOutQuad', transition: 'easeOutQuad',
onComplete: Lang.bind(this, function() { onComplete: Lang.bind(this, function() {
if (doneCallback)
doneCallback();
this.destroy(); this.destroy();
}) })
}); });

View File

@ -7,7 +7,6 @@ const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params;
// This module provides functionality for driving the shell user interface // This module provides functionality for driving the shell user interface
// in an automated fashion. The primary current use case for this is // in an automated fashion. The primary current use case for this is
@ -40,12 +39,11 @@ const Params = imports.misc.params;
function sleep(milliseconds) { function sleep(milliseconds) {
let cb; let cb;
let id = Mainloop.timeout_add(milliseconds, function() { Mainloop.timeout_add(milliseconds, function() {
if (cb) if (cb)
cb(); cb();
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
GLib.Source.set_name_by_id(id, '[gnome-shell] sleep');
return function(callback) { return function(callback) {
cb = callback; cb = callback;
@ -79,7 +77,6 @@ const PerfHelperIface = '<node> \
<arg type="i" direction="in" /> \ <arg type="i" direction="in" /> \
<arg type="b" direction="in" /> \ <arg type="b" direction="in" /> \
<arg type="b" direction="in" /> \ <arg type="b" direction="in" /> \
<arg type="b" direction="in" /> \
</method> \ </method> \
<method name="WaitWindows" /> \ <method name="WaitWindows" /> \
<method name="DestroyWindows" /> \ <method name="DestroyWindows" /> \
@ -99,36 +96,11 @@ function _getPerfHelper() {
return _perfHelper; return _perfHelper;
} }
function _callRemote(obj, method, ...args) {
let cb;
let errcb;
args.push(function(result, excp) {
if (excp) {
if (errcb)
errcb(excp);
} else {
if (cb)
cb();
}
});
method.apply(obj, args);
return function(callback, error_callback) {
cb = callback;
errcb = error_callback;
};
}
/** /**
* createTestWindow: * createTestWindow:
* @params: options for window creation. * @width: width of window, in pixels
* width - width of window, in pixels (default 640) * @height: height of window, in pixels
* height - height of window, in pixels (default 480) * @alpha: whether the window should be alpha transparent
* alpha - whether the window should have an alpha channel (default false)
* maximized - whether the window should be created maximized (default false)
* redraws - whether the window should continually redraw itself (default false)
* @maximized: whethe the window should be created maximized * @maximized: whethe the window should be created maximized
* *
* Creates a window using gnome-shell-perf-helper for testing purposes. * Creates a window using gnome-shell-perf-helper for testing purposes.
@ -137,17 +109,19 @@ function _callRemote(obj, method, ...args) {
* because of the normal X asynchronous mapping process, to actually wait * because of the normal X asynchronous mapping process, to actually wait
* until the window has been mapped and exposed, use waitTestWindows(). * until the window has been mapped and exposed, use waitTestWindows().
*/ */
function createTestWindow(width, height, params) { function createTestWindow(width, height, alpha, maximized) {
params = Params.parse(params, { width: 640, let cb;
height: 480,
alpha: false,
maximized: false,
redraws: false });
let perfHelper = _getPerfHelper(); let perfHelper = _getPerfHelper();
return _callRemote(perfHelper, perfHelper.CreateWindowRemote,
params.width, params.height, perfHelper.CreateWindowRemote(width, height, alpha, maximized,
params.alpha, params.maximized, params.redraws); function(result, excp) {
if (cb)
cb();
});
return function(callback) {
cb = callback;
};
} }
/** /**
@ -157,8 +131,17 @@ function createTestWindow(width, height, params) {
* created with createTestWindow have been mapped and exposed. * created with createTestWindow have been mapped and exposed.
*/ */
function waitTestWindows() { function waitTestWindows() {
let cb;
let perfHelper = _getPerfHelper(); let perfHelper = _getPerfHelper();
return _callRemote(perfHelper, perfHelper.WaitWindowsRemote);
perfHelper.WaitWindowsRemote(function(result, excp) {
if (cb)
cb();
});
return function(callback) {
cb = callback;
};
} }
/** /**
@ -171,8 +154,17 @@ function waitTestWindows() {
* process because of normal X asynchronicity. * process because of normal X asynchronicity.
*/ */
function destroyTestWindows() { function destroyTestWindows() {
let cb;
let perfHelper = _getPerfHelper(); let perfHelper = _getPerfHelper();
return _callRemote(perfHelper, perfHelper.DestroyWindowsRemote);
perfHelper.DestroyWindowsRemote(function(result, excp) {
if (cb)
cb();
});
return function(callback) {
cb = callback;
};
} }
/** /**
@ -215,10 +207,6 @@ function _step(g, finish, onError) {
let waitFunction = g.next(); let waitFunction = g.next();
waitFunction(function() { waitFunction(function() {
_step(g, finish, onError); _step(g, finish, onError);
},
function(err) {
if (onError)
onError(err);
}); });
} catch (err if err instanceof StopIteration) { } catch (err if err instanceof StopIteration) {
if (finish) if (finish)
@ -317,8 +305,8 @@ function _collect(scriptModule, outputFile) {
print ('------------------------------------------------------------'); print ('------------------------------------------------------------');
for (let i = 0; i < metrics.length; i++) { for (let i = 0; i < metrics.length; i++) {
let metric = metrics[i]; let metric = metrics[i];
print ('# ' + scriptModule.METRICS[metric].description); print ('# ' + scriptModule.METRIC_DESCRIPTIONS[metric]);
print (metric + ': ' + scriptModule.METRICS[metric].value + scriptModule.METRICS[metric].units); print (metric + ': ' + scriptModule.METRICS[metric]);
} }
print ('------------------------------------------------------------'); print ('------------------------------------------------------------');
} }
@ -371,12 +359,7 @@ function runPerfScript(scriptModule, outputFile) {
_step(g, _step(g,
function() { function() {
try { _collect(scriptModule, outputFile);
_collect(scriptModule, outputFile);
} catch (err) {
log("Script failed: " + err + "\n" + err.stack);
Meta.exit(Meta.ExitCode.ERROR);
}
Meta.exit(Meta.ExitCode.SUCCESS); Meta.exit(Meta.ExitCode.SUCCESS);
}, },
function(err) { function(err) {

View File

@ -2,12 +2,10 @@
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const Lang = imports.lang; const Lang = imports.lang;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk; const Gtk = imports.gi.Gtk;
const Meta = imports.gi.Meta; const Meta = imports.gi.Meta;
const Signals = imports.signals; const Signals = imports.signals;
const Shell = imports.gi.Shell;
const St = imports.gi.St; const St = imports.gi.St;
const Atk = imports.gi.Atk; const Atk = imports.gi.Atk;
@ -25,6 +23,107 @@ const SEARCH_PROVIDERS_SCHEMA = 'org.gnome.desktop.search-providers';
const MAX_LIST_SEARCH_RESULTS_ROWS = 3; const MAX_LIST_SEARCH_RESULTS_ROWS = 3;
const MAX_GRID_SEARCH_RESULTS_ROWS = 1; const MAX_GRID_SEARCH_RESULTS_ROWS = 1;
const SearchSystem = new Lang.Class({
Name: 'SearchSystem',
_init: function() {
this._providers = [];
this._registerProvider(new AppDisplay.AppSearchProvider());
this._searchSettings = new Gio.Settings({ schema: SEARCH_PROVIDERS_SCHEMA });
this._searchSettings.connect('changed::disabled', Lang.bind(this, this._reloadRemoteProviders));
this._searchSettings.connect('changed::disable-external', Lang.bind(this, this._reloadRemoteProviders));
this._searchSettings.connect('changed::sort-order', Lang.bind(this, this._reloadRemoteProviders));
this._reloadRemoteProviders();
this._cancellable = new Gio.Cancellable();
},
addProvider: function(provider) {
this._providers.push(provider);
this.emit('providers-changed');
},
_reloadRemoteProviders: function() {
let remoteProviders = this._providers.filter(function(provider) {
return provider.isRemoteProvider;
});
remoteProviders.forEach(Lang.bind(this, function(provider) {
this._unregisterProvider(provider);
}));
RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, function(providers) {
providers.forEach(Lang.bind(this, this._registerProvider));
}));
this.emit('providers-changed');
},
_registerProvider: function (provider) {
this._providers.push(provider);
},
_unregisterProvider: function (provider) {
let index = this._providers.indexOf(provider);
this._providers.splice(index, 1);
if (provider.display)
provider.display.destroy();
},
getProviders: function() {
return this._providers;
},
getTerms: function() {
return this._terms;
},
reset: function() {
this._terms = [];
this._results = {};
},
_gotResults: function(results, provider) {
this._results[provider.id] = results;
this.emit('search-updated', provider, results);
},
setTerms: function(terms) {
this._cancellable.cancel();
this._cancellable.reset();
let previousResults = this._results;
let previousTerms = this._terms;
this.reset();
if (!terms)
return;
let searchString = terms.join(' ');
let previousSearchString = previousTerms.join(' ');
if (searchString == previousSearchString)
return;
let isSubSearch = false;
if (previousTerms.length > 0)
isSubSearch = searchString.indexOf(previousSearchString) == 0;
this._terms = terms;
this._providers.forEach(Lang.bind(this, function(provider) {
let previousProviderResults = previousResults[provider.id];
if (isSubSearch && previousProviderResults)
provider.getSubsearchResultSet(previousProviderResults, terms, Lang.bind(this, this._gotResults, provider), this._cancellable);
else
provider.getInitialResultSet(terms, Lang.bind(this, this._gotResults, provider), this._cancellable);
}));
}
});
Signals.addSignalMethods(SearchSystem.prototype);
const MaxWidthBin = new Lang.Class({ const MaxWidthBin = new Lang.Class({
Name: 'MaxWidthBin', Name: 'MaxWidthBin',
Extends: St.Bin, Extends: St.Bin,
@ -64,6 +163,13 @@ const SearchResult = new Lang.Class({
activate: function() { activate: function() {
this.emit('activate', this.metaInfo.id); this.emit('activate', this.metaInfo.id);
},
setSelected: function(selected) {
if (selected)
this.actor.add_style_pseudo_class('selected');
else
this.actor.remove_style_pseudo_class('selected');
} }
}); });
Signals.addSignalMethods(SearchResult.prototype); Signals.addSignalMethods(SearchResult.prototype);
@ -124,11 +230,59 @@ const GridSearchResult = new Lang.Class({
this.actor.style_class = 'grid-search-result'; this.actor.style_class = 'grid-search-result';
this.icon = new IconGrid.BaseIcon(this.metaInfo['name'], let content = provider.createResultObject(metaInfo);
{ createIcon: this.metaInfo['createIcon'] }); let dragSource = null;
let content = new St.Bin({ child: this.icon.actor });
this.actor.set_child(content); if (content == null) {
this.actor.label_actor = this.icon.label; let actor = new St.Bin();
let icon = new IconGrid.BaseIcon(this.metaInfo['name'],
{ createIcon: this.metaInfo['createIcon'] });
actor.set_child(icon.actor);
actor.label_actor = icon.label;
dragSource = icon.icon;
content = { actor: actor, icon: icon };
} else {
if (content._delegate && content._delegate.getDragActorSource)
dragSource = content._delegate.getDragActorSource();
}
this.actor.set_child(content.actor);
this.actor.label_actor = content.actor.label_actor;
this.icon = content.icon;
let draggable = DND.makeDraggable(this.actor);
draggable.connect('drag-begin',
Lang.bind(this, function() {
Main.overview.beginItemDrag(this);
}));
draggable.connect('drag-cancelled',
Lang.bind(this, function() {
Main.overview.cancelledItemDrag(this);
}));
draggable.connect('drag-end',
Lang.bind(this, function() {
Main.overview.endItemDrag(this);
}));
if (!dragSource)
// not exactly right, but alignment problems are hard to notice
dragSource = content;
this._dragActorSource = dragSource;
},
getDragActorSource: function() {
return this._dragActorSource;
},
getDragActor: function() {
return this.metaInfo['createIcon'](Main.overview.dashIconSize);
},
shellWorkspaceLaunch: function(params) {
if (this.provider.dragActivateResult)
this.provider.dragActivateResult(this.metaInfo.id, params);
else
this.provider.activateResult(this.metaInfo.id, this.terms);
} }
}); });
@ -160,11 +314,7 @@ const SearchResultsBase = new Lang.Class({
this._terms = []; this._terms = [];
}, },
_createResultDisplay: function(meta) { _clearResultDisplay: function() {
if (this.provider.createResultObject)
return this.provider.createResultObject(meta);
return null;
}, },
clear: function() { clear: function() {
@ -234,10 +384,9 @@ const SearchResultsBase = new Lang.Class({
let hasMoreResults = results.length < providerResults.length; let hasMoreResults = results.length < providerResults.length;
this._ensureResultActors(results, Lang.bind(this, function(successful) { this._ensureResultActors(results, Lang.bind(this, function(successful) {
if (!successful) { this._clearResultDisplay();
this._clearResultDisplay(); if (!successful)
return; return;
}
// To avoid CSS transitions causing flickering when // To avoid CSS transitions causing flickering when
// the first search result stays the same, we hide the // the first search result stays the same, we hide the
@ -267,7 +416,6 @@ const ListSearchResults = new Lang.Class({
this.providerIcon.connect('key-focus-in', Lang.bind(this, this._keyFocusIn)); this.providerIcon.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this.providerIcon.connect('clicked', Lang.bind(this, this.providerIcon.connect('clicked', Lang.bind(this,
function() { function() {
this.providerIcon.animateLaunch();
provider.launchSearch(this._terms); provider.launchSearch(this._terms);
Main.overview.toggle(); Main.overview.toggle();
})); }));
@ -285,7 +433,7 @@ const ListSearchResults = new Lang.Class({
}, },
_setMoreIconVisible: function(visible) { _setMoreIconVisible: function(visible) {
this.providerIcon.moreIcon.visible = visible; this.providerIcon.moreIcon.visible = true;
}, },
_getMaxDisplayedResults: function() { _getMaxDisplayedResults: function() {
@ -297,7 +445,7 @@ const ListSearchResults = new Lang.Class({
}, },
_createResultDisplay: function(meta) { _createResultDisplay: function(meta) {
return this.parent(meta) || new ListSearchResult(this.provider, meta); return new ListSearchResult(this.provider, meta);
}, },
_addItem: function(display) { _addItem: function(display) {
@ -317,14 +465,8 @@ const GridSearchResults = new Lang.Class({
Name: 'GridSearchResults', Name: 'GridSearchResults',
Extends: SearchResultsBase, Extends: SearchResultsBase,
_init: function(provider, parentContainer) { _init: function(provider) {
this.parent(provider); this.parent(provider);
// We need to use the parent container to know how much results we can show.
// None of the actors in this class can be used for that, since the main actor
// goes hidden when no results are displayed, and then it lost its allocation.
// Then on the next use of _getMaxDisplayedResults allocation is 0, en therefore
// it doesn't show any result although we have some.
this._parentContainer = parentContainer;
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS, this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
xAlign: St.Align.START }); xAlign: St.Align.START });
@ -335,9 +477,16 @@ const GridSearchResults = new Lang.Class({
}, },
_getMaxDisplayedResults: function() { _getMaxDisplayedResults: function() {
let parentThemeNode = this._parentContainer.get_theme_node(); return this._grid.columnsForWidth(this._bin.width) * this._grid.getRowLimit();
let availableWidth = parentThemeNode.adjust_for_width(this._parentContainer.width); },
return this._grid.columnsForWidth(availableWidth) * this._grid.getRowLimit();
_renderResults: function(metas) {
for (let i = 0; i < metas.length; i++) {
let display = new GridSearchResult(this.provider, metas[i]);
display.connect('activate', Lang.bind(this, this._activateResult));
display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this._grid.addItem(display);
}
}, },
_clearResultDisplay: function () { _clearResultDisplay: function () {
@ -345,7 +494,7 @@ const GridSearchResults = new Lang.Class({
}, },
_createResultDisplay: function(meta) { _createResultDisplay: function(meta) {
return this.parent(meta) || new GridSearchResult(this.provider, meta); return new GridSearchResult(this.provider, meta);
}, },
_addItem: function(display) { _addItem: function(display) {
@ -397,136 +546,16 @@ const SearchResults = new Lang.Class({
this._statusText = new St.Label({ style_class: 'search-statustext' }); this._statusText = new St.Label({ style_class: 'search-statustext' });
this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE, this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE }); y_align: St.Align.MIDDLE });
this.actor.add(this._statusBin, { expand: true }); this._content.add(this._statusBin, { expand: true });
this._statusBin.add_actor(this._statusText); this._statusBin.add_actor(this._statusText);
this._highlightDefault = false; this._highlightDefault = false;
this._defaultResult = null; this._defaultResult = null;
this._startingSearch = false;
this._terms = []; this._searchSystem = new SearchSystem();
this._results = {}; this._searchSystem.connect('search-updated', Lang.bind(this, this._updateResults));
this._searchSystem.connect('providers-changed', Lang.bind(this, this._updateProviderDisplays));
this._providers = []; this._updateProviderDisplays();
this._searchSettings = new Gio.Settings({ schema_id: SEARCH_PROVIDERS_SCHEMA });
this._searchSettings.connect('changed::disabled', Lang.bind(this, this._reloadRemoteProviders));
this._searchSettings.connect('changed::disable-external', Lang.bind(this, this._reloadRemoteProviders));
this._searchSettings.connect('changed::sort-order', Lang.bind(this, this._reloadRemoteProviders));
this._searchTimeoutId = 0;
this._cancellable = new Gio.Cancellable();
this._registerProvider(new AppDisplay.AppSearchProvider());
this._reloadRemoteProviders();
},
_reloadRemoteProviders: function() {
let remoteProviders = this._providers.filter(function(provider) {
return provider.isRemoteProvider;
});
remoteProviders.forEach(Lang.bind(this, function(provider) {
this._unregisterProvider(provider);
}));
RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, function(providers) {
providers.forEach(Lang.bind(this, this._registerProvider));
}));
},
_registerProvider: function (provider) {
this._providers.push(provider);
this._ensureProviderDisplay(provider);
},
_unregisterProvider: function (provider) {
let index = this._providers.indexOf(provider);
this._providers.splice(index, 1);
if (provider.display)
provider.display.destroy();
},
_gotResults: function(results, provider) {
this._results[provider.id] = results;
this._updateResults(provider, results);
},
_clearSearchTimeout: function() {
if (this._searchTimeoutId > 0) {
GLib.source_remove(this._searchTimeoutId);
this._searchTimeoutId = 0;
}
},
_reset: function() {
this._terms = [];
this._results = {};
this._clearDisplay();
this._clearSearchTimeout();
this._defaultResult = null;
this._startingSearch = false;
this._updateSearchProgress();
},
_doSearch: function() {
this._startingSearch = false;
let previousResults = this._results;
this._results = {};
this._providers.forEach(Lang.bind(this, function(provider) {
provider.searchInProgress = true;
let previousProviderResults = previousResults[provider.id];
if (this._isSubSearch && previousProviderResults)
provider.getSubsearchResultSet(previousProviderResults, this._terms, Lang.bind(this, this._gotResults, provider), this._cancellable);
else
provider.getInitialResultSet(this._terms, Lang.bind(this, this._gotResults, provider), this._cancellable);
}));
this._updateSearchProgress();
this._clearSearchTimeout();
},
_onSearchTimeout: function() {
this._searchTimeoutId = 0;
this._doSearch();
return GLib.SOURCE_REMOVE;
},
setTerms: function(terms) {
// Check for the case of making a duplicate previous search before
// setting state of the current search or cancelling the search.
// This will prevent incorrect state being as a result of a duplicate
// search while the previous search is still active.
let searchString = terms.join(' ');
let previousSearchString = this._terms.join(' ');
if (searchString == previousSearchString)
return;
this._startingSearch = true;
this._cancellable.cancel();
this._cancellable.reset();
if (terms.length == 0) {
this._reset();
return;
}
let isSubSearch = false;
if (this._terms.length > 0)
isSubSearch = searchString.indexOf(previousSearchString) == 0;
this._terms = terms;
this._isSubSearch = isSubSearch;
this._updateSearchProgress();
if (this._searchTimeoutId == 0)
this._searchTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 150, Lang.bind(this, this._onSearchTimeout));
}, },
_onPan: function(action) { _onPan: function(action) {
@ -548,24 +577,44 @@ const SearchResults = new Lang.Class({
if (provider.appInfo) if (provider.appInfo)
providerDisplay = new ListSearchResults(provider); providerDisplay = new ListSearchResults(provider);
else else
providerDisplay = new GridSearchResults(provider, this.actor); providerDisplay = new GridSearchResults(provider);
providerDisplay.connect('key-focus-in', Lang.bind(this, this._keyFocusIn)); providerDisplay.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
providerDisplay.actor.hide();
this._content.add(providerDisplay.actor); this._content.add(providerDisplay.actor);
provider.display = providerDisplay; provider.display = providerDisplay;
}, },
_updateProviderDisplays: function() {
this._searchSystem.getProviders().forEach(Lang.bind(this, this._ensureProviderDisplay));
},
_clearDisplay: function() { _clearDisplay: function() {
this._providers.forEach(function(provider) { this._searchSystem.getProviders().forEach(function(provider) {
provider.display.clear(); provider.display.clear();
}); });
}, },
reset: function() {
this._searchSystem.reset();
this._statusBin.hide();
this._clearDisplay();
this._defaultResult = null;
},
startingSearch: function() {
this.reset();
this._statusText.set_text(_("Searching…"));
this._statusBin.show();
},
setTerms: function(terms) {
this._searchSystem.setTerms(terms);
},
_maybeSetInitialSelection: function() { _maybeSetInitialSelection: function() {
let newDefaultResult = null; let newDefaultResult = null;
let providers = this._providers; let providers = this._searchSystem.getProviders();
for (let i = 0; i < providers.length; i++) { for (let i = 0; i < providers.length; i++) {
let provider = providers[i]; let provider = providers[i];
let display = provider.display; let display = provider.display;
@ -581,64 +630,54 @@ const SearchResults = new Lang.Class({
} }
if (newDefaultResult != this._defaultResult) { if (newDefaultResult != this._defaultResult) {
this._setSelected(this._defaultResult, false); if (this._defaultResult)
this._setSelected(newDefaultResult, this._highlightDefault); this._defaultResult.setSelected(false);
if (newDefaultResult) {
newDefaultResult.setSelected(this._highlightDefault);
if (this._highlightDefault)
Util.ensureActorVisibleInScrollView(this._scrollView, newDefaultResult.actor);
}
this._defaultResult = newDefaultResult; this._defaultResult = newDefaultResult;
} }
}, },
get searchInProgress() { _updateStatusText: function () {
if (this._startingSearch) let haveResults = this._searchSystem.getProviders().some(function(provider) {
return true;
return this._providers.some(function(provider) {
return provider.searchInProgress;
});
},
_updateSearchProgress: function () {
let haveResults = this._providers.some(function(provider) {
let display = provider.display; let display = provider.display;
return (display.getFirstResult() != null); return (display.getFirstResult() != null);
}); });
this._scrollView.visible = haveResults;
this._statusBin.visible = !haveResults;
if (!haveResults) { if (!haveResults) {
if (this.searchInProgress) { this._statusText.set_text(_("No results."));
this._statusText.set_text(_("Searching…")); this._statusBin.show();
} else { } else {
this._statusText.set_text(_("No results.")); this._statusBin.hide();
}
} }
}, },
_updateResults: function(provider, results) { _updateResults: function(searchSystem, provider, results) {
let terms = this._terms; let terms = searchSystem.getTerms();
let display = provider.display; let display = provider.display;
display.updateSearch(results, terms, Lang.bind(this, function() { display.updateSearch(results, terms, Lang.bind(this, function() {
provider.searchInProgress = false;
this._maybeSetInitialSelection(); this._maybeSetInitialSelection();
this._updateSearchProgress(); this._updateStatusText();
})); }));
}, },
activateDefault: function() { activateDefault: function() {
// If we have a search queued up, force the search now.
if (this._searchTimeoutId > 0)
this._doSearch();
if (this._defaultResult) if (this._defaultResult)
this._defaultResult.activate(); this._defaultResult.activate();
}, },
highlightDefault: function(highlight) { highlightDefault: function(highlight) {
this._highlightDefault = highlight; this._highlightDefault = highlight;
this._setSelected(this._defaultResult, highlight); if (this._defaultResult) {
this._defaultResult.setSelected(highlight);
if (highlight)
Util.ensureActorVisibleInScrollView(this._scrollView, this._defaultResult.actor);
}
}, },
navigateFocus: function(direction) { navigateFocus: function(direction) {
@ -653,18 +692,6 @@ const SearchResults = new Lang.Class({
let from = this._defaultResult ? this._defaultResult.actor : null; let from = this._defaultResult ? this._defaultResult.actor : null;
this.actor.navigate_focus(from, direction, false); this.actor.navigate_focus(from, direction, false);
},
_setSelected: function(result, selected) {
if (!result)
return;
if (selected) {
result.actor.add_style_pseudo_class('selected');
Util.ensureActorVisibleInScrollView(this._scrollView, result.actor);
} else {
result.actor.remove_style_pseudo_class('selected');
}
} }
}); });
@ -698,12 +725,5 @@ const ProviderIcon = new Lang.Class({
gicon: provider.appInfo.get_icon() }); gicon: provider.appInfo.get_icon() });
this._content.add_actor(icon); this._content.add_actor(icon);
this._content.add_actor(this.moreIcon); this._content.add_actor(this.moreIcon);
},
animateLaunch: function() {
let appSys = Shell.AppSystem.get_default();
let app = appSys.lookup_app(this.provider.appInfo.get_id());
if (app.state == Shell.AppState.STOPPED)
IconGrid.zoomOutActor(this._content);
} }
}); });

View File

@ -18,6 +18,7 @@ const _modes = {
'restrictive': { 'restrictive': {
parentMode: null, parentMode: null,
stylesheetName: 'gnome-shell.css', stylesheetName: 'gnome-shell.css',
overridesSchema: 'org.gnome.shell.overrides',
hasOverview: false, hasOverview: false,
showCalendarEvents: false, showCalendarEvents: false,
allowSettings: false, allowSettings: false,
@ -139,14 +140,13 @@ function _loadModes() {
function listModes() { function listModes() {
_loadModes(); _loadModes();
let id = Mainloop.idle_add(function() { Mainloop.idle_add(function() {
let names = Object.getOwnPropertyNames(_modes); let names = Object.getOwnPropertyNames(_modes);
for (let i = 0; i < names.length; i++) for (let i = 0; i < names.length; i++)
if (_modes[names[i]].isPrimary) if (_modes[names[i]].isPrimary)
print(names[i]); print(names[i]);
Mainloop.quit('listModes'); Mainloop.quit('listModes');
}); });
GLib.Source.set_name_by_id(id, '[gnome-shell] listModes');
Mainloop.run('listModes'); Mainloop.run('listModes');
} }

View File

@ -141,7 +141,12 @@ const GnomeShell = new Lang.Class({
if (params['icon']) if (params['icon'])
icon = Gio.Icon.new_for_string(params['icon']); icon = Gio.Icon.new_for_string(params['icon']);
Main.osdWindowManager.show(monitorIndex, icon, params['label'], params['level']); Main.osdWindow.setIcon(icon);
Main.osdWindow.setMonitor (monitorIndex);
Main.osdWindow.setLabel(params['label']);
Main.osdWindow.setLevel(params['level']);
Main.osdWindow.show();
}, },
FocusApp: function(id) { FocusApp: function(id) {

View File

@ -17,6 +17,8 @@ const EntryMenu = new Lang.Class({
_init: function(entry) { _init: function(entry) {
this.parent(entry, 0, St.Side.TOP); this.parent(entry, 0, St.Side.TOP);
this.actor.add_style_class_name('entry-context-menu');
this._entry = entry; this._entry = entry;
this._clipboard = St.Clipboard.get_default(); this._clipboard = St.Clipboard.get_default();

View File

@ -24,7 +24,6 @@ const Slider = new Lang.Class({
accessible_role: Atk.Role.SLIDER }); accessible_role: Atk.Role.SLIDER });
this.actor.connect('repaint', Lang.bind(this, this._sliderRepaint)); this.actor.connect('repaint', Lang.bind(this, this._sliderRepaint));
this.actor.connect('button-press-event', Lang.bind(this, this._startDragging)); this.actor.connect('button-press-event', Lang.bind(this, this._startDragging));
this.actor.connect('touch-event', Lang.bind(this, this._touchDragging));
this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent)); this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
this.actor.connect('key-press-event', Lang.bind(this, this.onKeyPressEvent)); this.actor.connect('key-press-event', Lang.bind(this, this.onKeyPressEvent));
@ -122,21 +121,11 @@ const Slider = new Lang.Class({
this._dragging = true; this._dragging = true;
let device = event.get_device(); let device = event.get_device();
let sequence = event.get_event_sequence(); device.grab(this.actor);
if (sequence != null)
device.sequence_grab(sequence, this.actor);
else
device.grab(this.actor);
this._grabbedDevice = device; this._grabbedDevice = device;
this._grabbedSequence = sequence;
if (sequence == null) {
this._releaseId = this.actor.connect('button-release-event', Lang.bind(this, this._endDragging));
this._motionId = this.actor.connect('motion-event', Lang.bind(this, this._motionEvent));
}
this._releaseId = this.actor.connect('button-release-event', Lang.bind(this, this._endDragging));
this._motionId = this.actor.connect('motion-event', Lang.bind(this, this._motionEvent));
let absX, absY; let absX, absY;
[absX, absY] = event.get_coords(); [absX, absY] = event.get_coords();
this._moveHandle(absX, absY); this._moveHandle(absX, absY);
@ -145,17 +134,10 @@ const Slider = new Lang.Class({
_endDragging: function() { _endDragging: function() {
if (this._dragging) { if (this._dragging) {
if (this._releaseId) this.actor.disconnect(this._releaseId);
this.actor.disconnect(this._releaseId); this.actor.disconnect(this._motionId);
if (this._motionId)
this.actor.disconnect(this._motionId);
if (this._grabbedSequence != null) this._grabbedDevice.ungrab();
this._grabbedDevice.sequence_ungrab(this._grabbedSequence);
else
this._grabbedDevice.ungrab();
this._grabbedSequence = null;
this._grabbedDevice = null; this._grabbedDevice = null;
this._dragging = false; this._dragging = false;
@ -164,24 +146,6 @@ const Slider = new Lang.Class({
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
}, },
_touchDragging: function(actor, event) {
let device = event.get_device();
let sequence = event.get_event_sequence();
if (!this._dragging &&
event.type() == Clutter.EventType.TOUCH_BEGIN) {
this.startDragging(event);
return Clutter.EVENT_STOP;
} else if (device.sequence_get_grabbed_actor(sequence) == actor) {
if (event.type() == Clutter.EventType.TOUCH_UPDATE)
return this._motionEvent(actor, event);
else if (event.type() == Clutter.EventType.TOUCH_END)
return this._endDragging();
}
return Clutter.EVENT_PROPAGATE;
},
scroll: function(event) { scroll: function(event) {
let direction = event.get_scroll_direction(); let direction = event.get_scroll_direction();
let delta; let delta;

View File

@ -48,7 +48,7 @@ const ATIndicator = new Lang.Class({
this.actor.add_child(this._hbox); this.actor.add_child(this._hbox);
this._a11ySettings = new Gio.Settings({ schema_id: A11Y_SCHEMA }); this._a11ySettings = new Gio.Settings({ schema: A11Y_SCHEMA });
this._a11ySettings.connect('changed::' + KEY_ALWAYS_SHOW, Lang.bind(this, this._queueSyncMenuVisibility)); this._a11ySettings.connect('changed::' + KEY_ALWAYS_SHOW, Lang.bind(this, this._queueSyncMenuVisibility));
let highContrast = this._buildHCItem(); let highContrast = this._buildHCItem();
@ -103,7 +103,6 @@ const ATIndicator = new Lang.Class({
return; return;
this._syncMenuVisbilityIdle = Mainloop.idle_add(Lang.bind(this, this._syncMenuVisibility)); this._syncMenuVisbilityIdle = Mainloop.idle_add(Lang.bind(this, this._syncMenuVisibility));
GLib.Source.set_name_by_id(this._syncMenuVisbilityIdle, '[gnome-shell] this._syncMenuVisibility');
}, },
_buildItemExtended: function(string, initial_value, writable, on_set) { _buildItemExtended: function(string, initial_value, writable, on_set) {
@ -118,7 +117,7 @@ const ATIndicator = new Lang.Class({
}, },
_buildItem: function(string, schema, key) { _buildItem: function(string, schema, key) {
let settings = new Gio.Settings({ schema_id: schema }); let settings = new Gio.Settings({ schema: schema });
let widget = this._buildItemExtended(string, let widget = this._buildItemExtended(string,
settings.get_boolean(key), settings.get_boolean(key),
settings.is_writable(key), settings.is_writable(key),
@ -134,8 +133,8 @@ const ATIndicator = new Lang.Class({
}, },
_buildHCItem: function() { _buildHCItem: function() {
let interfaceSettings = new Gio.Settings({ schema_id: DESKTOP_INTERFACE_SCHEMA }); let interfaceSettings = new Gio.Settings({ schema: DESKTOP_INTERFACE_SCHEMA });
let wmSettings = new Gio.Settings({ schema_id: WM_SCHEMA }); let wmSettings = new Gio.Settings({ schema: WM_SCHEMA });
let gtkTheme = interfaceSettings.get_string(KEY_GTK_THEME); let gtkTheme = interfaceSettings.get_string(KEY_GTK_THEME);
let iconTheme = interfaceSettings.get_string(KEY_ICON_THEME); let iconTheme = interfaceSettings.get_string(KEY_ICON_THEME);
let wmTheme = wmSettings.get_string(KEY_WM_THEME); let wmTheme = wmSettings.get_string(KEY_WM_THEME);
@ -186,7 +185,7 @@ const ATIndicator = new Lang.Class({
}, },
_buildFontItem: function() { _buildFontItem: function() {
let settings = new Gio.Settings({ schema_id: DESKTOP_INTERFACE_SCHEMA }); let settings = new Gio.Settings({ schema: DESKTOP_INTERFACE_SCHEMA });
let factor = settings.get_double(KEY_TEXT_SCALING_FACTOR); let factor = settings.get_double(KEY_TEXT_SCALING_FACTOR);
let initial_setting = (factor > 1.0); let initial_setting = (factor > 1.0);

File diff suppressed because it is too large Load Diff

View File

@ -9,18 +9,8 @@ const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const LOCATION_SCHEMA = 'org.gnome.system.location'; const LOCATION_SCHEMA = 'org.gnome.shell.location';
const MAX_ACCURACY_LEVEL = 'max-accuracy-level'; const MAX_ACCURACY_LEVEL = 'max-accuracy-level';
const ENABLED = 'enabled';
const GeoclueAccuracyLevel = {
NONE: 0,
COUNTRY: 1,
CITY: 4,
NEIGHBORHOOD: 5,
STREET: 6,
EXACT: 8
};
var GeoclueIface = '<node> \ var GeoclueIface = '<node> \
<interface name="org.freedesktop.GeoClue2.Manager"> \ <interface name="org.freedesktop.GeoClue2.Manager"> \
@ -53,9 +43,7 @@ const Indicator = new Lang.Class({
_init: function() { _init: function() {
this.parent(); this.parent();
this._settings = new Gio.Settings({ schema_id: LOCATION_SCHEMA }); this._settings = new Gio.Settings({ schema: LOCATION_SCHEMA });
this._settings.connect('changed::' + ENABLED,
Lang.bind(this, this._onMaxAccuracyLevelChanged));
this._settings.connect('changed::' + MAX_ACCURACY_LEVEL, this._settings.connect('changed::' + MAX_ACCURACY_LEVEL,
Lang.bind(this, this._onMaxAccuracyLevelChanged)); Lang.bind(this, this._onMaxAccuracyLevelChanged));
@ -70,7 +58,6 @@ const Indicator = new Lang.Class({
this._item.status.text = _("Enabled"); this._item.status.text = _("Enabled");
this._onOffAction = this._item.menu.addAction(_("Disable"), Lang.bind(this, this._onOnOffAction)); this._onOffAction = this._item.menu.addAction(_("Disable"), Lang.bind(this, this._onOnOffAction));
this._item.menu.addSettingsAction(_("Privacy Settings"), 'gnome-privacy-panel.desktop');
this.menu.addMenuItem(this._item); this.menu.addMenuItem(this._item);
@ -106,12 +93,10 @@ const Indicator = new Lang.Class({
_syncIndicator: function() { _syncIndicator: function() {
if (this._proxy == null) { if (this._proxy == null) {
this._indicator.visible = false; this._indicator.visible = false;
this._item.actor.visible = false;
return; return;
} }
this._indicator.visible = this._proxy.InUse; this._indicator.visible = this._proxy.InUse;
this._item.actor.visible = this._indicator.visible;
this._updateMenuLabels(); this._updateMenuLabels();
}, },
@ -138,6 +123,7 @@ const Indicator = new Lang.Class({
this._propertiesChangedId = this._proxy.connect('g-properties-changed', this._propertiesChangedId = this._proxy.connect('g-properties-changed',
Lang.bind(this, this._onGeocluePropsChanged)); Lang.bind(this, this._onGeocluePropsChanged));
this._availableAccuracyLevel = this._proxy.AvailableAccuracyLevel;
this._syncIndicator(); this._syncIndicator();
this._proxy.AddAgentRemote('gnome-shell', Lang.bind(this, this._onAgentRegistered)); this._proxy.AddAgentRemote('gnome-shell', Lang.bind(this, this._onAgentRegistered));
@ -162,8 +148,10 @@ const Indicator = new Lang.Class({
}, },
_onOnOffAction: function() { _onOnOffAction: function() {
let enabled = this._settings.get_boolean(ENABLED); if (this._getMaxAccuracyLevel() == 0)
this._settings.set_boolean(ENABLED, !enabled); this._settings.set_enum(MAX_ACCURACY_LEVEL, this._availableAccuracyLevel);
else
this._settings.set_enum(MAX_ACCURACY_LEVEL, 0);
}, },
_onSessionUpdated: function() { _onSessionUpdated: function() {
@ -172,12 +160,12 @@ const Indicator = new Lang.Class({
}, },
_updateMenuLabels: function() { _updateMenuLabels: function() {
if (this._settings.get_boolean(ENABLED)) { if (this._getMaxAccuracyLevel() == 0) {
this._item.status.text = this._indicator.visible ? _("In Use") : _("Enabled");
this._onOffAction.label.text = _("Disable");
} else {
this._item.status.text = _("Disabled"); this._item.status.text = _("Disabled");
this._onOffAction.label.text = _("Enable"); this._onOffAction.label.text = _("Enable");
} else {
this._item.status.text = this._indicator.visible ? _("In Use") : _("Enabled");
this._onOffAction.label.text = _("Disable");
} }
}, },
@ -191,14 +179,7 @@ const Indicator = new Lang.Class({
}, },
_getMaxAccuracyLevel: function() { _getMaxAccuracyLevel: function() {
if (this._settings.get_boolean(ENABLED)) { return this._settings.get_enum(MAX_ACCURACY_LEVEL);
let level = this._settings.get_string(MAX_ACCURACY_LEVEL);
return GeoclueAccuracyLevel[level.toUpperCase()] ||
GeoclueAccuracyLevel.NONE;
} else {
return GeoclueAccuracyLevel.NONE;
}
}, },
_notifyMaxAccuracyLevel: function() { _notifyMaxAccuracyLevel: function() {
@ -210,6 +191,8 @@ const Indicator = new Lang.Class({
let unpacked = properties.deep_unpack(); let unpacked = properties.deep_unpack();
if ("InUse" in unpacked) if ("InUse" in unpacked)
this._syncIndicator(); this._syncIndicator();
if ("AvailableAccuracyLevel" in unpacked)
this._availableAccuracyLevel = this._proxy.AvailableAccuracyLevel;
} }
}); });

View File

@ -44,33 +44,6 @@ const NM80211Mode = NetworkManager['80211Mode'];
const NM80211ApFlags = NetworkManager['80211ApFlags']; const NM80211ApFlags = NetworkManager['80211ApFlags'];
const NM80211ApSecurityFlags = NetworkManager['80211ApSecurityFlags']; const NM80211ApSecurityFlags = NetworkManager['80211ApSecurityFlags'];
const PortalHelperResult = {
CANCELLED: 0,
COMPLETED: 1,
RECHECK: 2
};
const PortalHelperIface = '<node> \
<interface name="org.gnome.Shell.PortalHelper"> \
<method name="Authenticate"> \
<arg type="o" direction="in" name="connection" /> \
<arg type="s" direction="in" name="url" /> \
<arg type="u" direction="in" name="timestamp" /> \
</method> \
<method name="Close"> \
<arg type="o" direction="in" name="connection" /> \
</method> \
<method name="Refresh"> \
<arg type="o" direction="in" name="connection" /> \
</method> \
<signal name="Done"> \
<arg type="o" name="connection" /> \
<arg type="u" name="result" /> \
</signal> \
</interface> \
</node>';
const PortalHelperProxy = Gio.DBusProxy.makeProxyWrapper(PortalHelperIface);
function ssidCompare(one, two) { function ssidCompare(one, two) {
if (!one || !two) if (!one || !two)
return false; return false;
@ -234,23 +207,13 @@ const NMConnectionSection = new Lang.Class({
this.item.menu.addMenuItem(this._labelSection); this.item.menu.addMenuItem(this._labelSection);
this.item.menu.addMenuItem(this._radioSection); this.item.menu.addMenuItem(this._radioSection);
this._notifyConnectivityId = this._client.connect('notify::connectivity', Lang.bind(this, this._iconChanged)); this.connect('icon-changed', Lang.bind(this, this._sync));
}, },
destroy: function() { destroy: function() {
if (this._notifyConnectivityId != 0) {
this._client.disconnect(this._notifyConnectivityId);
this._notifyConnectivityId = 0;
}
this.item.destroy(); this.item.destroy();
}, },
_iconChanged: function() {
this._sync();
this.emit('icon-changed');
},
_sync: function() { _sync: function() {
let nItems = this._connectionItems.size; let nItems = this._connectionItems.size;
@ -315,7 +278,7 @@ const NMConnectionSection = new Lang.Class({
return; return;
item.connect('icon-changed', Lang.bind(this, function() { item.connect('icon-changed', Lang.bind(this, function() {
this._iconChanged(); this.emit('icon-changed');
})); }));
item.connect('activation-failed', Lang.bind(this, function(item, reason) { item.connect('activation-failed', Lang.bind(this, function(item, reason) {
this.emit('activation-failed', reason); this.emit('activation-failed', reason);
@ -460,18 +423,18 @@ const NMConnectionDevice = new Lang.Class({
case NetworkManager.DeviceState.UNMANAGED: case NetworkManager.DeviceState.UNMANAGED:
/* Translators: this is for network devices that are physically present but are not /* Translators: this is for network devices that are physically present but are not
under NetworkManager's control (and thus cannot be used in the menu) */ under NetworkManager's control (and thus cannot be used in the menu) */
return _("Unmanaged"); return _("unmanaged");
case NetworkManager.DeviceState.DEACTIVATING: case NetworkManager.DeviceState.DEACTIVATING:
return _("Disconnecting"); return _("disconnecting...");
case NetworkManager.DeviceState.PREPARE: case NetworkManager.DeviceState.PREPARE:
case NetworkManager.DeviceState.CONFIG: case NetworkManager.DeviceState.CONFIG:
case NetworkManager.DeviceState.IP_CONFIG: case NetworkManager.DeviceState.IP_CONFIG:
case NetworkManager.DeviceState.IP_CHECK: case NetworkManager.DeviceState.IP_CHECK:
case NetworkManager.DeviceState.SECONDARIES: case NetworkManager.DeviceState.SECONDARIES:
return _("Connecting"); return _("connecting...");
case NetworkManager.DeviceState.NEED_AUTH: case NetworkManager.DeviceState.NEED_AUTH:
/* Translators: this is for network connections that require some kind of key or password */ /* Translators: this is for network connections that require some kind of key or password */
return _("Authentication required"); return _("authentication required");
case NetworkManager.DeviceState.UNAVAILABLE: case NetworkManager.DeviceState.UNAVAILABLE:
// This state is actually a compound of various states (generically unavailable, // This state is actually a compound of various states (generically unavailable,
// firmware missing), that are exposed by different properties (whose state may // firmware missing), that are exposed by different properties (whose state may
@ -479,13 +442,13 @@ const NMConnectionDevice = new Lang.Class({
if (this._device.firmware_missing) { if (this._device.firmware_missing) {
/* Translators: this is for devices that require some kind of firmware or kernel /* Translators: this is for devices that require some kind of firmware or kernel
module, which is missing */ module, which is missing */
return _("Firmware missing"); return _("firmware missing");
} }
/* Translators: this is for a network device that cannot be activated (for example it /* Translators: this is for a network device that cannot be activated (for example it
is disabled by rfkill, or it has no coverage */ is disabled by rfkill, or it has no coverage */
return _("Unavailable"); return _("unavailable");
case NetworkManager.DeviceState.FAILED: case NetworkManager.DeviceState.FAILED:
return _("Connection failed"); return _("connection failed");
default: default:
log('Device state invalid, is %d'.format(this._device.state)); log('Device state invalid, is %d'.format(this._device.state));
return 'invalid'; return 'invalid';
@ -560,7 +523,7 @@ const NMDeviceModem = new Lang.Class({
if (this._mobileDevice) { if (this._mobileDevice) {
this._operatorNameId = this._mobileDevice.connect('notify::operator-name', Lang.bind(this, this._sync)); this._operatorNameId = this._mobileDevice.connect('notify::operator-name', Lang.bind(this, this._sync));
this._signalQualityId = this._mobileDevice.connect('notify::signal-quality', Lang.bind(this, function() { this._signalQualityId = this._mobileDevice.connect('notify::signal-quality', Lang.bind(this, function() {
this._iconChanged(); this.emit('icon-changed');
})); }));
} }
}, },
@ -1182,16 +1145,10 @@ const NMDeviceWireless = new Lang.Class({
this._wirelessHwEnabledChangedId = this._client.connect('notify::wireless-hardware-enabled', Lang.bind(this, this._sync)); this._wirelessHwEnabledChangedId = this._client.connect('notify::wireless-hardware-enabled', Lang.bind(this, this._sync));
this._activeApChangedId = this._device.connect('notify::active-access-point', Lang.bind(this, this._activeApChanged)); this._activeApChangedId = this._device.connect('notify::active-access-point', Lang.bind(this, this._activeApChanged));
this._stateChangedId = this._device.connect('state-changed', Lang.bind(this, this._deviceStateChanged)); this._stateChangedId = this._device.connect('state-changed', Lang.bind(this, this._deviceStateChanged));
this._notifyConnectivityId = this._client.connect('notify::connectivity', Lang.bind(this, this._iconChanged));
this._sync(); this._sync();
}, },
_iconChanged: function() {
this._sync();
this.emit('icon-changed');
},
destroy: function() { destroy: function() {
if (this._activeApChangedId) { if (this._activeApChangedId) {
GObject.Object.prototype.disconnect.call(this._device, this._activeApChangedId); GObject.Object.prototype.disconnect.call(this._device, this._activeApChangedId);
@ -1217,10 +1174,6 @@ const NMDeviceWireless = new Lang.Class({
this._dialog.destroy(); this._dialog.destroy();
this._dialog = null; this._dialog = null;
} }
if (this._notifyConnectivityId) {
this._client.disconnect(this._notifyConnectivityId);
this._notifyConnectivityId = 0;
}
this.item.destroy(); this.item.destroy();
}, },
@ -1258,7 +1211,7 @@ const NMDeviceWireless = new Lang.Class({
}, },
_strengthChanged: function() { _strengthChanged: function() {
this._iconChanged(); this.emit('icon-changed');
}, },
_activeApChanged: function() { _activeApChanged: function() {
@ -1608,7 +1561,6 @@ const NMApplet = new Lang.Class({
this._activeConnections = [ ]; this._activeConnections = [ ];
this._connections = [ ]; this._connections = [ ];
this._connectivityQueue = [ ];
this._mainConnection = null; this._mainConnection = null;
this._mainConnectionIconChangedId = 0; this._mainConnectionIconChangedId = 0;
@ -1637,7 +1589,6 @@ const NMApplet = new Lang.Class({
this._client.connect('notify::primary-connection', Lang.bind(this, this._syncMainConnection)); this._client.connect('notify::primary-connection', Lang.bind(this, this._syncMainConnection));
this._client.connect('notify::activating-connection', Lang.bind(this, this._syncMainConnection)); this._client.connect('notify::activating-connection', Lang.bind(this, this._syncMainConnection));
this._client.connect('notify::active-connections', Lang.bind(this, this._syncVPNConnections)); this._client.connect('notify::active-connections', Lang.bind(this, this._syncVPNConnections));
this._client.connect('notify::connectivity', Lang.bind(this, this._syncConnectivity));
this._client.connect('device-added', Lang.bind(this, this._deviceAdded)); this._client.connect('device-added', Lang.bind(this, this._deviceAdded));
this._client.connect('device-removed', Lang.bind(this, this._deviceRemoved)); this._client.connect('device-removed', Lang.bind(this, this._deviceRemoved));
this._settings.connect('new-connection', Lang.bind(this, this._newConnection)); this._settings.connect('new-connection', Lang.bind(this, this._newConnection));
@ -1806,7 +1757,6 @@ const NMApplet = new Lang.Class({
} }
this._updateIcon(); this._updateIcon();
this._syncConnectivity();
}, },
_syncVPNConnections: function() { _syncVPNConnections: function() {
@ -1912,97 +1862,6 @@ const NMApplet = new Lang.Class({
_syncNMState: function() { _syncNMState: function() {
this.indicators.visible = this._client.manager_running; this.indicators.visible = this._client.manager_running;
this.menu.actor.visible = this._client.networking_enabled; this.menu.actor.visible = this._client.networking_enabled;
this._syncConnectivity();
},
_flushConnectivityQueue: function() {
if (this._portalHelperProxy) {
for (let item of this._connectivityQueue)
this._portalHelperProxy.CloseRemote(item);
}
this._connectivityQueue = [];
},
_closeConnectivityCheck: function(path) {
let index = this._connectivityQueue.indexOf(path);
if (index >= 0) {
if (this._portalHelperProxy)
this._portalHelperProxy.CloseRemote(path);
this._connectivityQueue.splice(index, 1);
}
},
_portalHelperDone: function(proxy, emitter, parameters) {
let [path, result] = parameters;
if (result == PortalHelperResult.CANCELLED) {
// Keep the connection in the queue, so the user is not
// spammed with more logins until we next flush the queue,
// which will happen once he chooses a better connection
// or we get to full connectivity through other means
} else if (result == PortalHelperResult.COMPLETED) {
this._closeConnectivityCheck(path);
return;
} else if (result == PortalHelperResult.RECHECK) {
this._client.check_connectivity_async(null, Lang.bind(this, function(client, result) {
try {
let state = client.check_connectivity_finish(result);
if (state >= NetworkManager.ConnectivityState.FULL)
this._closeConnectivityCheck(path);
} catch(e) { }
}));
} else {
log('Invalid result from portal helper: ' + result);
}
},
_syncConnectivity: function() {
if (this._mainConnection == null ||
this._mainConnection.state != NetworkManager.ActiveConnectionState.ACTIVATED) {
this._flushConnectivityQueue();
return;
}
let isPortal = this._client.connectivity == NetworkManager.ConnectivityState.PORTAL;
// For testing, allow interpreting any value != FULL as PORTAL, because
// LIMITED (no upstream route after the default gateway) is easy to obtain
// with a tethered phone
// NONE is also possible, with a connection configured to force no default route
// (but in general we should only prompt a portal if we know there is a portal)
if (GLib.getenv('GNOME_SHELL_CONNECTIVITY_TEST') != null)
isPortal = isPortal || this._client.connectivity < NetworkManager.ConnectivityState.FULL;
if (!isPortal)
return;
let path = this._mainConnection.get_path();
for (let item of this._connectivityQueue) {
if (item == path)
return;
}
let timestamp = global.get_current_time();
if (this._portalHelperProxy) {
this._portalHelperProxy.AuthenticateRemote(path, '', timestamp);
} else {
new PortalHelperProxy(Gio.DBus.session, 'org.gnome.Shell.PortalHelper',
'/org/gnome/Shell/PortalHelper', Lang.bind(this, function (proxy, error) {
if (error) {
log('Error launching the portal helper: ' + error);
return;
}
this._portalHelperProxy = proxy;
proxy.connectSignal('Done', Lang.bind(this, this._portalHelperDone));
proxy.AuthenticateRemote(path, '', timestamp);
}));
}
this._connectivityQueue.push(path);
}, },
_updateIcon: function() { _updateIcon: function() {

View File

@ -95,11 +95,11 @@ const Indicator = new Lang.Class({
_init: function() { _init: function() {
this.parent(); this.parent();
this._screenSaverSettings = new Gio.Settings({ schema_id: SCREENSAVER_SCHEMA }); this._screenSaverSettings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA });
this._loginScreenSettings = new Gio.Settings({ schema_id: LOGIN_SCREEN_SCHEMA }); this._loginScreenSettings = new Gio.Settings({ schema: LOGIN_SCREEN_SCHEMA });
this._lockdownSettings = new Gio.Settings({ schema_id: LOCKDOWN_SCHEMA }); this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA });
this._privacySettings = new Gio.Settings({ schema_id: PRIVACY_SCHEMA }); this._privacySettings = new Gio.Settings({ schema: PRIVACY_SCHEMA });
this._orientationSettings = new Gio.Settings({ schema_id: 'org.gnome.settings-daemon.peripherals.touchscreen' }); this._orientationSettings = new Gio.Settings({ schema: 'org.gnome.settings-daemon.peripherals.touchscreen' });
this._session = new GnomeSession.SessionManager(); this._session = new GnomeSession.SessionManager();
this._loginManager = LoginManager.getLoginManager(); this._loginManager = LoginManager.getLoginManager();
@ -151,11 +151,11 @@ const Indicator = new Lang.Class({
Gio.DBus.session.watch_name('org.gnome.SettingsDaemon.Orientation', Gio.DBus.session.watch_name('org.gnome.SettingsDaemon.Orientation',
Gio.BusNameWatcherFlags.NONE, Gio.BusNameWatcherFlags.NONE,
Lang.bind(this, function() { Lang.bind(this, function() {
this._orientationExists = true; this._orentationExists = true;
this._updateOrientationLock(); this._updateOrientationLock();
}), }),
Lang.bind(this, function() { Lang.bind(this, function() {
this._orientationExists = false; this._orentationExists = false;
this._updateOrientationLock(); this._updateOrientationLock();
})); }));
this._updateOrientationLock(); this._updateOrientationLock();

View File

@ -102,17 +102,16 @@ const SwitcherPopup = new Lang.Class({
this._switcherList.actor.allocate(childBox, flags); this._switcherList.actor.allocate(childBox, flags);
}, },
_createSwitcher: function() {
throw new Error('Not implemented');
},
_initialSelection: function(backward, binding) { _initialSelection: function(backward, binding) {
if (backward) throw new Error('Not implemented');
this._select(this._items.length - 1);
else if (this._items.length == 1)
this._select(0);
else
this._select(1);
}, },
show: function(backward, binding, mask) { show: function(backward, binding, mask) {
if (this._items.length == 0) if (!this._createSwitcher())
return false; return false;
if (!Main.pushModal(this.actor)) { if (!Main.pushModal(this.actor)) {
@ -140,6 +139,11 @@ const SwitcherPopup = new Lang.Class({
this.actor.show(); this.actor.show();
this.actor.get_allocation_box(); this.actor.get_allocation_box();
if (this._items.length > 1)
this._selectedIndex = 1;
else
this._selectedIndex = 0;
this._initialSelection(backward, binding); this._initialSelection(backward, binding);
// There's a race condition; if the user released Alt before // There's a race condition; if the user released Alt before
@ -157,12 +161,11 @@ const SwitcherPopup = new Lang.Class({
// disturbed by the popup briefly flashing. // disturbed by the popup briefly flashing.
this._initialDelayTimeoutId = Mainloop.timeout_add(POPUP_DELAY_TIMEOUT, this._initialDelayTimeoutId = Mainloop.timeout_add(POPUP_DELAY_TIMEOUT,
Lang.bind(this, function () { Lang.bind(this, function () {
Main.osdWindowManager.hideAll(); Main.osdWindow.cancel();
this.actor.opacity = 255; this.actor.opacity = 255;
this._initialDelayTimeoutId = 0; this._initialDelayTimeoutId = 0;
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(this._initialDelayTimeoutId, '[gnome-shell] Main.osdWindow.cancel');
return true; return true;
}, },
@ -174,21 +177,22 @@ const SwitcherPopup = new Lang.Class({
return mod(this._selectedIndex - 1, this._items.length); return mod(this._selectedIndex - 1, this._items.length);
}, },
_keyPressHandler: function(keysym, action) { _keyPressHandler: function(keysym, backwards, action) {
throw new Error('Not implemented'); throw new Error('Not implemented');
}, },
_keyPressEvent: function(actor, event) { _keyPressEvent: function(actor, event) {
let keysym = event.get_key_symbol(); let keysym = event.get_key_symbol();
let action = global.display.get_keybinding_action(event.get_key_code(), event.get_state()); let event_state = event.get_state();
let backwards = event_state & Clutter.ModifierType.SHIFT_MASK;
let action = global.display.get_keybinding_action(event.get_key_code(), event_state);
this._disableHover(); this._disableHover();
if (this._keyPressHandler(keysym, action) != Clutter.EVENT_PROPAGATE)
return Clutter.EVENT_STOP;
if (keysym == Clutter.Escape) if (keysym == Clutter.Escape)
this.destroy(); this.destroy();
else
this._keyPressHandler(keysym, backwards, action);
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
}, },
@ -246,7 +250,6 @@ const SwitcherPopup = new Lang.Class({
Mainloop.source_remove(this._motionTimeoutId); Mainloop.source_remove(this._motionTimeoutId);
this._motionTimeoutId = Mainloop.timeout_add(DISABLE_HOVER_TIMEOUT, Lang.bind(this, this._mouseTimedOut)); this._motionTimeoutId = Mainloop.timeout_add(DISABLE_HOVER_TIMEOUT, Lang.bind(this, this._mouseTimedOut));
GLib.Source.set_name_by_id(this._motionTimeoutId, '[gnome-shell] this._mouseTimedOut');
}, },
_mouseTimedOut: function() { _mouseTimedOut: function() {

View File

@ -53,10 +53,8 @@ function _wrapTweening(target, tweeningParameters) {
} }
} }
if (!Gtk.Settings.get_default().gtk_enable_animations) { if (!Gtk.Settings.get_default().gtk_enable_animations)
tweeningParameters['time'] = 0.000001; tweeningParameters['time'] = 0.000001;
tweeningParameters['delay'] = 0.000001;
}
_addHandler(target, tweeningParameters, 'onComplete', _tweenCompleted); _addHandler(target, tweeningParameters, 'onComplete', _tweenCompleted);
} }

View File

@ -62,7 +62,7 @@ const UnlockDialog = new Lang.Class({
this.allowCancel = false; this.allowCancel = false;
let screenSaverSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.screensaver' }); let screenSaverSettings = new Gio.Settings({ schema: 'org.gnome.desktop.screensaver' });
if (screenSaverSettings.get_boolean('user-switch-enabled')) { if (screenSaverSettings.get_boolean('user-switch-enabled')) {
let otherUserLabel = new St.Label({ text: _("Log in as another user"), let otherUserLabel = new St.Label({ text: _("Log in as another user"),
style_class: 'login-dialog-not-listed-label' }); style_class: 'login-dialog-not-listed-label' });

View File

@ -28,12 +28,11 @@ const Avatar = new Lang.Class({
styleClass: 'framed-user-icon' }); styleClass: 'framed-user-icon' });
this._iconSize = params.iconSize; this._iconSize = params.iconSize;
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this.actor = new St.Bin({ style_class: params.styleClass, this.actor = new St.Bin({ style_class: params.styleClass,
track_hover: params.reactive, track_hover: params.reactive,
reactive: params.reactive, reactive: params.reactive,
width: this._iconSize * scaleFactor, width: this._iconSize,
height: this._iconSize * scaleFactor }); height: this._iconSize });
}, },
setSensitive: function(sensitive) { setSensitive: function(sensitive) {

View File

@ -19,8 +19,6 @@ const Search = imports.ui.search;
const ShellEntry = imports.ui.shellEntry; const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const WorkspacesView = imports.ui.workspacesView; const WorkspacesView = imports.ui.workspacesView;
const EdgeDragAction = imports.ui.edgeDragAction;
const IconGrid = imports.ui.iconGrid;
const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings'; const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
@ -51,80 +49,20 @@ function getTermsForSearchString(searchString) {
return terms; return terms;
} }
const ShowOverviewAction = new Lang.Class({
Name: 'ShowOverviewAction',
Extends: Clutter.GestureAction,
_init : function() {
this.parent();
this.set_n_touch_points(3);
global.display.connect('grab-op-begin', Lang.bind(this, function() {
this.cancel();
}));
},
vfunc_gesture_prepare : function(action, actor) {
return this.get_n_current_points() == this.get_n_touch_points();
},
_getBoundingRect : function(motion) {
let minX, minY, maxX, maxY;
for (let i = 0; i < this.get_n_current_points(); i++) {
let x, y;
if (motion == true) {
[x, y] = this.get_motion_coords(i);
} else {
[x, y] = this.get_press_coords(i);
}
if (i == 0) {
minX = maxX = x;
minY = maxY = y;
} else {
minX = Math.min(minX, x);
minY = Math.min(minY, y);
maxX = Math.max(maxX, x);
maxY = Math.max(maxY, y);
}
}
return new Meta.Rectangle({ x: minX,
y: minY,
width: maxX - minX,
height: maxY - minY });
},
vfunc_gesture_begin : function(action, actor) {
this._initialRect = this._getBoundingRect(false);
return true;
},
vfunc_gesture_end : function(action, actor) {
let rect = this._getBoundingRect(true);
let oldArea = this._initialRect.width * this._initialRect.height;
let newArea = rect.width * rect.height;
let areaDiff = newArea / oldArea;
this.emit('activated', areaDiff);
}
});
Signals.addSignalMethods(ShowOverviewAction.prototype);
const ViewSelector = new Lang.Class({ const ViewSelector = new Lang.Class({
Name: 'ViewSelector', Name: 'ViewSelector',
_init : function(searchEntry, showAppsButton) { _init : function(searchEntry, showAppsButton) {
this.actor = new Shell.Stack({ name: 'viewSelector' }); this.actor = new Shell.Stack({ name: 'viewSelector' });
this._showAppsBlocked = false;
this._showAppsButton = showAppsButton; this._showAppsButton = showAppsButton;
this._showAppsButton.connect('notify::checked', Lang.bind(this, this._onShowAppsButtonToggled)); this._showAppsButton.connect('notify::checked', Lang.bind(this, this._onShowAppsButtonToggled));
this._activePage = null; this._activePage = null;
this._searchActive = false; this._searchActive = false;
this._searchTimeoutId = 0;
this._entry = searchEntry; this._entry = searchEntry;
ShellEntry.addContextMenu(this._entry); ShellEntry.addContextMenu(this._entry);
@ -143,8 +81,12 @@ const ViewSelector = new Lang.Class({
this._entry.set_primary_icon(new St.Icon({ style_class: 'search-entry-icon', this._entry.set_primary_icon(new St.Icon({ style_class: 'search-entry-icon',
icon_name: 'edit-find-symbolic' })); icon_name: 'edit-find-symbolic' }));
this._clearIcon = new St.Icon({ style_class: 'search-entry-icon', if (this._entry.get_text_direction() == Clutter.TextDirection.RTL)
icon_name: 'edit-clear-symbolic' }); this._clearIcon = new St.Icon({ style_class: 'search-entry-icon',
icon_name: 'edit-clear-rtl-symbolic' });
else
this._clearIcon = new St.Icon({ style_class: 'search-entry-icon',
icon_name: 'edit-clear-symbolic' });
this._iconClickedId = 0; this._iconClickedId = 0;
this._capturedEventId = 0; this._capturedEventId = 0;
@ -176,93 +118,58 @@ const ViewSelector = new Lang.Class({
this._stageKeyPressId = 0; this._stageKeyPressId = 0;
Main.overview.connect('showing', Lang.bind(this, Main.overview.connect('showing', Lang.bind(this,
function () { function () {
this._resetShowAppsButton();
this._stageKeyPressId = global.stage.connect('key-press-event', this._stageKeyPressId = global.stage.connect('key-press-event',
Lang.bind(this, this._onStageKeyPress)); Lang.bind(this, this._onStageKeyPress));
})); }));
Main.overview.connect('hiding', Lang.bind(this, Main.overview.connect('hiding', Lang.bind(this,
function () { function () {
this._resetShowAppsButton();
if (this._stageKeyPressId != 0) { if (this._stageKeyPressId != 0) {
global.stage.disconnect(this._stageKeyPressId); global.stage.disconnect(this._stageKeyPressId);
this._stageKeyPressId = 0; this._stageKeyPressId = 0;
} }
})); }));
Main.overview.connect('shown', Lang.bind(this,
function() {
// If we were animating from the desktop view to the
// apps page the workspace page was visible, allowing
// the windows to animate, but now we no longer want to
// show it given that we are now on the apps page or
// search page.
if (this._activePage != this._workspacesPage) {
this._workspacesPage.opacity = 0;
this._workspacesPage.hide();
}
}));
Main.wm.addKeybinding('toggle-application-view', Main.wm.addKeybinding('toggle-application-view',
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }), new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.NONE, Meta.KeyBindingFlags.NONE,
Shell.KeyBindingMode.NORMAL | Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW, Shell.KeyBindingMode.OVERVIEW,
Lang.bind(this, this._toggleAppsPage)); Lang.bind(this, this._toggleAppsPage));
Main.wm.addKeybinding('toggle-overview', Main.wm.addKeybinding('toggle-overview',
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }), new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.NONE, Meta.KeyBindingFlags.NONE,
Shell.KeyBindingMode.NORMAL | Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW, Shell.KeyBindingMode.OVERVIEW,
Lang.bind(Main.overview, Main.overview.toggle)); Lang.bind(Main.overview, Main.overview.toggle));
let gesture;
gesture = new EdgeDragAction.EdgeDragAction(St.Side.LEFT);
gesture.connect('activated', Lang.bind(this, function() {
if (Main.overview.visible)
Main.overview.hide();
else
this.showApps();
}));
global.stage.add_action(gesture);
gesture = new ShowOverviewAction();
gesture.connect('activated', Lang.bind(this, function(action, areaDiff) {
if (areaDiff < 0.7)
Main.overview.show();
}));
global.stage.add_action(gesture);
}, },
_toggleAppsPage: function() { _toggleAppsPage: function() {
this._showAppsButton.checked = !this._showAppsButton.checked;
Main.overview.show(); Main.overview.show();
this._showAppsButton.checked = !this._showAppsButton.checked;
}, },
showApps: function() { showApps: function() {
this._showAppsButton.checked = true;
Main.overview.show(); Main.overview.show();
this._showAppsButton.checked = true;
}, },
show: function() { show: function() {
this.reset(); this.reset();
this._workspacesDisplay.show(this._showAppsButton.checked);
this._workspacesDisplay.show();
this._activePage = null; this._activePage = null;
if (this._showAppsButton.checked) this._showPage(this._workspacesPage);
this._showPage(this._appsPage);
else
this._showPage(this._workspacesPage);
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows()) if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
Main.overview.fadeOutDesktop(); Main.overview.fadeOutDesktop();
}, },
animateFromOverview: function() { zoomFromOverview: function() {
// Make sure workspace page is fully visible to allow this._workspacesDisplay.zoomFromOverview();
// workspace.js do the animation of the windows
this._workspacesPage.opacity = 255;
this._workspacesDisplay.animateFromOverview(this._activePage != this._workspacesPage);
this._showAppsButton.checked = false;
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows()) if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
Main.overview.fadeInDesktop(); Main.overview.fadeInDesktop();
@ -299,61 +206,21 @@ const ViewSelector = new Lang.Class({
return page; return page;
}, },
_fadePageIn: function() { _fadePageIn: function(oldPage) {
Tweener.addTween(this._activePage,
{ opacity: 255,
time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
transition: 'easeOutQuad'
});
},
_fadePageOut: function(page) {
let oldPage = page;
Tweener.addTween(page,
{ opacity: 0,
time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this, function() {
this._animateIn(oldPage);
})
});
},
_animateIn: function(oldPage) {
if (oldPage) if (oldPage)
oldPage.hide(); oldPage.hide();
this.emit('page-empty'); this.emit('page-empty');
this._activePage.show(); this._activePage.show();
Tweener.addTween(this._activePage,
if (this._activePage == this._appsPage && oldPage == this._workspacesPage) { { opacity: 255,
// Restore opacity, in case we animated via _fadePageOut time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
this._activePage.opacity = 255; transition: 'easeOutQuad'
this.appDisplay.animate(IconGrid.AnimationDirection.IN); });
} else {
this._fadePageIn();
}
}, },
_animateOut: function(page) { _showPage: function(page, noFade) {
let oldPage = page;
if (page == this._appsPage &&
this._activePage == this._workspacesPage &&
!Main.overview.animationInProgress) {
this.appDisplay.animate(IconGrid.AnimationDirection.OUT, Lang.bind(this,
function() {
this._animateIn(oldPage)
}));
} else {
this._fadePageOut(page);
}
},
_showPage: function(page) {
if (!Main.overview.visible)
return;
if (page == this._activePage) if (page == this._activePage)
return; return;
@ -361,10 +228,18 @@ const ViewSelector = new Lang.Class({
this._activePage = page; this._activePage = page;
this.emit('page-changed'); this.emit('page-changed');
if (oldPage) if (oldPage && !noFade)
this._animateOut(oldPage) Tweener.addTween(oldPage,
{ opacity: 0,
time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this,
function() {
this._fadePageIn(oldPage);
})
});
else else
this._animateIn(); this._fadePageIn(oldPage);
}, },
_a11yFocusPage: function(page) { _a11yFocusPage: function(page) {
@ -373,10 +248,21 @@ const ViewSelector = new Lang.Class({
}, },
_onShowAppsButtonToggled: function() { _onShowAppsButtonToggled: function() {
if (this._showAppsBlocked)
return;
this._showPage(this._showAppsButton.checked ? this._showPage(this._showAppsButton.checked ?
this._appsPage : this._workspacesPage); this._appsPage : this._workspacesPage);
}, },
_resetShowAppsButton: function() {
this._showAppsBlocked = true;
this._showAppsButton.checked = false;
this._showAppsBlocked = false;
this._showPage(this._workspacesPage, true);
},
_onStageKeyPress: function(actor, event) { _onStageKeyPress: function(actor, event) {
// Ignore events while anything but the overview has // Ignore events while anything but the overview has
// pushed a modal (system modals, looking glass, ...) // pushed a modal (system modals, looking glass, ...)
@ -396,13 +282,13 @@ const ViewSelector = new Lang.Class({
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} else if (this._shouldTriggerSearch(symbol)) { } else if (this._shouldTriggerSearch(symbol)) {
this.startSearch(event); this.startSearch(event);
} else if (!this._searchActive && !global.stage.key_focus) { } else if (!this._searchActive) {
if (symbol == Clutter.Tab || symbol == Clutter.Down) { if (symbol == Clutter.Tab || symbol == Clutter.Down) {
this._activePage.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); this._activePage.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
return Clutter.EVENT_STOP; return true;
} else if (symbol == Clutter.ISO_Left_Tab) { } else if (symbol == Clutter.ISO_Left_Tab) {
this._activePage.navigate_focus(null, Gtk.DirectionType.TAB_BACKWARD, false); this._activePage.navigate_focus(null, Gtk.DirectionType.TAB_BACKWARD, false);
return Clutter.EVENT_STOP; return true;
} }
} }
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
@ -472,10 +358,7 @@ const ViewSelector = new Lang.Class({
startSearch: function(event) { startSearch: function(event) {
global.stage.set_key_focus(this._text); global.stage.set_key_focus(this._text);
this._text.event(event, true);
let synthEvent = event.copy();
synthEvent.set_source(this._text);
this._text.event(synthEvent, true);
}, },
// the entry does not show the hint // the entry does not show the hint
@ -486,23 +369,34 @@ const ViewSelector = new Lang.Class({
_onTextChanged: function (se, prop) { _onTextChanged: function (se, prop) {
let terms = getTermsForSearchString(this._entry.get_text()); let terms = getTermsForSearchString(this._entry.get_text());
let searchPreviouslyActive = this._searchActive;
this._searchActive = (terms.length > 0); this._searchActive = (terms.length > 0);
this._searchResults.setTerms(terms);
let startSearch = this._searchActive && !searchPreviouslyActive;
if (startSearch)
this._searchResults.startingSearch();
if (this._searchActive) { if (this._searchActive) {
this._showPage(this._searchPage);
this._entry.set_secondary_icon(this._clearIcon); this._entry.set_secondary_icon(this._clearIcon);
if (this._iconClickedId == 0) if (this._iconClickedId == 0)
this._iconClickedId = this._entry.connect('secondary-icon-clicked', this._iconClickedId = this._entry.connect('secondary-icon-clicked',
Lang.bind(this, this.reset)); Lang.bind(this, this.reset));
if (this._searchTimeoutId == 0)
this._searchTimeoutId = Mainloop.timeout_add(150,
Lang.bind(this, this._doSearch));
} else { } else {
if (this._iconClickedId > 0) { if (this._iconClickedId > 0) {
this._entry.disconnect(this._iconClickedId); this._entry.disconnect(this._iconClickedId);
this._iconClickedId = 0; this._iconClickedId = 0;
} }
if (this._searchTimeoutId > 0) {
Mainloop.source_remove(this._searchTimeoutId);
this._searchTimeoutId = 0;
}
this._entry.set_secondary_icon(null); this._entry.set_secondary_icon(null);
this._searchCancelled(); this._searchCancelled();
} }
@ -540,6 +434,12 @@ const ViewSelector = new Lang.Class({
this._searchResults.navigateFocus(nextDirection); this._searchResults.navigateFocus(nextDirection);
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} else if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) { } else if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
// We can't connect to 'activate' here because search providers
// might want to do something with the modifiers in activateDefault.
if (this._searchTimeoutId > 0) {
Mainloop.source_remove(this._searchTimeoutId);
this._doSearch();
}
this._searchResults.activateDefault(); this._searchResults.activateDefault();
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
@ -562,6 +462,17 @@ const ViewSelector = new Lang.Class({
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
}, },
_doSearch: function () {
this._searchTimeoutId = 0;
let terms = getTermsForSearchString(this._entry.get_text());
this._searchResults.setTerms(terms);
this._showPage(this._searchPage);
return GLib.SOURCE_REMOVE;
},
getActivePage: function() { getActivePage: function() {
if (this._activePage == this._workspacesPage) if (this._activePage == this._workspacesPage)
return ViewPage.WINDOWS; return ViewPage.WINDOWS;

View File

@ -9,23 +9,14 @@ const Meta = imports.gi.Meta;
const Pango = imports.gi.Pango; const Pango = imports.gi.Pango;
const St = imports.gi.St; const St = imports.gi.St;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Signals = imports.signals;
const AltTab = imports.ui.altTab; const AltTab = imports.ui.altTab;
const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup; const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
const Main = imports.ui.main; const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog; const ModalDialog = imports.ui.modalDialog;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const WindowMenu = imports.ui.windowMenu;
const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings'; const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
const MAXIMIZE_WINDOW_ANIMATION_TIME = 0.15;
const UNMAXIMIZE_WINDOW_ANIMATION_TIME = 0.15;
const MINIMIZE_WINDOW_ANIMATION_TIME = 0.2;
const SHOW_WINDOW_ANIMATION_TIME = 0.15;
const DIALOG_SHOW_WINDOW_ANIMATION_TIME = 0.1;
const DESTROY_WINDOW_ANIMATION_TIME = 0.15;
const DIALOG_DESTROY_WINDOW_ANIMATION_TIME = 0.1;
const WINDOW_ANIMATION_TIME = 0.25; const WINDOW_ANIMATION_TIME = 0.25;
const DIM_BRIGHTNESS = -0.3; const DIM_BRIGHTNESS = -0.3;
const DIM_TIME = 0.500; const DIM_TIME = 0.500;
@ -91,7 +82,6 @@ const DisplayChangeDialog = new Lang.Class({
{ expand: false, x_fill: false, x_align: St.Align.END }); { expand: false, x_fill: false, x_align: St.Align.END });
this._timeoutId = Mainloop.timeout_add(ONE_SECOND, Lang.bind(this, this._tick)); this._timeoutId = Mainloop.timeout_add(ONE_SECOND, Lang.bind(this, this._tick));
GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] this._tick');
}, },
close: function(timestamp) { close: function(timestamp) {
@ -207,19 +197,12 @@ const WorkspaceTracker = new Lang.Class({
global.screen.connect('window-left-monitor', Lang.bind(this, this._windowLeftMonitor)); global.screen.connect('window-left-monitor', Lang.bind(this, this._windowLeftMonitor));
global.screen.connect('restacked', Lang.bind(this, this._windowsRestacked)); global.screen.connect('restacked', Lang.bind(this, this._windowsRestacked));
this._workspaceSettings = this._getWorkspaceSettings(); this._workspaceSettings = new Gio.Settings({ schema: Main.dynamicWorkspacesSchema });
this._workspaceSettings.connect('changed::dynamic-workspaces', Lang.bind(this, this._queueCheckWorkspaces)); this._workspaceSettings.connect('changed::dynamic-workspaces', Lang.bind(this, this._queueCheckWorkspaces));
this._nWorkspacesChanged(); this._nWorkspacesChanged();
}, },
_getWorkspaceSettings: function() {
let settings = global.get_overrides_settings();
if (settings.list_keys().indexOf('dynamic-workspaces') > -1)
return settings;
return new Gio.Settings({ schema_id: 'org.gnome.mutter' });
},
_checkWorkspaces: function() { _checkWorkspaces: function() {
let i; let i;
let emptyWorkspaces = []; let emptyWorkspaces = [];
@ -288,20 +271,18 @@ const WorkspaceTracker = new Lang.Class({
this._queueCheckWorkspaces(); this._queueCheckWorkspaces();
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(workspace._keepAliveId, '[gnome-shell] this._queueCheckWorkspaces');
}, },
_windowRemoved: function(workspace, window) { _windowRemoved: function(workspace, window) {
workspace._lastRemovedWindow = window; workspace._lastRemovedWindow = window;
this._queueCheckWorkspaces(); this._queueCheckWorkspaces();
let id = Mainloop.timeout_add(LAST_WINDOW_GRACE_TIME, Lang.bind(this, function() { Mainloop.timeout_add(LAST_WINDOW_GRACE_TIME, Lang.bind(this, function() {
if (workspace._lastRemovedWindow == window) { if (workspace._lastRemovedWindow == window) {
workspace._lastRemovedWindow = null; workspace._lastRemovedWindow = null;
this._queueCheckWorkspaces(); this._queueCheckWorkspaces();
} }
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(id, '[gnome-shell] this._queueCheckWorkspaces');
}, },
_windowLeftMonitor: function(metaScreen, monitorIndex, metaWin) { _windowLeftMonitor: function(metaScreen, monitorIndex, metaWin) {
@ -413,7 +394,7 @@ const TilePreview = new Lang.Class({
y: monitor.y, y: monitor.y,
width: monitor.width, width: monitor.width,
height: monitor.height }); height: monitor.height });
let [, rect] = window.get_frame_rect().intersect(monitorRect); let [, rect] = window.get_outer_rect().intersect(monitorRect);
this.actor.set_size(rect.width, rect.height); this.actor.set_size(rect.width, rect.height);
this.actor.set_position(rect.x, rect.y); this.actor.set_position(rect.x, rect.y);
this.actor.opacity = 0; this.actor.opacity = 0;
@ -464,120 +445,6 @@ const TilePreview = new Lang.Class({
} }
}); });
const WorkspaceSwitchAction = new Lang.Class({
Name: 'WorkspaceSwitchAction',
Extends: Clutter.GestureAction,
_init : function() {
this.parent();
this.set_n_touch_points(4);
global.display.connect('grab-op-begin', Lang.bind(this, function() {
this.cancel();
}));
},
vfunc_gesture_prepare : function(action, actor) {
return this.get_n_current_points() == this.get_n_touch_points();
},
vfunc_gesture_end : function(action, actor) {
const MOTION_THRESHOLD = 50;
// Just check one touchpoint here
let [startX, startY] = this.get_press_coords(0);
let [x, y] = this.get_motion_coords(0);
let offsetX = x - startX;
let offsetY = y - startY;
let direction;
if (Math.abs(offsetX) < MOTION_THRESHOLD &&
Math.abs(offsetY) < MOTION_THRESHOLD)
return;
if (Math.abs(offsetY) > Math.abs(offsetX)) {
if (offsetY > 0)
direction = Meta.MotionDirection.UP;
else
direction = Meta.MotionDirection.DOWN;
} else {
if (offsetX > 0)
direction = Meta.MotionDirection.LEFT;
else
direction = Meta.MotionDirection.RIGHT;
}
this.emit('activated', direction);
}
});
Signals.addSignalMethods(WorkspaceSwitchAction.prototype);
const AppSwitchAction = new Lang.Class({
Name: 'AppSwitchAction',
Extends: Clutter.GestureAction,
_init : function() {
this.parent();
this.set_n_touch_points(3);
global.display.connect('grab-op-begin', Lang.bind(this, function() {
this.cancel();
}));
},
vfunc_gesture_prepare : function(action, actor) {
if (Main.overview.visible) {
this.cancel();
return false;
}
return this.get_n_current_points() <= 4;
},
vfunc_gesture_begin : function(action, actor) {
// in milliseconds
const LONG_PRESS_TIMEOUT = 250;
let nPoints = this.get_n_current_points();
let event = this.get_last_event (nPoints - 1);
if (nPoints == 3)
this._longPressStartTime = event.get_time();
else if (nPoints == 4) {
// Check whether the 4th finger press happens after a 3-finger long press,
// this only needs to be checked on the first 4th finger press
if (this._longPressStartTime != null &&
event.get_time() < this._longPressStartTime + LONG_PRESS_TIMEOUT)
this.cancel();
else {
this._longPressStartTime = null;
this.emit('activated');
}
}
return this.get_n_current_points() <= 4;
},
vfunc_gesture_progress : function(action, actor) {
const MOTION_THRESHOLD = 30;
if (this.get_n_current_points() == 3) {
for (let i = 0; i < this.get_n_current_points(); i++) {
[startX, startY] = this.get_press_coords(i);
[x, y] = this.get_motion_coords(i);
if (Math.abs(x - startX) > MOTION_THRESHOLD ||
Math.abs(y - startY) > MOTION_THRESHOLD)
return false;
}
}
return true;
}
});
Signals.addSignalMethods(AppSwitchAction.prototype);
const WindowManager = new Lang.Class({ const WindowManager = new Lang.Class({
Name: 'WindowManager', Name: 'WindowManager',
@ -593,6 +460,8 @@ const WindowManager = new Lang.Class({
this._dimmedWindows = []; this._dimmedWindows = [];
this._animationBlockCount = 0;
this._allowedKeybindings = {}; this._allowedKeybindings = {};
this._switchData = null; this._switchData = null;
@ -608,7 +477,6 @@ const WindowManager = new Lang.Class({
this._shellwm.connect('switch-workspace', Lang.bind(this, this._switchWorkspace)); this._shellwm.connect('switch-workspace', Lang.bind(this, this._switchWorkspace));
this._shellwm.connect('show-tile-preview', Lang.bind(this, this._showTilePreview)); this._shellwm.connect('show-tile-preview', Lang.bind(this, this._showTilePreview));
this._shellwm.connect('hide-tile-preview', Lang.bind(this, this._hideTilePreview)); this._shellwm.connect('hide-tile-preview', Lang.bind(this, this._hideTilePreview));
this._shellwm.connect('show-window-menu', Lang.bind(this, this._showWindowMenu));
this._shellwm.connect('minimize', Lang.bind(this, this._minimizeWindow)); this._shellwm.connect('minimize', Lang.bind(this, this._minimizeWindow));
this._shellwm.connect('maximize', Lang.bind(this, this._maximizeWindow)); this._shellwm.connect('maximize', Lang.bind(this, this._maximizeWindow));
this._shellwm.connect('unmaximize', Lang.bind(this, this._unmaximizeWindow)); this._shellwm.connect('unmaximize', Lang.bind(this, this._unmaximizeWindow));
@ -636,10 +504,6 @@ const WindowManager = new Lang.Class({
Shell.KeyBindingMode.NORMAL | Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW, Shell.KeyBindingMode.OVERVIEW,
Lang.bind(this, this._showWorkspaceSwitcher)); Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('switch-to-workspace-last',
Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW,
Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('move-to-workspace-left', this.setCustomKeybindingHandler('move-to-workspace-left',
Shell.KeyBindingMode.NORMAL | Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW, Shell.KeyBindingMode.OVERVIEW,
@ -740,9 +604,6 @@ const WindowManager = new Lang.Class({
this.setCustomKeybindingHandler('move-to-workspace-12', this.setCustomKeybindingHandler('move-to-workspace-12',
Shell.KeyBindingMode.NORMAL, Shell.KeyBindingMode.NORMAL,
Lang.bind(this, this._showWorkspaceSwitcher)); Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('move-to-workspace-last',
Shell.KeyBindingMode.NORMAL,
Lang.bind(this, this._showWorkspaceSwitcher));
this.setCustomKeybindingHandler('switch-applications', this.setCustomKeybindingHandler('switch-applications',
Shell.KeyBindingMode.NORMAL, Shell.KeyBindingMode.NORMAL,
Lang.bind(this, this._startAppSwitcher)); Lang.bind(this, this._startAppSwitcher));
@ -777,13 +638,13 @@ const WindowManager = new Lang.Class({
Lang.bind(this, this._startA11ySwitcher)); Lang.bind(this, this._startA11ySwitcher));
this.addKeybinding('pause-resume-tweens', this.addKeybinding('pause-resume-tweens',
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }), new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.NONE, Meta.KeyBindingFlags.NONE,
Shell.KeyBindingMode.ALL, Shell.KeyBindingMode.ALL,
Lang.bind(this, this._toggleTweens)); Lang.bind(this, this._toggleTweens));
this.addKeybinding('open-application-menu', this.addKeybinding('open-application-menu',
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }), new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
Meta.KeyBindingFlags.NONE, Meta.KeyBindingFlags.NONE,
Shell.KeyBindingMode.NORMAL | Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.TOPBAR_POPUP, Shell.KeyBindingMode.TOPBAR_POPUP,
@ -798,60 +659,11 @@ const WindowManager = new Lang.Class({
this._dimWindow(this._dimmedWindows[i]); this._dimWindow(this._dimmedWindows[i]);
})); }));
this._windowMenuManager = new WindowMenu.WindowMenuManager();
if (Main.sessionMode.hasWorkspaces) if (Main.sessionMode.hasWorkspaces)
this._workspaceTracker = new WorkspaceTracker(this); this._workspaceTracker = new WorkspaceTracker(this);
global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT, global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT,
false, -1, 1); false, -1, 1);
let gesture = new WorkspaceSwitchAction();
gesture.connect('activated', Lang.bind(this, function(action, direction) {
let newWs = global.screen.get_active_workspace().get_neighbor(direction);
this.actionMoveWorkspace(newWs);
}));
global.stage.add_action(gesture);
gesture = new AppSwitchAction();
gesture.connect('activated', Lang.bind(this, this._switchApp));
global.stage.add_action(gesture);
},
_lookupIndex: function (windows, metaWindow) {
for (let i = 0; i < windows.length; i++) {
if (windows[i].metaWindow == metaWindow) {
return i;
}
}
return -1;
},
_switchApp : function () {
let windows = global.get_window_actors().filter(Lang.bind(this, function(actor) {
let win = actor.metaWindow;
return (!win.is_override_redirect() &&
win.located_on_workspace(global.screen.get_active_workspace()));
}));
if (windows.length == 0)
return;
let focusWindow = global.display.focus_window;
let nextWindow;
if (focusWindow == null)
nextWindow = windows[0].metaWindow;
else {
let index = this._lookupIndex (windows, focusWindow) + 1;
if (index >= windows.length)
index = 0;
nextWindow = windows[index].metaWindow;
}
Main.activateWindow(nextWindow);
}, },
keepWorkspaceAlive: function(workspace, duration) { keepWorkspaceAlive: function(workspace, duration) {
@ -882,16 +694,24 @@ const WindowManager = new Lang.Class({
this._allowedKeybindings[name] = modes; this._allowedKeybindings[name] = modes;
}, },
_shouldAnimate: function() { blockAnimations: function() {
return !Main.overview.visible; this._animationBlockCount++;
}, },
_shouldAnimateActor: function(actor, types) { unblockAnimations: function() {
this._animationBlockCount = Math.max(0, this._animationBlockCount - 1);
},
_shouldAnimate: function() {
return !(Main.overview.visible || this._animationBlockCount > 0);
},
_shouldAnimateActor: function(actor) {
if (!this._shouldAnimate()) if (!this._shouldAnimate())
return false; return false;
let windowType = actor.meta_window.get_window_type();
let type = actor.meta_window.get_window_type(); return windowType == Meta.WindowType.NORMAL ||
return types.indexOf(type) >= 0; windowType == Meta.WindowType.MODAL_DIALOG;
}, },
_removeEffect : function(list, actor) { _removeEffect : function(list, actor) {
@ -904,10 +724,7 @@ const WindowManager = new Lang.Class({
}, },
_minimizeWindow : function(shellwm, actor) { _minimizeWindow : function(shellwm, actor) {
let types = [Meta.WindowType.NORMAL, if (!this._shouldAnimateActor(actor)) {
Meta.WindowType.MODAL_DIALOG,
Meta.WindowType.DIALOG];
if (!this._shouldAnimateActor(actor, types)) {
shellwm.completed_minimize(actor); shellwm.completed_minimize(actor);
return; return;
} }
@ -919,7 +736,7 @@ const WindowManager = new Lang.Class({
if (actor.meta_window.is_monitor_sized()) { if (actor.meta_window.is_monitor_sized()) {
Tweener.addTween(actor, Tweener.addTween(actor,
{ opacity: 0, { opacity: 0,
time: MINIMIZE_WINDOW_ANIMATION_TIME, time: WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad', transition: 'easeOutQuad',
onComplete: this._minimizeWindowDone, onComplete: this._minimizeWindowDone,
onCompleteScope: this, onCompleteScope: this,
@ -951,8 +768,8 @@ const WindowManager = new Lang.Class({
scale_y: yScale, scale_y: yScale,
x: xDest, x: xDest,
y: yDest, y: yDest,
time: MINIMIZE_WINDOW_ANIMATION_TIME, time: WINDOW_ANIMATION_TIME,
transition: 'easeInExpo', transition: 'easeOutQuad',
onComplete: this._minimizeWindowDone, onComplete: this._minimizeWindowDone,
onCompleteScope: this, onCompleteScope: this,
onCompleteParams: [shellwm, actor], onCompleteParams: [shellwm, actor],
@ -968,7 +785,7 @@ const WindowManager = new Lang.Class({
Tweener.removeTweens(actor); Tweener.removeTweens(actor);
actor.set_scale(1.0, 1.0); actor.set_scale(1.0, 1.0);
actor.set_opacity(255); actor.set_opacity(255);
actor.set_pivot_point(0, 0); actor.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_WEST);
shellwm.completed_minimize(actor); shellwm.completed_minimize(actor);
} }
@ -1066,10 +883,7 @@ const WindowManager = new Lang.Class({
actor._windowType = type; actor._windowType = type;
})); }));
let types = [Meta.WindowType.NORMAL, if (!this._shouldAnimateActor(actor)) {
Meta.WindowType.DIALOG,
Meta.WindowType.MODAL_DIALOG];
if (!this._shouldAnimateActor(actor, types)) {
shellwm.completed_map(actor); shellwm.completed_map(actor);
return; return;
} }
@ -1077,23 +891,15 @@ const WindowManager = new Lang.Class({
if (actor.meta_window.is_attached_dialog()) { if (actor.meta_window.is_attached_dialog()) {
/* Scale the window from the center of the parent */ /* Scale the window from the center of the parent */
this._checkDimming(actor.get_meta_window().get_transient_for()); this._checkDimming(actor.get_meta_window().get_transient_for());
} actor.set_scale(1.0, 0.0);
actor.scale_gravity = Clutter.Gravity.CENTER;
switch (actor._windowType) {
case Meta.WindowType.NORMAL:
actor.set_pivot_point(0.5, 1.0);
actor.scale_x = 0.01;
actor.scale_y = 0.05;
actor.opacity = 0;
actor.show(); actor.show();
this._mapping.push(actor); this._mapping.push(actor);
Tweener.addTween(actor, Tweener.addTween(actor,
{ opacity: 255, { scale_y: 1,
scale_x: 1, time: WINDOW_ANIMATION_TIME,
scale_y: 1, transition: "easeOutQuad",
time: SHOW_WINDOW_ANIMATION_TIME,
transition: 'easeOutExpo',
onComplete: this._mapWindowDone, onComplete: this._mapWindowDone,
onCompleteScope: this, onCompleteScope: this,
onCompleteParams: [shellwm, actor], onCompleteParams: [shellwm, actor],
@ -1101,20 +907,15 @@ const WindowManager = new Lang.Class({
onOverwriteScope: this, onOverwriteScope: this,
onOverwriteParams: [shellwm, actor] onOverwriteParams: [shellwm, actor]
}); });
break; } else {
case Meta.WindowType.MODAL_DIALOG: /* Fade window in */
case Meta.WindowType.DIALOG:
actor.set_pivot_point(0.5, 0.5);
actor.scale_y = 0;
actor.opacity = 0; actor.opacity = 0;
actor.show(); actor.show();
this._mapping.push(actor); this._mapping.push(actor);
Tweener.addTween(actor, Tweener.addTween(actor,
{ opacity: 255, { opacity: 255,
scale_x: 1, time: WINDOW_ANIMATION_TIME,
scale_y: 1,
time: DIALOG_SHOW_WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad', transition: 'easeOutQuad',
onComplete: this._mapWindowDone, onComplete: this._mapWindowDone,
onCompleteScope: this, onCompleteScope: this,
@ -1123,10 +924,6 @@ const WindowManager = new Lang.Class({
onOverwriteScope: this, onOverwriteScope: this,
onOverwriteParams: [shellwm, actor] onOverwriteParams: [shellwm, actor]
}); });
break;
default:
shellwm.completed_map(actor);
return;
} }
}, },
@ -1134,11 +931,7 @@ const WindowManager = new Lang.Class({
if (this._removeEffect(this._mapping, actor)) { if (this._removeEffect(this._mapping, actor)) {
Tweener.removeTweens(actor); Tweener.removeTweens(actor);
actor.opacity = 255; actor.opacity = 255;
actor.set_pivot_point(0, 0);
actor.scale_y = 1; actor.scale_y = 1;
actor.scale_x = 1;
actor.translation_y = 0;
actor.translation_x = 0;
shellwm.completed_map(actor); shellwm.completed_map(actor);
} }
}, },
@ -1161,51 +954,30 @@ const WindowManager = new Lang.Class({
}); });
} }
let types = [Meta.WindowType.NORMAL, if (!this._shouldAnimateActor(actor)) {
Meta.WindowType.DIALOG,
Meta.WindowType.MODAL_DIALOG];
if (!this._shouldAnimateActor(actor, types)) {
shellwm.completed_destroy(actor); shellwm.completed_destroy(actor);
return; return;
} }
switch (actor._windowType) { this._destroying.push(actor);
case Meta.WindowType.NORMAL:
actor.set_pivot_point(0.5, 0.5);
this._destroying.push(actor);
Tweener.addTween(actor, if (window.is_attached_dialog()) {
{ opacity: 0, let parent = window.get_transient_for();
scale_x: 0.8, this._checkDimming(parent, window);
scale_y: 0.8,
time: DESTROY_WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._destroyWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._destroyWindowDone,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
break;
case Meta.WindowType.MODAL_DIALOG:
case Meta.WindowType.DIALOG:
actor.set_pivot_point(0.5, 0.5);
this._destroying.push(actor);
if (window.is_attached_dialog()) { actor.set_scale(1.0, 1.0);
let parent = window.get_transient_for(); actor.scale_gravity = Clutter.Gravity.CENTER;
this._checkDimming(parent, window); actor.show();
actor._parentDestroyId = parent.connect('unmanaged', Lang.bind(this, function () {
Tweener.removeTweens(actor); actor._parentDestroyId = parent.connect('unmanaged', Lang.bind(this, function () {
this._destroyWindowDone(shellwm, actor); Tweener.removeTweens(actor);
})); this._destroyWindowDone(shellwm, actor);
} }));
Tweener.addTween(actor, Tweener.addTween(actor,
{ scale_y: 0, { scale_y: 0,
time: DIALOG_DESTROY_WINDOW_ANIMATION_TIME, time: WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad', transition: "easeOutQuad",
onComplete: this._destroyWindowDone, onComplete: this._destroyWindowDone,
onCompleteScope: this, onCompleteScope: this,
onCompleteParams: [shellwm, actor], onCompleteParams: [shellwm, actor],
@ -1213,11 +985,9 @@ const WindowManager = new Lang.Class({
onOverwriteScope: this, onOverwriteScope: this,
onOverwriteParams: [shellwm, actor] onOverwriteParams: [shellwm, actor]
}); });
break;
default:
shellwm.completed_destroy(actor);
return; return;
} }
shellwm.completed_destroy(actor);
}, },
_destroyWindowDone : function(shellwm, actor) { _destroyWindowDone : function(shellwm, actor) {
@ -1379,10 +1149,6 @@ const WindowManager = new Lang.Class({
this._tilePreview.hide(); this._tilePreview.hide();
}, },
_showWindowMenu: function(shellwm, window, menu, rect) {
this._windowMenuManager.showWindowMenuForWindow(window, menu, rect);
},
_startAppSwitcher : function(display, screen, window, binding) { _startAppSwitcher : function(display, screen, window, binding) {
/* prevent a corner case where both popups show up at once */ /* prevent a corner case where both popups show up at once */
if (this._workspaceSwitcherPopup != null) if (this._workspaceSwitcherPopup != null)
@ -1390,7 +1156,9 @@ const WindowManager = new Lang.Class({
let tabPopup = new AltTab.AppSwitcherPopup(); let tabPopup = new AltTab.AppSwitcherPopup();
if (!tabPopup.show(binding.is_reversed(), binding.get_name(), binding.get_mask())) let modifiers = binding.get_modifiers();
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
if (!tabPopup.show(backwards, binding.get_name(), binding.get_mask()))
tabPopup.destroy(); tabPopup.destroy();
}, },
@ -1401,12 +1169,16 @@ const WindowManager = new Lang.Class({
let tabPopup = new AltTab.WindowSwitcherPopup(); let tabPopup = new AltTab.WindowSwitcherPopup();
if (!tabPopup.show(binding.is_reversed(), binding.get_name(), binding.get_mask())) let modifiers = binding.get_modifiers();
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
if (!tabPopup.show(backwards, binding.get_name(), binding.get_mask()))
tabPopup.destroy(); tabPopup.destroy();
}, },
_startA11ySwitcher : function(display, screen, window, binding) { _startA11ySwitcher : function(display, screen, window, binding) {
Main.ctrlAltTabManager.popup(binding.is_reversed(), binding.get_name(), binding.get_mask()); let modifiers = binding.get_modifiers();
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
Main.ctrlAltTabManager.popup(backwards, binding.get_name(), binding.get_mask());
}, },
_toggleAppMenu : function(display, screen, window, event, binding) { _toggleAppMenu : function(display, screen, window, event, binding) {
@ -1433,10 +1205,7 @@ const WindowManager = new Lang.Class({
let newWs; let newWs;
let direction; let direction;
if (target == 'last') { if (isNaN(target)) {
direction = Meta.MotionDirection.DOWN;
newWs = screen.get_workspace_by_index(screen.n_workspaces - 1);
} else if (isNaN(target)) {
direction = Meta.MotionDirection[target.toUpperCase()]; direction = Meta.MotionDirection[target.toUpperCase()];
newWs = screen.get_active_workspace().get_neighbor(direction); newWs = screen.get_active_workspace().get_neighbor(direction);
} else if (target > 0) { } else if (target > 0) {

View File

@ -1,185 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const BoxPointer = imports.ui.boxpointer;
const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu;
const RemoteMenu = imports.ui.remoteMenu;
const WindowMenu = new Lang.Class({
Name: 'WindowMenu',
Extends: PopupMenu.PopupMenu,
_init: function(window, sourceActor) {
this.parent(sourceActor, 0, St.Side.TOP);
this.actor.add_style_class_name('window-menu');
Main.layoutManager.uiGroup.add_actor(this.actor);
this.actor.hide();
this._buildMenu(window);
},
_buildMenu: function(window) {
let type = window.get_window_type();
let item;
item = this.addAction(_("Minimize"), Lang.bind(this, function(event) {
window.minimize();
}));
if (!window.can_minimize())
item.setSensitive(false);
if (window.get_maximized()) {
item = this.addAction(_("Unmaximize"), Lang.bind(this, function() {
window.unmaximize(Meta.MaximizeFlags.BOTH);
}));
} else {
item = this.addAction(_("Maximize"), Lang.bind(this, function() {
window.maximize(Meta.MaximizeFlags.BOTH);
}));
}
if (!window.can_maximize())
item.setSensitive(false);
item = this.addAction(_("Move"), Lang.bind(this, function(event) {
window.begin_grab_op(Meta.GrabOp.KEYBOARD_MOVING, true, event.get_time());
}));
if (!window.allows_move())
item.setSensitive(false);
item = this.addAction(_("Resize"), Lang.bind(this, function(event) {
window.begin_grab_op(Meta.GrabOp.KEYBOARD_RESIZING_UNKNOWN, true, event.get_time());
}));
if (!window.allows_resize())
item.setSensitive(false);
if (!window.titlebar_is_onscreen() && type != Meta.WindowType.DOCK && type != Meta.WindowType.DESKTOP) {
this.addAction(_("Move Titlebar Onscreen"), Lang.bind(this, function(event) {
window.shove_titlebar_onscreen();
}));
}
item = this.addAction(_("Always on Top"), Lang.bind(this, function() {
if (window.is_above())
window.unmake_above();
else
window.make_above();
}));
if (window.is_above())
item.setOrnament(PopupMenu.Ornament.DOT);
if (window.get_maximized() == Meta.MaximizeFlags.BOTH ||
type == Meta.WindowType.DOCK ||
type == Meta.WindowType.DESKTOP ||
type == Meta.WindowType.SPLASHSCREEN)
item.setSensitive(false);
if (Main.sessionMode.hasWorkspaces &&
(!Meta.prefs_get_workspaces_only_on_primary() ||
window.is_on_primary_monitor())) {
let isSticky = window.is_on_all_workspaces();
item = this.addAction(_("Always on Visible Workspace"), Lang.bind(this, function() {
if (isSticky)
window.unstick();
else
window.stick();
}));
if (isSticky)
item.setOrnament(PopupMenu.Ornament.DOT);
if (window.is_always_on_all_workspaces())
item.setSensitive(false);
let nWorkspaces = global.screen.n_workspaces;
if (!isSticky) {
let workspace = window.get_workspace();
let idx = workspace.index();
if (idx > 0) {
this.addAction(_("Move to Workspace Up"), Lang.bind(this, function(event) {
window.change_workspace(workspace.get_neighbor(Meta.MotionDirection.UP));
}));
}
if (idx < nWorkspaces) {
this.addAction(_("Move to Workspace Down"), Lang.bind(this, function(event) {
window.change_workspace(workspace.get_neighbor(Meta.MotionDirection.DOWN));
}));
}
}
}
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
item = this.addAction(_("Close"), Lang.bind(this, function(event) {
window.delete(event.get_time());
}));
if (!window.can_close())
item.setSensitive(false);
}
});
const AppMenu = new Lang.Class({
Name: 'AppMenu',
Extends: RemoteMenu.RemoteMenu,
_init: function(window, sourceActor) {
let app = Shell.WindowTracker.get_default().get_window_app(window);
this.parent(sourceActor, app.menu, app.action_group);
this.actor.add_style_class_name('fallback-app-menu');
let variant = window.get_gtk_theme_variant();
if (variant)
this.actor.add_style_class_name(variant);
Main.layoutManager.uiGroup.add_actor(this.actor);
this.actor.hide();
}
});
const WindowMenuManager = new Lang.Class({
Name: 'WindowMenuManager',
_init: function() {
this._manager = new PopupMenu.PopupMenuManager({ actor: Main.layoutManager.dummyCursor });
this._sourceActor = new St.Widget({ reactive: true, visible: false });
this._sourceActor.connect('button-press-event', Lang.bind(this,
function() {
this._manager.activeMenu.toggle();
}));
Main.uiGroup.add_actor(this._sourceActor);
},
showWindowMenuForWindow: function(window, type, rect) {
let menuType = (type == Meta.WindowMenuType.WM) ? WindowMenu : AppMenu;
let menu = new menuType(window, this._sourceActor);
this._manager.addMenu(menu);
menu.connect('activate', function() {
window.check_alive(global.get_current_time());
});
this._sourceActor.set_size(rect.width, rect.height);
this._sourceActor.set_position(rect.x, rect.y);
this._sourceActor.show();
menu.open(BoxPointer.PopupAnimation.NONE);
menu.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
menu.connect('open-state-changed', Lang.bind(this, function(menu_, isOpen) {
if (isOpen)
return;
this._sourceActor.hide();
menu.destroy();
}));
}
});

View File

@ -34,8 +34,6 @@ const DRAGGING_WINDOW_OPACITY = 100;
const LAYOUT_SCALE_WEIGHT = 1; const LAYOUT_SCALE_WEIGHT = 1;
const LAYOUT_SPACE_WEIGHT = 0.1; const LAYOUT_SPACE_WEIGHT = 0.1;
const WINDOW_ANIMATION_MAX_NUMBER_BLENDING = 3;
function _interpolate(start, end, step) { function _interpolate(start, end, step) {
return start + (end - start) * step; return start + (end - start) * step;
} }
@ -69,7 +67,7 @@ const WindowCloneLayout = new Lang.Class({
// paradoxically is the smaller rectangle, containing the positions // paradoxically is the smaller rectangle, containing the positions
// of the visible frame. The input rect contains everything, // of the visible frame. The input rect contains everything,
// including the invisible border padding. // including the invisible border padding.
let inputRect = window.get_buffer_rect(); let inputRect = window.get_input_rect();
let box = new Clutter.ActorBox(); let box = new Clutter.ActorBox();
@ -89,7 +87,7 @@ const WindowCloneLayout = new Lang.Class({
}, },
vfunc_allocate: function(container, box, flags) { vfunc_allocate: function(container, box, flags) {
container.get_children().forEach(Lang.bind(this, function (child) { let clone = container.get_children().forEach(function (child) {
let realWindow; let realWindow;
if (child == container._delegate._windowClone) if (child == container._delegate._windowClone)
realWindow = container._delegate.realWindow; realWindow = container._delegate.realWindow;
@ -98,8 +96,8 @@ const WindowCloneLayout = new Lang.Class({
child.allocate(this._makeBoxForWindow(realWindow.meta_window), child.allocate(this._makeBoxForWindow(realWindow.meta_window),
flags); flags);
})); }, this);
} },
}); });
const WindowClone = new Lang.Class({ const WindowClone = new Lang.Class({
@ -202,10 +200,6 @@ const WindowClone = new Lang.Class({
this.emit('size-changed'); this.emit('size-changed');
}, },
hasAttachedDialogs: function() {
return this.actor.get_n_children() > 1;
},
_doAddAttachedDialog: function(metaWin, realWin) { _doAddAttachedDialog: function(metaWin, realWin) {
let clone = new Clutter.Clone({ source: realWin }); let clone = new Clutter.Clone({ source: realWin });
clone._updateId = metaWin.connect('size-changed', Lang.bind(this, function() { clone._updateId = metaWin.connect('size-changed', Lang.bind(this, function() {
@ -241,20 +235,12 @@ const WindowClone = new Lang.Class({
return this._boundingBox; return this._boundingBox;
}, },
get width() {
return this._boundingBox.width;
},
get height() {
return this._boundingBox.height;
},
getOriginalPosition: function() { getOriginalPosition: function() {
return [this._boundingBox.x, this._boundingBox.y]; return [this._boundingBox.x, this._boundingBox.y];
}, },
_computeBoundingBox: function() { _computeBoundingBox: function() {
let rect = this.metaWindow.get_frame_rect(); let rect = this.metaWindow.get_outer_rect();
this.actor.get_children().forEach(function (child) { this.actor.get_children().forEach(function (child) {
let realWindow; let realWindow;
@ -264,11 +250,10 @@ const WindowClone = new Lang.Class({
realWindow = child.source; realWindow = child.source;
let metaWindow = realWindow.meta_window; let metaWindow = realWindow.meta_window;
rect = rect.union(metaWindow.get_frame_rect()); rect = rect.union(metaWindow.get_outer_rect());
}, this); }, this);
// Convert from a MetaRectangle to a native JS object this._boundingBox = rect;
this._boundingBox = { x: rect.x, y: rect.y, width: rect.width, height: rect.height };
this.actor.layout_manager.boundingBox = rect; this.actor.layout_manager.boundingBox = rect;
}, },
@ -519,7 +504,6 @@ const WindowOverlay = new Lang.Class({
Tweener.removeTweens(button); Tweener.removeTweens(button);
Tweener.removeTweens(border); Tweener.removeTweens(border);
Tweener.removeTweens(title);
let [cloneX, cloneY, cloneWidth, cloneHeight] = this._windowClone.slot; let [cloneX, cloneY, cloneWidth, cloneHeight] = this._windowClone.slot;
@ -598,8 +582,7 @@ const WindowOverlay = new Lang.Class({
}, },
_windowCanClose: function() { _windowCanClose: function() {
return this._windowClone.metaWindow.can_close() && return this._windowClone.metaWindow.can_close();
!this._windowClone.hasAttachedDialogs();
}, },
_onWindowAdded: function(workspace, win) { _onWindowAdded: function(workspace, win) {
@ -611,12 +594,11 @@ const WindowOverlay = new Lang.Class({
// use an idle handler to avoid mapping problems - // use an idle handler to avoid mapping problems -
// see comment in Workspace._windowAdded // see comment in Workspace._windowAdded
let id = Mainloop.idle_add(Lang.bind(this, Mainloop.idle_add(Lang.bind(this,
function() { function() {
this._windowClone.emit('selected'); this._windowClone.emit('selected');
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(id, '[gnome-shell] this._windowClone.emit');
} }
}, },
@ -687,10 +669,8 @@ const WindowOverlay = new Lang.Class({
}, },
_onLeave: function() { _onLeave: function() {
if (this._idleToggleCloseId == 0) { if (this._idleToggleCloseId == 0)
this._idleToggleCloseId = Mainloop.timeout_add(750, Lang.bind(this, this._idleToggleCloseButton)); this._idleToggleCloseId = Mainloop.timeout_add(750, Lang.bind(this, this._idleToggleCloseButton));
GLib.Source.set_name_by_id(this._idleToggleCloseId, '[gnome-shell] this._idleToggleCloseButton');
}
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
}, },
@ -844,7 +824,7 @@ const LayoutStrategy = new Lang.Class({
// thumbnails is much more important to preserve than the width of // thumbnails is much more important to preserve than the width of
// them, so two windows with equal height, but maybe differering // them, so two windows with equal height, but maybe differering
// widths line up. // widths line up.
let ratio = window.height / this._monitor.height; let ratio = window.actor.height / this._monitor.height;
// The purpose of this manipulation here is to prevent windows // The purpose of this manipulation here is to prevent windows
// from getting too small. For something like a calculator window, // from getting too small. For something like a calculator window,
@ -946,11 +926,11 @@ const LayoutStrategy = new Lang.Class({
let window = row.windows[j]; let window = row.windows[j];
let s = scale * this._computeWindowScale(window) * row.additionalScale; let s = scale * this._computeWindowScale(window) * row.additionalScale;
let cellWidth = window.width * s; let cellWidth = window.actor.width * s;
let cellHeight = window.height * s; let cellHeight = window.actor.height * s;
s = Math.min(s, WINDOW_CLONE_MAXIMUM_SCALE); s = Math.min(s, WINDOW_CLONE_MAXIMUM_SCALE);
let cloneWidth = window.width * s; let cloneWidth = window.actor.width * s;
let cloneX = x + (cellWidth - cloneWidth) / 2; let cloneX = x + (cellWidth - cloneWidth) / 2;
let cloneY = row.y + row.height - cellHeight; let cloneY = row.y + row.height - cellHeight;
@ -1004,7 +984,7 @@ const UnalignedLayoutStrategy = new Lang.Class({
for (let i = 0; i < windows.length; i++) { for (let i = 0; i < windows.length; i++) {
let window = windows[i]; let window = windows[i];
let s = this._computeWindowScale(window); let s = this._computeWindowScale(window);
totalWidth += window.width * s; totalWidth += window.actor.width * s;
} }
let idealRowWidth = totalWidth / numRows; let idealRowWidth = totalWidth / numRows;
@ -1017,8 +997,8 @@ const UnalignedLayoutStrategy = new Lang.Class({
for (; windowIdx < windows.length; windowIdx++) { for (; windowIdx < windows.length; windowIdx++) {
let window = windows[windowIdx]; let window = windows[windowIdx];
let s = this._computeWindowScale(window); let s = this._computeWindowScale(window);
let width = window.width * s; let width = window.actor.width * s;
let height = window.height * s; let height = window.actor.height * s;
row.fullHeight = Math.max(row.fullHeight, height); row.fullHeight = Math.max(row.fullHeight, height);
// either new width is < idealWidth or new width is nearer from idealWidth then oldWidth // either new width is < idealWidth or new width is nearer from idealWidth then oldWidth
@ -1143,11 +1123,6 @@ const Workspace = new Lang.Class({
this._positionWindowsFlags = 0; this._positionWindowsFlags = 0;
this._positionWindowsId = 0; this._positionWindowsId = 0;
this.actor.connect('notify::mapped', Lang.bind(this, function() {
if (this.actor.mapped)
this._syncActualGeometry();
}));
}, },
setFullGeometry: function(geom) { setFullGeometry: function(geom) {
@ -1155,9 +1130,7 @@ const Workspace = new Lang.Class({
return; return;
this._fullGeometry = geom; this._fullGeometry = geom;
this._recalculateWindowPositions(WindowPositionFlags.NONE);
if (this.actor.mapped)
this._recalculateWindowPositions(WindowPositionFlags.NONE);
}, },
setActualGeometry: function(geom) { setActualGeometry: function(geom) {
@ -1165,29 +1138,18 @@ const Workspace = new Lang.Class({
return; return;
this._actualGeometry = geom; this._actualGeometry = geom;
this._actualGeometryDirty = true;
if (this.actor.mapped) if (this._actualGeometryLater)
this._syncActualGeometry();
},
_syncActualGeometry: function() {
if (this._actualGeometryLater || !this._actualGeometryDirty)
return;
if (!this._actualGeometry)
return; return;
this._actualGeometryLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { this._actualGeometryLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
this._actualGeometryLater = 0;
if (!this.actor.mapped)
return false;
let geom = this._actualGeometry; let geom = this._actualGeometry;
this._dropRect.set_position(geom.x, geom.y); this._dropRect.set_position(geom.x, geom.y);
this._dropRect.set_size(geom.width, geom.height); this._dropRect.set_size(geom.width, geom.height);
this._updateWindowPositions(Main.overview.animationInProgress ? WindowPositionFlags.ANIMATE : WindowPositionFlags.NONE); this._updateWindowPositions(Main.overview.animationInProgress ? WindowPositionFlags.ANIMATE : WindowPositionFlags.NONE);
this._actualGeometryLater = 0;
return false; return false;
})); }));
}, },
@ -1209,18 +1171,14 @@ const Workspace = new Lang.Class({
return this._windows.length == 0; return this._windows.length == 0;
}, },
setReservedSlot: function(metaWindow) { setReservedSlot: function(clone) {
if (this._reservedSlotWindow == metaWindow) if (this._reservedSlot == clone)
return; return;
if (!metaWindow || this.containsMetaWindow(metaWindow)) { if (clone && this.containsMetaWindow(clone.metaWindow))
this._reservedSlotWindow = null; clone = null;
this._reservedSlot = null;
} else {
this._reservedSlotWindow = metaWindow;
this._reservedSlot = this._windows[this._lookupIndex(metaWindow)];
}
this._reservedSlot = clone;
this._recalculateWindowPositions(WindowPositionFlags.ANIMATE); this._recalculateWindowPositions(WindowPositionFlags.ANIMATE);
}, },
@ -1265,13 +1223,6 @@ const Workspace = new Lang.Class({
return; return;
} }
// We will reposition windows anyway when enter again overview or when ending the windows
// animations whith fade animation.
// In this way we avoid unwanted animations of windows repositioning while
// animating overview.
if (this.leavingOverview || this._animatingWindowsFade)
return;
let initialPositioning = flags & WindowPositionFlags.INITIAL; let initialPositioning = flags & WindowPositionFlags.INITIAL;
let animate = flags & WindowPositionFlags.ANIMATE; let animate = flags & WindowPositionFlags.ANIMATE;
@ -1334,7 +1285,7 @@ const Workspace = new Lang.Class({
}); });
} }
this._animateClone(clone, overlay, x, y, scale); this._animateClone(clone, overlay, x, y, scale, initialPositioning);
} else { } else {
// cancel any active tweens (otherwise they might override our changes) // cancel any active tweens (otherwise they might override our changes)
Tweener.removeTweens(clone.actor); Tweener.removeTweens(clone.actor);
@ -1363,7 +1314,7 @@ const Workspace = new Lang.Class({
} }
}, },
_animateClone: function(clone, overlay, x, y, scale) { _animateClone: function(clone, overlay, x, y, scale, initialPositioning) {
Tweener.addTween(clone.actor, Tweener.addTween(clone.actor,
{ x: x, { x: x,
y: y, y: y,
@ -1421,6 +1372,10 @@ const Workspace = new Lang.Class({
if (index == -1) if (index == -1)
return; return;
// Check if window still should be here
if (win && this._isMyWindow(win))
return;
let clone = this._windows[index]; let clone = this._windows[index];
this._windows.splice(index, 1); this._windows.splice(index, 1);
@ -1463,7 +1418,6 @@ const Workspace = new Lang.Class({
this._currentLayout = null; this._currentLayout = null;
this._repositionWindowsId = Mainloop.timeout_add(750, this._repositionWindowsId = Mainloop.timeout_add(750,
Lang.bind(this, this._delayedWindowRepositioning)); Lang.bind(this, this._delayedWindowRepositioning));
GLib.Source.set_name_by_id(this._repositionWindowsId, '[gnome-shell] this._delayedWindowRepositioning');
}, },
_doAddWindow : function(metaWin) { _doAddWindow : function(metaWin) {
@ -1475,15 +1429,14 @@ const Workspace = new Lang.Class({
if (!win) { if (!win) {
// Newly-created windows are added to a workspace before // Newly-created windows are added to a workspace before
// the compositor finds out about them... // the compositor finds out about them...
let id = Mainloop.idle_add(Lang.bind(this, Mainloop.idle_add(Lang.bind(this,
function () { function () {
if (this.actor && if (this.actor &&
metaWin.get_compositor_private() && metaWin.get_compositor_private() &&
metaWin.get_workspace() == this.metaWorkspace) metaWin.get_workspace() == this.metaWorkspace)
this._doAddWindow(metaWin); this._doAddWindow(metaWin);
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(id, '[gnome-shell] this._doAddWindow');
return; return;
} }
@ -1566,141 +1519,14 @@ const Workspace = new Lang.Class({
return false; return false;
}, },
fadeToOverview: function() { // Animate the full-screen to Overview transition.
// We don't want to reposition windows while animating in this way. zoomToOverview : function() {
this._animatingWindowsFade = true;
this._overviewShownId = Main.overview.connect('shown', Lang.bind(this,
this._doneShowingOverview));
if (this._windows.length == 0)
return;
if (this.metaWorkspace != null && this.metaWorkspace != global.screen.get_active_workspace())
return;
// Special case maximized windows, since it doesn't make sense
// to animate windows below in the stack
let topMaximizedWindow;
// It is ok to treat the case where there is no maximized
// window as if the bottom-most window was maximized given that
// it won't affect the result of the animation
for (topMaximizedWindow = this._windows.length - 1; topMaximizedWindow > 0; topMaximizedWindow--) {
let metaWindow = this._windows[topMaximizedWindow].metaWindow;
if (metaWindow.maximized_horizontally && metaWindow.maximized_vertically)
break;
}
let nTimeSlots = Math.min(WINDOW_ANIMATION_MAX_NUMBER_BLENDING + 1, this._windows.length - topMaximizedWindow);
let windowBaseTime = Overview.ANIMATION_TIME / nTimeSlots;
let topIndex = this._windows.length - 1;
for (let i = 0; i < this._windows.length; i++) {
if (i < topMaximizedWindow) {
// below top-most maximized window, don't animate
let overlay = this._windowOverlays[i];
if (overlay)
overlay.hide();
this._windows[i].actor.opacity = 0;
} else {
let fromTop = topIndex - i;
let time;
if (fromTop < nTimeSlots) // animate top-most windows gradually
time = windowBaseTime * (nTimeSlots - fromTop);
else
time = windowBaseTime;
this._windows[i].actor.opacity = 255;
this._fadeWindow(i, time, 0);
}
}
},
fadeFromOverview: function() {
this.leavingOverview = true;
this._overviewHiddenId = Main.overview.connect('hidden', Lang.bind(this,
this._doneLeavingOverview));
if (this._windows.length == 0)
return;
for (let i = 0; i < this._windows.length; i++) {
let clone = this._windows[i];
Tweener.removeTweens(clone.actor);
}
if (this._repositionWindowsId > 0) {
Mainloop.source_remove(this._repositionWindowsId);
this._repositionWindowsId = 0;
}
if (this.metaWorkspace != null && this.metaWorkspace != global.screen.get_active_workspace())
return;
// Special case maximized windows, since it doesn't make sense
// to animate windows below in the stack
let topMaximizedWindow;
// It is ok to treat the case where there is no maximized
// window as if the bottom-most window was maximized given that
// it won't affect the result of the animation
for (topMaximizedWindow = this._windows.length - 1; topMaximizedWindow > 0; topMaximizedWindow--) {
let metaWindow = this._windows[topMaximizedWindow].metaWindow;
if (metaWindow.maximized_horizontally && metaWindow.maximized_vertically)
break;
}
let nTimeSlots = Math.min(WINDOW_ANIMATION_MAX_NUMBER_BLENDING + 1, this._windows.length - topMaximizedWindow);
let windowBaseTime = Overview.ANIMATION_TIME / nTimeSlots;
let topIndex = this._windows.length - 1;
for (let i = 0; i < this._windows.length; i++) {
if (i < topMaximizedWindow) {
// below top-most maximized window, don't animate
let overlay = this._windowOverlays[i];
if (overlay)
overlay.hide();
this._windows[i].actor.opacity = 0;
} else {
let fromTop = topIndex - i;
let time;
if (fromTop < nTimeSlots) // animate top-most windows gradually
time = windowBaseTime * (fromTop + 1);
else
time = windowBaseTime * nTimeSlots;
this._windows[i].actor.opacity = 0;
this._fadeWindow(i, time, 255);
}
}
},
_fadeWindow: function(index, time, opacity) {
let clone = this._windows[index];
let overlay = this._windowOverlays[index];
if (overlay)
overlay.hide();
if (clone.metaWindow.showing_on_its_workspace()) {
let [origX, origY] = clone.getOriginalPosition();
clone.actor.scale_x = 1;
clone.actor.scale_y = 1;
clone.actor.x = origX;
clone.actor.y = origY;
Tweener.addTween(clone.actor,
{ time: time,
opacity: opacity,
transition: 'easeOutQuad'
});
} else {
// The window is hidden
clone.actor.opacity = 0;
}
},
zoomToOverview: function() {
// Position and scale the windows. // Position and scale the windows.
this._recalculateWindowPositions(WindowPositionFlags.ANIMATE | WindowPositionFlags.INITIAL); this._recalculateWindowPositions(WindowPositionFlags.ANIMATE | WindowPositionFlags.INITIAL);
}, },
zoomFromOverview: function() { // Animates the return from Overview mode
zoomFromOverview : function() {
let currentWorkspace = global.screen.get_active_workspace(); let currentWorkspace = global.screen.get_active_workspace();
this.leavingOverview = true; this.leavingOverview = true;
@ -1721,37 +1547,35 @@ const Workspace = new Lang.Class({
return; return;
// Position and scale the windows. // Position and scale the windows.
for (let i = 0; i < this._windows.length; i++) for (let i = 0; i < this._windows.length; i++) {
this._zoomWindowFromOverview(i); let clone = this._windows[i];
}, let overlay = this._windowOverlays[i];
_zoomWindowFromOverview: function(index) { if (overlay)
let clone = this._windows[index]; overlay.hide();
let overlay = this._windowOverlays[index];
if (overlay) if (clone.metaWindow.showing_on_its_workspace()) {
overlay.hide(); let [origX, origY] = clone.getOriginalPosition();
if (clone.metaWindow.showing_on_its_workspace()) { Tweener.addTween(clone.actor,
let [origX, origY] = clone.getOriginalPosition(); { x: origX,
Tweener.addTween(clone.actor, y: origY,
{ x: origX, scale_x: 1.0,
y: origY, scale_y: 1.0,
scale_x: 1.0, time: Overview.ANIMATION_TIME,
scale_y: 1.0, opacity: 255,
time: Overview.ANIMATION_TIME, transition: 'easeOutQuad'
opacity: 255, });
transition: 'easeOutQuad' } else {
}); // The window is hidden, make it shrink and fade it out
} else { Tweener.addTween(clone.actor,
// The window is hidden, make it shrink and fade it out { scale_x: 0,
Tweener.addTween(clone.actor, scale_y: 0,
{ scale_x: 0, opacity: 0,
scale_y: 0, time: Overview.ANIMATION_TIME,
opacity: 0, transition: 'easeOutQuad'
time: Overview.ANIMATION_TIME, });
transition: 'easeOutQuad' }
});
} }
}, },
@ -1790,11 +1614,6 @@ const Workspace = new Lang.Class({
this.leavingOverview = false; this.leavingOverview = false;
}, },
_doneShowingOverview: function() {
this._animatingWindowsFade = false;
this._recalculateWindowPositions(WindowPositionFlags.INITIAL);
},
// Tests if @actor belongs to this workspaces and monitor // Tests if @actor belongs to this workspaces and monitor
_isMyWindow : function (actor) { _isMyWindow : function (actor) {
let win = actor.meta_window; let win = actor.meta_window;
@ -1818,16 +1637,16 @@ const Workspace = new Lang.Class({
Lang.bind(this, this._onCloneSelected)); Lang.bind(this, this._onCloneSelected));
clone.connect('drag-begin', clone.connect('drag-begin',
Lang.bind(this, function() { Lang.bind(this, function() {
Main.overview.beginWindowDrag(clone.metaWindow); Main.overview.beginWindowDrag(clone);
overlay.hide(); overlay.hide();
})); }));
clone.connect('drag-cancelled', clone.connect('drag-cancelled',
Lang.bind(this, function() { Lang.bind(this, function() {
Main.overview.cancelledWindowDrag(clone.metaWindow); Main.overview.cancelledWindowDrag(clone);
})); }));
clone.connect('drag-end', clone.connect('drag-end',
Lang.bind(this, function() { Lang.bind(this, function() {
Main.overview.endWindowDrag(clone.metaWindow); Main.overview.endWindowDrag(clone);
overlay.show(); overlay.show();
})); }));
clone.connect('size-changed', clone.connect('size-changed',

View File

@ -52,7 +52,6 @@ const WorkspaceSwitcherPopup = new Lang.Class({
this._globalSignals.push(global.screen.connect('workspace-removed', Lang.bind(this, this._redisplay))); this._globalSignals.push(global.screen.connect('workspace-removed', Lang.bind(this, this._redisplay)));
this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, Lang.bind(this, this._onTimeout)); this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, Lang.bind(this, this._onTimeout));
GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] this._onTimeout');
}, },
_getPreferredHeight : function (actor, forWidth, alloc) { _getPreferredHeight : function (actor, forWidth, alloc) {
@ -146,7 +145,6 @@ const WorkspaceSwitcherPopup = new Lang.Class({
if (this._timeoutId != 0) if (this._timeoutId != 0)
Mainloop.source_remove(this._timeoutId); Mainloop.source_remove(this._timeoutId);
this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, Lang.bind(this, this._onTimeout)); this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, Lang.bind(this, this._onTimeout));
GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] this._onTimeout');
this._show(); this._show();
}, },

View File

@ -161,14 +161,14 @@ const WindowClone = new Lang.Class({
_updateDialogPosition: function(realDialog, cloneDialog) { _updateDialogPosition: function(realDialog, cloneDialog) {
let metaDialog = realDialog.meta_window; let metaDialog = realDialog.meta_window;
let dialogRect = metaDialog.get_frame_rect(); let dialogRect = metaDialog.get_outer_rect();
let rect = this.metaWindow.get_frame_rect(); let rect = this.metaWindow.get_outer_rect();
cloneDialog.set_position(dialogRect.x - rect.x, dialogRect.y - rect.y); cloneDialog.set_position(dialogRect.x - rect.x, dialogRect.y - rect.y);
}, },
_onPositionChanged: function() { _onPositionChanged: function() {
let rect = this.metaWindow.get_frame_rect(); let rect = this.metaWindow.get_outer_rect();
this.actor.set_position(this.realWindow.x, this.realWindow.y); this.actor.set_position(this.realWindow.x, this.realWindow.y);
}, },
@ -306,7 +306,7 @@ const WorkspaceThumbnail = new Lang.Class({
_createBackground: function() { _createBackground: function() {
this._bgManager = new Background.BackgroundManager({ monitorIndex: Main.layoutManager.primaryIndex, this._bgManager = new Background.BackgroundManager({ monitorIndex: Main.layoutManager.primaryIndex,
container: this._contents, container: this._contents,
vignette: false }); effects: Meta.BackgroundEffects.NONE });
}, },
setPorthole: function(x, y, width, height) { setPorthole: function(x, y, width, height) {
@ -332,7 +332,7 @@ const WorkspaceThumbnail = new Lang.Class({
let clone = this._windows[i]; let clone = this._windows[i];
let metaWindow = clone.metaWindow; let metaWindow = clone.metaWindow;
if (i == 0) { if (i == 0) {
clone.setStackAbove(this._bgManager.backgroundActor); clone.setStackAbove(this._bgManager.background.actor);
} else { } else {
let previousClone = this._windows[i - 1]; let previousClone = this._windows[i - 1];
clone.setStackAbove(previousClone.actor); clone.setStackAbove(previousClone.actor);
@ -367,6 +367,10 @@ const WorkspaceThumbnail = new Lang.Class({
if (index == -1) if (index == -1)
return; return;
// Check if window still should be here
if (win && this._isMyWindow(win) && this._isOverviewWindow(win))
return;
let clone = this._windows[index]; let clone = this._windows[index];
this._windows.splice(index, 1); this._windows.splice(index, 1);
@ -382,15 +386,14 @@ const WorkspaceThumbnail = new Lang.Class({
if (!win) { if (!win) {
// Newly-created windows are added to a workspace before // Newly-created windows are added to a workspace before
// the compositor finds out about them... // the compositor finds out about them...
let id = Mainloop.idle_add(Lang.bind(this, Mainloop.idle_add(Lang.bind(this,
function () { function () {
if (!this._removed && if (!this._removed &&
metaWin.get_compositor_private() && metaWin.get_compositor_private() &&
metaWin.get_workspace() == this.metaWorkspace) metaWin.get_workspace() == this.metaWorkspace)
this._doAddWindow(metaWin); this._doAddWindow(metaWin);
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(id, '[gnome-shell] this._doAddWindow');
return; return;
} }
@ -518,20 +521,20 @@ const WorkspaceThumbnail = new Lang.Class({
})); }));
clone.connect('drag-begin', clone.connect('drag-begin',
Lang.bind(this, function() { Lang.bind(this, function() {
Main.overview.beginWindowDrag(clone.metaWindow); Main.overview.beginWindowDrag(clone);
})); }));
clone.connect('drag-cancelled', clone.connect('drag-cancelled',
Lang.bind(this, function() { Lang.bind(this, function() {
Main.overview.cancelledWindowDrag(clone.metaWindow); Main.overview.cancelledWindowDrag(clone);
})); }));
clone.connect('drag-end', clone.connect('drag-end',
Lang.bind(this, function() { Lang.bind(this, function() {
Main.overview.endWindowDrag(clone.metaWindow); Main.overview.endWindowDrag(clone);
})); }));
this._contents.add_actor(clone.actor); this._contents.add_actor(clone.actor);
if (this._windows.length == 0) if (this._windows.length == 0)
clone.setStackAbove(this._bgManager.backgroundActor); clone.setStackAbove(this._bgManager.background.actor);
else else
clone.setStackAbove(this._windows[this._windows.length - 1].actor); clone.setStackAbove(this._windows[this._windows.length - 1].actor);
@ -661,7 +664,7 @@ const ThumbnailsBox = new Lang.Class({
Main.overview.connect('window-drag-cancelled', Main.overview.connect('window-drag-cancelled',
Lang.bind(this, this._onDragCancelled)); Lang.bind(this, this._onDragCancelled));
this._settings = new Gio.Settings({ schema_id: OVERRIDE_SCHEMA }); this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
this._settings.connect('changed::dynamic-workspaces', this._settings.connect('changed::dynamic-workspaces',
Lang.bind(this, this._updateSwitcherVisibility)); Lang.bind(this, this._updateSwitcherVisibility));
}, },
@ -822,14 +825,10 @@ const ThumbnailsBox = new Lang.Class({
window.change_workspace_by_index(window.get_workspace().index() + 1, true); window.change_workspace_by_index(window.get_workspace().index() + 1, true);
}); });
if (isWindow) { if (isWindow)
// ... and bam, a workspace, good as new. // ... and bam, a workspace, good as new.
// Move the window to our monitor first if necessary.
let thumbMonitor = this._thumbnails[newWorkspaceIndex].monitorIndex;
if (source.metaWindow.get_monitor() != thumbMonitor)
source.metaWindow.move_to_monitor(thumbMonitor);
source.metaWindow.change_workspace_by_index(newWorkspaceIndex, true); source.metaWindow.change_workspace_by_index(newWorkspaceIndex, true);
} else if (source.shellWorkspaceLaunch) { else if (source.shellWorkspaceLaunch) {
source.shellWorkspaceLaunch({ workspace: newWorkspaceIndex, source.shellWorkspaceLaunch({ workspace: newWorkspaceIndex,
timestamp: time }); timestamp: time });
// This new workspace will be automatically removed if the application fails // This new workspace will be automatically removed if the application fails
@ -874,6 +873,9 @@ const ThumbnailsBox = new Lang.Class({
for (let key in ThumbnailState) for (let key in ThumbnailState)
this._stateCounts[ThumbnailState[key]] = 0; this._stateCounts[ThumbnailState[key]] = 0;
// The "porthole" is the portion of the screen that we show in the workspaces
this._porthole = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
this.addThumbnails(0, global.screen.n_workspaces); this.addThumbnails(0, global.screen.n_workspaces);
this._updateSwitcherVisibility(); this._updateSwitcherVisibility();
@ -897,7 +899,6 @@ const ThumbnailsBox = new Lang.Class({
for (let w = 0; w < this._thumbnails.length; w++) for (let w = 0; w < this._thumbnails.length; w++)
this._thumbnails[w].destroy(); this._thumbnails[w].destroy();
this._thumbnails = []; this._thumbnails = [];
this._porthole = null;
}, },
_workspacesChanged: function() { _workspacesChanged: function() {
@ -928,7 +929,6 @@ const ThumbnailsBox = new Lang.Class({
}, },
addThumbnails: function(start, count) { addThumbnails: function(start, count) {
this._ensurePorthole();
for (let k = start; k < start + count; k++) { for (let k = start; k < start + count; k++) {
let metaWorkspace = global.screen.get_workspace_by_index(k); let metaWorkspace = global.screen.get_workspace_by_index(k);
let thumbnail = new WorkspaceThumbnail(metaWorkspace); let thumbnail = new WorkspaceThumbnail(metaWorkspace);
@ -1116,7 +1116,9 @@ const ThumbnailsBox = new Lang.Class({
// the size request to our children because we know how big they are and know // the size request to our children because we know how big they are and know
// that the actors aren't depending on the virtual functions being called. // that the actors aren't depending on the virtual functions being called.
this._ensurePorthole(); if (this._thumbnails.length == 0)
return;
let themeNode = this.actor.get_theme_node(); let themeNode = this.actor.get_theme_node();
let spacing = themeNode.get_length('spacing'); let spacing = themeNode.get_length('spacing');
@ -1128,7 +1130,8 @@ const ThumbnailsBox = new Lang.Class({
}, },
_getPreferredWidth: function(actor, forHeight, alloc) { _getPreferredWidth: function(actor, forHeight, alloc) {
this._ensurePorthole(); if (this._thumbnails.length == 0)
return;
let themeNode = this.actor.get_theme_node(); let themeNode = this.actor.get_theme_node();
@ -1146,13 +1149,6 @@ const ThumbnailsBox = new Lang.Class({
alloc.natural_size = width; alloc.natural_size = width;
}, },
// The "porthole" is the portion of the screen that we show in the
// workspaces
_ensurePorthole: function() {
if (!this._porthole)
this._porthole = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
},
_allocate: function(actor, box, flags) { _allocate: function(actor, box, flags) {
let rtl = (Clutter.get_default_text_direction () == Clutter.TextDirection.RTL); let rtl = (Clutter.get_default_text_direction () == Clutter.TextDirection.RTL);

View File

@ -21,11 +21,6 @@ const WORKSPACE_SWITCH_TIME = 0.25;
// Note that mutter has a compile-time limit of 36 // Note that mutter has a compile-time limit of 36
const MAX_WORKSPACES = 16; const MAX_WORKSPACES = 16;
const AnimationType = {
ZOOM: 0,
FADE: 1
};
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides'; const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
const WorkspacesViewBase = new Lang.Class({ const WorkspacesViewBase = new Lang.Class({
@ -63,9 +58,9 @@ const WorkspacesViewBase = new Lang.Class({
} }
}, },
_dragBegin: function(overview, window) { _dragBegin: function(overview, clone) {
this._inDrag = true; this._inDrag = true;
this._setReservedSlot(window); this._setReservedSlot(clone);
}, },
_dragEnd: function() { _dragEnd: function() {
@ -79,12 +74,12 @@ const WorkspacesViewBase = new Lang.Class({
setFullGeometry: function(geom) { setFullGeometry: function(geom) {
this._fullGeometry = geom; this._fullGeometry = geom;
this._syncFullGeometry(); this._syncGeometry();
}, },
setActualGeometry: function(geom) { setActualGeometry: function(geom) {
this._actualGeometry = geom; this._actualGeometry = geom;
this._syncActualGeometry(); this._syncGeometry();
}, },
}); });
@ -99,7 +94,7 @@ const WorkspacesView = new Lang.Class({
this._scrolling = false; // swipe-scrolling this._scrolling = false; // swipe-scrolling
this._animatingScroll = false; // programatically updating the adjustment this._animatingScroll = false; // programatically updating the adjustment
this._settings = new Gio.Settings({ schema_id: OVERRIDE_SCHEMA }); this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
let activeWorkspaceIndex = global.screen.get_active_workspace_index(); let activeWorkspaceIndex = global.screen.get_active_workspace_index();
this.scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex, this.scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex,
@ -127,17 +122,14 @@ const WorkspacesView = new Lang.Class({
Lang.bind(this, this._activeWorkspaceChanged)); Lang.bind(this, this._activeWorkspaceChanged));
}, },
_setReservedSlot: function(window) { _setReservedSlot: function(clone) {
for (let i = 0; i < this._workspaces.length; i++) for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].setReservedSlot(window); this._workspaces[i].setReservedSlot(clone);
}, },
_syncFullGeometry: function() { _syncGeometry: function() {
for (let i = 0; i < this._workspaces.length; i++) for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].setFullGeometry(this._fullGeometry); this._workspaces[i].setFullGeometry(this._fullGeometry);
},
_syncActualGeometry: function() {
for (let i = 0; i < this._workspaces.length; i++) for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].setActualGeometry(this._actualGeometry); this._workspaces[i].setActualGeometry(this._actualGeometry);
}, },
@ -147,25 +139,17 @@ const WorkspacesView = new Lang.Class({
return this._workspaces[active]; return this._workspaces[active];
}, },
animateToOverview: function(animationType) { zoomToOverview: function() {
for (let w = 0; w < this._workspaces.length; w++) { for (let w = 0; w < this._workspaces.length; w++)
if (animationType == AnimationType.ZOOM) this._workspaces[w].zoomToOverview();
this._workspaces[w].zoomToOverview();
else
this._workspaces[w].fadeToOverview();
}
this._updateWorkspaceActors(false); this._updateWorkspaceActors(false);
}, },
animateFromOverview: function(animationType) { zoomFromOverview: function() {
this.actor.remove_clip(); this.actor.remove_clip();
for (let w = 0; w < this._workspaces.length; w++) { for (let w = 0; w < this._workspaces.length; w++)
if (animationType == AnimationType.ZOOM) this._workspaces[w].zoomFromOverview();
this._workspaces[w].zoomFromOverview();
else
this._workspaces[w].fadeFromOverview();
}
}, },
syncStacking: function(stackIndices) { syncStacking: function(stackIndices) {
@ -276,12 +260,10 @@ const WorkspacesView = new Lang.Class({
} }
} }
if (this._fullGeometry) { if (this._fullGeometry)
this._updateWorkspaceActors(false); this._updateWorkspaceActors(false);
this._syncFullGeometry();
} this._syncGeometry();
if (this._actualGeometry)
this._syncActualGeometry();
}, },
_activeWorkspaceChanged: function(wm, from, to, direction) { _activeWorkspaceChanged: function(wm, from, to, direction) {
@ -366,30 +348,21 @@ const ExtraWorkspaceView = new Lang.Class({
this.actor.add_actor(this._workspace.actor); this.actor.add_actor(this._workspace.actor);
}, },
_setReservedSlot: function(window) { _setReservedSlot: function(clone) {
this._workspace.setReservedSlot(window); this._workspace.setReservedSlot(clone);
}, },
_syncFullGeometry: function() { _syncGeometry: function() {
this._workspace.setFullGeometry(this._fullGeometry); this._workspace.setFullGeometry(this._fullGeometry);
},
_syncActualGeometry: function() {
this._workspace.setActualGeometry(this._actualGeometry); this._workspace.setActualGeometry(this._actualGeometry);
}, },
animateToOverview: function(animationType) { zoomToOverview: function() {
if (animationType == AnimationType.ZOOM) this._workspace.zoomToOverview();
this._workspace.zoomToOverview();
else
this._workspace.fadeToOverview();
}, },
animateFromOverview: function(animationType) { zoomFromOverview: function() {
if (animationType == AnimationType.ZOOM) this._workspace.zoomFromOverview();
this._workspace.zoomFromOverview();
else
this._workspace.fadeFromOverview();
}, },
syncStacking: function(stackIndices) { syncStacking: function(stackIndices) {
@ -456,7 +429,7 @@ const WorkspacesDisplay = new Lang.Class({
this._workspacesViews = []; this._workspacesViews = [];
this._primaryScrollAdjustment = null; this._primaryScrollAdjustment = null;
this._settings = new Gio.Settings({ schema_id: OVERRIDE_SCHEMA }); this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
this._settings.connect('changed::workspaces-only-on-primary', this._settings.connect('changed::workspaces-only-on-primary',
Lang.bind(this, Lang.bind(this,
this._workspacesOnlyOnPrimaryChanged)); this._workspacesOnlyOnPrimaryChanged));
@ -481,16 +454,10 @@ const WorkspacesDisplay = new Lang.Class({
return this._getPrimaryView().actor.navigate_focus(from, direction, false); return this._getPrimaryView().actor.navigate_focus(from, direction, false);
}, },
show: function(fadeOnPrimary) { show: function() {
this._updateWorkspacesViews(); this._updateWorkspacesViews();
for (let i = 0; i < this._workspacesViews.length; i++) { for (let i = 0; i < this._workspacesViews.length; i++)
let animationType; this._workspacesViews[i].zoomToOverview();
if (fadeOnPrimary && i == this._primaryIndex)
animationType = AnimationType.FADE;
else
animationType = AnimationType.ZOOM;
this._workspacesViews[i].animateToOverview(animationType);
}
this._restackedNotifyId = this._restackedNotifyId =
Main.overview.connect('windows-restacked', Main.overview.connect('windows-restacked',
@ -499,15 +466,9 @@ const WorkspacesDisplay = new Lang.Class({
this._scrollEventId = Main.overview.connect('scroll-event', Lang.bind(this, this._onScrollEvent)); this._scrollEventId = Main.overview.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
}, },
animateFromOverview: function(fadeOnPrimary) { zoomFromOverview: function() {
for (let i = 0; i < this._workspacesViews.length; i++) { for (let i = 0; i < this._workspacesViews.length; i++)
let animationType; this._workspacesViews[i].zoomFromOverview();
if (fadeOnPrimary && i == this._primaryIndex)
animationType = AnimationType.FADE;
else
animationType = AnimationType.ZOOM;
this._workspacesViews[i].animateFromOverview(animationType);
}
}, },
hide: function() { hide: function() {
@ -637,9 +598,8 @@ const WorkspacesDisplay = new Lang.Class({
return; return;
let [x, y] = this.actor.get_transformed_position(); let [x, y] = this.actor.get_transformed_position();
let allocation = this.actor.allocation; let width = this.actor.allocation.x2 - this.actor.allocation.x1;
let width = allocation.x2 - allocation.x1; let height = this.actor.allocation.y2 - this.actor.allocation.y1;
let height = allocation.y2 - allocation.y1;
let primaryGeometry = { x: x, y: y, width: width, height: height }; let primaryGeometry = { x: x, y: y, width: width, height: height };
let monitors = Main.layoutManager.monitors; let monitors = Main.layoutManager.monitors;

View File

@ -45,7 +45,6 @@ mk
mr mr
ms ms
nb nb
ne
nl nl
nn nn
or or

View File

@ -6,13 +6,11 @@ data/gnome-shell.desktop.in.in
data/gnome-shell-extension-prefs.desktop.in.in data/gnome-shell-extension-prefs.desktop.in.in
data/gnome-shell-wayland.desktop.in.in data/gnome-shell-wayland.desktop.in.in
data/org.gnome.shell.gschema.xml.in.in data/org.gnome.shell.gschema.xml.in.in
data/org.gnome.Shell.PortalHelper.desktop.in
js/extensionPrefs/main.js js/extensionPrefs/main.js
js/gdm/authPrompt.js js/gdm/authPrompt.js
js/gdm/loginDialog.js js/gdm/loginDialog.js
js/gdm/util.js js/gdm/util.js
js/misc/util.js js/misc/util.js
js/portalHelper/main.js
js/ui/appDisplay.js js/ui/appDisplay.js
js/ui/appFavorites.js js/ui/appFavorites.js
js/ui/backgroundMenu.js js/ui/backgroundMenu.js
@ -57,7 +55,6 @@ js/ui/unlockDialog.js
js/ui/viewSelector.js js/ui/viewSelector.js
js/ui/windowAttentionHandler.js js/ui/windowAttentionHandler.js
js/ui/windowManager.js js/ui/windowManager.js
js/ui/windowMenu.js
src/calendar-server/evolution-calendar.desktop.in.in src/calendar-server/evolution-calendar.desktop.in.in
# Please do not remove this file from POTFILES.in. Run "git submodule init && git submodule update" to get it. # Please do not remove this file from POTFILES.in. Run "git submodule init && git submodule update" to get it.
src/gvc/gvc-mixer-control.c src/gvc/gvc-mixer-control.c

1794
po/af.po

File diff suppressed because it is too large Load Diff

1015
po/ar.po

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More