Compare commits

..

21 Commits

Author SHA1 Message Date
bf374ccabb nn 2014-06-03 13:51:59 -04:00
02060d2bbc nnn 2014-06-03 13:51:58 -04:00
8750f1edc0 drawer 2014-06-03 13:51:58 -04:00
798f17a97d kill tray 2014-06-03 13:51:57 -04:00
a4091adbf2 system tray elsewhere 2014-06-03 13:51:57 -04:00
ecf795b6ef reveal 2014-06-03 13:51:56 -04:00
75447b249c adjust timeout animation 2014-06-03 13:51:56 -04:00
26d2fb8a37 messageTray: Add a new message tray indicator 2014-06-03 13:51:55 -04:00
f7223763d2 messageTray: Add an indicatorCount property to the tray
So we don't have to do the property tracking here...
2014-06-03 13:51:55 -04:00
0b414308fb telepathyClient: Use a revealer for new messages in Telepathy as well 2014-06-03 13:51:55 -04:00
060917ae2b messageTray: Add a Revealer widget and use it to animate the notification in/out 2014-06-03 13:51:53 -04:00
9f2e5b9b51 messageTray: Glue the notification to the bottom of the screen, always
We'll animate notifications popping up with another system soon enough,
instead. The idea here is that instead of carefully animating the Y
position of the notificationWidget when a notification updates, we
simply animate the height of the new actor inside the notification.
This will fix some of the awkward updates where instead of the
notification content expanding, we see the buttons or action area
pushed off the edge of the screen...

Animations that happen as a result of adding something new to the
notification or expanding it should be done by tweeing the new actors
in inside the notification.
2014-06-03 13:30:46 -04:00
4a07eb77f6 messageTray: Restyle notifications 2014-06-03 13:30:45 -04:00
fbe379c81c messageTray: Considerably rework how layout is done in notifications
Use a series of nested BoxLayouts, Bins, and more instead of an StTable
and a custom ShellGenericContainer, and hacky style classes.

This also removes the customContent parameter in favor of subclasses
setting the child of this._bodyBin instead.

We lose a few of the fancy features like showing the first part of
the body, ellipsized, next the banner when it will fit, and other
layout logic. But since the layout of notifications is changing
substantially anyways, I don't feel too bad...
2014-06-03 13:30:16 -04:00
a07e8bbf37 messageTray: Remove addBody as a public API
As it's unused.
2014-06-03 13:30:16 -04:00
a6aabb1d3a messageTray: Remove support for notifications with images
This sufficiently complicates the code, and won't fit in the
new design.
2014-06-03 13:30:15 -04:00
aef6273fed messageTray: Remove support for resident notifications
Now the only resident notification is a chat notification. The convenient
thing about this special-case behavior is that there's already special-case
code for it and the shell, and we always know that a chat notification will
always be 1:1 with its chat source.
2014-06-03 13:30:15 -04:00
be8b1c7d2d notificationDaemon: Remove support for resident notifications
They're not really an API that has caught on, and not really one
we want to support, either.
2014-06-03 13:30:15 -04:00
14bc748cea notificationDaemon: Remove the special-case hack for system tray icons
Nothing in the system actually has a standard system tray icon anymore,
so this hack isn't necessary.
2014-06-03 13:30:15 -04:00
c32917f6c1 telepathyClient: Remove all the fancy features
This can be done with another app, like Empathy or Chat.
2014-06-03 12:32:56 -04:00
182d45dace autorunManager: Remove the resident "Removable Devices" notification
Users aren't usually the best at obeying the rules, and systems can
deal with hotplug without ejecting first.

https://bugzilla.gnome.org/show_bug.cgi?id=719857
2014-06-03 12:32:56 -04:00
367 changed files with 74604 additions and 105252 deletions

17
.gitignore vendored
View File

@ -16,18 +16,18 @@ config.log
config.status
config
configure
data/org.gnome.Shell.desktop
data/org.gnome.Shell.desktop.in
data/50-gnome-shell-*.xml
data/gnome-shell.desktop
data/gnome-shell.desktop.in
data/gnome-shell-wayland.desktop
data/gnome-shell-wayland.desktop.in
data/gnome-shell-extension-prefs.desktop
data/gnome-shell-extension-prefs.desktop.in
data/gnome-shell-theme.gresource
data/gschemas.compiled
data/perf-background.xml
data/org.gnome.shell.gschema.xml
data/org.gnome.shell.gschema.valid
data/org.gnome.Shell.PortalHelper.desktop
data/org.gnome.Shell.PortalHelper.service
data/theme/.sass-cache
data/org.gnome.shell.evolution.calendar.gschema.xml
data/org.gnome.shell.evolution.calendar.gschema.valid
docs/reference/*/*.args
docs/reference/*/*.bak
docs/reference/*/*.hierarchy
@ -71,6 +71,7 @@ src/*-marshal.[ch]
src/Makefile
src/Makefile.in
src/calendar-server/evolution-calendar.desktop
src/calendar-server/evolution-calendar.desktop.in
src/calendar-server/org.gnome.Shell.CalendarServer.service
src/gnome-shell
src/gnome-shell-calendar-server
@ -79,9 +80,7 @@ src/gnome-shell-extension-tool
src/gnome-shell-hotplug-sniffer
src/gnome-shell-perf-helper
src/gnome-shell-perf-tool
src/gnome-shell-portal-helper
src/hotplug-sniffer/org.gnome.Shell.HotplugSniffer.service
src/org-gtk-application.[ch]
src/run-js-test
src/test-recorder
src/test-recorder.ogg

3
.gitmodules vendored
View File

@ -1,6 +1,3 @@
[submodule "src/gvc"]
path = src/gvc
url = git://git.gnome.org/libgnome-volume-control
[submodule "data/theme/gnome-shell-sass"]
path = data/theme/gnome-shell-sass
url = git://git.gnome.org/gnome-shell-sass

840
NEWS
View File

@ -1,843 +1,3 @@
3.22.1
======
* Fix hidden network indicator on startup [Florian; #772249]
* Fix order of windows with modal dialogs in window switcher [Florian; #747153]
* Fix feedback loop between StClipboard and X11 bridge [Carlos; #760745]
* Reliably match windows from Flatpak apps [Florian; #772615]
* Misc. bug fixes [Philip; #742249]
Contributors:
Philip Chimento, Carlos Garnacho, Florian Müllner
Translations:
Inaki Larranaga Murgoitio [eu], Khaled Hosny [ar], BM [uz@cyrillic],
Milo Casagrande [it], Cheng-Chia Tseng [zh_TW], gogo [hr]
3.22.0
======
* Misc. bug fixes [Florian, Rui; #771391, #771536] #771656]
Contributors:
Rui Matos, Florian Müllner
Translations:
Ask Hjorth Larsen [da], GNOME Translation Robot [gd], Alexandre Franke [fr],
Daniel Korostil [uk], Jordi Mas [ca], Khaled Hosny [ar], David King [en_GB]
3.21.92
=======
* Adjust screen capture to work with multiple stage views [Jonas; #770128]
* Improve handling of cycle shortcuts [Florian; #771063]
* Fix windows not getting undimmed in some cases [Rui; #770163, #752524]
* Disable extension version check by default [Florian; #770887]
* Misc. bug fixes [Rui, Florian, Michael; #770382, #770888, #770328]
Contributors:
Jonas Ådahl, Michael Catanzaro, Fran Dieguez, Olivier Fourdan, Rui Matos,
Florian Müllner
Translations:
Changwoo Ryu [ko], Baurzhan Muftakhidinov [kk], Aurimas Černius [lt],
Muhammet Kara [tr], Trần Ngọc Quân [vi], A S Alam [pa], Yosef Or Boczko [he],
Anders Jonsson [sv], Tiago Santos [pt], Hannie Dumoleyn [nl],
Rūdolfs Mazurs [lv], Claude Paroz [fr], Arash Mousavi [fa],
Fran Dieguez [gl], Stas Solovey [ru], Tom Tryfonidis [el]
3.21.91
=======
Translations:
Mario Blättermann [de], Jiri Grönroos [fi], Dušan Kazik [sk],
Andika Triwidada [id], Daniel Mustieles [es], Fabio Tomat [fur],
Enrico Nicoletto [pt_BR], Matej Urbančič [sl], Мирослав Николић [sr, sr@latin]
3.21.90.1
=========
Contributors:
Piotr Drąg
Translations:
Marek Černocký [cs], Balázs Úr [hu]
3.21.90
=======
* Improve on-screen keyboard on wayland [Carlos; #765009]
* Misc. bug fixes [Florian; #769156, #769216, #769074]
Contributors:
Carlos Garnacho, Florian Müllner
Translations:
Fabio Tomat [fur], Tiago Santos [pt], Daniel Mustieles [es],
Bernd Homuth [de], Aurimas Černius [lt], Balázs Úr [hu],
Yosef Or Boczko [he], Jiri Grönroos [fi], Marek Cernocky [cs],
Muhammet Kara [tr], Enrico Nicoletto [pt_BR], Andika Triwidada [id]
3.21.4
======
* overview: Fix switching workspaces when scrolling on non-primary monitors
[Florian; #766883, #768316]
* Fix crash when using screen recorder under wayland [Rui; #767001]
* Update theme on video memory purge errors [Rui; #739178]
* Free old backgrounds immediately [Hyungwon; #766353]
* Add support for system upgrades to end session dialog [Kalev; #763611]
* Fix maximized windows flickering to the wrong size on restart [Owen; #761566]
* Hide ignored events in calendar as well [Florian; #768538]
* calendar: Only hide dismissed occurrence of recurring event [Florian; #748226]
* Provide org.freedesktop.impl.portal.access implementation [Florian; #768669]
* Misc. bug fixes and cleanups [Rui, Florian, Marinus, Jonas; #767954, #768317,
#746867, #762206, #768956, #768979]
Contributors:
Jonas Ådahl, Piotr Drąg, Hyungwon Hwang, Kalev Lember, Rui Matos,
Florian Müllner, Marinus Schraal, Owen W. Taylor
Translations:
Andika Triwidada [id], Daniel Mustieles [es], Bruce Cowan [en_GB],
Dušan Kazik [sk], Piotr Drąg [pl], Chao-Hsiung Liao [zh_HK]
3.21.3
======
* Do not disable suspend action when locked [Florian; #725960]
* Remember input sources MRU list [Cosimo; #766826]
* networkAgent: Handle VPN service aliases [David; #658484]
* Plug a memory leak [Hans; #710230]
Contributors:
Cosimo Cecchi, Florian Müllner, Hans Petter Jansson, David Woodhouse
Translations:
Tiago Santos [pt], Cédric Valmary [oc], Muhammet Kara [tr],
Daniel Mustieles [es], Rafael Fontenelle [pt_BR]
3.21.2
======
* Fix sorting of hidden apps in app switcher [Florian; #766238]
* Set logind's LockedHint property when locked [Victor; #764773]
* Allocate framebuffers early to fix a crash on NVIDIA [Martin; #764898]
* Fix cycle-windows/cycle-group keybindings [Florian; #730739]
* Switch to shared desktop schema for calendar settings [Iain; #766318]
* Misc. bug fixes [Florian, Cosimo, Michele; #766325, #758471, #757556,
#757019, #766598]
Contributors:
Cosimo Cecchi, Michele Gaio, Iain Lane, Florian Müllner, Martin Szulecki,
Victor Toso
Translations:
Tiago Santos [pt], Kjartan Maraas [nb], Jiro Matsuzawa [ja],
Cédric Valmary [oc], Sveinn í Felli [is]
3.21.1
======
* Save screencasts in HOME if XDG_VIDEO_DIR doesn't exist [Florian; #765015]
* Don't show orientation lock when g-s-d won't rotate [Florian; #765267]
* Misc. bug fixes [Heiher, Florian, Marek, Rui; #722752, #765061, #763068,
#765607, #757676, #760439]
Contributors:
Heiher, Marek Chalupa, Rui Matos, Florian Müllner
Translations:
Arash Mousavi [fa], Kristjan SCHMIDT [eo], GNOME Translation Robot [gd]
3.20.1
======
* Plug a memory leak [Aaron; #735705]
Contributors:
Aaron Plattner
Translations:
Daniel Korostil [uk], Matej Urbančič [sl], Inaki Larranaga Murgoitio [eu],
Cheng-Chia Tseng [zh_TW], Fabio Tomat [fur], Trần Ngọc Quân [vi],
YunQiang Su [zh_CN], Marek Černocký [cs], Arash Mousavi [fa],
Alexander Shopov [bg], Khaled Hosny [ar]
3.20.0
======
Translations:
Changwoo Ryu [ko], Baurzhan Muftakhidinov [kk], Milo Casagrande [it],
Anders Jonsson [sv], Muhammet Kara [tr], Alexandre Franke [fr],
Rūdolfs Mazurs [lv], Ask Hjorth Larsen [da], Jiro Matsuzawa [ja]
3.19.92
=======
* Update location dialog according to latest mockups [Zeeshan; #762480]
* Fix deleting chat notifications in calendar [Florian; #747991]
Contributors:
Zeeshan Ali (Khattak), Florian Müllner
Translations:
Rūdolfs Mazurs [lv], Changwoo Ryu [ko], Matej Urbančič [sl],
Justin van Steijn [nl], Fabio Tomat [fur], Kris Thomsen [da],
Marek Černocký [cs], Piotr Drąg [pl], Dušan Kazik [sk],
Мирослав Николић [sr, sr@latin], Balázs Úr [hu], Yosef Or Boczko [he],
Daniel Mustieles [es], Fran Dieguez [gl], Bernd Homuth [de],
Tom Tryfonidis [el], Jiri Grönroos [fi], Gil Forcada [ca],
Artur Morais [pt_BR], Aurimas Černius [lt], Stas Solovey [ru]
3.19.91
=======
* location: Ask user only once [Zeeshan; #762559]
* Fix jiggling when auto-hiding legacy tray [Florian; #747957]
* Misc. bug fixes [Florian, Michael, Ting-Wei; #762475, #762507, #755659]
Contributors:
Zeeshan Ali (Khattak), Michael Catanzaro, Ting-Wei Lan, Florian Müllner
Translations:
Мирослав Николић [sr, sr@latin], Piotr Drąg [pl], A S Alam [pa],
Artur de Aquino Morais [pt_BR], Daniel Mustieles [es],
Chao-Hsiung Liao [zh_TW], Daniel Korostil [uk], Fran Dieguez [gl],
Tom Tryfonidis [el], Bernd Homuth [de], Sebastian Rasmussen [sv],
Jordi Mas [ca], Piotr Drąg [ga], Cédric Valmary [oc], Gábor Kelemen [hu],
Baurzhan Muftakhidinov [kk], Friedel Wolff [af], Marek Černocký [cs],
Mingye Wang (Arthur2e5) [zh_CN], Aron Xu [zh_CN], Khaled Hosny [ar],
Aurimas Černius [lt], Stas Solovey [ru], Yosef Or Boczko [he]
3.19.90
=======
* Correctly identify VPN secret requests [Lubomir; #760999]
* Improve week number presentation [Jakub; #683245]
* Add audio device selection dialog [Florian; #760284]
* Add media controls to the time and date drop down [Florian; #756491]
* Fix IBus candidate popup position under wayland [Rui; #753476]
* Ask user to grant applications access to location [Zeeshan; #762119]
* Misc. bug fixes [Mario, Jakub, Florian; #761208, #761772, #762270]
Contributors:
Zeeshan Ali (Khattak), Michael Catanzaro, Rui Matos, Florian Müllner,
Lubomir Rintel, Mario Sanchez Prada, Jakub Steiner
Translations:
Alexander Shopov [bg], Balázs Meskó [hu], Fabio Tomat [fur],
Dušan Kazik [sk], Piotr Drąg [pl], Alexandre Franke [fr],
Mario Blättermann [de], Milo Casagrande [it], Jordi Mas [ca]
3.19.4
======
* gdm: Do not allow bypassing disabled Sign In button [Michael; #746180]
* Style week numbers in calendar [Jakub; #683245]
* Misc. bug fixes [Christophe, Jakub, Rui; #759708, #760577, #760945]
Contributors:
Michael Catanzaro, Marek Černocký, Christophe Fergeau, Rui Matos,
Jakub Steiner
Translations:
Aurimas Černius [lt], Enrico Nicoletto [pt_BR], Andika Triwidada [id],
Mario Blättermann [de], Marek Černocký [cs], Kjartan Maraas [nb],
Muhammet Kara [tr], Stas Solovey [ru]
3.19.3
======
* Fix thumbnail scaling in window switcher on HiDPI [Florian; #758676]
* Update animated backgrounds on timezone changes [Florian; #758939]
* loginDialog: Update user list on user changes [Michael; #758568]
* Fix touch interaction on wayland [Carlos; #756748]
Contributors:
Michael Catanzaro, Carlos Garnacho, Kalev Lember, Florian Müllner
Translations:
Daniel Korostil [uk], Muhammet Kara [tr], Dušan Kazik [sk],
Baurzhan Muftakhidinov [kk], Marek Černocký [cs]
3.19.2
======
* Make gnome-shell DBus activatable [Ray; #741666]
* Fix browser plugin crash in Firefox [Carlos; #737932, #757940]
* Optionally show battery percentage in system status area [Bastien; #735771]
* Misc. bug fixes [Kalev, Florian, Bastien; #757418, #757668, #757779, #757816,
#745626, #758220]
Contributors:
Michael Biebl, Michael Catanzaro, Piotr Drąg, Carlos Garcia Campos,
Kalev Lember, Florian Müllner, Bastien Nocera, Ray Strode
Translations:
Pedro Albuquerque [pt], liushuyu [zh_CN], Yosef Or Boczko [he],
Jiri Grönroos [fi], Kjartan Maraas [nb], GNOME Translation Robot [gd],
Daniel Mustieles [es], Marek Černocký [cs], Kristjan SCHMIDT [eo],
Stas Solovey [ru]
3.19.1
======
* Respect text-scaling factor under wayland [Owen; #756447]
* Show the Bluetooth submenu when there were setup devices [Bastien; #723848]
* Misc. bug fixes [Florian, Cosimo, Rui, Ray, Owen, Jakub, Bastien;
#756697, #756714, #756605, #754814, #738942, #756983, #756925,
#757011, #673235, #757150]
Contributors:
Cosimo Cecchi, Rui Matos, Florian Müllner, Bastien Nocera, Jakub Steiner,
Ray Strode, Owen W. Taylor
Translations:
Kjartan Maraas [nb], Khaled Hosny [ar], Balázs Meskó [hu],
Daniel Șerbănescu [ro], Marek Černocký [cs]
3.18.1
======
* Fix screen freezes when a notification is pushed [Carlos; #755425]
* Fix overzealous ellipsization in system status menu [Adel, Florian; #708472]
* Hide app menu when disabled by setting [Florian; #745919]
* Fix lightbox effect when animations are disabled [Rui; #755827]
* Do not mark hotplug notifications as critical [Florian; #657923]
* Fix icons getting cut off in dash [Florian; #745649]
* Animate fullscreen/unfullscreen operations [Cosimo; #707248]
* Misc. bug fixes [Florian, Owen; #748919, #674799, #754581]
Contributors:
Emmanuele Bassi, Michael Catanzaro, Cosimo Cecchi, Matthias Clasen,
Adel Gadllah, Carlos Garnacho, Ekaterina Gerasimova, Rui Matos,
Florian Müllner, Owen W. Taylor
Translations:
Марко Костић [sr], Милош Поповић [sr@latin], Khaled Hosny [ar],
Trần Ngọc Quân [vi], Petr Kovar [cs], Alexandre Franke [fr],
Fran Dieguez [gl], Anders Jonsson [sv], Piotr Drąg [pl], Dušan Kazik [sk],
Milo Casagrande [it], Changwoo Ryu [ko], Stas Solovey [ru],
Rafael Fontenelle [pt_BR], Tom Tryfonidis [el], Aurimas Černius [lt],
Seán de Búrca [ga], Christian Kirbach [de], Jiri Grönroos [fi],
Pedro Albuquerque [pt], Baurzhan Muftakhidinov [kk], Daniel Mustieles [es],
Marek Černocký [cs], Ask Hjorth Larsen [da], Inaki Larranaga Murgoitio [eu]
3.18.0
======
Translations:
Sendy Aditya Suryana [id], Kris Thomsen [da], Seán de Búrca [ga],
Andika Triwidada [id], Enrico Nicoletto [pt_BR], Anders Jonsson [sv],
Rūdolfs Mazurs [lv]
3.17.92
=======
* Fix race when loading multiple background animations [Josselin; #741453]
Contributors:
Michael Biebl, Josselin Mouette, Florian Müllner
Translations:
Baurzhan Muftakhidinov [kk], Changwoo Ryu [ko], Christian Kirbach [de],
Kjartan Maraas [nb], Jiri Grönroos [fi], Arash Mousavi [fa],
Jiro Matsuzawa [ja], Marek Černocký [cs], Milo Casagrande [it]
3.17.91
=======
* Fix login screen spinner causing wakeups while VT-switched away
[Ray, Rui; #753891]
* Fix scrolling of user list on login screen [Florian; #754525]
Contributors:
Piotr Drąg, Rui Matos, Florian Müllner, Ray Strode
Translations:
Dušan Kazik [sk], Jordi Mas [ca], Aurimas Černius [lt], Stas Solovey [ru],
Piotr Drąg [pl], Pedro Albuquerque [pt], Daniel Mustieles [es],
Chao-Hsiung Liao [zh_TW], Muhammet Kara [tr], Fran Dieguez [gl],
Hannie Dumoleyn [nl], Yosef Or Boczko [he], Tom Tryfonidis [el],
A S Alam [pa], Balázs Úr [hu], Alexandre Franke [fr], Frédéric Péters [fr]
3.17.90
=======
* Avoid caret/focus viewport changes during pointer movement [Rui; #752138]
* Match GTK+'s modal dialogs for system modal dialogs [Carlos; #746108]
* Refine message list style [Florian; #749958]
* Fix type-ahead behavior for backspace and compose key [Rui; #753319, #753320]
* Refine the system status menu [Florian; #751377]
* Misc. bug fixes and cleanups [Bastien, Ray, Florian, Jakub; #752779, #752739,
#741366, #651503, #753064, #753181, #752881]
Contributors:
Rui Matos, Florian Müllner, Bastien Nocera, Carlos Soriano, Jakub Steiner,
Ray Strode, Rico Tzschichholz
Translations:
Marek Černocký [cs], Kjartan Maraas [nb], Jordi Mas [ca], Muhammet Kara [tr],
Enrico Nicoletto [pt_BR]
3.17.4
======
* Fix fuzziness of app menu icon [Jakub; #747932]
* Implement 4 finger swipe gesture for touchpads [Carlos; #752250]
* Misc. bug fixes [Florian, Alexandre, Piotr, Ray, Mario; #751921, #659969,
#752438, #752675]
Contributors:
Piotr Drąg, Alexandre Franke, Carlos Garnacho, Florian Müllner,
Mario Sanchez Prada, Jakub Steiner, Jasper St. Pierre, Ray Strode
Translations:
Benjamin Steinwender [de], Pedro Albuquerque [pt], Fabio Tomat [fur],
Matej Urbančič [sl], Daniel Mustieles [es], Yosef Or Boczko [he],
Daniel Martinez [an]
3.17.3
======
* Handle touch events in OSK on wayland [Rui; #750287]
* Reinstate left/right movement to window menu [Ron; #751344]
* Allow extensions to disable "Window is ready" notification [Adel; #748846]
* Misc. bug fixes [Watson, Michael, Ray, Rui, Florian, Cosimo; #750465,
#751016, #751517, #750714, #751541, #751599]
Contributors:
Michael Biebl, Cosimo Cecchi, Adel Gadllah, Rui Matos, Florian Müllner,
Ray Strode, Wim Taymans, Ron Yorston, Watson Yuuma Sato
Translations:
Sebastian Rasmussen [sv], Dimitris Spingos [el], Muhammet Kara [tr],
Stas Solovey [ru], Benjamin Steinwender [de], Balázs Úr [hu],
Victor Ibragimov [tg], Dušan Kazik [sk], Pedro Albuquerque [pt]
3.17.2
======
* Remove StTable widget [Florian; #703833]
* Increase visibility of expanders in alt-tab popup [Jakub; #745058]
* Ensure suspend inhibitors are released when VT switched away [Rui; #749228]
* Use iio-sensor-proxy directly for orientation lock [Bastien; #749671]
* Misc. bug fixes [Florian, Lan, Carlos; #749279, #749383, #749529, #749490,
#749742]
Contributors:
Carlos Garnacho, Ting-Wei Lan, Rui Matos, Florian Müllner, Bastien Nocera,
Jakub Steiner
Translations:
Yosef Or Boczko [he], sun [zh_CN], Felipe Braga [pt_BR],
Victor Ibragimov [tg], Gábor Kelemen [hu], Cédric Valmary [oc],
Dušan Kazik [sk], Kjartan Maraas [nb], Bruno Ramalhete [pt],
Matej Urbančič [sl], Daniel Mustieles [es]
3.17.1
======
* Add Display Settings entry to background menu [Meet; #697346]
* Add window menu option to move to different monitor [Isaac; #633994]
* Improve switch style in default/highContrast themes [Jakub; #746294, #747912]
* Make event highlight in calendar more prominent [Jakub; #747715]
* Fix keyboard focus when focusing a notification banner [Florian; #747205]
* Move notification banners below the dateMenu [Meet, Florian; #745910]
* Misc. bug fixes [Mario, Rui; #748338, #748541]
Contributors:
Isaac Ge, Rui Matos, Florian Müllner, Meet Parikh, Mario Sanchez Prada,
Jakub Steiner, Jasper St. Pierre
Translations:
Sveinn í Felli [is], Marek Černocký [cs], laurent Soleil [oc]
3.16.1
======
* gdm: Move long session chooser menus to the side [Florian; #734352]
* Work around background corruption with NVIDIA driver [Rui; #739178]
* Don't allow move-to-workspace for always-sticky windows [Florian; #746782]
* Allow switching workspaces with PgUp/PgDown in overview [Devyani; #742581]
* Bump time PAM messages are displayed [Sarvjeet; #720885]
* Fix "stutter" when moving window past the last workspace [Shivam; #712778]
* Fix blurred text on login screen [Clément; #746912]
* keyboard: Restore whole MRU list after password mode [Rui; #746605]
* Pass event timestamps when activating remote actions [Owen; #747323]
* Fix hung login screen when password is typed too quickly [Shivam; #737586]
* Make on-screen keyboard work for shell chrome on wayland [Rui; #747274]
* Implement reexec_self() for FreeBSD [Ting-Wei; #747788]
* Allow to dismiss resident notifications [Florian; #746860]
* Temporarily reveal legacy tray when icons are added [Florian; #746025]
* Make concealed tray smaller to minimize overlap with apps [Florian; #746787]
* Misc. bug fixes [Florian, Rui, Giovanni; #746323, #746579, #746902, #746364,
#746509, #747636]
Contributors:
Sarvjeet, Giovanni Campagna, Adel Gadllah, Clément Guérin, Devyani Kota,
Ting-Wei Lan, Rui Matos, Shivam Mishra, Florian Müllner, Owen W. Taylor
Translations:
Khaled Hosny [ar], Dušan Kazik [sk], Yuri Myasoedov [ru], Stas Solovey [ru],
Hannie Dumoleyn [nl], Rūdolfs Mazurs [lv]
3.16.0
======
* Revert erroneous login dialog changes [Ray; #740142]
* Improve accessibility of legacy tray [Florian; #746487]
* Fix legacy status icons leaking into other monitors [Florian; #745824]
Contributors:
Florian Müllner, Ray Strode
Translations:
Daniel Martinez [an], Sebastian Rasmussen [sv], Fran Dieguez [gl],
Andika Triwidada [id], Jordi Mas [ca], Kjartan Maraas [nb],
Inaki Larranaga Murgoitio [eu], Muhammet Kara [tr], Khaled Hosny [ar],
Bernd Homuth [de], Jiro Matsuzawa [ja]
3.15.92
=======
* gdm: Fix user list accessibility [Florian; #729603]
* Handle multiline questions in mount operations [Ross; #745713]
* Improve classic theme [Jakub; #745686, #745687]
* Fix ordering of calendar events [Florian; #745988]
* Pick first input source for new windows when per-window [Rui; #746037]
* networkAgent: Show a notification for non-user-initiated password requests
[Giovanni; #660293]
* Fix dismissing calendar events [Florian; #744927]
* Add legacy tray to ctrl-alt-tab popup [Florian; #746022]
* Manage on-screen-keyboard visibility in gnome-shell [Carlos; #745977]
* Add pointer barriers to legacy tray [Cosimo; #746026]
* Use fallback when app icon cannot be resolved [Cosimo; #746219]
* Fix handling of removed smartcard at startup [Ray; #740143]
* gdm: Don't pick a random session for the user [Jasper; #740142]
* Make menu selection behavior consistent with GTK [Florian; #745246]
* gdm: Fix empty user list on user switching [Ray; #719418]
* Misc bug fixes [Florian, Giovanni, Clément, Rui; #745666, #746019, #745861,
#746027, #746223, #737502, #746343, #746288]
Contributors:
Giovanni Campagna, Cosimo Cecchi, Piotr Drąg, Adel Gadllah, Carlos Garnacho,
Clément Guérin, Ross Lagerwall, Rui Matos, Florian Müllner, Jakub Steiner,
Jasper St. Pierre, Ray Strode
Translations:
Piotr Drąg [pl], Changwoo Ryu [ko], Milo Casagrande [it],
Baurzhan Muftakhidinov [kk], Мирослав Николић [sr, sr@latin], Balázs Úr [hu],
IWAI, Masaharu [ja], Daniel Korostil [uk], Aurimas Černius [lt],
Matej Urbančič [sl], Daniel Mustieles [es], Kjartan Maraas [nb],
Victor Ibragimov [tg], Claude Paroz [fr], Jordi Mas [ca], Bernd Homuth [de],
Muhammet Kara [tr], Frédéric Péters [fr], Jiri Grönroos [fi],
Alexander Shopov [bg], Stas Solovey [ru], Trần Ngọc Quân [vi],
Samir Ribic [bs], Dušan Kazik [sk], Enrico Nicoletto [pt_BR],
Marek Černocký [cs], A S Alam [pa], Ask Hjorth Larsen [da],
Tom Tryfonidis [el], Alexandre Franke [fr], Yosef Or Boczko [he],
Chao-Hsiung Liao [zh_TW]
3.15.91
=======
* Don't disable all shortcuts while non-panel menus are open [Florian; #745039]
* Do not wake up the screen for disabled notifications [Florian; #744114]
* Add unminimize animation [Florian; #702662]
* Change default shortcut for viewing notifications [Florian; #687986]
* Add shortcut to dismiss notifications from list [Florian; #745279]
* Use Polari instead of Empathy for IRC conversations [Giovanni; #745431]
* Add a hideable bottom tray for legacy status icons [Florian; #745162]
* Improve accessibility of calendar/message list [Florian; #706903, #745393]
* Fix window thumbnail scaling in overview [Sebastian; #744883]
* Stop handling non-chat notifications for Empathy [Giovanni; #745503]
* Fix mouse interaction with ibus candidate window [Rui; #745167, #745245]
* Misc bug fixes and cleanups [Giovanni, Florian, Miguel, Cosimo, Jakub,
Michele, Raul, Matthias, Rui; #677412, #744880, #744900, #744894, #744907,
#745061, #741111, #744912, #745175, #745246, #744959, #744575, #745570,
#652742, #659187, #745412, #745521, #745521, #741665, #745574, #745627,
#745494, #745111, #745132, #745110]
Contributors:
Michele, Giovanni Campagna, Cosimo Cecchi, Matthias Clasen,
Raul Gutierrez Segales, Sebastian Keller, David Liang, Rui Matos,
Florian Müllner, Yosef Or Boczko, Jakub Steiner, Jasper St. Pierre,
Rico Tzschichholz, Miguel Vaello Martínez
Translations:
Dušan Kazik [sk], Chao-Hsiung Liao [zh_TW], Muhammet Kara [tr],
Balázs Úr [hu], Daniel Mustieles [es], Frédéric Péters [fr],
Rafael Ferreira [pt_BR], Aurimas Černius [lt], Milo Casagrande [it],
Yosef Or Boczko [he], Stas Solovey [ru], Baurzhan Muftakhidinov [kk],
Daniel Korostil [uk], Fran Dieguez [gl], Kjartan Maraas [nb],
Tom Tryfonidis [el], Cheng-Chia Tseng [zh_TW], Friedel Wolff [af],
Alexandre Franke [fr], Efstathios Iosifidis [el], Aron Xu [zh_CN],
Marek Černocký [cs], Enrico Nicoletto [pt_BR]
3.15.90
=======
* gdm: Fix reactivity of first user in user list [Ray; #743370]
* Prevent DND to dash when favorites are locked down [David; #741325]
* Prevent DND in app picker when favorites are locked down [Murray; #741325]
* Implement Display panel's OSD monitor labels in the shell [Rui; #743744]
* Remove GSystem dependency [Colin; #744457]
* Do not duplicate "New Window" action in dash [Florian; #744446]
* Fix 'draw-cursor' option of screen recorder [Alexander; #744599]
* Fix screencast timestamps [Sebastian; #744642]
* Allow keybindings for switching to VT8-VT12 [Ray; #744800]
* Implement notification redesign [Florian; #744498, #744815, #744817, #744850]
* Fix struts computation of chrome on non-primary monitors [Sylvain; #744183]
* Visual refresh based on GTK+ theme redesign [Jakub, Carlos; #737785, #744680]
* Misc. bug fixes and cleanups [Ray, Bastien, Cosimo, Rui, Florian; #743371,
#736182, #744013, #743993, #744665]
Contributors:
Cosimo Cecchi, Murray Cumming, Sebastian Dröge, David King,
Alexander Larsson, Rui Matos, Florian Müllner, Bastien Nocera,
Sylvain Pasche, Carlos Soriano, Jakub Steiner, Jasper St. Pierre, Ray Strode,
Colin Walters
Translations:
Daniel Martinez [an], Sveinn í Felli [is], GNOME Translation Robot [de],
Yosef Or Boczko [he], Kristjan SCHMIDT [eo], Dušan Kazik [sk],
Andika Triwidada [id], Marek Černocký [cs], Muhammet Kara [tr],
Matej Urbančič [sl], Milo Casagrande [it], Anders Jonsson [sv]
3.15.4
======
* Add mode parameter to AcceleratorActivated signal [Florian; #711682]
* Fix PID based window/app association [Sebastian; #736527]
* Fix current day highlight on day change [Sebastian; #742492]
* Switch to vp9 for screencast recordings [Adel; #742744]
* Disable IBus input sources on password entries [Takao; #730628]
* Make slider scrolling smoother [Adel; #742648]
* Allow move-up shortcut to move window above top workspace [Florian; #665764]
* Misc. bug fixes [Adel, Rui; #742748, #742824, #741114]
Contributors:
Cosimo Cecchi, Takao Fujiwara, Adel Gadllah, Sebastian Keller, Rui Matos,
Florian Müllner, Jasper St. Pierre
Translations:
Andika Triwidada [id], Matej Urbančič [sl], Saibal Ray [bn_IN],
Inaki Larranaga Murgoitio [eu], Stas Solovey [ru], Kjartan Maraas [nb],
Balázs Úr [hu], Marek Černocký [cs], Rafael Ferreira [pt_BR],
Bernd Homuth [de], Daniel Mustieles [es], Fabio Tomat [fur]
3.15.3
======
* Add support for high-contrast themes [Florian; #740447]
* Fix banner message on login screen without user list [Ray; #703972]
* Fix flicker when activating windows on another workspace [Florian; #741680]
* Misc. bug fixes [Giovanni, Florian; #735308, #740237]
Contributors:
Giovanni Campagna, Florian Müllner, Jasper St. Pierre, Ray Strode
Translations:
Balázs Úr [hu], Josef Andersson [sv], Muhammet Kara [tr],
Baurzhan Muftakhidinov [kk], Inaki Larranaga Murgoitio [eu]
3.15.2
======
* Fix visual glitch of window preview outline in overview [Chris; #699044]
* Change user facing name of "Captive Portal" to "Network Login" [Elad; #737198]
* Port to Python 3 [Slavek; #732478]
* Hide Airplane mode indicator when g-s-d says so [Cosimo; #736292]
* Allow translators to change non-work days [Lavi; #664645]
* Delay invocation of caribou daemon until really needed [Daiki; #739712]
* Don't lock screen after crash if locking is disabled [Adel; #704884]
* Improve layout of extension installation dialog [William; #739888]
* Fix workspace changes from app picker [Yuki; #737534]
* Preload all ibus input sources in user configuration [Takao; #695428]
* Properly remove network connections from list [Ryan; #740227]
* Support CSS margin property [Carlos; #728437]
* Improve handling of BUSY application state [Phillip; #736492]
* Fix erroneous week numbers in calendar [Florian; #736722]
* Misc. bugfixes and cleanups [Darcy, Yuki, Alexander, Eskild, Bastien, Cosimo, Colin,
Ray; #738725, #739497, #739241, #672500, #739822, #740074, #704163, #740141]
Contributors:
Yuki, Lavi .A, Elad Alfassa, Cosimo Cecchi, Takao Fujiwara, Adel Gadllah,
Eskild Hustvedt, Chris Johns, William Jon McCann, Slavek Kabrda, Ryan Lortie,
Florian Müllner, Bastien Nocera, Christian Persch, Carlos Soriano,
Jasper St. Pierre, Ray Strode, Alexander Tsoy, Daiki Ueno, Colin Walters,
Phillip Wood
Translations:
Jorge Perez Perez [an], Daniel Martinez [an], Daniel Mustieles [es],
Trần Ngọc Quân [vi], Changwoo Ryu [ko], Kjartan Maraas [nb],
Yosef Or Boczko [he], Marek Černocký [cs]
3.15.1
======
* Use GResources for theme loading [Cosimo; #736936]
* Reset the OSK to primary on monitor changes [Rui; #738536]
* Use LC_TIME locale for format string translations [Florian; #738640]
* Summarize queued up notifications [Devyani; #702460]
* Improve handling of multi-day events [Andreas; #727302]
* Support EXTERNAL scroll policy type [Florian; #739379]
* Misc. bugfixes [Owen, Rui; #738652, #739252]
Contributors:
Andreas Brauchli, Cosimo Cecchi, Devyani Kota, Rui Matos, Florian Müllner,
Jasper St. Pierre, Owen W. Taylor
Translations:
Bahodir Mansurov [uz@cyrillic]
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
======
* Make airplane mode menu insensitive in lock screen [Giovanni; #729224]

View File

@ -4,6 +4,8 @@
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
PKG_NAME="gnome-shell"
(test -f $srcdir/configure.ac \
&& test -d $srcdir/src) || {
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
@ -12,7 +14,7 @@ test -z "$srcdir" && srcdir=.
}
# Fetch submodules if needed
if test ! -f src/gvc/Makefile.am || test ! -f data/theme/gnome-shell-sass/COPYING;
if test ! -f src/gvc/Makefile.am;
then
echo "+ Setting up submodules"
git submodule init
@ -24,4 +26,4 @@ which gnome-autogen.sh || {
echo "your OS vendor's package manager)."
exit 1
}
. gnome-autogen.sh
USE_GNOME2_MACROS=1 USE_COMMON_DOC_BUILD=yes . gnome-autogen.sh

View File

@ -3,10 +3,7 @@ mozillalibdir = $(BROWSER_PLUGIN_DIR)
mozillalib_LTLIBRARIES = libgnome-shell-browser-plugin.la
# Browsers can unload and reload the module while browsing, which is not supported by GObject.
# We pass -Wl,-z,nodelete to the linker to ensure the module is never unloaded.
# https://bugzilla.gnome.org/show_bug.cgi?id=737932
libgnome_shell_browser_plugin_la_LDFLAGS = -module -avoid-version -no-undefined -Wl,-z,nodelete
libgnome_shell_browser_plugin_la_LDFLAGS = -module -avoid-version -no-undefined
libgnome_shell_browser_plugin_la_LIBADD = \
$(BROWSER_PLUGIN_LIBS)

View File

@ -33,16 +33,20 @@
#include <json-glib/json-glib.h>
#define ORIGIN "extensions.gnome.org"
#define PLUGIN_NAME "GNOME Shell Integration"
#define PLUGIN_DESCRIPTION "This plugin provides integration with GNOME Shell " \
#define PLUGIN_NAME "Gnome Shell Integration"
#define PLUGIN_DESCRIPTION "This plugin provides integration with Gnome Shell " \
"for live extension enabling and disabling. " \
"It can be used only by extensions.gnome.org"
#define PLUGIN_MIME_STRING "application/x-gnome-shell-integration::GNOME Shell Integration Dummy Content-Type";
#define PLUGIN_MIME_STRING "application/x-gnome-shell-integration::Gnome Shell Integration Dummy Content-Type";
#define PLUGIN_API_VERSION 5
#define EXTENSION_DISABLE_VERSION_CHECK_KEY "disable-extension-version-validation"
typedef struct {
GDBusProxy *proxy;
} PluginData;
static NPNetscapeFuncs funcs;
static inline gchar *
@ -141,6 +145,121 @@ check_origin_and_protocol (NPP instance)
return ret;
}
/* =============== public entry points =================== */
NPError
NP_Initialize(NPNetscapeFuncs *pfuncs, NPPluginFuncs *plugin)
{
/* global initialization routine, called once when plugin
is loaded */
g_debug ("plugin loaded");
memcpy (&funcs, pfuncs, sizeof (funcs));
plugin->size = sizeof(NPPluginFuncs);
plugin->newp = NPP_New;
plugin->destroy = NPP_Destroy;
plugin->getvalue = NPP_GetValue;
plugin->setwindow = NPP_SetWindow;
return NPERR_NO_ERROR;
}
NPError
NP_Shutdown(void)
{
return NPERR_NO_ERROR;
}
const char*
NP_GetMIMEDescription(void)
{
return PLUGIN_MIME_STRING;
}
NPError
NP_GetValue(void *instance,
NPPVariable variable,
void *value)
{
switch (variable) {
case NPPVpluginNameString:
*(char**)value = PLUGIN_NAME;
break;
case NPPVpluginDescriptionString:
*(char**)value = PLUGIN_DESCRIPTION;
break;
default:
;
}
return NPERR_NO_ERROR;
}
NPError
NPP_New(NPMIMEType mimetype,
NPP instance,
uint16_t mode,
int16_t argc,
char **argn,
char **argv,
NPSavedData *saved)
{
/* instance initialization function */
PluginData *data;
GError *error = NULL;
g_debug ("plugin created");
if (!check_origin_and_protocol (instance))
return NPERR_GENERIC_ERROR;
data = g_slice_new (PluginData);
instance->pdata = data;
data->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_NONE,
NULL, /* interface info */
"org.gnome.Shell",
"/org/gnome/Shell",
"org.gnome.Shell.Extensions",
NULL, /* GCancellable */
&error);
if (!data->proxy)
{
/* ignore error if the shell is not running, otherwise warn */
if (error->domain != G_DBUS_ERROR ||
error->code != G_DBUS_ERROR_NAME_HAS_NO_OWNER)
{
g_warning ("Failed to set up Shell proxy: %s", error->message);
}
g_clear_error (&error);
return NPERR_GENERIC_ERROR;
}
g_debug ("plugin created successfully");
return NPERR_NO_ERROR;
}
NPError
NPP_Destroy(NPP instance,
NPSavedData **saved)
{
/* instance finalization function */
PluginData *data = instance->pdata;
g_debug ("plugin destroyed");
g_object_unref (data->proxy);
g_slice_free (PluginData, data);
return NPERR_NO_ERROR;
}
/* =================== scripting interface =================== */
typedef struct {
@ -211,18 +330,45 @@ static NPObject *
plugin_object_allocate (NPP instance,
NPClass *klass)
{
PluginObject *obj = (PluginObject *) funcs.memalloc (sizeof (PluginObject));
PluginData *data = instance->pdata;
PluginObject *obj = g_slice_new0 (PluginObject);
memset (obj, 0, sizeof (PluginObject));
obj->instance = instance;
obj->proxy = g_object_ref (data->proxy);
obj->settings = g_settings_new (SHELL_SCHEMA);
obj->signal_id = g_signal_connect (obj->proxy, "g-signal",
G_CALLBACK (on_shell_signal), obj);
return (NPObject*) obj;
obj->watch_name_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
"org.gnome.Shell",
G_BUS_NAME_WATCHER_FLAGS_NONE,
on_shell_appeared,
NULL,
obj,
NULL);
g_debug ("plugin object created");
return (NPObject*)obj;
}
static void
plugin_object_deallocate (NPObject *npobj)
{
funcs.memfree (npobj);
PluginObject *obj = (PluginObject*)npobj;
g_signal_handler_disconnect (obj->proxy, obj->signal_id);
g_object_unref (obj->proxy);
if (obj->listener)
funcs.releaseobject (obj->listener);
if (obj->watch_name_id)
g_bus_unwatch_name (obj->watch_name_id);
g_debug ("plugin object destroyed");
g_slice_free (PluginObject, obj);
}
static inline gboolean
@ -873,149 +1019,6 @@ init_methods_and_properties (void)
onextension_changed_id = funcs.getstringidentifier ("onchange");
}
/* =============== public entry points =================== */
NPError
NP_Initialize(NPNetscapeFuncs *pfuncs, NPPluginFuncs *plugin)
{
/* global initialization routine, called once when plugin
is loaded */
g_debug ("plugin loaded");
memcpy (&funcs, pfuncs, sizeof (funcs));
plugin->size = sizeof(NPPluginFuncs);
plugin->newp = NPP_New;
plugin->destroy = NPP_Destroy;
plugin->getvalue = NPP_GetValue;
plugin->setwindow = NPP_SetWindow;
plugin->event = NPP_HandleEvent;
return NPERR_NO_ERROR;
}
NPError
NP_Shutdown(void)
{
return NPERR_NO_ERROR;
}
const char*
NP_GetMIMEDescription(void)
{
return PLUGIN_MIME_STRING;
}
NPError
NP_GetValue(void *instance,
NPPVariable variable,
void *value)
{
switch (variable) {
case NPPVpluginNameString:
*(char**)value = PLUGIN_NAME;
break;
case NPPVpluginDescriptionString:
*(char**)value = PLUGIN_DESCRIPTION;
break;
default:
;
}
return NPERR_NO_ERROR;
}
NPError
NPP_New(NPMIMEType mimetype,
NPP instance,
uint16_t mode,
int16_t argc,
char **argn,
char **argv,
NPSavedData *saved)
{
/* instance initialization function */
PluginObject *obj;
GError *error = NULL;
g_debug ("plugin created");
if (!check_origin_and_protocol (instance))
return NPERR_GENERIC_ERROR;
/* set windowless mode */
funcs.setvalue(instance, NPPVpluginWindowBool, NULL);
g_debug ("creating scriptable object");
init_methods_and_properties ();
obj = (PluginObject *) funcs.createobject (instance, &plugin_class);
instance->pdata = obj;
obj->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_NONE,
NULL, /* interface info */
"org.gnome.Shell",
"/org/gnome/Shell",
"org.gnome.Shell.Extensions",
NULL, /* GCancellable */
&error);
if (!obj->proxy)
{
/* ignore error if the shell is not running, otherwise warn */
if (!g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER))
{
g_warning ("Failed to set up Shell proxy: %s", error->message);
}
g_clear_error (&error);
return NPERR_GENERIC_ERROR;
}
obj->settings = g_settings_new (SHELL_SCHEMA);
obj->signal_id = g_signal_connect (obj->proxy, "g-signal",
G_CALLBACK (on_shell_signal), obj);
obj->watch_name_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
"org.gnome.Shell",
G_BUS_NAME_WATCHER_FLAGS_NONE,
on_shell_appeared,
NULL,
obj,
NULL);
g_debug ("plugin created successfully");
return NPERR_NO_ERROR;
}
NPError
NPP_Destroy(NPP instance,
NPSavedData **saved)
{
/* instance finalization function */
PluginObject *obj = (PluginObject *) instance->pdata;
if (!obj)
return NPERR_INVALID_INSTANCE_ERROR;
g_debug ("plugin destroyed");
g_signal_handler_disconnect (obj->proxy, obj->signal_id);
g_object_unref (obj->proxy);
if (obj->listener)
funcs.releaseobject (obj->listener);
if (obj->restart_listener)
funcs.releaseobject (obj->restart_listener);
if (obj->watch_name_id)
g_bus_unwatch_name (obj->watch_name_id);
funcs.releaseobject((NPObject *)obj);
return NPERR_NO_ERROR;
}
NPError
NPP_GetValue(NPP instance,
NPPVariable variable,
@ -1026,10 +1029,13 @@ NPP_GetValue(NPP instance,
switch (variable) {
case NPPVpluginScriptableNPObject:
g_debug ("creating scriptable object");
if (!instance->pdata)
return NPERR_INVALID_INSTANCE_ERROR;
init_methods_and_properties ();
*(NPObject**)value = instance->pdata;
*(NPObject**)value = funcs.createobject (instance, &plugin_class);
break;
case NPPVpluginNeedsXEmbed:
*(bool *)value = TRUE;
break;
default:
@ -1047,11 +1053,3 @@ NPP_SetWindow(NPP instance,
{
return NPERR_NO_ERROR;
}
int16_t
NPP_HandleEvent(NPP instance,
void *event)
{
/* Ignore the event */
return FALSE;
}

View File

@ -1,6 +1,5 @@
AC_PREREQ(2.63)
AC_INIT([gnome-shell],[3.22.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AX_IS_RELEASE([git-directory])
AC_INIT([gnome-shell],[3.13.2],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c])
@ -24,14 +23,13 @@ LT_PREREQ([2.2.6])
LT_INIT([disable-static])
# i18n
IT_PROG_INTLTOOL([0.40])
GETTEXT_PACKAGE=gnome-shell
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
[The prefix for our gettext translation domains.])
AM_GNU_GETTEXT_VERSION([0.19.6])
AM_GNU_GETTEXT([external])
PKG_PROG_PKG_CONFIG([0.22])
AC_PATH_PROG([XSLTPROC], [xsltproc])
@ -39,7 +37,7 @@ AC_PATH_PROG([XSLTPROC], [xsltproc])
GLIB_GSETTINGS
# Get a value to substitute into gnome-shell.in
AM_PATH_PYTHON([3])
AM_PATH_PYTHON([2.5])
AC_SUBST(PYTHON)
# We need at least this, since gst_plugin_register_static() was added
@ -53,7 +51,7 @@ if $PKG_CONFIG --exists gstreamer-1.0 '>=' $GSTREAMER_MIN_VERSION ; then
AC_MSG_RESULT(yes)
build_recorder=true
recorder_modules="gstreamer-1.0 gstreamer-base-1.0 x11 gtk+-3.0"
PKG_CHECK_MODULES(TEST_SHELL_RECORDER, $recorder_modules mutter-clutter-1.0)
PKG_CHECK_MODULES(TEST_SHELL_RECORDER, $recorder_modules clutter-1.0)
else
AC_MSG_RESULT(no)
fi
@ -65,8 +63,8 @@ AC_ARG_ENABLE([systemd],
[enable_systemd=$enableval],
[enable_systemd=auto])
AS_IF([test x$enable_systemd != xno], [
AC_MSG_CHECKING([for libsystemd])
PKG_CHECK_EXISTS([libsystemd],
AC_MSG_CHECKING([for libsystemd-journal])
PKG_CHECK_EXISTS([libsystemd-journal],
[have_systemd=yes
AC_DEFINE([HAVE_SYSTEMD], [1], [Define if we have systemd])],
[have_systemd=no])
@ -75,14 +73,14 @@ AS_IF([test x$enable_systemd != xno], [
AC_MSG_RESULT($enable_systemd)
CLUTTER_MIN_VERSION=1.21.5
GOBJECT_INTROSPECTION_MIN_VERSION=1.49.1
CLUTTER_MIN_VERSION=1.15.90
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=1.39.0
MUTTER_MIN_VERSION=3.22.1
GTK_MIN_VERSION=3.15.0
GIO_MIN_VERSION=2.45.3
MUTTER_MIN_VERSION=3.13.2
GTK_MIN_VERSION=3.7.9
GIO_MIN_VERSION=2.37.0
LIBECAL_MIN_VERSION=3.5.3
LIBEDATASERVER_MIN_VERSION=3.17.2
LIBEDATASERVER_MIN_VERSION=3.5.3
TELEPATHY_GLIB_MIN_VERSION=0.17.5
POLKIT_MIN_VERSION=0.100
STARTUP_NOTIFICATION_MIN_VERSION=0.11
@ -99,8 +97,9 @@ SHARED_PCS="gio-unix-2.0 >= $GIO_MIN_VERSION
gjs-internals-1.0 >= $GJS_MIN_VERSION
$recorder_modules
gdk-x11-3.0 libsoup-2.4
mutter-clutter-1.0 >= $CLUTTER_MIN_VERSION
mutter-cogl-pango-1.0
xtst
clutter-x11-1.0 >= $CLUTTER_MIN_VERSION
clutter-glx-1.0 >= $CLUTTER_MIN_VERSION
libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_MIN_VERSION
gobject-introspection-1.0 >= $GOBJECT_INTROSPECTION_MIN_VERSION
libcanberra libcanberra-gtk3
@ -108,19 +107,20 @@ SHARED_PCS="gio-unix-2.0 >= $GIO_MIN_VERSION
polkit-agent-1 >= $POLKIT_MIN_VERSION
gcr-base-3 >= $GCR_MIN_VERSION"
if test x$have_systemd = xyes; then
SHARED_PCS="${SHARED_PCS} libsystemd"
SHARED_PCS="${SHARED_PCS} libsystemd-journal"
fi
PKG_CHECK_MODULES(GNOME_SHELL, $SHARED_PCS)
PKG_CHECK_MODULES(MUTTER, libmutter >= $MUTTER_MIN_VERSION)
PKG_CHECK_MODULES(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION)
PKG_CHECK_MODULES(ST, mutter-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)
PKG_CHECK_MODULES(SHELL_PERF_HELPER, gtk+-3.0 gio-2.0)
PKG_CHECK_MODULES(SHELL_HOTPLUG_SNIFFER, gio-2.0 gdk-pixbuf-2.0)
PKG_CHECK_MODULES(TRAY, mutter-clutter-1.0 gtk+-3.0)
PKG_CHECK_MODULES(TRAY, gtk+-3.0)
PKG_CHECK_MODULES(GVC, libpulse >= $PULSE_MIN_VERS libpulse-mainloop-glib gobject-2.0)
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.21.3)
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.7.4)
PKG_CHECK_MODULES(CARIBOU, caribou-1.0 >= 0.4.8)
AC_ARG_ENABLE(browser-plugin,
[AS_HELP_STRING([--enable-browser-plugin],
@ -222,7 +222,7 @@ if test "$enable_man" != no; then
fi
AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no)
AX_COMPILER_FLAGS()
GNOME_COMPILE_WARNINGS([error])
case "$WARN_CFLAGS" in
*-Werror*)
WARN_CFLAGS="$WARN_CFLAGS -Wno-error=deprecated-declarations"
@ -232,19 +232,9 @@ esac
AM_CFLAGS="$AM_CFLAGS $WARN_CFLAGS"
AC_SUBST(AM_CFLAGS)
if test -z "${BROWSER_PLUGIN_DIR}"; then
BROWSER_PLUGIN_DIR="\${libdir}/mozilla/plugins"
fi
BROWSER_PLUGIN_DIR="${BROWSER_PLUGIN_DIR:-"\${libdir}/mozilla/plugins"}"
AC_ARG_VAR([BROWSER_PLUGIN_DIR],[Where to install the plugin to])
AC_ARG_VAR([GDBUS_CODEGEN],[the gdbus-codegen programme])
AC_PATH_PROG([GDBUS_CODEGEN],[gdbus-codegen],[])
if test -z "$GDBUS_CODEGEN"; then
AC_MSG_ERROR([gdbus-codegen not found])
fi
AC_PATH_PROG([SASS],[sass],[])
AC_CONFIG_FILES([
Makefile
data/Makefile
@ -255,6 +245,7 @@ AC_CONFIG_FILES([
docs/reference/st/Makefile
docs/reference/st/st-docs.sgml
js/Makefile
src/calendar-server/evolution-calendar.desktop.in
src/Makefile
src/gvc/Makefile
browser-plugin/Makefile
@ -270,7 +261,7 @@ Build configuration:
Prefix: ${prefix}
Source code location: ${srcdir}
Compiler: ${CC}
Compiler Warnings: $ax_enable_compile_warnings
Compiler Warnings: $enable_compile_warnings
Support for NetworkManager: $have_networkmanager
Support for GStreamer recording: $build_recorder

View File

@ -1,24 +1,24 @@
<?xml version="1.0" encoding="UTF-8" ?>
<KeyListEntries schema="org.gnome.shell.keybindings"
group="system"
name="System"
_name="System"
wm_name="GNOME Shell"
package="gnome-shell">
<KeyListEntry name="toggle-message-tray"
description="Show the notification list"/>
_description="Show the message tray"/>
<KeyListEntry name="focus-active-notification"
description="Focus the active notification"/>
_description="Focus the active notification"/>
<KeyListEntry name="toggle-overview"
description="Show the overview"/>
_description="Show the overview"/>
<KeyListEntry name="toggle-application-view"
description="Show all applications"/>
_description="Show all applications"/>
<KeyListEntry name="open-application-menu"
description="Open the application menu"/>
_description="Open the application menu"/>
</KeyListEntries>

View File

@ -1,29 +1,5 @@
CLEANFILES =
NULL =
desktopdir=$(datadir)/applications
desktop_DATA = org.gnome.Shell.desktop gnome-shell-extension-prefs.desktop
if HAVE_NETWORKMANAGER
desktop_DATA += org.gnome.Shell.PortalHelper.desktop
portaldir = $(datadir)/xdg-desktop-portal/portals
portal_DATA = gnome-shell.portal
servicedir = $(datadir)/dbus-1/services
service_DATA = org.gnome.Shell.PortalHelper.service
CLEANFILES += \
org.gnome.Shell.PortalHelper.service \
org.gnome.Shell.PortalHelper.desktop \
org.gnome.Shell.PortalHelper.desktop.in \
$(NULL)
endif
%.service: %.service.in
$(AM_V_GEN) sed -e "s|@libexecdir[@]|$(libexecdir)|" \
$< > $@ || rm $@
desktop_DATA = gnome-shell.desktop gnome-shell-wayland.desktop gnome-shell-extension-prefs.desktop
# We substitute in bindir so it works as an autostart
# file when built in a non-system prefix
@ -32,65 +8,64 @@ endif
-e "s|@VERSION[@]|$(VERSION)|" \
$< > $@ || rm $@
%.desktop:%.desktop.in
$(AM_V_GEN) $(MSGFMT) --desktop --template $(builddir)/$< \
-d $(top_srcdir)/po -o $@
@INTLTOOL_DESKTOP_RULE@
introspectiondir = $(datadir)/dbus-1/interfaces
introspection_DATA = \
org.gnome.Shell.Screencast.xml \
org.gnome.Shell.Screenshot.xml \
org.gnome.ShellSearchProvider.xml \
org.gnome.ShellSearchProvider2.xml \
$(NULL)
org.gnome.ShellSearchProvider2.xml
theme_sources = \
theme/gnome-shell-high-contrast.scss \
theme/gnome-shell.scss \
theme/gnome-shell-sass/_colors.scss \
theme/gnome-shell-sass/_common.scss \
theme/gnome-shell-sass/_drawing.scss \
theme/gnome-shell-sass/_high-contrast-colors.scss \
$(NULL)
dist_theme_files = \
$(theme_sources) \
theme/Gemfile \
theme/HACKING \
theme/README \
theme/gnome-shell-sass/COPYING \
theme/gnome-shell-sass/HACKING \
theme/gnome-shell-sass/NEWS \
theme/gnome-shell-sass/README \
theme/gnome-shell-sass/gnome-shell-sass.doap \
theme/parse-sass.sh \
$(NULL)
%.css: %.scss $(theme_sources)
@if test -n "$(SASS)"; then \
if $(AM_V_P); then PS4= set -x; else echo " GEN $@"; fi; \
$(SASS) --sourcemap=none -f -q --update $<; \
fi
resource_files = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir)/theme --generate-dependencies $(srcdir)/gnome-shell-theme.gresource.xml)
gnome-shell-theme.gresource: gnome-shell-theme.gresource.xml $(resource_files)
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir)/theme $<
resourcedir = $(pkgdatadir)
resource_DATA = gnome-shell-theme.gresource
backgrounddir = $(pkgdatadir)
background_DATA = perf-background.xml
perf-background.xml: perf-background.xml.in
$(AM_V_GEN) sed -e "s|@datadir[@]|$(datadir)|" \
$< > $@ || rm $@
themedir = $(pkgdatadir)/theme
dist_theme_DATA = \
theme/calendar-arrow-left.svg \
theme/calendar-arrow-right.svg \
theme/calendar-today.svg \
theme/checkbox-focused.svg \
theme/checkbox-off-focused.svg \
theme/checkbox-off.svg \
theme/checkbox.svg \
theme/close-window.svg \
theme/close.svg \
theme/corner-ripple-ltr.png \
theme/corner-ripple-rtl.png \
theme/dash-placeholder.svg \
theme/filter-selected-ltr.svg \
theme/filter-selected-rtl.svg \
theme/gnome-shell.css \
theme/logged-in-indicator.svg \
theme/menu-arrow-symbolic.svg \
theme/message-tray-background.png \
theme/more-results.svg \
theme/noise-texture.png \
theme/page-indicator-active.svg \
theme/page-indicator-inactive.svg \
theme/page-indicator-checked.svg \
theme/page-indicator-hover.svg \
theme/panel-button-border.svg \
theme/panel-button-highlight-narrow.svg \
theme/panel-button-highlight-wide.svg \
theme/process-working.svg \
theme/running-indicator.svg \
theme/source-button-border.svg \
theme/summary-counter.svg \
theme/toggle-off-us.svg \
theme/toggle-off-intl.svg \
theme/toggle-on-us.svg \
theme/toggle-on-intl.svg \
theme/ws-switch-arrow-up.png \
theme/ws-switch-arrow-down.png
keysdir = @GNOME_KEYBINDINGS_KEYSDIR@
keys_DATA = 50-gnome-shell-system.xml
keys_in_files = 50-gnome-shell-system.xml.in
keys_DATA = $(keys_in_files:.xml.in=.xml)
gsettings_SCHEMAS = org.gnome.shell.gschema.xml
%.gschema.xml: %.gschema.xml.in Makefile
@INTLTOOL_XML_NOMERGE_RULE@
%.gschema.xml.in: %.gschema.xml.in.in Makefile
$(AM_V_GEN) sed -e 's|@GETTEXT_PACKAGE[@]|$(GETTEXT_PACKAGE)|g' \
$< > $@ || rm $@
@ -107,29 +82,22 @@ convertdir = $(datadir)/GConf/gsettings
convert_DATA = gnome-shell-overrides.convert
EXTRA_DIST = \
org.gnome.Shell.desktop.in.in \
gnome-shell.desktop.in.in \
gnome-shell-wayland.desktop.in.in \
gnome-shell-extension-prefs.desktop.in.in \
$(portal_DATA) \
$(introspection_DATA) \
$(menu_DATA) \
$(convert_DATA) \
$(keys_DATA) \
$(dist_theme_files) \
perf-background.xml.in \
org.gnome.Shell.PortalHelper.desktop.in.in \
org.gnome.Shell.PortalHelper.service.in \
org.gnome.shell.gschema.xml.in \
gnome-shell-theme.gresource.xml \
$(resource_files) \
$(NULL)
$(keys_in_files) \
org.gnome.shell.gschema.xml.in.in
CLEANFILES += \
org.gnome.Shell.desktop.in \
CLEANFILES = \
gnome-shell.desktop.in \
gnome-shell-wayland.desktop.in \
gnome-shell-extension-prefs.in \
$(desktop_DATA) \
$(keys_DATA) \
$(gsettings_SCHEMAS) \
perf-background.xml \
gschemas.compiled \
org.gnome.shell.gschema.valid \
gnome-shell-theme.gresource \
$(NULL)
org.gnome.shell.gschema.xml.in

View File

@ -1,7 +1,7 @@
[Desktop Entry]
Type=Application
Name=GNOME Shell Extension Preferences
Comment=Configure GNOME Shell Extensions
_Name=GNOME Shell Extension Preferences
_Comment=Configure GNOME Shell Extensions
Exec=@bindir@/gnome-shell-extension-prefs %u
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-shell

View File

@ -1,4 +1,5 @@
[org.gnome.shell.overrides]
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
workspaces-only-on-primary = /desktop/gnome/shell/windows/workspaces_only_on_primary

View File

@ -1,42 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/shell/theme">
<file>calendar-arrow-left.svg</file>
<file>calendar-arrow-right.svg</file>
<file>calendar-today.svg</file>
<file>checkbox-focused.svg</file>
<file>checkbox-off-focused.svg</file>
<file>checkbox-off.svg</file>
<file>checkbox.svg</file>
<file>close-window.svg</file>
<file>close.svg</file>
<file>corner-ripple-ltr.png</file>
<file>corner-ripple-rtl.png</file>
<file>dash-placeholder.svg</file>
<file>filter-selected-ltr.svg</file>
<file>filter-selected-rtl.svg</file>
<file>gnome-shell.css</file>
<file>gnome-shell-high-contrast.css</file>
<file>logged-in-indicator.svg</file>
<file>more-results.svg</file>
<file>no-events.svg</file>
<file>no-notifications.svg</file>
<file>noise-texture.png</file>
<file>page-indicator-active.svg</file>
<file>page-indicator-inactive.svg</file>
<file>page-indicator-checked.svg</file>
<file>page-indicator-hover.svg</file>
<file>process-working.svg</file>
<file>running-indicator.svg</file>
<file>source-button-border.svg</file>
<file>summary-counter.svg</file>
<file>toggle-off-us.svg</file>
<file>toggle-off-intl.svg</file>
<file>toggle-off-hc.svg</file>
<file>toggle-on-us.svg</file>
<file>toggle-on-intl.svg</file>
<file>toggle-on-hc.svg</file>
<file>ws-switch-arrow-up.png</file>
<file>ws-switch-arrow-down.png</file>
</gresource>
</gresources>

View File

@ -0,0 +1,15 @@
[Desktop Entry]
Type=Application
_Name=GNOME Shell (wayland compositor)
_Comment=Window management and application launching
Exec=@bindir@/gnome-shell --wayland --display-server
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-shell
X-GNOME-Bugzilla-Component=general
X-GNOME-Bugzilla-Version=@VERSION@
Categories=GNOME;GTK;Core;
OnlyShowIn=GNOME;
NoDisplay=true
X-GNOME-Autostart-Phase=DisplayServer
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=false

View File

@ -1,7 +1,7 @@
[Desktop Entry]
Type=Application
Name=GNOME Shell
Comment=Window management and application launching
_Name=GNOME Shell
_Comment=Window management and application launching
Exec=@bindir@/gnome-shell
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-shell
@ -10,7 +10,7 @@ X-GNOME-Bugzilla-Version=@VERSION@
Categories=GNOME;GTK;Core;
OnlyShowIn=GNOME;
NoDisplay=true
X-GNOME-Autostart-Phase=DisplayServer
X-GNOME-Autostart-Phase=WindowManager
X-GNOME-Provides=panel;windowmanager;
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=false

View File

@ -1,4 +0,0 @@
[portal]
DBusName=org.freedesktop.impl.portal.desktop.gnome
Interfaces=org.freedesktop.impl.portal.Access
UseIn=gnome

View File

@ -1,10 +0,0 @@
[Desktop Entry]
Name=Network Login
Type=Application
Exec=gapplication launch org.gnome.Shell.PortalHelper
DBusActivatable=true
NoDisplay=true
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
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">
<arg type="s" direction="in" name="file_template"/>
<arg type="a{sv}" direction="in" name="options"/>
<arg type="b" direction="in" name="flash"/>
<arg type="b" direction="out" name="success"/>
<arg type="s" direction="out" name="filename_used"/>
</method>

View File

@ -3,40 +3,40 @@
gettext-domain="@GETTEXT_PACKAGE@">
<key name="development-tools" type="b">
<default>true</default>
<summary>
<_summary>
Enable internal tools useful for developers and testers from Alt-F2
</summary>
<description>
</_summary>
<_description>
Allows access to internal debugging and monitoring tools
using the Alt-F2 dialog.
</description>
</_description>
</key>
<key name="enabled-extensions" type="as">
<default>[]</default>
<summary>UUIDs of extensions to enable</summary>
<description>
<_summary>UUIDs of extensions to enable</_summary>
<_description>
GNOME Shell extensions have a UUID property; this key lists extensions
which should be loaded. Any extension that wants to be loaded needs
to be in this list. You can also manipulate this list with the
EnableExtension and DisableExtension D-Bus methods on org.gnome.Shell.
</description>
</_description>
</key>
<key name="disable-extension-version-validation" type="b">
<default>true</default>
<summary>Disables the validation of extension version compatibility</summary>
<description>
<default>false</default>
<_summary>Disables the validation of extension version compatibility</_summary>
<_description>
GNOME Shell will only load extensions that claim to support the current
running version. Enabling this option will disable this check and try to
load all extensions regardless of the versions they claim to support.
</description>
</_description>
</key>
<key name="favorite-apps" type="as">
<default>[ 'epiphany.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ]</default>
<summary>List of desktop file IDs for favorite applications</summary>
<description>
<default>[ 'epiphany.desktop', 'evolution.desktop', 'empathy.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'libreoffice-writer.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Documents.desktop' ]</default>
<_summary>List of desktop file IDs for favorite applications</_summary>
<_description>
The applications corresponding to these identifiers
will be displayed in the favorites area.
</description>
</_description>
</key>
<key name="app-picker-view" type="u">
<default>0</default>
@ -47,82 +47,84 @@
</key>
<key name="command-history" type="as">
<default>[]</default>
<summary>History for command (Alt-F2) dialog</summary>
<_summary>History for command (Alt-F2) dialog</_summary>
</key>
<key name="looking-glass-history" type="as">
<default>[]</default>
<!-- Translators: looking glass is a debugger and inspector tool, see https://wiki.gnome.org/Projects/GnomeShell/LookingGlass -->
<summary>History for the looking glass dialog</summary>
<_summary>History for the looking glass dialog</_summary>
</key>
<key name="always-show-log-out" type="b">
<default>false</default>
<summary>Always show the 'Log out' menu item in the user menu.</summary>
<description>
<_summary>Always show the 'Log out' menu item in the user menu.</_summary>
<_description>
This key overrides the automatic hiding of the 'Log out'
menu item in single-user, single-session situations.
</description>
</_description>
</key>
<key name="remember-mount-password" type="b">
<default>false</default>
<summary>Whether to remember password for mounting encrypted or remote filesystems</summary>
<description>
<_summary>Whether to remember password for mounting encrypted or remote filesystems</_summary>
<_description>
The shell will request a password when an encrypted device or a
remote filesystem is mounted. If the password can be saved for
future use a 'Remember Password' checkbox will be present.
This key sets the default state of the checkbox.
</description>
</key>
<key name="had-bluetooth-devices-setup" type="b">
<default>false</default>
<summary>Whether the default Bluetooth adapter had set up devices associated to it</summary>
<description>
The shell will only show a Bluetooth menu item if a Bluetooth
adapter is powered, or if there were devices set up associated
with the default adapter. This will be reset if the default
adapter is ever seen not to have devices associated to it.
</description>
</_description>
</key>
<child name="calendar" schema="org.gnome.shell.calendar"/>
<child name="keybindings" schema="org.gnome.shell.keybindings"/>
<child name="keyboard" schema="org.gnome.shell.keyboard"/>
<child name="location" schema="org.gnome.shell.location"/>
</schema>
<schema id="org.gnome.shell.calendar" path="/org/gnome/shell/calendar/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="show-weekdate" type="b">
<default>false</default>
<_summary>Show the week date in the calendar</_summary>
<_description>
If true, display the ISO week date in the calendar.
</_description>
</key>
</schema>
<schema id="org.gnome.shell.keybindings" path="/org/gnome/shell/keybindings/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="open-application-menu" type="as">
<default>["&lt;Super&gt;F10"]</default>
<summary>Keybinding to open the application menu</summary>
<description>
<_summary>Keybinding to open the application menu</_summary>
<_description>
Keybinding to open the application menu.
</description>
</_description>
</key>
<key name="toggle-application-view" type="as">
<default>["&lt;Super&gt;a"]</default>
<summary>Keybinding to open the "Show Applications" view</summary>
<description>
<_summary>Keybinding to open the "Show Applications" view</_summary>
<_description>
Keybinding to open the "Show Applications" view of the Activities
Overview.
</description>
</_description>
</key>
<key name="toggle-overview" type="as">
<default>["&lt;Super&gt;s"]</default>
<summary>Keybinding to open the overview</summary>
<description>
<_summary>Keybinding to open the overview</_summary>
<_description>
Keybinding to open the Activities Overview.
</description>
</_description>
</key>
<key name="toggle-message-tray" type="as">
<default>["&lt;Super&gt;v","&lt;Super&gt;m"]</default>
<summary>Keybinding to toggle the visibility of the notification list</summary>
<description>
Keybinding to toggle the visibility of the notification list.
</description>
<default>["&lt;Super&gt;m"]</default>
<_summary>Keybinding to toggle the visibility of the message tray</_summary>
<_description>
Keybinding to toggle the visibility of the message tray.
</_description>
</key>
<key name="focus-active-notification" type="as">
<default>["&lt;Super&gt;n"]</default>
<summary>Keybinding to focus the active notification</summary>
<description>
<_summary>Keybinding to focus the active notification</_summary>
<_description>
Keybinding to focus the active notification.
</description>
</_description>
</key>
<key name="pause-resume-tweens" type="as">
<default>[]</default>
@ -135,10 +137,36 @@
gettext-domain="@GETTEXT_PACKAGE@">
<key name="keyboard-type" type="s">
<default>'touch'</default>
<summary>Which keyboard to use</summary>
<description>
<_summary>Which keyboard to use</_summary>
<_description>
The type of keyboard to use.
</description>
</_description>
</key>
</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>
@ -165,12 +193,12 @@
gettext-domain="@GETTEXT_PACKAGE@">
<key name="app-icon-mode" enum="org.gnome.shell.window-switcher.AppIconMode">
<default>'both'</default>
<summary>The application icon mode.</summary>
<description>
<_summary>The application icon mode.</_summary>
<_description>
Configures how the windows are shown in the switcher. Valid possibilities
are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-only'
(shows only the application icon) or 'both'.
</description>
</_description>
</key>
<key type="b" name="current-workspace-only">
<default>true</default>
@ -186,43 +214,43 @@
gettext-domain="@GETTEXT_PACKAGE@">
<key name="attach-modal-dialogs" type="b">
<default>true</default>
<summary>Attach modal dialog to the parent window</summary>
<description>
<_summary>Attach modal dialog to the parent window</_summary>
<_description>
This key overrides the key in org.gnome.mutter when running
GNOME Shell.
</description>
</_description>
</key>
<key name="edge-tiling" type="b">
<default>true</default>
<summary>Enable edge tiling when dropping windows on screen edges</summary>
<description>
<_summary>Enable edge tiling when dropping windows on screen edges</_summary>
<_description>
This key overrides the key in org.gnome.mutter when running GNOME Shell.
</description>
</_description>
</key>
<key name="dynamic-workspaces" type="b">
<default>true</default>
<summary>Workspaces are managed dynamically</summary>
<description>
<_summary>Workspaces are managed dynamically</_summary>
<_description>
This key overrides the key in org.gnome.mutter when running GNOME Shell.
</description>
</_description>
</key>
<key name="workspaces-only-on-primary" type="b">
<default>true</default>
<summary>Workspaces only on primary monitor</summary>
<description>
<_summary>Workspaces only on primary monitor</_summary>
<_description>
This key overrides the key in org.gnome.mutter when running GNOME Shell.
</description>
</_description>
</key>
<key name="focus-change-on-pointer-rest" type="b">
<default>true</default>
<summary>Delay focus changes in mouse mode until the pointer stops moving</summary>
<description>
<_summary>Delay focus changes in mouse mode until the pointer stops moving</_summary>
<_description>
This key overrides the key in org.gnome.mutter when running GNOME Shell.
</description>
</_description>
</key>
</schema>
</schemalist>

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

@ -1 +0,0 @@
gem "sass", "~> 3.4.0"

View File

@ -1,3 +0,0 @@
To generate the css files, from the project directory:
sass --sourcemap=none --update .

View File

@ -1,36 +0,0 @@
Summary
-------
* Do not edit the CSS directly, edit the source SCSS files and process them with SASS (running
`make` should do that when you have the required software installed, as described below;
run `/.parse-sass.sh` manually if it doesn't)
* To be able to use the lates/adequate version of sass, install ruby, gem, sass & bundle.
On Fedora F20, this is done with `sudo dnf install rubygems && gem install bundle && bundle install`
from the same directory this README resides in.
How to tweak the theme
----------------------
Adwaita is a complex theme, so to keep it maintainable it's written and processed in SASS, the
generated CSS is then transformed into a gresource file during gtk build and used at runtime in a
non-legible or editable form.
It is very likely your change will happen in the _common.scss file. That's where all the widget
selectors are defined. Here's a rundown of the "supporting" stylesheets, that are unlikely to be the
right place for a drive by stylesheet fix:
_colors.scss - global color definitions. We keep the number of defined colors to a necessary minimum,
most colors are derived from a handful of basics. It is an exact copy of the gtk+
counterpart. Light theme is used for the classic theme and dark is for GNOME3 shell
default.
_drawing.scss - drawing helper mixings/functions to allow easier definition of widget drawing under
specific context. This is why Adwaita isn't 15000 LOC.
_common.scss - actual definitions of style for each widget. This is where you are likely to add/remove
your changes.
You can read about SASS at http://sass-lang.com/documentation/. Once you make your changes to the
_common.scss file, you can either run the ./parse-sass.sh script or keep SASS watching for changes as you
edit. This is done by running `bundle exec sass --watch --sourcemap=none .` If sass is out of date, or is
missing, you can install it with `bundle install`.

View File

@ -10,11 +10,11 @@
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24"
height="24"
width="29"
height="29"
id="svg10621"
version="1.1"
inkscape:version="0.91 r13725"
inkscape:version="0.48.2 r9819"
sodipodi:docname="calendar-today.svg">
<defs
id="defs10623">
@ -118,6 +118,17 @@
fx="51"
fy="30"
r="42" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient34508-1-3"
id="radialGradient3113"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.72146227,0,0,0.27484277,14.205424,21.754717)"
cx="51"
cy="30"
fx="51"
fy="30"
r="42" />
</defs>
<sodipodi:namedview
id="base"
@ -126,23 +137,22 @@
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="8"
inkscape:cx="-23.537329"
inkscape:cy="-31.442864"
inkscape:zoom="15.839192"
inkscape:cx="20.652108"
inkscape:cy="11.839084"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
showgrid="true"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="2133"
inkscape:window-height="1241"
inkscape:window-x="238"
inkscape:window-y="88"
inkscape:window-maximized="0"
borderlayer="true"
inkscape:showpageshadow="false">
inkscape:window-width="1280"
inkscape:window-height="741"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
borderlayer="true">
<inkscape:grid
type="xygrid"
id="grid3109"
@ -159,7 +169,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@ -167,12 +177,28 @@
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-469.08263,-537.99307)">
<circle
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:0.23756906;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="path7305"
cx="481.57138"
cy="559.4649"
r="1.5" />
transform="translate(-469.08263,-532.99307)">
<path
sodipodi:type="arc"
style="opacity:0.4625;color:#000000;fill:url(#radialGradient3113);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path34506-3"
sodipodi:cx="51"
sodipodi:cy="30"
sodipodi:rx="42"
sodipodi:ry="16"
d="M 9,29.999999 A 42,16 0 0 1 93,30 l -42,0 z"
sodipodi:start="3.1415927"
sodipodi:end="6.2831853"
transform="matrix(0.43692393,0,0,1.3783114,461.29951,517.6437)"
inkscape:export-filename="/home/jimmac/src/cvs/gnome/gnome-shell-design/mockups/motion/textures/panel.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<rect
style="fill:#ffffff;fill-opacity:0.50196078;stroke-width:0.43599999;stroke-miterlimit:4;stroke-dasharray:none"
id="rect2996"
width="31"
height="3"
x="468.08264"
y="558.99304" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -14,7 +14,7 @@
height="22"
id="svg3199"
version="1.1"
inkscape:version="0.48.5 r10040"
inkscape:version="0.48.1 r9760"
sodipodi:docname="checkbox.svg">
<defs
id="defs3201">
@ -132,54 +132,51 @@
xlink:href="#linearGradient10597-5"
inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5581-5-2-4-6-8-7-35-8"
id="linearGradient11811"
y2="-388.72955"
x2="-93.031357"
y1="-396.34738"
x1="-93.031357"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.685418)"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(3.0317573,0,0,1.0053174,-102.66338,-0.82153381)"
x1="63.568954"
y1="127.16142"
x2="63.568954"
y2="152.6618" />
id="linearGradient14219-6"
xlink:href="#linearGradient15404-9"
inkscape:collect="always" />
<linearGradient
id="linearGradient5581-5-2-4-6-8-7-35-8">
id="linearGradient15404-9"
inkscape:collect="always">
<stop
id="stop5583-0-92-8-0-7-6-5-1"
id="stop15406-6"
offset="0"
style="stop-color:#454c4c;stop-opacity:1;" />
style="stop-color:#515151;stop-opacity:1" />
<stop
style="stop-color:#393f3f;stop-opacity:1;"
offset="0.40000001"
id="stop5585-4-7-2-7-9-9-92-0" />
<stop
id="stop5587-6-7-2-0-3-1-21-5"
id="stop15408-7"
offset="1"
style="stop-color:#2d3232;stop-opacity:1;" />
style="stop-color:#292929;stop-opacity:1" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#a2a2a2"
pagecolor="#000000"
bordercolor="#2d2d2d"
borderopacity="1"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
inkscape:cx="9.6447897"
inkscape:cy="12.591409"
inkscape:zoom="1"
inkscape:cx="71.516955"
inkscape:cy="5.8710559"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1412"
inkscape:window-height="1067"
inkscape:window-x="184"
inkscape:window-y="233"
inkscape:window-x="2635"
inkscape:window-y="226"
inkscape:window-maximized="0"
borderlayer="true"
inkscape:showpageshadow="false"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
showborder="true">
showborder="false">
<inkscape:grid
type="xygrid"
id="grid14843"
@ -206,56 +203,87 @@
id="layer1"
transform="translate(-342.5,-521.36218)">
<g
style="display:inline"
id="use5671"
transform="matrix(1.3594109,0,0,1.3564242,319.2059,481.99447)">
<rect
transform="matrix(0.47304779,0,0,0.4807373,-6.3607039,-29.396216)"
rx="4.4136767"
y="125.3458"
x="50.440369"
height="29.154205"
width="29.559635"
id="rect11803"
style="color:#000000;fill:url(#linearGradient11811);fill-opacity:1;stroke:#3465a4;stroke-width:1.54426003000000001;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
ry="4.4233952" />
<path
inkscape:connector-curvature="0"
id="path11809"
d="m 17.87105,33.844107 0,-0.773112 c 0,-1.031264 0.807171,-1.836142 1.811982,-1.836142 l 9.612456,0 c 1.004811,0 1.787822,0.804878 1.787822,1.836142 l 0,0.773112 c 0,-1.031264 -0.783011,-1.836142 -1.787822,-1.836142 l -9.612456,0 c -1.004811,0 -1.811982,0.804878 -1.811982,1.836142 z"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
sodipodi:nodetypes="csssscssc" />
<path
sodipodi:nodetypes="csssscssc"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
d="m 17.87105,41.158551 0,0.773112 c 0,1.031264 0.807171,1.836142 1.811982,1.836142 l 9.612456,0 c 1.004811,0 1.787822,-0.804878 1.787822,-1.836142 l 0,-0.773112 c 0,1.031264 -0.783011,1.836142 -1.787822,1.836142 l -9.612456,0 c -1.004811,0 -1.811982,-0.804878 -1.811982,-1.836142 z"
id="path11867"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path11869"
d="m 17.87105,41.895784 0,0.773112 c 0,1.031264 0.644622,1.836142 1.649433,1.836142 l 10.067593,0 c 1.004811,0 1.495234,-0.804878 1.495234,-1.836142 l 0,-0.773112 c 0,1.031264 -0.783011,1.836142 -1.787822,1.836142 l -9.612456,0 c -1.004811,0 -1.811982,-0.804878 -1.811982,-1.836142 z"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#000000;fill-opacity:0.85253451;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
sodipodi:nodetypes="csssscssc" />
transform="matrix(0.80230061,0,0,0.80230061,-87.624044,-453.10297)"
id="g14586-0"
style="stroke-width:2.3714385;stroke-miterlimit:4;stroke-dasharray:none">
<g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
transform="matrix(1.9969286,0,0,1.9969286,-397.05491,877.00482)"
id="g15291-9-6"
style="stroke-width:1.18754292;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new">
<g
transform="translate(877.50354,-102.83507)"
id="g16853-4-9"
style="stroke-width:1.18754292;stroke-miterlimit:4;stroke-dasharray:none;enable-background:new">
<rect
transform="scale(1,-1)"
style="color:#000000;fill:url(#linearGradient14219-6);fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:1.24833274;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
id="rect6506-6"
width="11.281681"
height="11.26221"
x="-409.59354"
y="-284.40115"
rx="1.0052766"
ry="1.0052764" />
</g>
</g>
<g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
transform="translate(343.99999,987.99997)"
id="g5886-5"
style="stroke-width:2.3714385;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new" />
</g>
<g
transform="matrix(0.84337,0,0,0.84337,-110.16632,-503.56182)"
id="g14586">
<g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
transform="matrix(1.9969286,0,0,1.9969286,-397.05491,877.00482)"
id="g15291-9"
style="display:inline;enable-background:new">
<g
transform="translate(877.50354,-102.83507)"
id="g16853-4"
style="enable-background:new" />
</g>
<g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
transform="translate(343.99999,987.99997)"
id="g5886"
style="display:inline;enable-background:new">
<path
style="fill:none;stroke:url(#linearGradient5891-0-4);stroke-width:7.11431503;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 198.5,240 5.25,5.25 13.98616,-14.43081"
id="path5835"
inkscape:path-effect="#path-effect5837-4-6"
inkscape:original-d="m 198.5,240 5.25,5.25 13.98616,-14.43081"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
inkscape:connector-curvature="0"
inkscape:original-d="m 198.5,240 5.25,5.25 13.91205,-14.31964"
inkscape:path-effect="#path-effect5837-4-6"
id="path5880"
d="m 198.5,240 5.25,5.25 13.91205,-14.31964"
style="fill:none;stroke:#4787c8;stroke-width:3.55715752;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#7ea7d3;stroke-width:1.18571913px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 197.45937,240.47455 c -0.17828,-0.29362 -0.20087,-0.67548 -0.0603,-0.98892 0.14055,-0.31344 0.43739,-0.54812 0.77144,-0.62817 0.33405,-0.08 0.69314,-0.01 0.99635,0.15175 0.30321,0.16144 0.55146,0.40727 0.79165,0.65284 l 3.66429,3.74643 12.87946,-12.98973 c 0.20796,-0.20974 0.42306,-0.41969 0.68548,-0.55522 0.26242,-0.13553 0.57293,-0.19052 0.85827,-0.11426 0.14267,0.0381 0.27708,0.10787 0.38874,0.20452 0.11167,0.0966 0.20021,0.22004 0.25479,0.35726 0.0546,0.13722 0.075,0.28793 0.0585,0.43468 -0.0165,0.14674 -0.07,0.28919 -0.15422,0.41052"
id="path5882"
inkscape:path-effect="#path-effect5884-4-7"
inkscape:original-d="m 197.45937,240.47455 c 0.65604,-0.56057 2.02485,-1.34847 2.49911,-0.8125 l 3.66429,3.74643 12.87946,-12.98973 c 0.6875,-0.6875 2.09152,0.7375 2.09152,0.7375"
inkscape:connector-curvature="0"
sodipodi:nodetypes="csccc" />
</g>
</g>
<rect
style="color:#000000;fill:none;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect17347"
width="21.943846"
height="21.943846"
x="342.29913"
y="521.58435" />
<path
inkscape:connector-curvature="0"
style="opacity:0.8;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.99999994;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 359.97505,524.8252 -7.88606,7.71465 -2.57155,-2.57155 -2.91442,-0.0427 0,2.35727 4.02875,3.98587 c 0.80342,0.80309 2.111,0.80309 2.91442,0 l 8.18609,-8.22894 0,-0.38573 c 0,-1.24128 0.19944,-1.76801 -0.82915,-2.29836 z"
id="rect5147-9-1-5-7-6-5-8-7"
sodipodi:nodetypes="ccccccccscc" />
<path
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:sans-serif;-inkscape-font-specification:sans-serif"
d="m 361.65223,524.52745 -9.5602,9.36735 -2.56345,-2.56344 -2.92846,-0.0214 0.0153,2.32639 4.02203,4.02206 c 0.80341,0.80309 2.10565,0.80309 2.90906,0 l 10.95049,-11.05765 0.003,-2.1502 z"
id="path12830-4-17-0"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccc" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -14,10 +14,22 @@
height="22"
id="svg3199"
version="1.1"
inkscape:version="0.48.5 r10040"
inkscape:version="0.48.1 r9760"
sodipodi:docname="checkbox-off.svg">
<defs
id="defs3201">
<linearGradient
id="linearGradient15404"
inkscape:collect="always">
<stop
id="stop15406"
offset="0"
style="stop-color:#515151;stop-opacity:1" />
<stop
id="stop15408"
offset="1"
style="stop-color:#292929;stop-opacity:1" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
@ -44,6 +56,16 @@
effect="spiro"
id="path-effect5884-4-7"
is_visible="true" />
<linearGradient
y2="-388.72955"
x2="-93.031357"
y1="-396.34738"
x1="-93.031357"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.685418)"
gradientUnits="userSpaceOnUse"
id="linearGradient14219"
xlink:href="#linearGradient15404"
inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
id="linearGradient10013-4-63-6">
@ -88,55 +110,30 @@
id="linearGradient15376"
xlink:href="#linearGradient10597-5"
inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5581-5-2-4-6-8-7-35-8"
id="linearGradient11811"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(3.0317573,0,0,1.0053174,-102.66338,-0.82153381)"
x1="63.568954"
y1="127.16142"
x2="63.568954"
y2="152.6618" />
<linearGradient
id="linearGradient5581-5-2-4-6-8-7-35-8">
<stop
id="stop5583-0-92-8-0-7-6-5-1"
offset="0"
style="stop-color:#454c4c;stop-opacity:1;" />
<stop
style="stop-color:#393f3f;stop-opacity:1;"
offset="0.40000001"
id="stop5585-4-7-2-7-9-9-92-0" />
<stop
id="stop5587-6-7-2-0-3-1-21-5"
offset="1"
style="stop-color:#2d3232;stop-opacity:1;" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#a2a2a2"
pagecolor="#000000"
bordercolor="#2d2d2d"
borderopacity="1"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="5.6568542"
inkscape:cx="19.79113"
inkscape:cy="11.232334"
inkscape:zoom="1"
inkscape:cx="6.1225392"
inkscape:cy="3.6003241"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1412"
inkscape:window-height="1067"
inkscape:window-x="184"
inkscape:window-y="233"
inkscape:window-x="2116"
inkscape:window-y="261"
inkscape:window-maximized="0"
borderlayer="true"
inkscape:showpageshadow="false"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
showborder="true">
showborder="false">
<inkscape:grid
type="xygrid"
id="grid14843"
@ -163,44 +160,39 @@
id="layer1"
transform="translate(-342.5,-521.36218)">
<g
style="display:inline"
id="use5671"
transform="matrix(1.3594109,0,0,1.3564242,319.2059,481.99447)">
<rect
transform="matrix(0.47304779,0,0,0.4807373,-6.3607039,-29.396216)"
rx="4.4136767"
y="125.3458"
x="50.440369"
height="29.154205"
width="29.559635"
id="rect11803"
style="color:#000000;fill:url(#linearGradient11811);fill-opacity:1;stroke:#3465a4;stroke-width:1.54426003000000001;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
ry="4.4233952" />
<path
inkscape:connector-curvature="0"
id="path11809"
d="m 17.87105,33.844107 0,-0.773112 c 0,-1.031264 0.807171,-1.836142 1.811982,-1.836142 l 9.612456,0 c 1.004811,0 1.787822,0.804878 1.787822,1.836142 l 0,0.773112 c 0,-1.031264 -0.783011,-1.836142 -1.787822,-1.836142 l -9.612456,0 c -1.004811,0 -1.811982,0.804878 -1.811982,1.836142 z"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
sodipodi:nodetypes="csssscssc" />
<path
sodipodi:nodetypes="csssscssc"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
d="m 17.87105,41.158551 0,0.773112 c 0,1.031264 0.807171,1.836142 1.811982,1.836142 l 9.612456,0 c 1.004811,0 1.787822,-0.804878 1.787822,-1.836142 l 0,-0.773112 c 0,1.031264 -0.783011,1.836142 -1.787822,1.836142 l -9.612456,0 c -1.004811,0 -1.811982,-0.804878 -1.811982,-1.836142 z"
id="path11867"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path11869"
d="m 17.87105,41.895784 0,0.773112 c 0,1.031264 0.644622,1.836142 1.649433,1.836142 l 10.067593,0 c 1.004811,0 1.495234,-0.804878 1.495234,-1.836142 l 0,-0.773112 c 0,1.031264 -0.783011,1.836142 -1.787822,1.836142 l -9.612456,0 c -1.004811,0 -1.811982,-0.804878 -1.811982,-1.836142 z"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#000000;fill-opacity:0.85253451;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
sodipodi:nodetypes="csssscssc" />
transform="matrix(0.80230061,0,0,0.80230061,-87.624044,-453.10297)"
id="g14586"
style="stroke-width:2.3714385;stroke-miterlimit:4;stroke-dasharray:none">
<g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
transform="matrix(1.9969286,0,0,1.9969286,-397.05491,877.00482)"
id="g15291-9"
style="stroke-width:1.18754292;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new">
<g
transform="translate(877.50354,-102.83507)"
id="g16853-4"
style="stroke-width:1.18754292;stroke-miterlimit:4;stroke-dasharray:none;enable-background:new">
<rect
transform="scale(1,-1)"
style="color:#000000;fill:url(#linearGradient14219);fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:1.24833274;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
id="rect6506-6"
width="11.281681"
height="11.26221"
x="-409.59354"
y="-284.40115"
rx="1.0052766"
ry="1.0052764" />
</g>
</g>
<g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
transform="translate(343.99999,987.99997)"
id="g5886"
style="stroke-width:2.3714385;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new" />
</g>
<rect
style="color:#000000;fill:none;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect17347"
width="21.943846"
height="21.943846"
x="342.29913"
y="521.58435" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -14,10 +14,22 @@
height="22"
id="svg3199"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="checkbox-focused.svg">
inkscape:version="0.48.1 r9760"
sodipodi:docname="checkbox.svg">
<defs
id="defs3201">
<linearGradient
id="linearGradient15404"
inkscape:collect="always">
<stop
id="stop15406"
offset="0"
style="stop-color:#515151;stop-opacity:1" />
<stop
id="stop15408"
offset="1"
style="stop-color:#292929;stop-opacity:1" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
@ -32,6 +44,27 @@
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5872-5-1"
id="linearGradient5891-0-4"
gradientUnits="userSpaceOnUse"
x1="205.84143"
y1="246.7094"
x2="206.74803"
y2="231.24142" />
<linearGradient
inkscape:collect="always"
id="linearGradient5872-5-1">
<stop
style="stop-color:#0b2e52;stop-opacity:1"
offset="0"
id="stop5874-4-4" />
<stop
style="stop-color:#1862af;stop-opacity:1"
offset="1"
id="stop5876-0-5" />
</linearGradient>
<inkscape:path-effect
effect="spiro"
id="path-effect5837-4-6"
@ -44,6 +77,16 @@
effect="spiro"
id="path-effect5884-4-7"
is_visible="true" />
<linearGradient
y2="-388.72955"
x2="-93.031357"
y1="-396.34738"
x1="-93.031357"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.685418)"
gradientUnits="userSpaceOnUse"
id="linearGradient14219"
xlink:href="#linearGradient15404"
inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
id="linearGradient10013-4-63-6">
@ -88,55 +131,30 @@
id="linearGradient15376"
xlink:href="#linearGradient10597-5"
inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5581-5-2-4-6-8-7-35-8"
id="linearGradient11811"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(3.0317573,0,0,1.0053174,-102.66338,-0.82153381)"
x1="63.568954"
y1="127.16142"
x2="63.568954"
y2="152.6618" />
<linearGradient
id="linearGradient5581-5-2-4-6-8-7-35-8">
<stop
id="stop5583-0-92-8-0-7-6-5-1"
offset="0"
style="stop-color:#454c4c;stop-opacity:1;" />
<stop
style="stop-color:#393f3f;stop-opacity:1;"
offset="0.40000001"
id="stop5585-4-7-2-7-9-9-92-0" />
<stop
id="stop5587-6-7-2-0-3-1-21-5"
offset="1"
style="stop-color:#2d3232;stop-opacity:1;" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#a2a2a2"
pagecolor="#000000"
bordercolor="#2d2d2d"
borderopacity="1"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="9.6447897"
inkscape:cy="12.591409"
inkscape:zoom="4"
inkscape:cx="71.247925"
inkscape:cy="33.339093"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1412"
inkscape:window-height="1067"
inkscape:window-x="184"
inkscape:window-y="233"
inkscape:window-x="2116"
inkscape:window-y="261"
inkscape:window-maximized="0"
borderlayer="true"
inkscape:showpageshadow="false"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
showborder="true">
showborder="false">
<inkscape:grid
type="xygrid"
id="grid14843"
@ -163,44 +181,38 @@
id="layer1"
transform="translate(-342.5,-521.36218)">
<g
style="display:inline"
id="use5671"
transform="matrix(1.3594109,0,0,1.3564242,319.2059,481.99447)">
<rect
transform="matrix(0.47304779,0,0,0.4807373,-6.3607039,-29.396216)"
rx="4.4136767"
y="125.3458"
x="50.440369"
height="29.154205"
width="29.559635"
id="rect11803"
style="color:#000000;fill:url(#linearGradient11811);fill-opacity:1;stroke:#1c1f1f;stroke-width:1.54426003;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
ry="4.4233952" />
<path
inkscape:connector-curvature="0"
id="path11809"
d="m 17.87105,33.844107 0,-0.773112 c 0,-1.031264 0.807171,-1.836142 1.811982,-1.836142 l 9.612456,0 c 1.004811,0 1.787822,0.804878 1.787822,1.836142 l 0,0.773112 c 0,-1.031264 -0.783011,-1.836142 -1.787822,-1.836142 l -9.612456,0 c -1.004811,0 -1.811982,0.804878 -1.811982,1.836142 z"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
sodipodi:nodetypes="csssscssc" />
<path
sodipodi:nodetypes="csssscssc"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
d="m 17.87105,41.158551 0,0.773112 c 0,1.031264 0.807171,1.836142 1.811982,1.836142 l 9.612456,0 c 1.004811,0 1.787822,-0.804878 1.787822,-1.836142 l 0,-0.773112 c 0,1.031264 -0.783011,1.836142 -1.787822,1.836142 l -9.612456,0 c -1.004811,0 -1.811982,-0.804878 -1.811982,-1.836142 z"
id="path11867"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path11869"
d="m 17.87105,41.895784 0,0.773112 c 0,1.031264 0.644622,1.836142 1.649433,1.836142 l 10.067593,0 c 1.004811,0 1.495234,-0.804878 1.495234,-1.836142 l 0,-0.773112 c 0,1.031264 -0.783011,1.836142 -1.787822,1.836142 l -9.612456,0 c -1.004811,0 -1.811982,-0.804878 -1.811982,-1.836142 z"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#000000;fill-opacity:0.85253451;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
sodipodi:nodetypes="csssscssc" />
transform="matrix(0.84337,0,0,0.84337,-110.16632,-503.56182)"
id="g14586">
<g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
transform="matrix(1.9969286,0,0,1.9969286,-397.05491,877.00482)"
id="g15291-9"
style="display:inline;enable-background:new">
<g
transform="translate(877.50354,-102.83507)"
id="g16853-4"
style="enable-background:new">
<rect
transform="scale(1,-1)"
style="color:#000000;fill:url(#linearGradient14219);fill-opacity:1;fill-rule:nonzero;stroke:#868686;stroke-width:0.59377144999999998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
id="rect6506-6"
width="11.281681"
height="11.26221"
x="-409.59354"
y="-284.40115"
rx="0.95632279"
ry="0.95632273" />
</g>
</g>
<g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
transform="translate(343.99999,987.99997)"
id="g5886"
style="display:inline;enable-background:new" />
</g>
<rect
style="color:#000000;fill:none;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect17347"
width="21.943846"
height="21.943846"
x="342.29913"
y="521.58435" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@ -14,8 +14,8 @@
height="22"
id="svg3199"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="checkbox.svg">
inkscape:version="0.48.1 r9760"
sodipodi:docname="checkbox-focused.svg">
<defs
id="defs3201">
<linearGradient
@ -131,55 +131,30 @@
id="linearGradient15376"
xlink:href="#linearGradient10597-5"
inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5581-5-2-4-6-8-7-35-8"
id="linearGradient11811"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(3.0317573,0,0,1.0053174,-102.66338,-0.82153381)"
x1="63.568954"
y1="127.16142"
x2="63.568954"
y2="152.6618" />
<linearGradient
id="linearGradient5581-5-2-4-6-8-7-35-8">
<stop
id="stop5583-0-92-8-0-7-6-5-1"
offset="0"
style="stop-color:#454c4c;stop-opacity:1;" />
<stop
style="stop-color:#393f3f;stop-opacity:1;"
offset="0.40000001"
id="stop5585-4-7-2-7-9-9-92-0" />
<stop
id="stop5587-6-7-2-0-3-1-21-5"
offset="1"
style="stop-color:#2d3232;stop-opacity:1;" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#a2a2a2"
pagecolor="#000000"
bordercolor="#2d2d2d"
borderopacity="1"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="-0.17876005"
inkscape:cy="11.944326"
inkscape:cx="64.516955"
inkscape:cy="13.871056"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="2560"
inkscape:window-height="1375"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:window-width="1412"
inkscape:window-height="1067"
inkscape:window-x="2635"
inkscape:window-y="226"
inkscape:window-maximized="0"
borderlayer="true"
inkscape:showpageshadow="false"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
showborder="true">
showborder="false">
<inkscape:grid
type="xygrid"
id="grid14843"
@ -196,7 +171,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
@ -206,56 +181,63 @@
id="layer1"
transform="translate(-342.5,-521.36218)">
<g
style="display:inline"
id="use5671"
transform="matrix(1.3594109,0,0,1.3564242,319.2059,481.99447)">
<rect
transform="matrix(0.47304779,0,0,0.4807373,-6.3607039,-29.396216)"
rx="4.4136767"
y="125.3458"
x="50.440369"
height="29.154205"
width="29.559635"
id="rect11803"
style="color:#000000;fill:url(#linearGradient11811);fill-opacity:1;stroke:#1c1f1f;stroke-width:1.54426003;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
ry="4.4233952" />
<path
inkscape:connector-curvature="0"
id="path11809"
d="m 17.87105,33.844107 0,-0.773112 c 0,-1.031264 0.807171,-1.836142 1.811982,-1.836142 l 9.612456,0 c 1.004811,0 1.787822,0.804878 1.787822,1.836142 l 0,0.773112 c 0,-1.031264 -0.783011,-1.836142 -1.787822,-1.836142 l -9.612456,0 c -1.004811,0 -1.811982,0.804878 -1.811982,1.836142 z"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
sodipodi:nodetypes="csssscssc" />
<path
sodipodi:nodetypes="csssscssc"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
d="m 17.87105,41.158551 0,0.773112 c 0,1.031264 0.807171,1.836142 1.811982,1.836142 l 9.612456,0 c 1.004811,0 1.787822,-0.804878 1.787822,-1.836142 l 0,-0.773112 c 0,1.031264 -0.783011,1.836142 -1.787822,1.836142 l -9.612456,0 c -1.004811,0 -1.811982,-0.804878 -1.811982,-1.836142 z"
id="path11867"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path11869"
d="m 17.87105,41.895784 0,0.773112 c 0,1.031264 0.644622,1.836142 1.649433,1.836142 l 10.067593,0 c 1.004811,0 1.495234,-0.804878 1.495234,-1.836142 l 0,-0.773112 c 0,1.031264 -0.783011,1.836142 -1.787822,1.836142 l -9.612456,0 c -1.004811,0 -1.811982,-0.804878 -1.811982,-1.836142 z"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#000000;fill-opacity:0.85253451;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
sodipodi:nodetypes="csssscssc" />
transform="matrix(0.84337,0,0,0.84337,-110.16632,-503.56182)"
id="g14586">
<g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
transform="matrix(1.9969286,0,0,1.9969286,-397.05491,877.00482)"
id="g15291-9"
style="display:inline;enable-background:new">
<g
transform="translate(877.50354,-102.83507)"
id="g16853-4"
style="enable-background:new">
<rect
transform="scale(1,-1)"
style="color:#000000;fill:url(#linearGradient14219);fill-opacity:1;fill-rule:nonzero;stroke:#868686;stroke-width:0.59377144999999998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
id="rect6506-6"
width="11.281681"
height="11.26221"
x="-409.59354"
y="-284.40115"
rx="0.95632279"
ry="0.95632273" />
</g>
</g>
<g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
transform="translate(343.99999,987.99997)"
id="g5886"
style="display:inline;enable-background:new">
<path
style="fill:none;stroke:url(#linearGradient5891-0-4);stroke-width:7.11431503;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 198.5,240 5.25,5.25 13.98616,-14.43081"
id="path5835"
inkscape:path-effect="#path-effect5837-4-6"
inkscape:original-d="m 198.5,240 5.25,5.25 13.98616,-14.43081"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
inkscape:connector-curvature="0"
inkscape:original-d="m 198.5,240 5.25,5.25 13.91205,-14.31964"
inkscape:path-effect="#path-effect5837-4-6"
id="path5880"
d="m 198.5,240 5.25,5.25 13.91205,-14.31964"
style="fill:none;stroke:#4787c8;stroke-width:3.55715752;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#7ea7d3;stroke-width:1.18571913px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 197.45937,240.47455 c -0.17828,-0.29362 -0.20087,-0.67548 -0.0603,-0.98892 0.14055,-0.31344 0.43739,-0.54812 0.77144,-0.62817 0.33405,-0.08 0.69314,-0.01 0.99635,0.15175 0.30321,0.16144 0.55146,0.40727 0.79165,0.65284 l 3.66429,3.74643 12.87946,-12.98973 c 0.20796,-0.20974 0.42306,-0.41969 0.68548,-0.55522 0.26242,-0.13553 0.57293,-0.19052 0.85827,-0.11426 0.14267,0.0381 0.27708,0.10787 0.38874,0.20452 0.11167,0.0966 0.20021,0.22004 0.25479,0.35726 0.0546,0.13722 0.075,0.28793 0.0585,0.43468 -0.0165,0.14674 -0.07,0.28919 -0.15422,0.41052"
id="path5882"
inkscape:path-effect="#path-effect5884-4-7"
inkscape:original-d="m 197.45937,240.47455 c 0.65604,-0.56057 2.02485,-1.34847 2.49911,-0.8125 l 3.66429,3.74643 12.87946,-12.98973 c 0.6875,-0.6875 2.09152,0.7375 2.09152,0.7375"
inkscape:connector-curvature="0"
sodipodi:nodetypes="csccc" />
</g>
</g>
<rect
style="color:#000000;fill:none;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect17347"
width="21.943846"
height="21.943846"
x="342.29913"
y="521.58435" />
<path
inkscape:connector-curvature="0"
style="opacity:0.8;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.99999994;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 359.97505,524.8252 -7.88606,7.71465 -2.57155,-2.57155 -2.91442,-0.0427 0,2.35727 4.02875,3.98587 c 0.80342,0.80309 2.111,0.80309 2.91442,0 l 8.18609,-8.22894 0,-0.38573 c 0,-1.24128 0.19944,-1.76801 -0.82915,-2.29836 z"
id="rect5147-9-1-5-7-6-5-8-7"
sodipodi:nodetypes="ccccccccscc" />
<path
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:sans-serif;-inkscape-font-specification:sans-serif"
d="m 361.65223,524.52745 -9.5602,9.36735 -2.56345,-2.56344 -2.92846,-0.0214 0.0153,2.32639 4.02203,4.02206 c 0.80341,0.80309 2.10565,0.80309 2.90906,0 l 10.95049,-11.05765 0.003,-2.1502 z"
id="path12830-4-17-0"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccc" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +0,0 @@
@import "gnome-shell-sass/_high-contrast-colors"; //use gtk colors
@import "gnome-shell-sass/_drawing";
@import "gnome-shell-sass/_common";
//force symbolic icons
stage {
-st-icon-style: symbolic;
}
.toggle-switch { width: 48px; }
.toggle-switch-us, .toggle-switch-intl {
background-image: url("resource:///org/gnome/shell/theme/toggle-off-hc.svg");
&:checked { background-image: url("resource:///org/gnome/shell/theme/toggle-on-hc.svg"); }
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +0,0 @@
$variant: 'dark';
@import "gnome-shell-sass/_colors"; //use gtk colors
@import "gnome-shell-sass/_drawing";
@import "gnome-shell-sass/_common";

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -1,119 +0,0 @@
<?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="64px"
height="64px"
id="svg3471"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="New document 5">
<defs
id="defs3473" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.5"
inkscape:cx="32"
inkscape:cy="32"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1461"
inkscape:window-height="772"
inkscape:window-x="37"
inkscape:window-y="64"
inkscape:window-maximized="0" />
<metadata
id="metadata3476">
<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">
<g
transform="matrix(4,0,0,4,1.9999997,2.3636364)"
id="g19145"
style="fill:#bebebe;fill-opacity:1;display:inline">
<g
id="g19147"
inkscape:label="status"
style="fill:#bebebe;fill-opacity:1;display:inline"
transform="translate(-541.0002,-301)" />
<g
style="fill:#bebebe;fill-opacity:1"
id="g19149"
inkscape:label="devices"
transform="translate(-541.0002,-301)" />
<g
style="fill:#bebebe;fill-opacity:1"
id="g19151"
inkscape:label="apps"
transform="translate(-541.0002,-301)" />
<g
style="fill:#bebebe;fill-opacity:1"
id="g19153"
inkscape:label="places"
transform="translate(-541.0002,-301)" />
<g
style="fill:#bebebe;fill-opacity:1"
id="g19155"
inkscape:label="mimetypes"
transform="translate(-541.0002,-301)">
<path
inkscape:connector-curvature="0"
d="m 543.0002,301 c -1.05237,0 -2,0.84508 -2,1.9375 l 0,11.125 c 0,1.09242 0.94763,1.9375 2,1.9375 l 11,0 c 1.05237,0 2,-0.84508 2,-1.9375 l 0,-11.125 c 0,-1.09242 -0.94763,-1.9375 -2,-1.9375 l -11,0 z m 0,5 3.03125,0 0,2 -3.03125,0 0,-2 z m 4.03125,0 2.96875,0 0,2 -2.96875,0 0,-2 z m 3.96875,0 3,0 0,2 -3,0 0,-2 z m -8,3 3.03125,0 0,2 -3.03125,0 0,-2 z m 4.03125,0 2.96875,0 0,2 -2.96875,0 0,-2 z m 3.96875,0 3,0 0,2 -3,0 0,-2 z m -8,3 3.03125,0 0,2 -3.03125,0 0,-2 z m 4.03125,0 2.96875,0 0,2 -2.96875,0 0,-2 z m 3.96875,0 3,0 0,2 -3,0 0,-2 z"
id="path19157"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new;font-family:Sans;-inkscape-font-specification:Sans" />
<rect
height="1.9999993"
id="rect19159"
style="opacity:0.35;color:#000000;fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
width="2.9999993"
x="551.00018"
y="309" />
</g>
<g
id="g19161"
inkscape:label="emblems"
style="fill:#bebebe;fill-opacity:1;display:inline"
transform="translate(-541.0002,-301)" />
<g
id="g19163"
inkscape:label="emotes"
style="fill:#bebebe;fill-opacity:1;display:inline"
transform="translate(-541.0002,-301)" />
<g
id="g19165"
inkscape:label="categories"
style="fill:#bebebe;fill-opacity:1;display:inline"
transform="translate(-541.0002,-301)" />
<g
id="g19167"
inkscape:label="actions"
style="fill:#bebebe;fill-opacity:1;display:inline"
transform="translate(-541.0002,-301)" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -1,114 +0,0 @@
<?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="64px"
height="64px"
id="svg3393"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="New document 2">
<defs
id="defs3395" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.5"
inkscape:cx="32"
inkscape:cy="32"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="697"
inkscape:window-height="613"
inkscape:window-x="100"
inkscape:window-y="77"
inkscape:window-maximized="0" />
<metadata
id="metadata3398">
<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">
<g
style="display:inline"
transform="matrix(4,0,0,4,0.29733827,-0.35415646)"
id="g19245">
<g
id="g19247"
inkscape:label="status"
style="display:inline"
transform="translate(-323.02908,-649.02581)" />
<g
id="g19249"
inkscape:label="devices"
transform="translate(-323.02908,-649.02581)" />
<g
id="g19251"
inkscape:label="apps"
transform="translate(-323.02908,-649.02581)">
<path
inkscape:connector-curvature="0"
d="m 331.9377,653 c 0.0187,0.16677 0.0625,0.32822 0.0625,0.5 0,2.48528 -2.01472,4.5 -4.5,4.5 -0.11769,0 -0.22834,-0.0224 -0.34375,-0.0312 l 0,2.21875 c 0,1.00412 0.80838,1.8125 1.8125,1.8125 l 1.54511,-5e-5 2,2.04688 2.0625,-2.04688 1.61114,0 c 1.00413,0 1.8125,-0.80838 1.8125,-1.8125 l 0,-5.375 c 0,-1.00412 -0.80837,-1.8125 -1.8125,-1.8125 z"
id="path19253"
sodipodi:nodetypes="csscsscccssssc"
style="opacity:0.5;color:#000000;fill:#c3c3c3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
inkscape:connector-curvature="0"
d="m 327.5002,650 c -1.933,0 -3.5,1.567 -3.5,3.5 0,1.933 1.567,3.5 3.5,3.5 1.933,0 3.5,-1.567 3.5,-3.5 0,-1.933 -1.567,-3.5 -3.5,-3.5 z m -0.53125,1 1.03125,0 -0.0625,1.375 a 0.19951718,0.19951718 0 0 0 0,0.0625 0.19951718,0.19951718 0 0 0 0,0.0312 0.19951718,0.19951718 0 0 0 0.125,0.125 0.19951718,0.19951718 0 0 0 0.0312,0 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 l 1.15625,-0.75 0.5,0.90625 -1.21875,0.625 a 0.19951718,0.19951718 0 0 0 -0.0312,0 0.19951718,0.19951718 0 0 0 -0.0312,0.0312 0.19951718,0.19951718 0 0 0 -0.0312,0.0937 0.19951718,0.19951718 0 0 0 0,0.0625 0.19951718,0.19951718 0 0 0 0,0.0312 0.19951718,0.19951718 0 0 0 0.0312,0.0625 0.19951718,0.19951718 0 0 0 0.0312,0.0312 0.19951718,0.19951718 0 0 0 0.0312,0.0312 l 1.25,0.625 -0.53125,0.90625 -1.15625,-0.781 a 0.19951718,0.19951718 0 0 0 -0.0312,0 0.19951718,0.19951718 0 0 0 -0.0625,-0.0312 0.19951718,0.19951718 0 0 0 -0.0625,0 0.19951718,0.19951718 0 0 0 -0.125,0.0937 0.19951718,0.19951718 0 0 0 -0.0312,0.0312 0.19951718,0.19951718 0 0 0 0,0.0312 0.19951718,0.19951718 0 0 0 0,0.0625 l 0.0625,1.3751 -1.03125,0 0.0937,-1.375 a 0.19951718,0.19951718 0 0 0 -0.0312,-0.0937 0.19951718,0.19951718 0 0 0 -0.0312,-0.0625 0.19951718,0.19951718 0 0 0 -0.0625,-0.0312 0.19951718,0.19951718 0 0 0 -0.0625,-0.0312 0.19951718,0.19951718 0 0 0 -0.0312,0 0.19951718,0.19951718 0 0 0 -0.0937,0.0312 l -1.1875,0.78125 -0.5,-0.90625 1.25,-0.625 a 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0625 0.19951718,0.19951718 0 0 0 0,-0.0312 0.19951718,0.19951718 0 0 0 0,-0.0625 0.19951718,0.19951718 0 0 0 0,-0.0312 0.19951718,0.19951718 0 0 0 -0.0312,-0.0625 0.19951718,0.19951718 0 0 0 -0.0312,-0.0312 0.19951718,0.19951718 0 0 0 -0.0312,0 l -1.25,-0.625 0.5,-0.90625 1.1875,0.75 a 0.19951718,0.19951718 0 0 0 0.0312,0.0312 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0312,0 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0625 0.19951718,0.19951718 0 0 0 0,-0.0312 L 326.96895,651 z"
id="path19255"
style="color:#000000;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
<g
id="g19257"
inkscape:label="places"
transform="translate(-323.02908,-649.02581)" />
<g
id="g19259"
inkscape:label="mimetypes"
transform="translate(-323.02908,-649.02581)" />
<g
id="g19261"
inkscape:label="emblems"
style="display:inline"
transform="translate(-323.02908,-649.02581)" />
<g
id="g19263"
inkscape:label="emotes"
style="display:inline"
transform="translate(-323.02908,-649.02581)" />
<g
id="g19265"
inkscape:label="categories"
style="display:inline"
transform="translate(-323.02908,-649.02581)" />
<g
id="g19267"
inkscape:label="actions"
style="display:inline"
transform="translate(-323.02908,-649.02581)" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -0,0 +1,74 @@
<?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="17"
height="10"
id="svg2"
version="1.1"
inkscape:version="0.48.1 r9760"
sodipodi:docname="panel-button-border.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="44.8"
inkscape:cx="8.6594891"
inkscape:cy="5.7029946"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1440"
inkscape:window-height="843"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1"
guidetolerance="10000"
objecttolerance="10000">
<inkscape:grid
type="xygrid"
id="grid3792"
empspacing="10"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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 />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke-width:0.43599999;stroke-miterlimit:4;stroke-dasharray:none"
id="rect3796"
width="7"
height="2"
x="5"
y="8" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,111 @@
<?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:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="30"
height="25"
id="svg10621"
version="1.1"
inkscape:version="0.48.1 r9760"
sodipodi:docname="panel-button-highlight-narrow.svg">
<defs
id="defs10623">
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient34508-1-3"
id="radialGradient99561-1"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.72146227,0,0,0.27484277,14.205424,21.754717)"
cx="51"
cy="30"
fx="51"
fy="30"
r="42" />
<linearGradient
inkscape:collect="always"
id="linearGradient34508-1-3">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop34510-1-9" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop34512-4-5" />
</linearGradient>
<radialGradient
r="42"
fy="30"
fx="51"
cy="30"
cx="51"
gradientTransform="matrix(0.72146227,0,0,0.27484277,14.205424,21.754717)"
gradientUnits="userSpaceOnUse"
id="radialGradient10592"
xlink:href="#linearGradient34508-1-3"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1.979899"
inkscape:cx="-171.36384"
inkscape:cy="-53.255157"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1440"
inkscape:window-height="843"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1" />
<metadata
id="metadata10626">
<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 />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-468.08632,-537.03477)">
<path
sodipodi:type="arc"
style="opacity:0.4625;color:#000000;fill:url(#radialGradient10592);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path34506-3"
sodipodi:cx="51"
sodipodi:cy="30"
sodipodi:rx="42"
sodipodi:ry="16"
d="M 9,29.999999 C 9.0000011,21.163443 27.804042,14 51.000002,14 74.195961,14 93,21.163444 93,30 l -42,0 z"
sodipodi:start="3.1415927"
sodipodi:end="6.2831853"
transform="matrix(0.35714286,0,0,1.5625,464.87203,515.15977)"
inkscape:export-filename="/home/jimmac/src/cvs/gnome/gnome-shell-design/mockups/motion/textures/panel.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,111 @@
<?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:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="84"
height="25"
id="svg10621"
version="1.1"
inkscape:version="0.48.0 r9654"
sodipodi:docname="panel-button-highlight-wide.svg">
<defs
id="defs10623">
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient34508-1-3"
id="radialGradient99561-1"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.72146227,0,0,0.27484277,14.205424,21.754717)"
cx="51"
cy="30"
fx="51"
fy="30"
r="42" />
<linearGradient
inkscape:collect="always"
id="linearGradient34508-1-3">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop34510-1-9" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop34512-4-5" />
</linearGradient>
<radialGradient
r="42"
fy="30"
fx="51"
cy="30"
cx="51"
gradientTransform="matrix(0.72146227,0,0,0.27484277,14.205424,21.754717)"
gradientUnits="userSpaceOnUse"
id="radialGradient10592"
xlink:href="#linearGradient34508-1-3"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1.979899"
inkscape:cx="-118.50071"
inkscape:cy="27.304508"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1440"
inkscape:window-height="843"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1" />
<metadata
id="metadata10626">
<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 />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-441.08632,-537.03477)">
<path
sodipodi:type="arc"
style="opacity:0.4625;color:#000000;fill:url(#radialGradient10592);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path34506-3"
sodipodi:cx="51"
sodipodi:cy="30"
sodipodi:rx="42"
sodipodi:ry="16"
d="M 9,29.999999 C 9.0000011,21.163443 27.804042,14 51.000002,14 74.195961,14 93,21.163444 93,30 l -42,0 z"
sodipodi:start="3.1415927"
sodipodi:end="6.2831853"
transform="matrix(1,0,0,1.5625,432.08632,515.15977)"
inkscape:export-filename="/home/jimmac/src/cvs/gnome/gnome-shell-design/mockups/motion/textures/panel.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -1,3 +0,0 @@
#!/usr/bin/bash
bundle exec sass --update --sourcemap=none .

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@ -1,133 +0,0 @@
<?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="48"
height="22"
id="svg2857"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="toggle-off-hc.svg">
<defs
id="defs2859">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective2865" />
<inkscape:perspective
id="perspective2843"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:path-effect
effect="spiro"
id="path-effect77541-4"
is_visible="true" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="-6.1820581"
inkscape:cy="-16.463788"
inkscape:document-units="px"
inkscape:current-layer="g37994"
showgrid="false"
inkscape:window-width="2560"
inkscape:window-height="1364"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
borderlayer="true"
inkscape:showpageshadow="false"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
showborder="true">
<inkscape:grid
type="xygrid"
id="grid12954"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata2862">
<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
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-444.64286,-781.36218)">
<g
transform="matrix(0.6526046,0,0,0.80554422,99.592644,-636.32172)"
id="g37994">
<g
transform="matrix(1.5323214,0,0,1.2413968,-324.76058,489.69039)"
id="toggle-off"
inkscape:label="#g8477">
<circle
cy="1033.993"
cx="571.95966"
id="path8444"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
r="7" />
<rect
ry="2.0108337"
rx="1.9562569"
y="1031.9885"
x="565.0083"
height="4.0216675"
width="34.850178"
id="rect8461"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
</g>
<g
transform="matrix(1.5323214,0,0,1.2413968,-324.85635,491.16456)"
id="toggle-on"
inkscape:label="#g8481">
<rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#3465a4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect8475"
width="34.850178"
height="4.0216675"
x="565.0083"
y="1070.9279"
rx="1.9562569"
ry="2.0108337" />
<circle
transform="scale(-1,1)"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#3465a4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="circle8463"
cx="-591.0213"
cy="1072.9402"
r="9" />
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -7,127 +7,51 @@
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:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="65"
height="22"
id="svg2857"
id="svg3273"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="toggle-off-us.svg">
inkscape:version="0.47 r22583"
sodipodi:docname="New document 14">
<defs
id="defs2859">
id="defs3275">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective2865" />
id="perspective3281" />
<inkscape:perspective
id="perspective2843"
id="perspective3261"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient76469-7-7-4"
id="linearGradient38024"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0215462,0,0,1.0322581,717.22867,428.68472)"
x1="6"
y1="102.95528"
x2="6"
y2="84.505203" />
<linearGradient
inkscape:collect="always"
id="linearGradient76469-7-7-4">
<stop
style="stop-color:#2e3232;stop-opacity:1"
offset="0"
id="stop76471-7-1-5" />
<stop
style="stop-color:#3e4545;stop-opacity:1"
offset="1"
id="stop76473-9-0-0" />
</linearGradient>
<inkscape:path-effect
effect="spiro"
id="path-effect77541-4"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect77541-4-0"
is_visible="true" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient37802-8"
id="linearGradient12311-3-1-0-5-4"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.071426)"
x1="610.13782"
y1="501.43866"
x2="610.13782"
y2="492.52756" />
<linearGradient
id="linearGradient37802-8"
inkscape:collect="always">
<stop
id="stop37804-1"
offset="0"
style="stop-color:#2c2c2c;stop-opacity:1" />
<stop
id="stop37806-8"
offset="1"
style="stop-color:#16191a;stop-opacity:1" />
</linearGradient>
<linearGradient
y2="492.52756"
x2="610.13782"
y1="501.43866"
x1="610.13782"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-900.56122,-423.92857)"
gradientUnits="userSpaceOnUse"
id="linearGradient13602"
xlink:href="#linearGradient37802-8"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#000000"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="-5.0602834"
inkscape:cy="16.473273"
inkscape:zoom="0.35"
inkscape:cx="32.000004"
inkscape:cy="10.999997"
inkscape:document-units="px"
inkscape:current-layer="g37994"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="2560"
inkscape:window-height="1375"
inkscape:window-width="609"
inkscape:window-height="501"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
borderlayer="true"
inkscape:showpageshadow="false"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
showborder="false">
<inkscape:grid
type="xygrid"
id="grid12954"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
inkscape:window-y="26"
inkscape:window-maximized="0" />
<metadata
id="metadata2862">
id="metadata3278">
<rdf:RDF>
<cc:Work
rdf:about="">
@ -142,68 +66,61 @@
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-444.64286,-781.36218)">
transform="translate(-343,-521.36218)">
<g
transform="matrix(0.6526046,0,0,0.80554422,99.592644,-636.32172)"
id="g37994">
id="g17454"
transform="translate(-453,448.36218)"
style="display:inline">
<rect
transform="scale(-1,1)"
ry="4"
rx="4"
y="74.5"
x="-859.5"
height="19"
width="63.000004"
id="rect17456"
style="color:#000000;fill:none;stroke:#2e3436;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<rect
transform="scale(-1,1)"
ry="4"
rx="4"
y="74"
x="-828"
height="20"
width="31"
id="rect17458"
style="fill:#000000;fill-opacity:1;stroke:#5f5f5f;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline" />
<g
id="g37996"
transform="translate(-115,1277)">
<rect
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964000000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0.19591837"
id="rect13475"
width="98"
height="25"
x="644.5"
y="484.61118"
rx="4.7429576"
ry="3.8424656" />
<rect
ry="3.8424656"
rx="4.7429576"
y="483.5"
x="644.5"
height="25"
width="98"
id="rect38000"
style="color:#000000;fill:url(#linearGradient12311-3-1-0-5-4);fill-opacity:1;fill-rule:nonzero;stroke:#16191a;stroke-width:1.37920942;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
</g>
<g
transform="translate(-49.946213,-1.890275)"
id="g38002">
<g
transform="translate(-115,1247)"
style="display:inline"
id="g38004">
<rect
ry="3.7972314"
rx="4.6871223"
y="515.5"
x="694.53046"
height="25"
width="45.969578"
id="rect38006"
style="color:#000000;fill:url(#linearGradient38024);fill-opacity:1;fill-rule:nonzero;stroke:#1f2020;stroke-width:1.37920964;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
sodipodi:nodetypes="cc"
style="opacity:0.1;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 699.09675,516.7365 36.86904,0"
id="path38016"
inkscape:path-effect="#path-effect77541-4"
inkscape:original-d="m 699.09675,516.7365 36.86904,0"
inkscape:connector-curvature="0" />
</g>
transform="matrix(-1,0,0,1,1619.1239,-33.986291)"
id="g17460"
style="display:inline">
<path
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="m 803.6322,115.48629 0,4.29495"
id="path17462"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
d="m 806.62805,115.48629 0,4.29495"
id="path17464"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
d="m 809.6239,115.48629 0,4.29495"
id="path17466"
inkscape:connector-curvature="0" />
</g>
<path
sodipodi:type="arc"
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:2.15627193;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
id="path13479"
sodipodi:cx="16.4375"
sodipodi:cy="10.8125"
sodipodi:rx="4.3125"
sodipodi:ry="4.3125"
d="m 20.75,10.8125 a 4.3125,4.3125 0 1 1 -8.625,0 4.3125,4.3125 0 1 1 8.625,0 z"
transform="matrix(1.4212691,0,0,1.1514287,577.38488,1761.1138)" />
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.96875012;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path18722"
sodipodi:cx="47.6875"
sodipodi:cy="11.5625"
sodipodi:rx="3.9375"
sodipodi:ry="3.9375"
d="m 51.625,11.5625 c 0,2.174621 -1.762879,3.9375 -3.9375,3.9375 -2.174621,0 -3.9375,-1.762879 -3.9375,-3.9375 0,-2.1746212 1.762879,-3.9375 3.9375,-3.9375 2.174621,0 3.9375,1.7628788 3.9375,3.9375 z"
transform="matrix(1.0158729,0,0,1.0158729,795.55556,72.25399)" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -7,171 +7,51 @@
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:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="65"
height="22"
id="svg2857"
id="svg3012"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="toggle-on-intl.svg">
inkscape:version="0.47 r22583"
sodipodi:docname="New document 6">
<defs
id="defs2859">
id="defs3014">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective2865" />
id="perspective3020" />
<inkscape:perspective
id="perspective2843"
id="perspective2997"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient76469-7-7-4"
id="linearGradient38024"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0215462,0,0,1.0322581,717.22867,428.68472)"
x1="6"
y1="102.95528"
x2="6"
y2="84.505203" />
<linearGradient
inkscape:collect="always"
id="linearGradient76469-7-7-4">
<stop
style="stop-color:#2e3232;stop-opacity:1"
offset="0"
id="stop76471-7-1-5" />
<stop
style="stop-color:#3e4545;stop-opacity:1"
offset="1"
id="stop76473-9-0-0" />
</linearGradient>
<inkscape:path-effect
effect="spiro"
id="path-effect77541-4"
is_visible="true" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient37802"
id="linearGradient12311-3-1-0-5"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.071426)"
x1="610.13782"
y1="501.43866"
x2="610.13782"
y2="492.52756" />
<linearGradient
id="linearGradient37802"
inkscape:collect="always">
<stop
id="stop37804"
offset="0"
style="stop-color:#2c2c2c;stop-opacity:1" />
<stop
id="stop37806"
offset="1"
style="stop-color:#16191a;stop-opacity:1" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient76469-7-7-4-3"
id="linearGradient77680"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,1.0322581,717.71949,428.68472)"
x1="6"
y1="102.95528"
x2="6"
y2="84.505203" />
<linearGradient
inkscape:collect="always"
id="linearGradient76469-7-7-4-3">
<stop
style="stop-color:#2e3232;stop-opacity:1"
offset="0"
id="stop76471-7-1-5-7" />
<stop
style="stop-color:#3e4545;stop-opacity:1"
offset="1"
id="stop76473-9-0-0-9" />
</linearGradient>
<inkscape:path-effect
effect="spiro"
id="path-effect77541-4-0"
is_visible="true" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient37802-8"
id="linearGradient12311-3-1-0-5-4"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.071426)"
x1="610.13782"
y1="501.43866"
x2="610.13782"
y2="492.52756" />
<linearGradient
id="linearGradient37802-8"
inkscape:collect="always">
<stop
id="stop37804-1"
offset="0"
style="stop-color:#2c2c2c;stop-opacity:1" />
<stop
id="stop37806-8"
offset="1"
style="stop-color:#16191a;stop-opacity:1" />
</linearGradient>
<linearGradient
y2="492.52756"
x2="610.13782"
y1="501.43866"
x1="610.13782"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-900.56122,-423.92857)"
gradientUnits="userSpaceOnUse"
id="linearGradient13602"
xlink:href="#linearGradient37802-8"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#000000"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="16.760995"
inkscape:cy="21.955673"
inkscape:zoom="0.35"
inkscape:cx="32.000004"
inkscape:cy="10.999997"
inkscape:document-units="px"
inkscape:current-layer="g37994"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="2560"
inkscape:window-height="1375"
inkscape:window-width="609"
inkscape:window-height="501"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
borderlayer="true"
inkscape:showpageshadow="false"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
showborder="false">
<inkscape:grid
type="xygrid"
id="grid12954"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
inkscape:window-y="26"
inkscape:window-maximized="0" />
<metadata
id="metadata2862">
id="metadata3017">
<rdf:RDF>
<cc:Work
rdf:about="">
@ -186,70 +66,73 @@
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-444.64286,-781.36218)">
transform="translate(-343,-521.36218)">
<g
transform="matrix(0.6526046,0,0,0.80554422,99.592644,-636.32172)"
id="g37994">
id="g17454"
transform="translate(-453,448.36218)"
style="display:inline">
<rect
transform="scale(-1,1)"
ry="4"
rx="4"
y="74.5"
x="-859.5"
height="19"
width="63.000004"
id="rect17456"
style="color:#000000;fill:none;stroke:#2e3436;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<rect
transform="scale(-1,1)"
ry="4"
rx="4"
y="74"
x="-828"
height="20"
width="31"
id="rect17458"
style="fill:#000000;fill-opacity:1;stroke:#5f5f5f;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline" />
<g
id="g37996"
transform="translate(-115,1277)">
<rect
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964000000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0.19591837"
id="rect13475"
width="98"
height="25"
x="644.5"
y="484.61118"
rx="4.7429576"
ry="3.8424656" />
<rect
ry="3.8424656"
rx="4.7429576"
y="483.5"
x="644.5"
height="25"
width="98"
id="rect38000"
style="color:#000000;fill:url(#linearGradient12311-3-1-0-5-4);fill-opacity:1;fill-rule:nonzero;stroke:#16191a;stroke-width:1.37920942;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
transform="matrix(-1,0,0,1,1619.1239,-33.986291)"
id="g17460"
style="display:inline">
<path
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="m 803.6322,115.48629 0,4.29495"
id="path17462"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
d="m 806.62805,115.48629 0,4.29495"
id="path17464"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
d="m 809.6239,115.48629 0,4.29495"
id="path17466"
inkscape:connector-curvature="0" />
</g>
<g
transform="translate(-49.946213,-1.890275)"
id="g38002">
<g
transform="translate(-115,1247)"
style="display:inline"
id="g38004">
<rect
ry="3.7972314"
rx="4.6871223"
y="515.5"
x="694.53046"
height="25"
width="45.969578"
id="rect38006"
style="color:#000000;fill:url(#linearGradient38024);fill-opacity:1;fill-rule:nonzero;stroke:#1f2020;stroke-width:1.37920964;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
sodipodi:nodetypes="cc"
style="opacity:0.1;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 699.09675,516.7365 36.86904,0"
id="path38016"
inkscape:path-effect="#path-effect77541-4"
inkscape:original-d="m 699.09675,516.7365 36.86904,0"
inkscape:connector-curvature="0" />
</g>
style="font-size:8.95877075px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:125%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
id="text17468"
transform="translate(0.34375,0)">
<path
d="m 837.28518,80.750726 c 0.63282,6e-6 1.19566,0.123947 1.68852,0.371824 0.49284,0.247888 0.8807,0.609505 1.16359,1.084851 0.28287,0.472439 0.42431,1.022155 0.42431,1.649149 0,0.635748 -0.13853,1.200045 -0.41556,1.692892 -0.27706,0.489934 -0.66638,0.870507 -1.16797,1.141719 -0.5016,0.271213 -1.07756,0.406819 -1.72789,0.406819 -0.42869,0 -0.83551,-0.06562 -1.22045,-0.196848 -0.38495,-0.134148 -0.73053,-0.32808 -1.03674,-0.581795 -0.30329,-0.256631 -0.54534,-0.589085 -0.72615,-0.997363 -0.17789,-0.408276 -0.26684,-0.869045 -0.26683,-1.382311 -10e-6,-0.638658 0.13997,-1.200039 0.41994,-1.684144 0.27996,-0.487011 0.66782,-0.858835 1.16359,-1.115472 0.49576,-0.259541 1.06297,-0.389315 1.70164,-0.389321 m 0.57305,1.089225 c -0.20123,-0.05249 -0.40683,-0.07873 -0.61679,-0.07874 -0.20998,5e-6 -0.41412,0.02625 -0.61242,0.07874 -0.19831,0.04958 -0.38933,0.129779 -0.57305,0.240592 -0.18081,0.107907 -0.33974,0.242055 -0.47681,0.402445 -0.13706,0.160399 -0.24642,0.358705 -0.32808,0.594918 -0.0816,0.233306 -0.12248,0.491395 -0.12248,0.774269 0,0.67366 0.20851,1.214627 0.62554,1.622903 0.41702,0.408278 0.93758,0.612416 1.56166,0.612416 0.25954,0 0.51034,-0.04229 0.7524,-0.126858 0.24496,-0.08457 0.47097,-0.20997 0.67803,-0.376198 0.20705,-0.166226 0.37328,-0.392236 0.49868,-0.678032 0.12539,-0.285792 0.18809,-0.610956 0.1881,-0.975492 -10e-6,-0.297455 -0.0437,-0.568668 -0.13123,-0.813638 -0.0875,-0.247878 -0.20415,-0.453475 -0.34995,-0.61679 -0.14291,-0.163307 -0.31059,-0.301829 -0.50306,-0.415568 -0.18956,-0.11373 -0.38641,-0.195385 -0.59054,-0.244967"
style="line-height:125%;fill:#ffffff;fill-opacity:1;marker:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
id="path18599"
inkscape:connector-curvature="0" />
<path
d="m 843.5362,81.831203 0,1.17917 2.94834,0 0,1.014861 -2.94834,0 0,3.00713 -1.10673,0 0,-6.216022 4.31754,0 0,1.014861 -3.21081,0"
style="line-height:125%;fill:#ffffff;fill-opacity:1;marker:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
id="path18601"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccc" />
<path
d="m 849.71285,81.831203 0,1.17917 2.94834,0 0,1.014861 -2.94834,0 0,3.00713 -1.10672,0 0,-6.216022 4.31753,0 0,1.014861 -3.21081,0"
style="line-height:125%;fill:#ffffff;fill-opacity:1;marker:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
id="path18603"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccc" />
</g>
<text
xml:space="preserve"
style="font-size:13.79166794px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
x="520.29974"
y="1997.0011"
id="text75614"
sodipodi:linespacing="125%"
transform="scale(1.1236771,0.88993537)"><tspan
sodipodi:role="line"
id="tspan75616"
x="520.29974"
y="1997.0011">OFF</tspan></text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@ -1,113 +0,0 @@
<?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="48"
height="22"
id="svg2857"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="toggle-on-hc.svg">
<defs
id="defs2859">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective2865" />
<inkscape:perspective
id="perspective2843"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:path-effect
effect="spiro"
id="path-effect77541-4"
is_visible="true" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="-222.95215"
inkscape:cy="3.9378433"
inkscape:document-units="px"
inkscape:current-layer="g37994"
showgrid="false"
inkscape:window-width="2560"
inkscape:window-height="1364"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
borderlayer="true"
inkscape:showpageshadow="false"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
showborder="true">
<inkscape:grid
type="xygrid"
id="grid12954"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata2862">
<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
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-444.64286,-781.36218)">
<g
transform="matrix(0.6526046,0,0,0.80554422,99.592644,-636.32172)"
id="g37994">
<g
transform="matrix(1.5323214,0,0,1.2413968,-324.85635,441.50868)"
id="toggle-on"
inkscape:label="#g8481">
<rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#3465a4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect8475"
width="34.850178"
height="4.0216675"
x="565.0083"
y="1070.9279"
rx="1.9562569"
ry="2.0108337" />
<circle
transform="scale(-1,1)"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#3465a4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="circle8463"
cx="-591.0213"
cy="1072.9402"
r="9" />
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -7,113 +7,51 @@
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:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="65"
height="22"
id="svg2857"
id="svg3199"
version="1.1"
inkscape:version="0.91 r13725"
inkscape:version="0.48.1 r9760"
sodipodi:docname="toggle-on-intl.svg">
<defs
id="defs2859">
id="defs3201">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective2865" />
id="perspective3207" />
<inkscape:perspective
id="perspective2843"
id="perspective3187"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient77461"
id="linearGradient77551"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.3066667,0,0,1,-841.64667,-483)"
x1="1164.7644"
y1="962.93695"
x2="1164.7644"
y2="970.51404" />
<linearGradient
id="linearGradient77461"
inkscape:collect="always">
<stop
id="stop77463"
offset="0"
style="stop-color:#182f4c;stop-opacity:1" />
<stop
id="stop77465"
offset="1"
style="stop-color:#205b9a;stop-opacity:1" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient76469-7-7-4"
id="linearGradient38024"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0215462,0,0,1.0322581,717.22867,428.68472)"
x1="6"
y1="102.95528"
x2="6"
y2="84.505203" />
<linearGradient
inkscape:collect="always"
id="linearGradient76469-7-7-4">
<stop
style="stop-color:#2e3232;stop-opacity:1"
offset="0"
id="stop76471-7-1-5" />
<stop
style="stop-color:#3e4545;stop-opacity:1"
offset="1"
id="stop76473-9-0-0" />
</linearGradient>
<inkscape:path-effect
effect="spiro"
id="path-effect77541-4"
is_visible="true" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#000000"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="37.410841"
inkscape:cy="16.009314"
inkscape:cx="49.147112"
inkscape:cy="17.532036"
inkscape:document-units="px"
inkscape:current-layer="g37994"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="2560"
inkscape:window-height="1376"
inkscape:window-width="1412"
inkscape:window-height="1067"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
borderlayer="true"
inkscape:showpageshadow="false"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
showborder="false">
<inkscape:grid
type="xygrid"
id="grid12954"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
inkscape:window-y="26"
inkscape:window-maximized="0" />
<metadata
id="metadata2862">
id="metadata3204">
<rdf:RDF>
<cc:Work
rdf:about="">
@ -128,65 +66,57 @@
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-444.64286,-781.36218)">
transform="translate(-342.5,-521.36218)">
<g
transform="matrix(0.6526046,0,0,0.80554422,99.592644,-636.32172)"
id="g37994">
<g
id="g37996"
transform="translate(-115,1277)">
<rect
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964000000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0.19591837"
id="rect13475"
width="98"
height="25"
x="644.5"
y="484.61118"
rx="4.7429576"
ry="3.8424656" />
<rect
ry="3.8424656"
rx="4.7429576"
y="483.5"
x="644.5"
height="25"
width="98"
id="rect38000"
style="color:#000000;fill:url(#linearGradient77551);fill-opacity:1;fill-rule:nonzero;stroke:#182f4c;stroke-width:1.37920964;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
<g
transform="translate(2.0625,-2)"
id="g38002">
<g
transform="translate(-115,1247)"
style="display:inline"
id="g38004">
<rect
ry="3.7972314"
rx="4.6871223"
y="515.5"
x="694.53046"
height="25"
width="45.969578"
id="rect38006"
style="color:#000000;fill:url(#linearGradient38024);fill-opacity:1;fill-rule:nonzero;stroke:#1f2020;stroke-width:1.37920964;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
sodipodi:nodetypes="cc"
style="opacity:0.1;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 699.09675,516.7365 36.86904,0"
id="path38016"
inkscape:path-effect="#path-effect77541-4"
inkscape:original-d="m 699.09675,516.7365 36.86904,0"
inkscape:connector-curvature="0" />
</g>
</g>
style="display:inline"
transform="translate(-453.5,448.36218)"
id="g16453">
<rect
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999994;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
id="rect13678"
width="3.0646207"
height="12.414008"
x="554.77728"
y="1767.3566" />
style="color:#000000;fill:#4a90d9;fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:0.99999994000000003;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect16256-9-4"
width="63.000004"
height="19"
x="-859.5"
y="74.5"
rx="4"
ry="4"
transform="scale(-1,1)" />
<rect
style="fill:#000000;fill-opacity:1;stroke:#5f5f5f;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
id="rect16258-5-4"
width="31"
height="20"
x="-860"
y="74"
rx="4"
ry="4"
transform="scale(-1,1)" />
<g
style="display:inline"
id="g16298-3-6"
transform="matrix(-1,0,0,1,1651.1322,-33.986291)">
<path
inkscape:connector-curvature="0"
id="path16265-3-5"
d="m 803.6322,115.48629 0,4.29495"
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path16265-0-2-0"
d="m 806.62805,115.48629 0,4.29495"
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
<path
inkscape:connector-curvature="0"
id="path16265-8-7-1"
d="m 809.6239,115.48629 0,4.29495"
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
</g>
<path
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 16,27.9375 0,10.125"
id="path19232"
inkscape:connector-curvature="0"
transform="translate(796,51.00002)" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -7,14 +7,13 @@
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:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="65"
height="22"
id="svg2857"
version="1.1"
inkscape:version="0.91 r13725"
inkscape:version="0.48.1 r9760"
sodipodi:docname="toggle-on-us.svg">
<defs
id="defs2859">
@ -32,96 +31,27 @@
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient76469-7-7-4"
id="linearGradient38024"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0215462,0,0,1.0322581,717.22867,428.68472)"
x1="6"
y1="102.95528"
x2="6"
y2="84.505203" />
<linearGradient
inkscape:collect="always"
id="linearGradient76469-7-7-4">
<stop
style="stop-color:#2e3232;stop-opacity:1"
offset="0"
id="stop76471-7-1-5" />
<stop
style="stop-color:#3e4545;stop-opacity:1"
offset="1"
id="stop76473-9-0-0" />
</linearGradient>
<inkscape:path-effect
effect="spiro"
id="path-effect77541-4"
is_visible="true" />
<linearGradient
id="linearGradient77461-1"
inkscape:collect="always">
<stop
id="stop77463-1"
offset="0"
style="stop-color:#182f4c;stop-opacity:1" />
<stop
id="stop77465-4"
offset="1"
style="stop-color:#205b9a;stop-opacity:1" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient77461-1"
id="linearGradient77551-6-5"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.8527367,0,0,0.80554422,-969.41608,-778.00299)"
x1="1164.7644"
y1="962.93695"
x2="1164.7644"
y2="970.51404" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient77461-1"
id="linearGradient11198"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.3066667,0,0,1,-1066.3709,794.25325)"
x1="1322.5831"
y1="-312.51855"
x2="1322.5831"
y2="-306.53461" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#000000"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="-26.798898"
inkscape:cy="5.3753009"
inkscape:cx="19.689855"
inkscape:cy="2.0517979"
inkscape:document-units="px"
inkscape:current-layer="g37994"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="2560"
inkscape:window-height="1376"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:window-width="941"
inkscape:window-height="751"
inkscape:window-x="2577"
inkscape:window-y="206"
inkscape:window-maximized="0"
borderlayer="true"
inkscape:showpageshadow="false"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
showborder="false">
<inkscape:grid
type="xygrid"
id="grid12954"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
inkscape:showpageshadow="false" />
<metadata
id="metadata2862">
<rdf:RDF>
@ -140,68 +70,61 @@
id="layer1"
transform="translate(-444.64286,-781.36218)">
<g
transform="matrix(0.6526046,0,0,0.80554422,99.592644,-636.32172)"
id="g37994">
style="display:inline"
transform="translate(-351.35714,708.36218)"
id="g16453">
<rect
style="color:#000000;fill:#4a90d9;fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:0.99999994000000003;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect16256-9-4"
width="63.000004"
height="19"
x="-859.5"
y="74.5"
rx="4"
ry="4"
transform="scale(-1,1)" />
<rect
style="fill:#000000;fill-opacity:1;stroke:#5f5f5f;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
id="rect16258-5-4"
width="31"
height="20"
x="-860"
y="74"
rx="4"
ry="4"
transform="scale(-1,1)" />
<g
id="g37996"
transform="translate(-115,1277)">
<rect
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964000000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0.19591837"
id="rect13475"
width="98"
height="25"
x="644.5"
y="484.61118"
rx="4.7429576"
ry="3.8424656" />
<rect
ry="3.8424656"
rx="4.7429576"
y="483.5"
x="644.5"
height="25"
width="98"
id="rect38000"
style="color:#000000;fill:url(#linearGradient11198);fill-opacity:1;fill-rule:nonzero;stroke:#182f4c;stroke-width:1.37920964;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;clip-rule:nonzero;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;filter-blend-mode:normal;filter-gaussianBlur-deviation:0;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto" />
style="display:inline"
id="g16298-3-6"
transform="matrix(-1,0,0,1,1651.1322,-33.986291)">
<path
inkscape:connector-curvature="0"
id="path16265-3-5"
d="m 803.6322,115.48629 0,4.29495"
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path16265-0-2-0"
d="m 806.62805,115.48629 0,4.29495"
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
<path
inkscape:connector-curvature="0"
id="path16265-8-7-1"
d="m 809.6239,115.48629 0,4.29495"
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
</g>
<g
transform="translate(2.0625,-2)"
id="g38002">
<g
transform="translate(-115,1247)"
style="display:inline"
id="g38004">
<rect
ry="3.7972314"
rx="4.6871223"
y="515.5"
x="694.53046"
height="25"
width="45.969578"
id="rect38006"
style="color:#000000;fill:url(#linearGradient38024);fill-opacity:1;fill-rule:nonzero;stroke:#1f2020;stroke-width:1.37920964;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
sodipodi:nodetypes="cc"
style="opacity:0.1;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 699.09675,516.7365 36.86904,0"
id="path38016"
inkscape:path-effect="#path-effect77541-4"
inkscape:original-d="m 699.09675,516.7365 36.86904,0"
inkscape:connector-curvature="0" />
</g>
style="font-size:8.95877075px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:125%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
id="text42229-3-0">
<path
d="m 808.01473,80.573953 c 0.63283,6e-6 1.19567,0.123947 1.68852,0.371824 0.49284,0.247888 0.88071,0.609505 1.16359,1.084851 0.28287,0.472439 0.42431,1.022155 0.42432,1.649149 -10e-6,0.635748 -0.13853,1.200045 -0.41557,1.692892 -0.27705,0.489934 -0.66637,0.870506 -1.16796,1.141719 -0.50161,0.271212 -1.07757,0.406819 -1.72789,0.406819 -0.4287,0 -0.83552,-0.06562 -1.22046,-0.196848 -0.38495,-0.134148 -0.73053,-0.32808 -1.03673,-0.581795 -0.3033,-0.256631 -0.54535,-0.589085 -0.72615,-0.997363 -0.1779,-0.408276 -0.26684,-0.869045 -0.26684,-1.382311 0,-0.638658 0.13998,-1.200039 0.41994,-1.684144 0.27996,-0.487011 0.66782,-0.858835 1.16359,-1.115472 0.49576,-0.259541 1.06298,-0.389315 1.70164,-0.389321 m 0.57305,1.089225 c -0.20123,-0.05249 -0.40682,-0.07873 -0.61679,-0.07874 -0.20998,5e-6 -0.41411,0.02625 -0.61242,0.07874 -0.19831,0.04958 -0.38932,0.129779 -0.57304,0.240592 -0.18081,0.107907 -0.33975,0.242055 -0.47681,0.402445 -0.13707,0.160399 -0.24643,0.358705 -0.32808,0.594918 -0.0817,0.233305 -0.12249,0.491395 -0.12249,0.774269 0,0.67366 0.20851,1.214627 0.62554,1.622902 0.41703,0.408279 0.93758,0.612417 1.56166,0.612416 0.25955,10e-7 0.51035,-0.04228 0.7524,-0.126857 0.24496,-0.08457 0.47097,-0.20997 0.67803,-0.376199 0.20705,-0.166225 0.37328,-0.392236 0.49868,-0.678031 0.1254,-0.285792 0.1881,-0.610956 0.1881,-0.975492 0,-0.297455 -0.0437,-0.568668 -0.13123,-0.813638 -0.0875,-0.247878 -0.20414,-0.453475 -0.34995,-0.61679 -0.1429,-0.163307 -0.31059,-0.301829 -0.50306,-0.415568 -0.18956,-0.11373 -0.38641,-0.195385 -0.59054,-0.244967"
style="line-height:125%;fill:#ffffff;fill-opacity:1;marker:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
id="path18606" />
<path
d="m 813.15903,80.639569 1.21608,0 3.4689,4.776844 0,-4.776844 1.10235,0 0,6.216022 -1.22921,0 -3.45577,-4.785594 0,4.785594 -1.10235,0 0,-6.216022"
style="line-height:125%;fill:#ffffff;fill-opacity:1;marker:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
id="path18608" />
</g>
<text
transform="scale(1.1000946,0.90901274)"
sodipodi:linespacing="125%"
id="text38018"
y="1955.5205"
x="495.94223"
style="font-size:13.29953671px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
xml:space="preserve"><tspan
y="1955.5205"
x="495.94223"
id="tspan38020"
sodipodi:role="line">ON</tspan></text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@ -113,7 +113,7 @@ expand_content_files=
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS=$(GNOME_SHELL_CFLAGS)
GTKDOC_LIBS=$(GNOME_SHELL_LIBS) $(top_builddir)/src/libgnome-shell-menu.la $(top_builddir)/src/libgnome-shell-base.la $(top_builddir)/src/libgnome-shell.la -rpath $(MUTTER_TYPELIB_DIR)
GTKDOC_LIBS=$(GNOME_SHELL_LIBS) $(top_builddir)/src/libgnome-shell-menu.la $(top_builddir)/src/libgnome-shell-base.la $(top_builddir)/src/libgnome-shell.la
# This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make

View File

@ -17,6 +17,7 @@
<chapter>
<title>Actors</title>
<xi:include href="xml/shell-generic-container.xml"/>
<xi:include href="xml/shell-slicer.xml"/>
<xi:include href="xml/shell-stack.xml"/>
</chapter>
<chapter>
@ -45,7 +46,7 @@
<xi:include href="doc-gen-org.gnome.Shell.SearchProvider.xml"/>
<xi:include href="doc-gen-org.gnome.Shell.SearchProvider2.xml"/>
<xi:include href="xml/shell-global.xml"/>
<xi:include href="xml/shell-action-modes.xml"/>
<xi:include href="xml/shell-keybinding-modes.xml"/>
<xi:include href="xml/shell-wm.xml"/>
<xi:include href="xml/shell-util.xml"/>
<xi:include href="xml/shell-mount-operation.xml"/>

View File

@ -78,7 +78,7 @@ expand_content_files=
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS=
GTKDOC_LIBS=$(top_builddir)/src/libst-1.0.la -rpath $(MUTTER_TYPELIB_DIR)
GTKDOC_LIBS=$(top_builddir)/src/libst-1.0.la
# This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make

View File

@ -35,6 +35,7 @@
<xi:include href="xml/st-bin.xml"/>
<xi:include href="xml/st-box-layout.xml"/>
<xi:include href="xml/st-scroll-view.xml"/>
<xi:include href="xml/st-table.xml"/>
</chapter>
<chapter id="styling">

View File

@ -27,9 +27,7 @@ its dependencies to build from tarballs.</description>
<download-page rdf:resource="http://download.gnome.org/sources/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" />
<programming-language>JavaScript</programming-language>
<programming-language>C</programming-language>
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
<maintainer>
<foaf:Person>

View File

@ -13,7 +13,7 @@ misc/config.js: misc/config.js.in Makefile
-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
$(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

View File

@ -23,6 +23,11 @@ const GnomeShellIface = '<node> \
</interface> \
</node>';
const customCss = '.prefs-button { \
padding: 8px; \
border-radius: 20px; \
}';
const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface);
function stripPrefix(string, prefix) {
@ -57,6 +62,9 @@ const Application = new Lang.Class({
if (!extension)
return false;
if (ExtensionUtils.isOutOfDate(extension))
return false;
if (!extension.dir.get_child('prefs.js').query_exists(null))
return false;
@ -152,7 +160,6 @@ const Application = new Lang.Class({
let scroll = new Gtk.ScrolledWindow({ hscrollbar_policy: Gtk.PolicyType.NEVER,
shadow_type: Gtk.ShadowType.IN,
halign: Gtk.Align.CENTER,
propagate_natural_width: true,
margin: 18 });
this._window.add(scroll);
@ -172,6 +179,21 @@ const Application = new Lang.Class({
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;
@ -220,6 +242,7 @@ const Application = new Lang.Class({
_onStartup: function(app) {
this._buildUI(app);
this._addCustomStyle();
this._scanExtensions();
},
@ -255,15 +278,11 @@ const ExtensionRow = new Lang.Class({
this.uuid = uuid;
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' });
this._settings = new Gio.Settings({ schema: '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();
},
@ -296,13 +315,12 @@ const ExtensionRow = new Lang.Class({
button.add(new Gtk.Image({ icon_name: 'emblem-system-symbolic',
icon_size: Gtk.IconSize.BUTTON,
visible: true }));
button.get_style_context().add_class('circular');
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() {
@ -315,13 +333,6 @@ const ExtensionRow = new Lang.Class({
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;

View File

@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Signals = imports.signals;
const St = imports.gi.St;
@ -14,7 +13,7 @@ const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const UserWidget = imports.ui.userWidget;
const DEFAULT_BUTTON_WELL_ICON_SIZE = 16;
const DEFAULT_BUTTON_WELL_ICON_SIZE = 24;
const DEFAULT_BUTTON_WELL_ANIMATION_DELAY = 1.0;
const DEFAULT_BUTTON_WELL_ANIMATION_TIME = 0.3;
@ -127,7 +126,7 @@ const AuthPrompt = new Lang.Class({
this._initButtons();
let spinnerIcon = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
let spinnerIcon = global.datadir + '/theme/process-working.svg';
this._spinner = new Animation.AnimatedIcon(spinnerIcon, DEFAULT_BUTTON_WELL_ICON_SIZE);
this._spinner.actor.opacity = 0;
this._spinner.actor.show();
@ -135,12 +134,13 @@ const AuthPrompt = new Lang.Class({
},
_onDestroy: function() {
this._userVerifier.destroy();
this._userVerifier.clear();
this._userVerifier.disconnectAll();
this._userVerifier = null;
},
_initButtons: function() {
this.cancelButton = new St.Button({ style_class: 'modal-dialog-button button',
this.cancelButton = new St.Button({ style_class: 'modal-dialog-button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
reactive: true,
can_focus: true,
@ -162,7 +162,7 @@ const AuthPrompt = new Lang.Class({
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.MIDDLE });
this.nextButton = new St.Button({ style_class: 'modal-dialog-button button',
this.nextButton = new St.Button({ style_class: 'modal-dialog-button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
reactive: true,
can_focus: true,
@ -189,21 +189,22 @@ const AuthPrompt = new Lang.Class({
this._updateNextButtonSensitivity(this._entry.text.length > 0);
}));
this._entry.clutter_text.connect('activate', Lang.bind(this, function() {
if (this.nextButton.reactive)
this.emit('next');
this.emit('next');
}));
},
_onAskQuestion: function(verifier, serviceName, question, passwordChar) {
if (this._preemptiveAnswer) {
if (this._queryingService)
this._userVerifier.answerQuery(this._queryingService, this._preemptiveAnswer);
this._preemptiveAnswer = null;
return;
}
if (this._queryingService)
this.clear();
this._queryingService = serviceName;
if (this._preemptiveAnswer) {
this._userVerifier.answerQuery(this._queryingService, this._preemptiveAnswer);
this._preemptiveAnswer = null;
return;
}
this.setPasswordChar(passwordChar);
this.setQuestion(question);
@ -259,9 +260,7 @@ const AuthPrompt = new Lang.Class({
},
_onVerificationComplete: function() {
this.setActorInDefaultButtonWell(null);
this.verificationStatus = AuthPromptStatus.VERIFICATION_SUCCEEDED;
this.cancelButton.reactive = false;
},
_onReset: function() {
@ -283,12 +282,6 @@ const AuthPrompt = new Lang.Class({
if (oldActor)
Tweener.removeTweens(oldActor);
let wasSpinner;
if (oldActor == this._spinner.actor)
wasSpinner = true;
else
wasSpinner = false;
let isSpinner;
if (actor == this._spinner.actor)
isSpinner = true;
@ -298,11 +291,6 @@ const AuthPrompt = new Lang.Class({
if (this._defaultButtonWellActor != actor && oldActor) {
if (!animate) {
oldActor.opacity = 0;
if (wasSpinner) {
if (this._spinner)
this._spinner.stop();
}
} else {
Tweener.addTween(oldActor,
{ opacity: 0,
@ -311,7 +299,7 @@ const AuthPrompt = new Lang.Class({
transition: 'linear',
onCompleteScope: this,
onComplete: function() {
if (wasSpinner) {
if (isSpinner) {
if (this._spinner)
this._spinner.stop();
}
@ -414,7 +402,7 @@ const AuthPrompt = new Lang.Class({
},
updateSensitivity: function(sensitive) {
this._updateNextButtonSensitivity(sensitive && this._entry.text.length > 0);
this._updateNextButtonSensitivity(sensitive);
this._entry.reactive = sensitive;
this._entry.clutter_text.editable = sensitive;
},
@ -431,23 +419,19 @@ const AuthPrompt = new Lang.Class({
},
setUser: function(user) {
let oldChild = this._userWell.get_child();
if (oldChild)
oldChild.destroy();
if (user) {
let userWidget = new UserWidget.UserWidget(user);
this._userWell.set_child(userWidget.actor);
} else {
this._userWell.set_child(null);
}
},
reset: function() {
let oldStatus = this.verificationStatus;
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
this.cancelButton.reactive = true;
this.nextButton.label = _("Next");
if (this._userVerifier)
if (oldStatus == AuthPromptStatus.VERIFYING)
this._userVerifier.cancel();
this._queryingService = null;
@ -502,7 +486,6 @@ const AuthPrompt = new Lang.Class({
finish: function(onComplete) {
if (!this._userVerifier.hasPendingMessages) {
this._userVerifier.clear();
onComplete();
return;
}
@ -510,15 +493,11 @@ const AuthPrompt = new Lang.Class({
let signalId = this._userVerifier.connect('no-more-messages',
Lang.bind(this, function() {
this._userVerifier.disconnect(signalId);
this._userVerifier.clear();
onComplete();
}));
},
cancel: function() {
if (this.verificationStatus == AuthPromptStatus.VERIFICATION_SUCCEEDED) {
return;
}
this.reset();
this.emit('cancelled');
}

View File

@ -16,34 +16,6 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/*
* In order for transformation animations to look good, they need to be
* incremental and have some order to them (e.g., fade out hidden items,
* then shrink to close the void left over). Chaining animations in this way can
* be error-prone and wordy using just Tweener callbacks.
*
* The classes in this file help with this:
*
* - Task. encapsulates schedulable work to be run in a specific scope.
*
* - ConsecutiveBatch. runs a series of tasks in order and completes
* when the last in the series finishes.
*
* - ConcurrentBatch. runs a set of tasks at the same time and completes
* when the last to finish completes.
*
* - Hold. prevents a batch from completing the pending task until
* the hold is released.
*
* The tasks associated with a batch are specified in a list at batch
* construction time as either task objects or plain functions.
* Batches are task objects, themselves, so they can be nested.
*
* These classes aren't specific to GDM, but were found to be unintuitive and so
* are not used elsewhere. These APIs may ultimately get dropped entirely and
* replaced by something else.
*/
const Lang = imports.lang;
const Signals = imports.signals;

View File

@ -22,12 +22,10 @@ const Clutter = imports.gi.Clutter;
const Gdm = imports.gi.Gdm;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
@ -49,7 +47,6 @@ const _FADE_ANIMATION_TIME = 0.25;
const _SCROLL_ANIMATION_TIME = 0.5;
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
const _LOGO_ICON_HEIGHT = 48;
const _MAX_BOTTOM_MENU_ITEMS = 5;
const UserListItem = new Lang.Class({
Name: 'UserListItem',
@ -67,15 +64,10 @@ const UserListItem = new Lang.Class({
reactive: true,
x_align: St.Align.START,
x_fill: true });
this.actor.connect('destroy',
Lang.bind(this, this._onDestroy));
this._userWidget = new UserWidget.UserWidget(this.user);
layout.add(this._userWidget.actor);
this._userWidget.actor.bind_property('label-actor', this.actor, 'label-actor',
GObject.BindingFlags.SYNC_CREATE);
this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator',
scale_x: 0 });
layout.add(this._timedLoginIndicator);
@ -95,10 +87,6 @@ const UserListItem = new Lang.Class({
this.actor.remove_style_pseudo_class('logged-in');
},
_onDestroy: function() {
this.user.disconnect(this._userChangedId);
},
_onClicked: function() {
this.emit('activate');
},
@ -212,10 +200,6 @@ const UserList = new Lang.Class({
return item;
},
containsUser: function(user) {
return this._items[user.get_user_name()] != null;
},
addUser: function(user) {
if (!user.is_loaded)
return;
@ -288,16 +272,7 @@ const SessionMenuButton = new Lang.Class({
this.actor = new St.Bin({ child: this._button });
let side = St.Side.TOP;
let align = 0;
if (Gdm.get_session_ids().length > _MAX_BOTTOM_MENU_ITEMS) {
if (this.actor.text_direction == Clutter.TextDirection.RTL)
side = St.Side.RIGHT;
else
side = St.Side.LEFT;
align = 0.5;
}
this._menu = new PopupMenu.PopupMenu(this._button, align, side);
this._menu = new PopupMenu.PopupMenu(this._button, 0, St.Side.TOP);
Main.uiGroup.add_actor(this._menu.actor);
this._menu.actor.hide();
@ -383,19 +358,31 @@ const LoginDialog = new Lang.Class({
Name: 'LoginDialog',
_init: function(parentActor) {
this.actor = new Shell.GenericContainer({ style_class: 'login-dialog',
visible: false });
this.actor.get_accessible().set_role(Atk.Role.WINDOW);
this.actor = new St.Widget({ accessible_role: Atk.Role.WINDOW,
layout_manager: new Clutter.BinLayout(),
style_class: 'login-dialog',
visible: false });
this.actor.add_constraint(new Layout.MonitorConstraint({ primary: true }));
this.actor.connect('allocate', Lang.bind(this, this._onAllocate));
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
parentActor.add_child(this.actor);
this._userManager = AccountsService.UserManager.get_default()
this._gdmClient = new Gdm.Client();
let gdmClient = new Gdm.Client();
this._settings = new Gio.Settings({ schema_id: GdmUtil.LOGIN_SCREEN_SCHEMA });
if (GLib.getenv('GDM_GREETER_TEST') != '1') {
this._greeter = gdmClient.get_greeter_sync(null);
this._greeter.connect('default-session-name-changed',
Lang.bind(this, this._onDefaultSessionChanged));
this._greeter.connect('session-opened',
Lang.bind(this, this._onSessionOpened));
this._greeter.connect('timed-login-requested',
Lang.bind(this, this._onTimedLoginRequested));
}
this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA });
this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_KEY,
Lang.bind(this, this._updateBanner));
@ -407,23 +394,30 @@ const LoginDialog = new Lang.Class({
Lang.bind(this, this._updateLogo));
this._textureCache = St.TextureCache.get_default();
this._updateLogoTextureId = this._textureCache.connect('texture-file-changed',
Lang.bind(this, this._updateLogoTexture));
this._textureCache.connect('texture-file-changed',
Lang.bind(this, this._updateLogoTexture));
this._userSelectionBox = new St.BoxLayout({ style_class: 'login-dialog-user-selection-box',
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
x_expand: true,
y_expand: true,
vertical: true,
visible: false });
this.actor.add_child(this._userSelectionBox);
this._bannerLabel = new St.Label({ style_class: 'login-dialog-banner',
text: '' });
this._userSelectionBox.add(this._bannerLabel);
this._updateBanner();
this._userList = new UserList();
this._userSelectionBox.add(this._userList.actor,
{ expand: true,
x_fill: true,
y_fill: true });
this._authPrompt = new AuthPrompt.AuthPrompt(this._gdmClient, AuthPrompt.AuthPromptMode.UNLOCK_OR_LOG_IN);
this._authPrompt = new AuthPrompt.AuthPrompt(gdmClient, AuthPrompt.AuthPromptMode.UNLOCK_OR_LOG_IN);
this._authPrompt.connect('prompted', Lang.bind(this, this._onPrompted));
this._authPrompt.connect('reset', Lang.bind(this, this._onReset));
this._authPrompt.hide();
@ -451,25 +445,11 @@ const LoginDialog = new Lang.Class({
x_align: St.Align.START,
x_fill: true });
this._bannerView = new St.ScrollView({ style_class: 'login-dialog-banner-view',
opacity: 0,
vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
hscrollbar_policy: Gtk.PolicyType.NEVER });
this.actor.add_child(this._bannerView);
let bannerBox = new St.BoxLayout({ vertical: true });
this._bannerView.add_actor(bannerBox);
this._bannerLabel = new St.Label({ style_class: 'login-dialog-banner',
text: '' });
this._bannerLabel.clutter_text.line_wrap = true;
this._bannerLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
bannerBox.add_child(this._bannerLabel);
this._updateBanner();
this._logoBin = new St.Widget({ style_class: 'login-dialog-logo-bin',
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.END });
y_align: Clutter.ActorAlign.END,
x_expand: true,
y_expand: true });
this.actor.add_child(this._logoBin);
this._updateLogo();
@ -491,201 +471,13 @@ const LoginDialog = new Lang.Class({
this._disableUserList = undefined;
this._userListLoaded = false;
this._realmManager = new Realmd.Manager();
this._realmSignalId = this._realmManager.connect('login-format-changed',
Lang.bind(this, this._showRealmLoginHint));
LoginManager.getLoginManager().getCurrentSessionProxy(Lang.bind(this, this._gotGreeterSessionProxy));
// 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
// focus later
this._startupCompleteId = Main.layoutManager.connect('startup-complete',
Lang.bind(this, this._updateDisableUserList));
},
_getBannerAllocation: function (dialogBox) {
let actorBox = new Clutter.ActorBox();
let [minWidth, minHeight, natWidth, natHeight] = this._bannerView.get_preferred_size();
let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
actorBox.x1 = Math.floor(centerX - natWidth / 2);
actorBox.y1 = dialogBox.y1 + Main.layoutManager.panelBox.height;
actorBox.x2 = actorBox.x1 + natWidth;
actorBox.y2 = actorBox.y1 + natHeight;
return actorBox;
},
_getLogoBinAllocation: function (dialogBox) {
let actorBox = new Clutter.ActorBox();
let [minWidth, minHeight, natWidth, natHeight] = this._logoBin.get_preferred_size();
let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
actorBox.x1 = Math.floor(centerX - natWidth / 2);
actorBox.y1 = dialogBox.y2 - natHeight;
actorBox.x2 = actorBox.x1 + natWidth;
actorBox.y2 = actorBox.y1 + natHeight;
return actorBox;
},
_getCenterActorAllocation: function (dialogBox, actor) {
let actorBox = new Clutter.ActorBox();
let [minWidth, minHeight, natWidth, natHeight] = actor.get_preferred_size();
let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
let centerY = dialogBox.y1 + (dialogBox.y2 - dialogBox.y1) / 2;
natWidth = Math.min(natWidth, dialogBox.x2 - dialogBox.x1);
natHeight = Math.min(natHeight, dialogBox.y2 - dialogBox.y1);
actorBox.x1 = Math.floor(centerX - natWidth / 2);
actorBox.y1 = Math.floor(centerY - natHeight / 2);
actorBox.x2 = actorBox.x1 + natWidth;
actorBox.y2 = actorBox.y1 + natHeight;
return actorBox;
},
_onAllocate: function (actor, dialogBox, flags) {
let dialogWidth = dialogBox.x2 - dialogBox.x1;
let dialogHeight = dialogBox.y2 - dialogBox.y1;
// First find out what space the children require
let bannerAllocation = null;
let bannerHeight = 0;
let bannerWidth = 0;
if (this._bannerView.visible) {
bannerAllocation = this._getBannerAllocation(dialogBox, this._bannerView);
bannerHeight = bannerAllocation.y2 - bannerAllocation.y1;
bannerWidth = bannerAllocation.x2 - bannerAllocation.x1;
}
let authPromptAllocation = null;
let authPromptHeight = 0;
let authPromptWidth = 0;
if (this._authPrompt.actor.visible) {
authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt.actor);
authPromptHeight = authPromptAllocation.y2 - authPromptAllocation.y1;
authPromptWidth = authPromptAllocation.x2 - authPromptAllocation.x1;
}
let userSelectionAllocation = null;
let userSelectionHeight = 0;
if (this._userSelectionBox.visible) {
userSelectionAllocation = this._getCenterActorAllocation(dialogBox, this._userSelectionBox);
userSelectionHeight = userSelectionAllocation.y2 - userSelectionAllocation.y1;
}
let logoAllocation = null;
let logoHeight = 0;
if (this._logoBin.visible) {
logoAllocation = this._getLogoBinAllocation(dialogBox);
logoHeight = logoAllocation.y2 - logoAllocation.y1;
}
// Then figure out if we're overly constrained and need to
// try a different layout, or if we have what extra space we
// can hand out
if (bannerAllocation) {
let bannerSpace;
if (authPromptAllocation)
bannerSpace = authPromptAllocation.y1 - bannerAllocation.y1;
else
bannerSpace = 0;
let leftOverYSpace = bannerSpace - bannerHeight;
if (leftOverYSpace > 0) {
// First figure out how much left over space is up top
let leftOverTopSpace = leftOverYSpace / 2;
// Then, shift the banner into the middle of that extra space
let yShift = Math.floor(leftOverTopSpace / 2);
bannerAllocation.y1 += yShift;
bannerAllocation.y2 += yShift;
} else {
// Then figure out how much space there would be if we switched to a
// wide layout with banner on one side and authprompt on the other.
let leftOverXSpace = dialogWidth - authPromptWidth;
// In a wide view, half of the available space goes to the banner,
// and the other half goes to the margins.
let wideBannerWidth = leftOverXSpace / 2;
let wideSpacing = leftOverXSpace - wideBannerWidth;
// If we do go with a wide layout, we need there to be at least enough
// space for the banner and the auth prompt to be the same width,
// so it doesn't look unbalanced.
if (authPromptWidth > 0 && wideBannerWidth > authPromptWidth) {
let centerX = dialogBox.x1 + dialogWidth / 2;
let centerY = dialogBox.y1 + dialogHeight / 2;
// A small portion of the spacing goes down the center of the
// screen to help delimit the two columns of the wide view
let centerGap = wideSpacing / 8;
// place the banner along the left edge of the center margin
bannerAllocation.x2 = Math.floor(centerX - centerGap / 2);
bannerAllocation.x1 = Math.floor(bannerAllocation.x2 - wideBannerWidth);
// figure out how tall it would like to be and try to accomodate
// but don't let it get too close to the logo
let [wideMinHeight, wideBannerHeight] = this._bannerView.get_preferred_height(wideBannerWidth);
let maxWideHeight = dialogHeight - 3 * logoHeight;
wideBannerHeight = Math.min(maxWideHeight, wideBannerHeight);
bannerAllocation.y1 = Math.floor(centerY - wideBannerHeight / 2);
bannerAllocation.y2 = bannerAllocation.y1 + wideBannerHeight;
// place the auth prompt along the right edge of the center margin
authPromptAllocation.x1 = Math.floor(centerX + centerGap / 2);
authPromptAllocation.x2 = authPromptAllocation.x1 + authPromptWidth;
} else {
// If we aren't going to do a wide view, then we need to limit
// the height of the banner so it will present scrollbars
// First figure out how much space there is without the banner
leftOverYSpace += bannerHeight;
// Then figure out how much of that space is up top
let availableTopSpace = Math.floor(leftOverYSpace / 2);
// Then give all of that space to the banner
bannerAllocation.y2 = bannerAllocation.y1 + availableTopSpace;
}
}
} else if (userSelectionAllocation) {
// Grow the user list to fill the space
let leftOverYSpace = dialogHeight - userSelectionHeight - logoHeight;
if (leftOverYSpace > 0) {
let topExpansion = Math.floor(leftOverYSpace / 2);
let bottomExpansion = topExpansion;
userSelectionAllocation.y1 -= topExpansion;
userSelectionAllocation.y2 += bottomExpansion;
}
}
// Finally hand out the allocations
if (bannerAllocation) {
this._bannerView.allocate(bannerAllocation, flags);
}
if (authPromptAllocation)
this._authPrompt.actor.allocate(authPromptAllocation, flags);
if (userSelectionAllocation)
this._userSelectionBox.allocate(userSelectionAllocation, flags);
if (logoAllocation)
this._logoBin.allocate(logoAllocation, flags);
Main.layoutManager.connect('startup-complete',
Lang.bind(this, this._updateDisableUserList));
},
_ensureUserListLoaded: function() {
@ -740,38 +532,24 @@ const LoginDialog = new Lang.Class({
}
},
_fadeInBannerView: function() {
this._bannerView.show();
Tweener.addTween(this._bannerView,
{ opacity: 255,
time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad' });
},
_hideBannerView: function() {
Tweener.removeTweens(this._bannerView);
this._bannerView.opacity = 0;
this._bannerView.hide();
},
_updateLogoTexture: function(cache, file) {
if (this._logoFile && !this._logoFile.equal(file))
_updateLogoTexture: function(cache, uri) {
if (this._logoFileUri != uri)
return;
this._logoBin.destroy_all_children();
if (this._logoFile) {
if (this._logoFileUri) {
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._logoBin.add_child(this._textureCache.load_file_async(this._logoFile,
-1, _LOGO_ICON_HEIGHT,
scaleFactor));
this._logoBin.add_child(this._textureCache.load_uri_async(this._logoFileUri,
-1, _LOGO_ICON_HEIGHT,
scaleFactor));
}
},
_updateLogo: function() {
let path = this._settings.get_string(GdmUtil.LOGO_KEY);
this._logoFile = path ? Gio.file_new_for_path(path) : null;
this._updateLogoTexture(this._textureCache, this._logoFile);
this._logoFileUri = path ? Gio.file_new_for_path(path).get_uri() : null;
this._updateLogoTexture(this._textureCache, this._logoFileUri);
},
_onPrompted: function() {
@ -782,33 +560,11 @@ const LoginDialog = new Lang.Class({
this._showPrompt();
},
_resetGreeterProxy: function() {
if (GLib.getenv('GDM_GREETER_TEST') != '1') {
if (this._greeter) {
this._greeter.run_dispose();
}
this._greeter = this._gdmClient.get_greeter_sync(null);
this._defaultSessionChangedId = this._greeter.connect('default-session-name-changed',
Lang.bind(this, this._onDefaultSessionChanged));
this._sessionOpenedId = this._greeter.connect('session-opened',
Lang.bind(this, this._onSessionOpened));
this._timedLoginRequestedId = this._greeter.connect('timed-login-requested',
Lang.bind(this, this._onTimedLoginRequested));
}
},
_onReset: function(authPrompt, beginRequest) {
this._resetGreeterProxy();
this._sessionMenuButton.updateSensitivity(true);
this._user = null;
if (this._nextSignalId) {
this._authPrompt.disconnect(this._nextSignalId);
this._nextSignalId = 0;
}
if (beginRequest == AuthPrompt.BeginRequestType.PROVIDE_USERNAME) {
if (!this._disableUserList)
this._showUserList();
@ -843,7 +599,6 @@ const LoginDialog = new Lang.Class({
{ opacity: 255,
time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad' });
this._fadeInBannerView();
},
_showRealmLoginHint: function(realmManager, hint) {
@ -863,30 +618,31 @@ const LoginDialog = new Lang.Class({
this._authPrompt.setPasswordChar('');
this._authPrompt.setQuestion(_("Username: "));
this._showRealmLoginHint(this._realmManager.loginFormat);
let realmManager = new Realmd.Manager();
let realmSignalId = realmManager.connect('login-format-changed',
Lang.bind(this, this._showRealmLoginHint));
this._showRealmLoginHint(realmManager.loginFormat);
if (this._nextSignalId)
this._authPrompt.disconnect(this._nextSignalId);
this._nextSignalId = this._authPrompt.connect('next',
Lang.bind(this, function() {
this._authPrompt.disconnect(this._nextSignalId);
this._nextSignalId = 0;
this._authPrompt.updateSensitivity(false);
let answer = this._authPrompt.getAnswer();
this._user = this._userManager.get_user(answer);
this._authPrompt.clear();
this._authPrompt.startSpinning();
this._authPrompt.begin({ userName: answer });
this._updateCancelButton();
}));
let nextSignalId = this._authPrompt.connect('next',
Lang.bind(this, function() {
this._authPrompt.disconnect(nextSignalId);
this._authPrompt.updateSensitivity(false);
let answer = this._authPrompt.getAnswer();
this._user = this._userManager.get_user(answer);
this._authPrompt.clear();
this._authPrompt.startSpinning();
this._authPrompt.begin({ userName: answer });
this._updateCancelButton();
realmManager.disconnect(realmSignalId)
realmManager.release();
}));
this._updateCancelButton();
this._authPrompt.updateSensitivity(true);
this._showPrompt();
},
_loginScreenSessionActivated: function() {
if (this.actor.opacity == 255 && this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFICATION_SUCCEEDED)
return;
Tweener.addTween(this.actor,
@ -903,19 +659,16 @@ const LoginDialog = new Lang.Class({
},
onUpdateScope: this,
onComplete: function() {
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
this._authPrompt.reset();
this._authPrompt.reset();
},
onCompleteScope: this });
},
_gotGreeterSessionProxy: function(proxy) {
this._greeterSessionProxy = proxy;
this._greeterSessionProxyChangedId =
proxy.connect('g-properties-changed', Lang.bind(this, function() {
if (proxy.Active)
this._loginScreenSessionActivated();
}));
proxy.connect('g-properties-changed', Lang.bind(this, function() {
if (proxy.Active)
this._loginScreenSessionActivated();
}));
},
_startSession: function(serviceName) {
@ -933,7 +686,11 @@ const LoginDialog = new Lang.Class({
},
onUpdateScope: this,
onComplete: function() {
this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
let id = Mainloop.idle_add(Lang.bind(this, function() {
this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
return GLib.SOURCE_REMOVE;
}));
GLib.Source.set_name_by_id(id, '[gnome-shell] this._greeter.call_start_session_when_ready_sync');
},
onCompleteScope: this });
},
@ -1094,7 +851,6 @@ const LoginDialog = new Lang.Class({
_showUserList: function() {
this._ensureUserListLoaded();
this._authPrompt.hide();
this._hideBannerView();
this._sessionMenuButton.close();
this._setUserListExpanded(true);
this._notListedButton.show();
@ -1113,11 +869,18 @@ const LoginDialog = new Lang.Class({
},
_onUserListActivated: function(activatedItem) {
let tasks = [function() {
return GdmUtil.cloneAndFadeOutActor(this._userSelectionBox);
},
function() {
this._setUserListExpanded(false);
}];
this._user = activatedItem.user;
this._updateCancelButton();
let batch = new Batch.ConcurrentBatch(this, [GdmUtil.cloneAndFadeOutActor(this._userSelectionBox),
let batch = new Batch.ConcurrentBatch(this, [new Batch.ConsecutiveBatch(this, tasks),
this._beginVerificationForItem(activatedItem)]);
batch.run();
},
@ -1127,40 +890,6 @@ const LoginDialog = new Lang.Class({
this._userManager.disconnect(this._userManagerLoadedId);
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;
}
if (this._userChangedId) {
this._userManager.disconnect(this._userChangedId);
this._userChangedId = 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;
}
if (this._realmManager) {
this._realmManager.disconnect(this._realmSignalId);
this._realmSignalId = 0;
this._realmManager.release();
this._realmManager = null;
}
},
_loadUserList: function() {
@ -1175,23 +904,15 @@ const LoginDialog = new Lang.Class({
this._userList.addUser(users[i]);
}
this._userAddedId = this._userManager.connect('user-added',
Lang.bind(this, function(userManager, user) {
this._userList.addUser(user);
}));
this._userManager.connect('user-added',
Lang.bind(this, function(userManager, user) {
this._userList.addUser(user);
}));
this._userRemovedId = this._userManager.connect('user-removed',
Lang.bind(this, function(userManager, user) {
this._userList.removeUser(user);
}));
this._userChangedId = this._userManager.connect('user-changed',
Lang.bind(this, function(userManager, user) {
if (this._userList.containsUser(user) && user.locked)
this._userList.removeUser(user);
else if (!this._userList.containsUser(user) && !user.locked)
this._userList.addUser(user);
}));
this._userManager.connect('user-removed',
Lang.bind(this, function(userManager, user) {
this._userList.removeUser(user);
}));
return GLib.SOURCE_REMOVE;
},
@ -1205,8 +926,6 @@ const LoginDialog = new Lang.Class({
this.actor.show();
this.actor.opacity = 0;
Main.pushModal(this.actor, { actionMode: Shell.ActionMode.LOGIN_SCREEN });
Tweener.addTween(this.actor,
{ opacity: 255,
time: 1,
@ -1216,8 +935,7 @@ const LoginDialog = new Lang.Class({
},
close: function() {
Main.popModal(this.actor);
Main.ctrlAltTabManager.removeGroup(this.actor);
Main.ctrlAltTabManager.removeGroup(this.dialogLayout);
},
cancel: function() {

View File

@ -35,8 +35,8 @@ const ALLOWED_FAILURES_KEY = 'allowed-failures';
const LOGO_KEY = 'logo';
const DISABLE_USER_LIST_KEY = 'disable-user-list';
// Give user 48ms to read each character of a PAM message
const USER_READ_TIME = 48
// Give user 16ms to read each character of a PAM message
const USER_READ_TIME = 16
const MessageType = {
NONE: 0,
@ -128,7 +128,7 @@ const ShellUserVerifier = new Lang.Class({
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',
Lang.bind(this, this._updateDefaultService));
this._updateDefaultService();
@ -142,10 +142,10 @@ const ShellUserVerifier = new Lang.Class({
// after a user has been picked.
this._checkForSmartcard();
this._smartcardInsertedId = this._smartcardManager.connect('smartcard-inserted',
Lang.bind(this, this._checkForSmartcard));
this._smartcardRemovedId = this._smartcardManager.connect('smartcard-removed',
Lang.bind(this, this._checkForSmartcard));
this._smartcardManager.connect('smartcard-inserted',
Lang.bind(this, this._checkForSmartcard));
this._smartcardManager.connect('smartcard-removed',
Lang.bind(this, this._checkForSmartcard));
this._messageQueue = [];
this._messageQueueTimeoutId = 0;
@ -159,8 +159,8 @@ const ShellUserVerifier = new Lang.Class({
if (this._oVirtCredentialsManager.hasToken())
this._oVirtUserAuthenticated(this._oVirtCredentialsManager.getToken());
this._oVirtUserAuthenticatedId = this._oVirtCredentialsManager.connect('user-authenticated',
Lang.bind(this, this._oVirtUserAuthenticated));
this._oVirtCredentialsManager.connect('user-authenticated',
Lang.bind(this, this._oVirtUserAuthenticated));
},
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() {
if (this._cancellable) {
this._cancellable.cancel();
this._cancellable = null;
}
this._clearUserVerifier();
if (this._userVerifier) {
this._userVerifier.run_dispose();
this._userVerifier = null;
}
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) {
if (!this.hasPendingMessages) {
this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null);
@ -300,10 +283,9 @@ const ShellUserVerifier = new Lang.Class({
this._fprintManager.GetDefaultDeviceRemote(Gio.DBusCallFlags.NONE, this._cancellable, Lang.bind(this,
function(device, error) {
if (!error && device) {
if (!error && device)
this._haveFingerprintReader = true;
this._updateDefaultService();
}
}));
},
@ -344,7 +326,6 @@ const ShellUserVerifier = new Lang.Class({
_reauthenticationChannelOpened: function(client, result) {
try {
this._clearUserVerifier();
this._userVerifier = client.open_reauthentication_channel_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return;
@ -368,7 +349,6 @@ const ShellUserVerifier = new Lang.Class({
_userVerifierGot: function(client, result) {
try {
this._clearUserVerifier();
this._userVerifier = client.get_user_verifier_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return;
@ -410,7 +390,7 @@ const ShellUserVerifier = new Lang.Class({
_updateDefaultService: function() {
if (this._settings.get_boolean(PASSWORD_AUTHENTICATION_KEY))
this._defaultService = PASSWORD_SERVICE_NAME;
else if (this._settings.get_boolean(SMARTCARD_AUTHENTICATION_KEY))
else if (this.smartcardDetected)
this._defaultService = SMARTCARD_SERVICE_NAME;
else if (this._haveFingerprintReader)
this._defaultService = FINGERPRINT_SERVICE_NAME;

View File

@ -16,9 +16,7 @@
<file>misc/fileUtils.js</file>
<file>misc/gnomeSession.js</file>
<file>misc/history.js</file>
<file>misc/ibusManager.js</file>
<file>misc/jsParse.js</file>
<file>misc/keyboardManager.js</file>
<file>misc/loginManager.js</file>
<file>misc/modemManager.js</file>
<file>misc/objectManager.js</file>
@ -27,16 +25,11 @@
<file>misc/util.js</file>
<file>perf/core.js</file>
<file>perf/hwtest.js</file>
<file>portalHelper/main.js</file>
<file>ui/accessDialog.js</file>
<file>ui/altTab.js</file>
<file>ui/animation.js</file>
<file>ui/appDisplay.js</file>
<file>ui/appFavorites.js</file>
<file>ui/audioDeviceSelection.js</file>
<file>ui/backgroundMenu.js</file>
<file>ui/background.js</file>
<file>ui/boxpointer.js</file>
@ -46,7 +39,6 @@
<file>ui/dash.js</file>
<file>ui/dateMenu.js</file>
<file>ui/dnd.js</file>
<file>ui/edgeDragAction.js</file>
<file>ui/endSessionDialog.js</file>
<file>ui/environment.js</file>
<file>ui/extensionDownloader.js</file>
@ -59,17 +51,13 @@
<file>ui/layout.js</file>
<file>ui/lightbox.js</file>
<file>ui/lookingGlass.js</file>
<file>ui/legacyTray.js</file>
<file>ui/magnifier.js</file>
<file>ui/magnifierDBus.js</file>
<file>ui/main.js</file>
<file>ui/messageTray.js</file>
<file>ui/messageList.js</file>
<file>ui/modalDialog.js</file>
<file>ui/mpris.js</file>
<file>ui/notificationDaemon.js</file>
<file>ui/osdWindow.js</file>
<file>ui/osdMonitorLabeler.js</file>
<file>ui/overview.js</file>
<file>ui/overviewControls.js</file>
<file>ui/panel.js</file>

View File

@ -43,7 +43,7 @@ function getCurrentExtension() {
let path = match[1];
let file = Gio.File.new_for_path(path);
// Walk up the directory tree, looking for an extension with
// Walk up the directory tree, looking for an extesion with
// the same UUID as a directory name.
while (file != null) {
let extension = extensions[file.get_basename()];

View File

@ -1,234 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
try {
var IBus = imports.gi.IBus;
_checkIBusVersion(1, 5, 2);
const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
} catch (e) {
var IBus = null;
log(e);
}
let _ibusManager = null;
function _checkIBusVersion(requiredMajor, requiredMinor, requiredMicro) {
if ((IBus.MAJOR_VERSION > requiredMajor) ||
(IBus.MAJOR_VERSION == requiredMajor && IBus.MINOR_VERSION > requiredMinor) ||
(IBus.MAJOR_VERSION == requiredMajor && IBus.MINOR_VERSION == requiredMinor &&
IBus.MICRO_VERSION >= requiredMicro))
return;
throw "Found IBus version %d.%d.%d but required is %d.%d.%d".
format(IBus.MAJOR_VERSION, IBus.MINOR_VERSION, IBus.MINOR_VERSION,
requiredMajor, requiredMinor, requiredMicro);
}
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
_PRELOAD_ENGINES_DELAY_TIME: 30, // sec
_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._preloadEnginesId = 0;
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));
try {
// IBus versions older than 1.5.10 have a bug which
// causes spurious set-content-type emissions when
// switching input focus that temporarily lose purpose
// and hints defeating its intended semantics and
// confusing users. We thus don't use it in that case.
_checkIBusVersion(1, 5, 10);
this._panelService.connect('set-content-type', Lang.bind(this, this._setContentType));
} catch (e) {
}
// 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);
},
_setContentType: function(panel, purpose, hints) {
this.emit('set-content-type', purpose, hints);
},
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) {
// Send id even if id == this._currentEngineName
// because 'properties-registered' signal can be emitted
// while this._ibusSources == null on a lock screen.
if (!IBus || !this._ready) {
if (callback)
callback();
return;
}
this._ibus.set_global_engine_async(id, this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
null, callback);
},
preloadEngines: function(ids) {
if (!IBus || !this._ibus || ids.length == 0)
return;
if (this._preloadEnginesId != 0) {
Mainloop.source_remove(this._preloadEnginesId);
this._preloadEnginesId = 0;
}
this._preloadEnginesId =
Mainloop.timeout_add_seconds(this._PRELOAD_ENGINES_DELAY_TIME,
Lang.bind(this, function() {
this._ibus.preload_engines_async(
ids,
-1,
null,
null);
this._preloadEnginesId = 0;
return GLib.SOURCE_REMOVE;
}));
},
});
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.display.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

@ -40,9 +40,6 @@ const SystemdLoginSessionIface = '<node> \
<signal name="Lock" /> \
<signal name="Unlock" /> \
<property name="Active" type="b" access="read" /> \
<method name="SetLockedHint"> \
<arg type="b" direction="in"/> \
</method> \
</interface> \
</node>';
@ -134,13 +131,10 @@ const LoginManagerSystemd = new Lang.Class({
canSuspend: function(asyncCallback) {
this._proxy.CanSuspendRemote(function(result, error) {
if (error) {
asyncCallback(false, false);
} else {
let needsAuth = result[0] == 'challenge';
let canSuspend = needsAuth || result[0] == 'yes';
asyncCallback(canSuspend, needsAuth);
}
if (error)
asyncCallback(false);
else
asyncCallback(result[0] != 'no');
});
},
@ -193,7 +187,7 @@ const LoginManagerDummy = new Lang.Class({
},
canSuspend: function(asyncCallback) {
asyncCallback(false, false);
asyncCallback(false);
},
listSessions: function(asyncCallback) {

View File

@ -4,12 +4,10 @@ const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const Params = imports.misc.params;
const SCROLL_TIME = 0.1;
@ -40,8 +38,6 @@ const _urlRegexp = new RegExp(
')' +
')', 'gi');
let _desktopSettings = null;
// findUrls:
// @str: string to find URLs in
//
@ -161,105 +157,6 @@ function _handleSpawnError(command, err) {
Main.notifyError(title, err.message);
}
function formatTime(time, params) {
let date;
// HACK: The built-in Date type sucks at timezones, which we need for the
// world clock; it's often more convenient though, so allow either
// Date or GLib.DateTime as parameter
if (time instanceof Date)
date = GLib.DateTime.new_from_unix_local(time.getTime() / 1000);
else
date = time;
let now = GLib.DateTime.new_now_local();
let daysAgo = now.difference(date) / (24 * 60 * 60 * 1000 * 1000);
let format;
if (_desktopSettings == null)
_desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
let clockFormat = _desktopSettings.get_string('clock-format');
let hasAmPm = date.format('%p') != '';
params = Params.parse(params, { timeOnly: false });
if (clockFormat == '24h' || !hasAmPm) {
// Show only the time if date is on today
if (daysAgo < 1 || params.timeOnly)
/* Translators: Time in 24h format */
format = N_("%H\u2236%M");
// Show the word "Yesterday" and time if date is on yesterday
else if (daysAgo <2)
/* Translators: this is the word "Yesterday" followed by a
time string in 24h format. i.e. "Yesterday, 14:30" */
// xgettext:no-c-format
format = N_("Yesterday, %H\u2236%M");
// Show a week day and time if date is in the last week
else if (daysAgo < 7)
/* Translators: this is the week day name followed by a time
string in 24h format. i.e. "Monday, 14:30" */
// xgettext:no-c-format
format = N_("%A, %H\u2236%M");
else if (date.get_year() == now.get_year())
/* Translators: this is the month name and day number
followed by a time string in 24h format.
i.e. "May 25, 14:30" */
// xgettext:no-c-format
format = N_("%B %d, %H\u2236%M");
else
/* Translators: this is the month name, day number, year
number followed by a time string in 24h format.
i.e. "May 25 2012, 14:30" */
// xgettext:no-c-format
format = N_("%B %d %Y, %H\u2236%M");
} else {
// Show only the time if date is on today
if (daysAgo < 1 || params.timeOnly)
/* Translators: Time in 12h format */
format = N_("%l\u2236%M %p");
// Show the word "Yesterday" and time if date is on yesterday
else if (daysAgo <2)
/* Translators: this is the word "Yesterday" followed by a
time string in 12h format. i.e. "Yesterday, 2:30 pm" */
// xgettext:no-c-format
format = N_("Yesterday, %l\u2236%M %p");
// Show a week day and time if date is in the last week
else if (daysAgo < 7)
/* 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 = N_("%A, %l\u2236%M %p");
else if (date.get_year() == now.get_year())
/* Translators: this is the month name and day number
followed by a time string in 12h format.
i.e. "May 25, 2:30 pm" */
// xgettext:no-c-format
format = N_("%B %d, %l\u2236%M %p");
else
/* Translators: this is the month name, day number, year
number followed by a time string in 12h format.
i.e. "May 25 2012, 2:30 pm"*/
// xgettext:no-c-format
format = N_("%B %d %Y, %l\u2236%M %p");
}
return date.format(Shell.util_translate_time_string(format));
}
function createTimeLabel(date, params) {
if (_desktopSettings == null)
_desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
let label = new St.Label({ text: formatTime(date, params) });
let id = _desktopSettings.connect('changed::clock-format', function() {
label.text = formatTime(date, params);
});
label.connect('destroy', function() {
_desktopSettings.disconnect(id);
});
return label;
}
// lowerBound:
// @array: an array or array-like object, already sorted
// according to @cmp

View File

@ -72,9 +72,6 @@ function run() {
Scripting.defineScriptEvent("applicationsShowStart", "Starting to switch 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() {
Scripting.scriptEvent('overviewShowDone');
});
@ -90,10 +87,7 @@ function run() {
yield Scripting.destroyTestWindows();
for (let k = 0; k < config.count; k++)
yield Scripting.createTestWindow({ width: config.width,
height: config.height,
alpha: config.alpha,
maximized: config.maximized });
yield Scripting.createTestWindow(config.width, config.height, config.alpha, config.maximized);
yield Scripting.waitTestWindows();
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

@ -1,202 +0,0 @@
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const CheckBox = imports.ui.checkBox;
const ModalDialog = imports.ui.modalDialog;
const RequestIface = '<node> \
<interface name="org.freedesktop.impl.portal.Request"> \
<method name="Close"/> \
</interface> \
</node>';
const AccessIface = '<node> \
<interface name="org.freedesktop.impl.portal.Access"> \
<method name="AccessDialog"> \
<arg type="o" name="handle" direction="in"/> \
<arg type="s" name="app_id" direction="in"/> \
<arg type="s" name="parent_window" direction="in"/> \
<arg type="s" name="title" direction="in"/> \
<arg type="s" name="subtitle" direction="in"/> \
<arg type="s" name="body" direction="in"/> \
<arg type="a{sv}" name="options" direction="in"/> \
<arg type="u" name="response" direction="out"/> \
<arg type="a{sv}" name="results" direction="out"/> \
</method> \
</interface> \
</node>';
const DialogResponse = {
OK: 0,
CANCEL: 1,
CLOSED: 2
};
const AccessDialog = new Lang.Class({
Name: 'AccessDialog',
Extends: ModalDialog.ModalDialog,
_init: function(invocation, handle, title, subtitle, body, options) {
this.parent({ styleClass: 'access-dialog' });
this._invocation = invocation;
this._handle = handle;
this._requestExported = false;
this._request = Gio.DBusExportedObject.wrapJSObject(RequestIface, this);
for (let option in options)
options[option] = options[option].deep_unpack();
this._buildLayout(title, subtitle, body, options);
},
_buildLayout: function(title, subtitle, body, options) {
// No support for non-modal system dialogs, so ignore the option
//let modal = options['modal'] || true;
let denyLabel = options['deny_label'] || _("Deny Access");
let grantLabel = options['grant_label'] || _("Grant Access");
let iconName = options['icon'] || null;
let choices = options['choices'] || [];
let mainContentBox = new St.BoxLayout();
mainContentBox.style_class = 'access-dialog-main-layout';
this.contentLayout.add_actor(mainContentBox);
let icon = new St.Icon({ style_class: 'access-dialog-icon',
icon_name: iconName,
y_align: Clutter.ActorAlign.START });
mainContentBox.add_actor(icon);
let messageBox = new St.BoxLayout({ vertical: true });
messageBox.style_class = 'access-dialog-content',
mainContentBox.add_actor(messageBox);
let label;
label = new St.Label({ style_class: 'access-dialog-title headline',
text: title });
messageBox.add_actor(label);
label = new St.Label({ style_class: 'access-dialog-subtitle',
text: subtitle });
label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
label.clutter_text.line_wrap = true;
messageBox.add_actor(label);
this._choices = new Map();
for (let i = 0; i < choices.length; i++) {
let [id, name, opts, selected] = choices[i];
if (opts.length > 0)
continue; // radio buttons, not implemented
let check = new CheckBox.CheckBox();
check.getLabelActor().text = name;
check.actor.checked = selected == "true";
messageBox.add_actor(check.actor);
this._choices.set(id, check);
}
label = new St.Label({ text: body });
label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
label.clutter_text.line_wrap = true;
messageBox.add_actor(label);
this.addButton({ label: denyLabel,
action: () => {
this._sendResponse(DialogResponse.CANCEL);
},
key: Clutter.KEY_Escape });
this.addButton({ label: grantLabel,
action: () => {
this._sendResponse(DialogResponse.OK);
}});
},
open: function() {
this.parent();
let connection = this._invocation.get_connection();
this._requestExported = this._request.export(connection, this._handle);
},
CloseAsync: function(invocation, params) {
if (this._invocation.get_sender() != invocation.get_sender()) {
invocation.return_error_literal(Gio.DBusError,
Gio.DBusError.ACCESS_DENIED,
'');
return;
}
this._sendResponse(DialogResponse.CLOSED);
},
_sendResponse: function(response) {
if (this._requestExported)
this._request.unexport();
this._requestExported = false;
let results = {};
if (response == DialogResponse.OK) {
for (let [id, check] of this._choices) {
let checked = check.actor.checked ? 'true' : 'false';
results[id] = new GLib.Variant('s', checked);
}
}
// Delay actual response until the end of the close animation (if any)
this.connect('closed', () => {
this._invocation.return_value(new GLib.Variant('(ua{sv})',
[response, results]));
});
this.close();
}
});
const AccessDialogDBus = new Lang.Class({
Name: 'AccessDialogDBus',
_init: function() {
this._accessDialog = null;
this._windowTracker = Shell.WindowTracker.get_default();
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(AccessIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/portal/desktop');
Gio.DBus.session.own_name('org.freedesktop.impl.portal.desktop.gnome', Gio.BusNameOwnerFlags.REPLACE, null, null);
},
AccessDialogAsync: function(params, invocation) {
if (this._accessDialog) {
invocation.return_error_literal(Gio.DBusError,
Gio.DBusError.LIMITS_EXCEEDED,
'Already showing a system access dialog');
return;
}
let [handle, appId, parentWindow, title, subtitle, body, options] = params;
// We probably want to use parentWindow and global.display.focus_window
// for this check in the future
if (appId && appId + '.desktop' != this._windowTracker.focus_app.id) {
invocation.return_error_literal(Gio.DBusError,
Gio.DBusError.ACCESS_DENIED,
'Only the focused app is allowed to show a system access dialog');
return;
}
let dialog = new AccessDialog(invocation, handle, title,
subtitle, body, options);
dialog.open();
dialog.connect('closed', () => { this._accessDialog = null; });
this._accessDialog = dialog;
}
});

View File

@ -46,19 +46,6 @@ function _createWindowClone(window, size) {
y_expand: true });
};
function getWindows(workspace) {
// We ignore skip-taskbar windows in switchers, but if they are attached
// to their parent, their position in the MRU list may be more appropriate
// than the parent; so start with the complete list ...
let windows = global.display.get_tab_list(Meta.TabList.NORMAL_ALL,
workspace);
// ... map windows to their parent where appropriate ...
return windows.map(w => {
return w.is_attached_dialog() ? w.get_transient_for() : w;
// ... and filter out skip-taskbar windows and duplicates
}).filter((w, i, a) => !w.skip_taskbar && a.indexOf(w) == i);
}
const AppSwitcherPopup = new Lang.Class({
Name: 'AppSwitcherPopup',
Extends: SwitcherPopup.SwitcherPopup,
@ -71,14 +58,6 @@ const AppSwitcherPopup = new Lang.Class({
this._currentWindow = -1;
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) {
@ -94,6 +73,7 @@ const AppSwitcherPopup = new Lang.Class({
let leftPadding = this.actor.get_theme_node().get_padding(St.Side.LEFT);
let rightPadding = this.actor.get_theme_node().get_padding(St.Side.RIGHT);
let bottomPadding = this.actor.get_theme_node().get_padding(St.Side.BOTTOM);
let vPadding = this.actor.get_theme_node().get_vertical_padding();
let hPadding = leftPadding + rightPadding;
let icon = this._items[this._selectedIndex].actor;
@ -119,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) {
if (binding == 'switch-group') {
if (backward) {
@ -157,13 +151,13 @@ const AppSwitcherPopup = new Lang.Class({
this._items[this._selectedIndex].cachedWindows.length);
},
_keyPressHandler: function(keysym, action) {
_keyPressHandler: function(keysym, backwards, action) {
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) {
this._select(this._selectedIndex, this._previousWindow());
} 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) {
this._select(this._previous());
} else if (this._thumbnailsFocused) {
@ -367,175 +361,48 @@ const AppSwitcherPopup = new Lang.Class({
}
});
const CyclerHighlight = new Lang.Class({
Name: 'CyclerHighlight',
_init: function() {
this._window = null;
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this._clone = new Clutter.Clone();
this.actor.add_actor(this._clone);
this._highlight = new St.Widget({ style_class: 'cycler-highlight' });
this.actor.add_actor(this._highlight);
let coordinate = Clutter.BindCoordinate.ALL;
let constraint = new Clutter.BindConstraint({ coordinate: coordinate });
this._clone.bind_property('source', constraint, 'source', 0);
this.actor.add_constraint(constraint);
this.actor.connect('notify::allocation',
Lang.bind(this, this._onAllocationChanged));
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
},
set window(w) {
if (this._window == w)
return;
this._window = w;
if (this._clone.source)
this._clone.source.sync_visibility();
let windowActor = this._window ? this._window.get_compositor_private()
: null;
if (windowActor)
windowActor.hide();
this._clone.source = windowActor;
},
_onAllocationChanged: function() {
if (!this._window) {
this._highlight.set_size(0, 0);
this._highlight.hide();
} else {
let [x, y] = this.actor.allocation.get_origin();
let rect = this._window.get_frame_rect();
this._highlight.set_size(rect.width, rect.height);
this._highlight.set_position(rect.x - x, rect.y - y);
this._highlight.show();
}
},
_onDestroy: function() {
this.window = null;
}
});
const CyclerPopup = new Lang.Class({
Name: 'CyclerPopup',
Extends: SwitcherPopup.SwitcherPopup,
Abstract: true,
_init : function() {
this.parent();
this._items = this._getWindows();
if (this._items.length == 0)
return;
this._highlight = new CyclerHighlight();
global.window_group.add_actor(this._highlight.actor);
// We don't show an actual popup, so just provide what SwitcherPopup
// expects instead of inheriting from SwitcherList
this._switcherList = { actor: new St.Widget(),
highlight: Lang.bind(this, this._highlightItem),
connect: function() {} };
},
_highlightItem: function(index, justOutline) {
this._highlight.window = this._items[index];
global.window_group.set_child_above_sibling(this._highlight.actor, null);
},
_finish: function() {
let window = this._items[this._selectedIndex];
let ws = window.get_workspace();
let activeWs = global.screen.get_active_workspace();
if (window.minimized) {
Main.wm.skipNextEffect(window.get_compositor_private());
window.unminimize();
}
if (activeWs == ws) {
Main.activateWindow(window);
} else {
// If the selected window is on a different workspace, we don't
// want it to disappear, then slide in with the workspace; instead,
// always activate it on the active workspace ...
activeWs.activate_with_focus(window, global.get_current_time());
// ... then slide it over to the original workspace if necessary
Main.wm.actionMoveWindow(window, ws);
}
this.parent();
},
_onDestroy: function() {
this._highlight.actor.destroy();
this.parent();
}
});
const GroupCyclerPopup = new Lang.Class({
Name: 'GroupCyclerPopup',
Extends: CyclerPopup,
_getWindows: function() {
let app = Shell.WindowTracker.get_default().focus_app;
return app ? app.get_windows() : [];
},
_keyPressHandler: function(keysym, action) {
if (action == Meta.KeyBindingAction.CYCLE_GROUP)
this._select(this._next());
else if (action == Meta.KeyBindingAction.CYCLE_GROUP_BACKWARD)
this._select(this._previous());
else
return Clutter.EVENT_PROPAGATE;
return Clutter.EVENT_STOP;
}
});
const WindowSwitcherPopup = new Lang.Class({
Name: 'WindowSwitcherPopup',
Extends: SwitcherPopup.SwitcherPopup,
_init: function() {
this.parent();
this._settings = new Gio.Settings({ schema_id: '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;
_init: function(items) {
this.parent(items);
this._settings = new Gio.Settings({ schema: 'org.gnome.shell.window-switcher' });
},
_getWindowList: function() {
let workspace = this._settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace() : null;
return getWindows(workspace);
return global.display.get_tab_list(Meta.TabList.NORMAL, 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) {
this._select(this._next());
this._select(backwards ? this._previous() : this._next());
} else if (action == Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD) {
this._select(this._previous());
} else {
@ -557,32 +424,6 @@ const WindowSwitcherPopup = new Lang.Class({
}
});
const WindowCyclerPopup = new Lang.Class({
Name: 'WindowCyclerPopup',
Extends: CyclerPopup,
_init: function() {
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
this.parent();
},
_getWindows: function() {
let workspace = this._settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace() : null;
return getWindows(workspace);
},
_keyPressHandler: function(keysym, action) {
if (action == Meta.KeyBindingAction.CYCLE_WINDOWS)
this._select(this._next());
else if (action == Meta.KeyBindingAction.CYCLE_WINDOWS_BACKWARD)
this._select(this._previous());
else
return Clutter.EVENT_PROPAGATE;
return Clutter.EVENT_STOP;
}
});
const AppIcon = new Lang.Class({
Name: 'AppIcon',
@ -615,7 +456,7 @@ const AppSwitcher = new Lang.Class({
this._arrows = [];
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()
: null;
let allWindows = global.display.get_tab_list(Meta.TabList.NORMAL, workspace);
@ -630,6 +471,8 @@ const AppSwitcher = new Lang.Class({
});
if (appIcon.cachedWindows.length > 0)
this._addIcon(appIcon);
else if (workspace == null)
throw new Error('%s appears to be running, but doesn\'t have any windows'.format(appIcon.app.get_name()));
}
this._curApp = -1;
@ -867,17 +710,15 @@ const WindowIcon = new Lang.Class({
this._icon.destroy_all_children();
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
switch (mode) {
case AppIconMode.THUMBNAIL_ONLY:
size = WINDOW_PREVIEW_SIZE;
this._icon.add_actor(_createWindowClone(mutterWindow, size * scaleFactor));
this._icon.add_actor(_createWindowClone(mutterWindow, WINDOW_PREVIEW_SIZE));
break;
case AppIconMode.BOTH:
size = WINDOW_PREVIEW_SIZE;
this._icon.add_actor(_createWindowClone(mutterWindow, size * scaleFactor));
this._icon.add_actor(_createWindowClone(mutterWindow, WINDOW_PREVIEW_SIZE));
if (this.app)
this._icon.add_actor(this._createAppIcon(this.app,
@ -889,7 +730,7 @@ const WindowIcon = new Lang.Class({
this._icon.add_actor(this._createAppIcon(this.app, size));
}
this._icon.set_size(size * scaleFactor, size * scaleFactor);
this._icon.set_size(size, size);
},
_createAppIcon: function(app, size) {

View File

@ -7,12 +7,12 @@ const St = imports.gi.St;
const Signals = imports.signals;
const Atk = imports.gi.Atk;
const ANIMATED_ICON_UPDATE_TIMEOUT = 16;
const ANIMATED_ICON_UPDATE_TIMEOUT = 100;
const Animation = new Lang.Class({
Name: 'Animation',
_init: function(file, width, height, speed) {
_init: function(filename, width, height, speed) {
this.actor = new St.Bin();
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._speed = speed;
@ -23,7 +23,7 @@ const Animation = new Lang.Class({
this._frame = 0;
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._animations = St.TextureCache.get_default().load_sliced_image (file, width, height, scaleFactor,
this._animations = St.TextureCache.get_default().load_sliced_image (filename, width, height, scaleFactor,
Lang.bind(this, this._animationsLoaded));
this.actor.set_child(this._animations);
},
@ -33,7 +33,7 @@ const Animation = new Lang.Class({
if (this._frame == 0)
this._showFrame(0);
this._timeoutId = GLib.timeout_add(GLib.PRIORITY_LOW, 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');
}
@ -82,7 +82,7 @@ const AnimatedIcon = new Lang.Class({
Name: 'AnimatedIcon',
Extends: Animation,
_init: function(file, size) {
this.parent(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
_init: function(filename, size) {
this.parent(filename, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
}
});

View File

@ -16,7 +16,6 @@ const Atk = imports.gi.Atk;
const AppFavorites = imports.ui.appFavorites;
const BoxPointer = imports.ui.boxpointer;
const DND = imports.ui.dnd;
const GrabHelper = imports.ui.grabHelper;
const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main;
const Overview = imports.ui.overview;
@ -34,9 +33,7 @@ const MIN_COLUMNS = 4;
const MIN_ROWS = 4;
const INACTIVE_GRID_OPACITY = 77;
// This time needs to be less than IconGrid.EXTRA_SPACE_ANIMATION_TIME
// to not clash with other animations
const INACTIVE_GRID_OPACITY_ANIMATION_TIME = 0.24;
const INACTIVE_GRID_OPACITY_ANIMATION_TIME = 0.40;
const FOLDER_SUBICON_FRACTION = .4;
const MIN_FREQUENT_APPS_COUNT = 3;
@ -45,16 +42,6 @@ const INDICATORS_BASE_TIME = 0.25;
const INDICATORS_ANIMATION_DELAY = 0.125;
const INDICATORS_ANIMATION_MAX_TIME = 0.75;
// Follow iconGrid animations approach and divide by 2 to animate out to
// not annoy the user when the user wants to quit appDisplay.
// 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 VIEWS_SWITCH_TIME = 0.4;
@ -189,98 +176,26 @@ const BaseAppView = new Lang.Class({
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);
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({
Name:'PageIndicators',
_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._currentPage = undefined;
this.actor.connect('notify::mapped',
Lang.bind(this, function() {
this.animateIndicators(IconGrid.AnimationDirection.IN);
})
);
Lang.bind(this, this._animateIndicators));
},
setNPages: function(nPages) {
@ -321,7 +236,7 @@ const PageIndicators = new Lang.Class({
children[i].set_checked(i == this._currentPage);
},
animateIndicators: function(animationDirection) {
_animateIndicators: function() {
if (!this.actor.mapped)
return;
@ -329,32 +244,24 @@ const PageIndicators = new Lang.Class({
if (children.length == 0)
return;
for (let i = 0; i < this._nPages; i++)
Tweener.removeTweens(children[i]);
let offset;
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL)
offset = -children[0].width;
else
offset = children[0].width;
let isAnimationIn = animationDirection == IconGrid.AnimationDirection.IN;
let delay = isAnimationIn ? INDICATORS_ANIMATION_DELAY :
INDICATORS_ANIMATION_DELAY_OUT;
let baseTime = isAnimationIn ? INDICATORS_BASE_TIME : INDICATORS_BASE_TIME_OUT;
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;
let delay = INDICATORS_ANIMATION_DELAY;
let totalAnimationTime = INDICATORS_BASE_TIME + INDICATORS_ANIMATION_DELAY * this._nPages;
if (totalAnimationTime > INDICATORS_ANIMATION_MAX_TIME)
delay -= (totalAnimationTime - INDICATORS_ANIMATION_MAX_TIME) / this._nPages;
for (let i = 0; i < this._nPages; i++) {
children[i].translation_x = isAnimationIn ? offset : 0;
children[i].translation_x = offset;
Tweener.addTween(children[i],
{ translation_x: isAnimationIn ? 0 : offset,
time: baseTime + delay * i,
{ translation_x: 0,
time: INDICATORS_BASE_TIME + delay * i,
transition: 'easeInOutQuad',
delay: isAnimationIn ? VIEWS_SWITCH_ANIMATION_DELAY : 0
delay: VIEWS_SWITCH_ANIMATION_DELAY
});
}
}
@ -379,7 +286,9 @@ const AllView = new Lang.Class({
this.actor.add_actor(this._scrollView);
this._scrollView.set_policy(Gtk.PolicyType.NEVER,
Gtk.PolicyType.EXTERNAL);
Gtk.PolicyType.AUTOMATIC);
// we are only using ScrollView for the fade effect, hide scrollbars
this._scrollView.vscroll.hide();
this._adjustment = this._scrollView.vscroll.adjustment;
this._pageIndicators = new PageIndicators();
@ -395,7 +304,7 @@ const AllView = new Lang.Class({
this._stack = new St.Widget({ layout_manager: new Clutter.BinLayout() });
let box = new St.BoxLayout({ vertical: true });
this._grid.currentPage = 0;
this._currentPage = 0;
this._stack.add_actor(this._grid.actor);
this._eventBlocker = new St.Widget({ x_expand: true, y_expand: true });
this._stack.add_actor(this._eventBlocker);
@ -461,7 +370,7 @@ const AllView = new Lang.Class({
Shell.AppSystem.get_default().connect('installed-changed', Lang.bind(this, function() {
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() {
Main.queueDeferredWork(this._redisplayWorkId);
}));
@ -500,11 +409,6 @@ const AllView = new Lang.Class({
_loadApps: function() {
let apps = Gio.AppInfo.get_all().filter(function(appInfo) {
try {
let id = appInfo.get_id(); // catch invalid file encodings
} catch(e) {
return false;
}
return appInfo.should_show();
}).map(function(app) {
return app.get_id();
@ -522,19 +426,9 @@ const AllView = new Lang.Class({
this.folderIcons.push(icon);
}));
// Allow dragging of the icon only if the Dash would accept a drop to
// change favorite-apps. There are no other possible drop targets from
// the app picker, so there's no other need for a drag to start,
// at least on single-monitor setups.
// This also disables drag-to-launch on multi-monitor setups,
// but we hope that is not used much.
let favoritesWritable = global.settings.is_writable('favorite-apps');
apps.forEach(Lang.bind(this, function(appId) {
let app = appSys.lookup_app(appId);
let icon = new AppIcon(app,
{ isDraggable: favoritesWritable });
let icon = new AppIcon(app);
this.addItem(icon);
}));
@ -542,59 +436,14 @@ const AllView = new Lang.Class({
this._refilterApps();
},
// Overriden from BaseAppView
animate: function (animationDirection, onComplete) {
this._scrollView.reactive = false;
let completionFunc = Lang.bind(this, function() {
this._scrollView.reactive = true;
if (onComplete)
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, completionFunc);
}));
} else {
this.parent(animationDirection, completionFunc);
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() {
return this._grid.getPageY(this._grid.currentPage);
return this._grid.getPageY(this._currentPage);
},
goToPage: function(pageNumber) {
pageNumber = clamp(pageNumber, 0, this._grid.nPages() - 1);
if (this._grid.currentPage == pageNumber && this._displayingPopup && this._currentPopup)
if (this._currentPage == pageNumber && this._displayingPopup && this._currentPopup)
return;
if (this._displayingPopup && this._currentPopup)
this._currentPopup.popdown();
@ -614,7 +463,7 @@ const AllView = new Lang.Class({
let time;
// Only take the velocity into account on page changes, otherwise
// 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);
velocity = Math.max(minVelocity, velocity);
time = (diffToPage / velocity) / 1000;
@ -625,9 +474,9 @@ const AllView = new Lang.Class({
// longer than PAGE_SWITCH_TIME
time = Math.min(time, PAGE_SWITCH_TIME);
this._grid.currentPage = pageNumber;
this._currentPage = pageNumber;
Tweener.addTween(this._adjustment,
{ value: this._grid.getPageY(this._grid.currentPage),
{ value: this._grid.getPageY(this._currentPage),
time: time,
transition: 'easeOutQuad' });
this._pageIndicators.setCurrentPage(pageNumber);
@ -651,14 +500,14 @@ const AllView = new Lang.Class({
},
_onScroll: function(actor, event) {
if (this._displayingPopup || !this._scrollView.reactive)
if (this._displayingPopup)
return Clutter.EVENT_STOP;
let direction = event.get_scroll_direction();
if (direction == Clutter.ScrollDirection.UP)
this.goToPage(this._grid.currentPage - 1);
this.goToPage(this._currentPage - 1);
else if (direction == Clutter.ScrollDirection.DOWN)
this.goToPage(this._grid.currentPage + 1);
this.goToPage(this._currentPage + 1);
return Clutter.EVENT_STOP;
},
@ -698,10 +547,10 @@ const AllView = new Lang.Class({
return Clutter.EVENT_STOP;
if (event.get_key_symbol() == Clutter.Page_Up) {
this.goToPage(this._grid.currentPage - 1);
this.goToPage(this._currentPage - 1);
return Clutter.EVENT_STOP;
} else if (event.get_key_symbol() == Clutter.Page_Down) {
this.goToPage(this._grid.currentPage + 1);
this.goToPage(this._currentPage + 1);
return Clutter.EVENT_STOP;
}
@ -758,12 +607,10 @@ const AllView = new Lang.Class({
let fadeOffset = Math.min(this._grid.topPadding,
this._grid.bottomPadding);
this._scrollView.update_fade_effect(fadeOffset, 0);
if (fadeOffset > 0)
this._scrollView.get_effect('fade').fade_edges = true;
this._scrollView.get_effect('fade').fade_edges = true;
if (this._availWidth != availWidth || this._availHeight != availHeight || oldNPages != this._grid.nPages()) {
this._adjustment.value = 0;
this._grid.currentPage = 0;
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
function() {
this._pageIndicators.setNPages(this._grid.nPages());
@ -786,7 +633,6 @@ const FrequentView = new Lang.Class({
_init: function() {
this.parent(null, { fillParent: true });
this.actor = new St.Widget({ style_class: 'frequent-apps',
layout_manager: new Clutter.BinLayout(),
x_expand: true, y_expand: true });
@ -823,19 +669,10 @@ const FrequentView = new Lang.Class({
if(!hasUsefulData)
return;
// Allow dragging of the icon only if the Dash would accept a drop to
// change favorite-apps. There are no other possible drop targets from
// the app picker, so there's no other need for a drag to start,
// at least on single-monitor setups.
// This also disables drag-to-launch on multi-monitor setups,
// but we hope that is not used much.
let favoritesWritable = global.settings.is_writable('favorite-apps');
for (let i = 0; i < mostUsed.length; i++) {
if (!mostUsed[i].get_app_info().should_show())
continue;
let appIcon = new AppIcon(mostUsed[i],
{ isDraggable: favoritesWritable });
let appIcon = new AppIcon(mostUsed[i]);
this._grid.addItem(appIcon, -1);
}
},
@ -903,7 +740,7 @@ const AppDisplay = new Lang.Class({
Name: 'AppDisplay',
_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',
Lang.bind(this, this._updateFrequentVisibility));
@ -912,14 +749,14 @@ const AppDisplay = new Lang.Class({
let view, button;
view = new FrequentView();
button = new St.Button({ label: _("Frequent"),
style_class: 'app-view-control button',
style_class: 'app-view-control',
can_focus: true,
x_expand: true });
this._views[Views.FREQUENT] = { 'view': view, 'control': button };
view = new AllView();
button = new St.Button({ label: _("All"),
style_class: 'app-view-control button',
style_class: 'app-view-control',
can_focus: true,
x_expand: true });
this._views[Views.ALL] = { 'view': view, 'control': button };
@ -935,19 +772,6 @@ const AppDisplay = new Lang.Class({
let layout = new ControlsBoxLayout({ homogeneous: true });
this._controls = new St.Widget({ style_class: 'app-view-controls',
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);
this.actor.add_actor(new St.Bin({ child: this._controls }));
@ -971,39 +795,23 @@ const AppDisplay = new Lang.Class({
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) {
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)
this._views[i].control.add_style_pseudo_class('checked');
else
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);
}
},
@ -1066,7 +874,7 @@ const AppSearchProvider = new Lang.Class({
getInitialResultSet: function(terms, callback, cancellable) {
let query = terms.join(' ');
let groups = Shell.AppSystem.search(query);
let groups = Gio.DesktopAppInfo.search(query);
let usage = Shell.AppUsage.get_default();
let results = [];
groups.forEach(function(group) {
@ -1085,6 +893,26 @@ const AppSearchProvider = new Lang.Class({
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) {
let app = this._appSys.lookup_app(resultMeta['id']);
return new AppIcon(app);
@ -1116,20 +944,14 @@ const FolderView = new Lang.Class({
Util.ensureActorVisibleInScrollView(this.actor, actor);
},
// Overriden from BaseAppView
animate: function(animationDirection) {
this._grid.animatePulse(animationDirection);
},
createFolderIcon: function(size) {
let layout = new Clutter.GridLayout();
let layout = new Clutter.TableLayout();
let icon = new St.Widget({ layout_manager: layout,
style_class: 'app-folder-icon' });
layout.hookup_style(icon);
let subSize = Math.floor(FOLDER_SUBICON_FRACTION * size);
let numItems = this._allItems.length;
let rtl = icon.get_text_direction() == Clutter.TextDirection.RTL;
for (let i = 0; i < 4; i++) {
let bin;
if (i < numItems) {
@ -1138,7 +960,7 @@ const FolderView = new Lang.Class({
} else {
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;
@ -1295,13 +1117,9 @@ const FolderIcon = new Lang.Class({
if (!_listsIntersect(folderCategories, appCategories))
return;
try {
addAppId(appInfo.get_id()); // catch invalid file encodings
} catch(e) {
}
addAppId(appInfo.get_id());
});
this.actor.visible = this.view.getAllItems().length > 0;
this.view.loadGrid();
this.emit('apps-changed');
},
@ -1431,53 +1249,18 @@ const AppFolderPopup = new Lang.Class({
function() {
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));
},
_onKeyPress: function(actor, event) {
if (global.stage.get_key_focus() != actor)
if (!this._isOpen)
return Clutter.EVENT_PROPAGATE;
// Since we need to only grab focus on one item child when the user
// actually press a key we don't use navigate_focus when opening
// 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
if (event.get_key_symbol() != Clutter.KEY_Escape)
return Clutter.EVENT_PROPAGATE;
// Use TAB_FORWARD for down key and right key
// and TAB_BACKWARD for up key and left key on ltr
// 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);
this.popdown();
return Clutter.EVENT_STOP;
},
toggle: function() {
@ -1491,27 +1274,15 @@ const AppFolderPopup = new Lang.Class({
if (this._isOpen)
return;
this._isOpen = this._grabHelper.grab({ actor: this.actor,
onUngrab: Lang.bind(this, this.popdown) });
if (!this._isOpen)
return;
this.actor.show();
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 |
BoxPointer.PopupAnimation.SLIDE,
Lang.bind(this,
function() {
this._view.actor.opacity = 255;
this._view.animate(IconGrid.AnimationDirection.IN);
}));
BoxPointer.PopupAnimation.SLIDE);
this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
this._isOpen = true;
this.emit('open-state-changed', true);
},
@ -1519,8 +1290,6 @@ const AppFolderPopup = new Lang.Class({
if (!this._isOpen)
return;
this._grabHelper.ungrab({ actor: this.actor });
this._boxPointer.hide(BoxPointer.PopupAnimation.FADE |
BoxPointer.PopupAnimation.SLIDE);
this._isOpen = false;
@ -1559,70 +1328,47 @@ const AppIcon = new Lang.Class({
can_focus: true,
x_fill: true,
y_fill: true });
this._dot = new St.Widget({ style_class: 'app-well-app-running-dot',
layout_manager: new Clutter.BinLayout(),
x_expand: true, y_expand: true,
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.END });
this._iconContainer = new St.Widget({ layout_manager: new Clutter.BinLayout(),
x_expand: true, y_expand: true });
this.actor.set_child(this._iconContainer);
this._iconContainer.add_child(this._dot);
this.actor._delegate = this;
if (!iconParams)
iconParams = {};
// Get the isDraggable property without passing it on to the BaseIcon:
let appIconParams = Params.parse(iconParams, { isDraggable: true }, true);
let isDraggable = appIconParams['isDraggable'];
delete iconParams['isDraggable'];
iconParams['createIcon'] = Lang.bind(this, this._createIcon);
iconParams['setSizeManually'] = true;
this.icon = new IconGrid.BaseIcon(app.get_name(), iconParams);
this._iconContainer.add_child(this.icon.actor);
this.actor.set_child(this.icon.actor);
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('touch-event', Lang.bind(this, this._onTouchEvent));
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
this.actor.connect('popup-menu', Lang.bind(this, this._onKeyboardPopupMenu));
this._menu = null;
this._menuManager = new PopupMenu.PopupMenuManager(this);
if (isDraggable) {
this._draggable = DND.makeDraggable(this.actor);
this._draggable.connect('drag-begin', Lang.bind(this,
function () {
this._removeMenuTimeout();
Main.overview.beginItemDrag(this);
}));
this._draggable.connect('drag-cancelled', Lang.bind(this,
function () {
Main.overview.cancelledItemDrag(this);
}));
this._draggable.connect('drag-end', Lang.bind(this,
function () {
Main.overview.endItemDrag(this);
}));
}
this._draggable = DND.makeDraggable(this.actor);
this._draggable.connect('drag-begin', Lang.bind(this,
function () {
this._removeMenuTimeout();
Main.overview.beginItemDrag(this);
}));
this._draggable.connect('drag-cancelled', Lang.bind(this,
function () {
Main.overview.cancelledItemDrag(this);
}));
this._draggable.connect('drag-end', Lang.bind(this,
function () {
Main.overview.endItemDrag(this);
}));
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._menuTimeoutId = 0;
this._stateChangedId = this.app.connect('notify::state', Lang.bind(this,
function () {
this._updateRunningStyle();
}));
this._updateRunningStyle();
this._stateChangedId = this.app.connect('notify::state',
Lang.bind(this,
this._onStateChanged));
this._onStateChanged();
},
_onDestroy: function() {
@ -1643,33 +1389,24 @@ const AppIcon = new Lang.Class({
}
},
_updateRunningStyle: function() {
_onStateChanged: function() {
if (this.app.state != Shell.AppState.STOPPED)
this._dot.show();
this.actor.add_style_class_name('running');
else
this._dot.hide();
},
_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();
this.actor.remove_style_class_name('running');
},
_onButtonPress: function(actor, event) {
let button = event.get_button();
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;
}));
GLib.Source.set_name_by_id(this._menuTimeoutId, '[gnome-shell] this.popupMenu');
} else if (button == 3) {
this.popupMenu();
return Clutter.EVENT_STOP;
@ -1677,16 +1414,16 @@ const AppIcon = new Lang.Class({
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) {
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() {
@ -1701,9 +1438,7 @@ const AppIcon = new Lang.Class({
popupMenu: function() {
this._removeMenuTimeout();
this.actor.fake_release();
if (this._draggable)
this._draggable.fakeRelease();
this._draggable.fakeRelease();
if (!this._menu) {
this._menu = new AppIconMenu(this);
@ -1714,10 +1449,7 @@ const AppIcon = new Lang.Class({
if (!isPoppedUp)
this._onMenuPoppedDown();
}));
let id = Main.overview.connect('hiding', Lang.bind(this, function () { this._menu.close(); }));
this.actor.connect('destroy', function() {
Main.overview.disconnect(id);
});
Main.overview.connect('hiding', Lang.bind(this, function () { this._menu.close(); }));
this._menuManager.addMenu(this._menu);
}
@ -1745,29 +1477,19 @@ const AppIcon = new Lang.Class({
this.emit('menu-state-changed', false);
},
activate: function (button) {
let event = Clutter.get_current_event();
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;
_onActivate: function (event) {
let modifiers = event.get_state();
if (this.app.state == Shell.AppState.STOPPED || openNewWindow)
this.animateLaunch();
if (openNewWindow)
if (modifiers & Clutter.ModifierType.CONTROL_MASK
&& this.app.state == Shell.AppState.RUNNING) {
this.app.open_new_window(-1);
else
} else {
this.app.activate();
}
Main.overview.hide();
},
animateLaunch: function() {
this.icon.animateZoomOut();
},
shellWorkspaceLaunch : function(params) {
params = Params.parse(params, { workspace: -1,
timestamp: 0 });
@ -1814,7 +1536,7 @@ const AppIconMenu = new Lang.Class({
if (!source.actor.mapped)
this.close();
}));
source.actor.connect('destroy', Lang.bind(this, this.destroy));
source.actor.connect('destroy', Lang.bind(this, function () { this.actor.destroy(); }));
Main.uiGroup.add_actor(this.actor);
},
@ -1846,21 +1568,15 @@ const AppIconMenu = new Lang.Class({
if (!this._source.app.is_window_backed()) {
this._appendSeparator();
this._newWindowMenuItem = this._appendMenuItem(_("New Window"));
this._newWindowMenuItem.connect('activate', Lang.bind(this, function() {
this._source.app.open_new_window(-1);
this.emit('activate-window', null);
}));
this._appendSeparator();
let appInfo = this._source.app.get_app_info();
let actions = appInfo.list_actions();
if (this._source.app.can_open_new_window() &&
actions.indexOf('new-window') == -1) {
this._newWindowMenuItem = this._appendMenuItem(_("New Window"));
this._newWindowMenuItem.connect('activate', Lang.bind(this, function() {
if (this._source.app.state == Shell.AppState.STOPPED)
this._source.animateLaunch();
this._source.app.open_new_window(-1);
this.emit('activate-window', null);
}));
this._appendSeparator();
}
for (let i = 0; i < actions.length; i++) {
let action = actions[i];
let item = this._appendMenuItem(appInfo.get_action_name(action));
@ -1869,27 +1585,22 @@ const AppIconMenu = new Lang.Class({
this.emit('activate-window', null);
}));
}
this._appendSeparator();
let canFavorite = global.settings.is_writable('favorite-apps');
let isFavorite = AppFavorites.getAppFavorites().isFavorite(this._source.app.get_id());
if (canFavorite) {
this._appendSeparator();
let isFavorite = AppFavorites.getAppFavorites().isFavorite(this._source.app.get_id());
if (isFavorite) {
let item = this._appendMenuItem(_("Remove from Favorites"));
item.connect('activate', Lang.bind(this, function() {
let favs = AppFavorites.getAppFavorites();
favs.removeFavorite(this._source.app.get_id());
}));
} else {
let item = this._appendMenuItem(_("Add to Favorites"));
item.connect('activate', Lang.bind(this, function() {
let favs = AppFavorites.getAppFavorites();
favs.addFavorite(this._source.app.get_id());
}));
}
if (isFavorite) {
let item = this._appendMenuItem(_("Remove from Favorites"));
item.connect('activate', Lang.bind(this, function() {
let favs = AppFavorites.getAppFavorites();
favs.removeFavorite(this._source.app.get_id());
}));
} else {
let item = this._appendMenuItem(_("Add to Favorites"));
item.connect('activate', Lang.bind(this, function() {
let favs = AppFavorites.getAppFavorites();
favs.addFavorite(this._source.app.get_id());
}));
}
if (Shell.AppSystem.get_default().lookup_app('org.gnome.Software.desktop')) {

View File

@ -6,38 +6,6 @@ const Signals = imports.signals;
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': 'org.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-nibbles.desktop': 'org.gnome.Nibbles.desktop',
'gnome-photos.desktop': 'org.gnome.Photos.desktop',
'gnome-screenshot.desktop': 'org.gnome.Screenshot.desktop',
'gnome-software.desktop': 'org.gnome.Software.desktop',
'gnome-terminal.desktop': 'org.gnome.Terminal.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({
Name: 'AppFavorites',
@ -56,21 +24,6 @@ const AppFavorites = new Lang.Class({
reload: function() {
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 apps = ids.map(function (id) {
return appSys.lookup_app(id);

View File

@ -1,216 +0,0 @@
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
const AudioDevice = {
HEADPHONES: 1 << 0,
HEADSET: 1 << 1,
MICROPHONE: 1 << 2
};
const AudioDeviceSelectionIface = '<node> \
<interface name="org.gnome.Shell.AudioDeviceSelection"> \
<method name="Open"> \
<arg name="devices" direction="in" type="as" /> \
</method> \
<method name="Close"> \
</method> \
<signal name="DeviceSelected"> \
<arg name="device" type="s" /> \
</signal> \
</interface> \
</node>';
const AudioDeviceSelectionDialog = new Lang.Class({
Name: 'AudioDeviceSelectionDialog',
Extends: ModalDialog.ModalDialog,
_init: function(devices) {
this.parent({ styleClass: 'audio-device-selection-dialog' });
this._deviceItems = {};
this._buildLayout();
if (devices & AudioDevice.HEADPHONES)
this._addDevice(AudioDevice.HEADPHONES);
if (devices & AudioDevice.HEADSET)
this._addDevice(AudioDevice.HEADSET);
if (devices & AudioDevice.MICROPHONE)
this._addDevice(AudioDevice.MICROPHONE);
if (this._selectionBox.get_n_children() < 2)
throw new Error('Too few devices for a selection');
},
destroy: function() {
this.parent();
},
_buildLayout: function(devices) {
let title = new St.Label({ style_class: 'audio-selection-title',
text: _("Select Audio Device"),
x_align: Clutter.ActorAlign.CENTER });
this.contentLayout.style_class = 'audio-selection-content';
this.contentLayout.add(title);
this._selectionBox = new St.BoxLayout({ style_class: 'audio-selection-box' });
this.contentLayout.add(this._selectionBox, { expand: true });
this.addButton({ action: Lang.bind(this, this._openSettings),
label: _("Sound Settings") });
this.addButton({ action: Lang.bind(this, this.close),
label: _("Cancel"),
key: Clutter.Escape });
},
_getDeviceLabel: function(device) {
switch(device) {
case AudioDevice.HEADPHONES:
return _("Headphones");
case AudioDevice.HEADSET:
return _("Headset");
case AudioDevice.MICROPHONE:
return _("Microphone");
default:
return null;
}
},
_getDeviceIcon: function(device) {
switch(device) {
case AudioDevice.HEADPHONES:
return 'audio-headphones-symbolic';
case AudioDevice.HEADSET:
return 'audio-headset-symbolic';
case AudioDevice.MICROPHONE:
return 'audio-input-microphone-symbolic';
default:
return null;
}
},
_addDevice: function(device) {
let box = new St.BoxLayout({ style_class: 'audio-selection-device-box',
vertical: true });
box.connect('notify::height',
function() {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
function() {
box.width = box.height;
});
});
let icon = new St.Icon({ style_class: 'audio-selection-device-icon',
icon_name: this._getDeviceIcon(device) });
box.add(icon);
let label = new St.Label({ style_class: 'audio-selection-device-label',
text: this._getDeviceLabel(device),
x_align: Clutter.ActorAlign.CENTER });
box.add(label);
let button = new St.Button({ style_class: 'audio-selection-device',
can_focus: true,
child: box });
this._selectionBox.add(button);
button.connect('clicked', Lang.bind(this,
function() {
this.emit('device-selected', device);
this.close();
Main.overview.hide();
}));
},
_openSettings: function() {
let desktopFile = 'gnome-sound-panel.desktop'
let app = Shell.AppSystem.get_default().lookup_app(desktopFile);
if (!app) {
log('Settings panel for desktop file ' + desktopFile + ' could not be loaded!');
return;
}
this.close();
Main.overview.hide();
app.activate();
}
});
const AudioDeviceSelectionDBus = new Lang.Class({
Name: 'AudioDeviceSelectionDBus',
_init: function() {
this._audioSelectionDialog = null;
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(AudioDeviceSelectionIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/AudioDeviceSelection');
Gio.DBus.session.own_name('org.gnome.Shell.AudioDeviceSelection', Gio.BusNameOwnerFlags.REPLACE, null, null);
},
_onDialogClosed: function() {
this._audioSelectionDialog = null;
},
_onDeviceSelected: function(dialog, device) {
let connection = this._dbusImpl.get_connection();
let info = this._dbusImpl.get_info();
let deviceName = Object.keys(AudioDevice).filter(
function(dev) {
return AudioDevice[dev] == device;
})[0].toLowerCase();
connection.emit_signal(this._audioSelectionDialog._sender,
this._dbusImpl.get_object_path(),
info ? info.name : null,
'DeviceSelected',
GLib.Variant.new('(s)', [deviceName]));
},
OpenAsync: function(params, invocation) {
if (this._audioSelectionDialog) {
invocation.return_value(null);
return;
}
let [deviceNames] = params;
let devices = 0;
deviceNames.forEach(function(n) {
devices |= AudioDevice[n.toUpperCase()];
});
let dialog;
try {
dialog = new AudioDeviceSelectionDialog(devices);
} catch(e) {
invocation.return_value(null);
return;
}
dialog._sender = invocation.get_sender();
dialog.connect('closed', Lang.bind(this, this._onDialogClosed));
dialog.connect('device-selected',
Lang.bind(this, this._onDeviceSelected));
dialog.open();
this._audioSelectionDialog = dialog;
invocation.return_value(null);
},
CloseAsync: function(params, invocation) {
if (this._audioSelectionDialog &&
this._audioSelectionDialog._sender == invocation.get_sender())
this._audioSelectionDialog.close();
invocation.return_value(null);
}
});

File diff suppressed because it is too large Load Diff

View File

@ -16,10 +16,9 @@ const BackgroundMenu = new Lang.Class({
_init: function(layoutManager) {
this.parent(layoutManager.dummyCursor, 0, St.Side.TOP);
this.addSettingsAction(_("Change Background…"), 'gnome-background-panel.desktop');
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.addSettingsAction(_("Display Settings"), 'gnome-display-panel.desktop');
this.addSettingsAction(_("Settings"), 'gnome-control-center.desktop');
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.addSettingsAction(_("Change Background…"), 'gnome-background-panel.desktop');
this.actor.add_style_class_name('background-menu');
@ -34,7 +33,8 @@ function addBackgroundMenu(actor, layoutManager) {
actor._backgroundManager = new PopupMenu.PopupMenuManager({ actor: actor });
actor._backgroundManager.addMenu(actor._backgroundMenu);
function openMenu(x, y) {
function openMenu() {
let [x, y] = global.get_pointer();
Main.layoutManager.setDummyCursorGeometry(x, y, 0, 0);
actor._backgroundMenu.open(BoxPointer.PopupAnimation.NONE);
}
@ -42,32 +42,22 @@ function addBackgroundMenu(actor, layoutManager) {
let clickAction = new Clutter.ClickAction();
clickAction.connect('long-press', function(action, actor, state) {
if (state == Clutter.LongPressState.QUERY)
return ((action.get_button() == 0 ||
action.get_button() == 1) &&
!actor._backgroundMenu.isOpen);
return action.get_button() == 1 && !actor._backgroundMenu.isOpen;
if (state == Clutter.LongPressState.ACTIVATE) {
let [x, y] = action.get_coords();
openMenu(x, y);
openMenu();
actor._backgroundManager.ignoreRelease();
}
return true;
});
clickAction.connect('clicked', function(action) {
if (action.get_button() == 3) {
let [x, y] = action.get_coords();
openMenu(x, y);
}
if (action.get_button() == 3)
openMenu();
});
actor.add_action(clickAction);
let grabOpBeginId = global.display.connect('grab-op-begin', function () {
clickAction.release();
});
actor.connect('destroy', function() {
actor._backgroundMenu.destroy();
actor._backgroundMenu = null;
actor._backgroundManager = null;
global.display.disconnect(grabOpBeginId);
});
}

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,7 @@ const AutomountManager = new Lang.Class({
Name: 'AutomountManager',
_init: function() {
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA });
this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
this._volumeQueue = [];
this._session = new GnomeSession.SessionManager();
this._session.connectSignal('InhibitorAdded',

View File

@ -24,11 +24,11 @@ const AutorunSetting = {
};
// misc utils
function shouldAutorunMount(mount) {
function shouldAutorunMount(mount, forTransient) {
let root = mount.get_root();
let volume = mount.get_volume();
if (!volume || !volume.allowAutorun)
if (!volume || (!volume.allowAutorun && forTransient))
return false;
if (root.is_native() && isMountRootHidden(root))
@ -96,7 +96,7 @@ const ContentTypeDiscoverer = new Lang.Class({
_init: function(callback) {
this._callback = callback;
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA });
this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
},
guessContentTypes: function(mount) {
@ -167,10 +167,12 @@ const AutorunManager = new Lang.Class({
this._session = new GnomeSession.SessionManager();
this._volumeMonitor = Gio.VolumeMonitor.get();
this._dispatcher = new AutorunDispatcher(this);
this._transDispatcher = new AutorunTransientDispatcher(this);
},
enable: function() {
this._scanMounts();
this._mountAddedId = this._volumeMonitor.connect('mount-added', Lang.bind(this, this._onMountAdded));
this._mountRemovedId = this._volumeMonitor.connect('mount-removed', Lang.bind(this, this._onMountRemoved));
},
@ -180,30 +182,101 @@ const AutorunManager = new Lang.Class({
this._volumeMonitor.disconnect(this._mountRemovedId);
},
_processMount: function(mount, hotplug) {
let discoverer = new ContentTypeDiscoverer(Lang.bind(this, function(mount, apps, contentTypes) {
if (hotplug)
this._transDispatcher.addMount(mount, apps, contentTypes);
}));
discoverer.guessContentTypes(mount);
},
_scanMounts: function() {
let mounts = this._volumeMonitor.get_mounts();
mounts.forEach(Lang.bind(this, function(mount) {
this._processMount(mount, false);
}));
},
_onMountAdded: function(monitor, mount) {
// don't do anything if our session is not the currently
// active one
if (!this._session.SessionIsActive)
return;
let discoverer = new ContentTypeDiscoverer(Lang.bind(this, function(mount, apps, contentTypes) {
this._dispatcher.addMount(mount, apps, contentTypes);
}));
discoverer.guessContentTypes(mount);
this._processMount(mount, true);
},
_onMountRemoved: function(monitor, mount) {
this._dispatcher.removeMount(mount);
}
this._transDispatcher.removeMount(mount);
},
ejectMount: function(mount) {
let mountOp = new ShellMountOperation.ShellMountOperation(mount);
// first, see if we have a drive
let drive = mount.get_drive();
let volume = mount.get_volume();
if (drive &&
drive.get_start_stop_type() == Gio.DriveStartStopType.SHUTDOWN &&
drive.can_stop()) {
drive.stop(0, mountOp.mountOp, null,
Lang.bind(this, this._onStop));
} else {
if (mount.can_eject()) {
mount.eject_with_operation(0, mountOp.mountOp, null,
Lang.bind(this, this._onEject));
} else if (volume && volume.can_eject()) {
volume.eject_with_operation(0, mountOp.mountOp, null,
Lang.bind(this, this._onEject));
} else if (drive && drive.can_eject()) {
drive.eject_with_operation(0, mountOp.mountOp, null,
Lang.bind(this, this._onEject));
} else if (mount.can_unmount()) {
mount.unmount_with_operation(0, mountOp.mountOp, null,
Lang.bind(this, this._onUnmount));
}
}
},
_onUnmount: function(mount, res) {
try {
mount.unmount_with_operation_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
log('Unable to eject the mount ' + mount.get_name()
+ ': ' + e.toString());
}
},
_onEject: function(source, res) {
try {
source.eject_with_operation_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
log('Unable to eject the drive ' + source.get_name()
+ ': ' + e.toString());
}
},
_onStop: function(drive, res) {
try {
drive.stop_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
log('Unable to stop the drive ' + drive.get_name()
+ ': ' + e.toString());
}
},
});
const AutorunDispatcher = new Lang.Class({
Name: 'AutorunDispatcher',
const AutorunTransientDispatcher = new Lang.Class({
Name: 'AutorunTransientDispatcher',
_init: function(manager) {
this._manager = manager;
this._sources = [];
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA });
this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
},
_getAutorunSettingForType: function(contentType) {
@ -244,7 +317,7 @@ const AutorunDispatcher = new Lang.Class({
return;
// add a new source
this._sources.push(new AutorunSource(this._manager, mount, apps));
this._sources.push(new AutorunTransientSource(this._manager, mount, apps));
},
addMount: function(mount, apps, contentTypes) {
@ -253,7 +326,7 @@ const AutorunDispatcher = new Lang.Class({
return;
// if the mount doesn't want to be autorun, return
if (!shouldAutorunMount(mount))
if (!shouldAutorunMount(mount, true))
return;
let setting = this._getAutorunSettingForType(contentTypes[0]);
@ -293,8 +366,8 @@ const AutorunDispatcher = new Lang.Class({
}
});
const AutorunSource = new Lang.Class({
Name: 'AutorunSource',
const AutorunTransientSource = new Lang.Class({
Name: 'AutorunTransientSource',
Extends: MessageTray.Source,
_init: function(manager, mount, apps) {
@ -304,7 +377,7 @@ const AutorunSource = new Lang.Class({
this.parent(mount.get_name());
this._notification = new AutorunNotification(this._manager, this);
this._notification = new AutorunTransientNotification(this._manager, this);
// add ourselves as a source, and popup the notification
Main.messageTray.add(this);
@ -313,35 +386,38 @@ const AutorunSource = new Lang.Class({
getIcon: function() {
return this.mount.get_icon();
},
_createPolicy: function() {
return new MessageTray.NotificationApplicationPolicy('org.gnome.Nautilus');
}
});
const AutorunNotification = new Lang.Class({
Name: 'AutorunNotification',
const AutorunTransientNotification = new Lang.Class({
Name: 'AutorunTransientNotification',
Extends: MessageTray.Notification,
_init: function(manager, source) {
this.parent(source, source.title);
this._manager = manager;
this._box = new St.BoxLayout({ style_class: 'hotplug-transient-box',
vertical: true });
this._bodyBin.child = this._box;
this._mount = source.mount;
},
createBanner: function() {
let banner = new MessageTray.NotificationBanner(this);
this.source.apps.forEach(Lang.bind(this, function (app) {
source.apps.forEach(Lang.bind(this, function (app) {
let actor = this._buttonForApp(app);
if (actor)
banner.addButton(actor);
this._box.add(actor, { x_fill: true,
x_align: St.Align.START });
}));
return banner;
this._box.add(this._buttonForEject(), { x_fill: true,
x_align: St.Align.START });
// set the notification to transient and urgent, so that it
// expands out
this.setTransient(true);
this.setUrgency(MessageTray.Urgency.CRITICAL);
},
_buttonForApp: function(app) {
@ -359,9 +435,8 @@ const AutorunNotification = new Lang.Class({
let button = new St.Button({ child: box,
x_fill: true,
x_align: St.Align.START,
x_expand: true,
button_mask: St.ButtonMask.ONE,
style_class: 'hotplug-notification-item button' });
style_class: 'hotplug-notification-item' });
button.connect('clicked', Lang.bind(this, function() {
startAppForMount(app, this._mount);
@ -371,11 +446,29 @@ const AutorunNotification = new Lang.Class({
return button;
},
activate: function() {
this.parent();
_buttonForEject: function() {
let box = new St.BoxLayout();
let icon = new St.Icon({ icon_name: 'media-eject-symbolic',
style_class: 'hotplug-notification-item-icon' });
box.add(icon);
let app = Gio.app_info_get_default_for_type('inode/directory', false);
startAppForMount(app, this._mount);
let label = new St.Bin({ y_align: St.Align.MIDDLE,
child: new St.Label
({ text: _("Eject") })
});
box.add(label);
let button = new St.Button({ child: box,
x_fill: true,
x_align: St.Align.START,
button_mask: St.ButtonMask.ONE,
style_class: 'hotplug-notification-item' });
button.connect('clicked', Lang.bind(this, function() {
this._manager.ejectMount(this._mount);
}));
return button;
}
});

View File

@ -9,15 +9,9 @@ const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Gcr = imports.gi.Gcr;
const Animation = imports.ui.animation;
const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry;
const CheckBox = imports.ui.checkBox;
const Tweener = imports.ui.tweener;
const WORK_SPINNER_ICON_SIZE = 16;
const WORK_SPINNER_ANIMATION_DELAY = 1.0;
const WORK_SPINNER_ANIMATION_TIME = 0.3;
const KeyringDialog = new Lang.Class({
Name: 'KeyringDialog',
@ -47,7 +41,7 @@ const KeyringDialog = new Lang.Class({
mainContentBox.add(this._messageBox,
{ y_align: St.Align.START, expand: true, x_fill: true, y_fill: true });
let subject = new St.Label({ style_class: 'prompt-dialog-headline headline' });
let subject = new St.Label({ style_class: 'prompt-dialog-headline' });
this.prompt.bind_property('message', subject, 'text', GObject.BindingFlags.SYNC_CREATE);
this._messageBox.add(subject,
@ -64,107 +58,66 @@ const KeyringDialog = new Lang.Class({
{ y_fill: true,
y_align: St.Align.START });
this._workSpinner = null;
this._controlTable = null;
this._cancelButton = this.addButton({ label: '',
action: Lang.bind(this, this._onCancelButton),
key: Clutter.Escape });
key: Clutter.Escape },
{ expand: true, x_fill: false, x_align: St.Align.START });
this.placeSpinner({ expand: false,
x_fill: false,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.MIDDLE });
this._continueButton = this.addButton({ label: '',
action: Lang.bind(this, this._onContinueButton),
default: true });
default: true },
{ expand: false, x_fill: false, x_align: St.Align.END });
this.prompt.bind_property('cancel-label', this._cancelButton, 'label', GObject.BindingFlags.SYNC_CREATE);
this.prompt.bind_property('continue-label', this._continueButton, 'label', GObject.BindingFlags.SYNC_CREATE);
},
_setWorking: function(working) {
if (!this._workSpinner)
return;
Tweener.removeTweens(this._workSpinner.actor);
if (working) {
this._workSpinner.play();
Tweener.addTween(this._workSpinner.actor,
{ opacity: 255,
delay: WORK_SPINNER_ANIMATION_DELAY,
time: WORK_SPINNER_ANIMATION_TIME,
transition: 'linear'
});
} else {
Tweener.addTween(this._workSpinner.actor,
{ opacity: 0,
time: WORK_SPINNER_ANIMATION_TIME,
transition: 'linear',
onCompleteScope: this,
onComplete: function() {
if (this._workSpinner)
this._workSpinner.stop();
}
});
}
},
_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',
layout_manager: layout });
layout.hookup_style(table);
let rtl = table.get_text_direction() == Clutter.TextDirection.RTL;
let row = 0;
if (this.prompt.password_visible) {
let label = new St.Label({ style_class: 'prompt-dialog-password-label',
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.CENTER });
let label = new St.Label({ style_class: 'prompt-dialog-password-label' });
label.set_text(_("Password:"));
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',
text: '',
can_focus: true,
x_expand: true });
can_focus: true });
this._passwordEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
this._passwordEntry.clutter_text.connect('activate', Lang.bind(this, this._onPasswordActivate));
let spinnerIcon = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE);
this._workSpinner.actor.opacity = 0;
if (rtl) {
layout.attach(this._workSpinner.actor, 0, row, 1, 1);
layout.attach(this._passwordEntry, 1, row, 1, 1);
layout.attach(label, 2, row, 1, 1);
} else {
layout.attach(label, 0, row, 1, 1);
layout.attach(this._passwordEntry, 1, row, 1, 1);
layout.attach(this._workSpinner.actor, 2, row, 1, 1);
}
layout.pack(this._passwordEntry, 1, row);
row++;
} else {
this._workSpinner = null;
this._passwordEntry = null;
}
if (this.prompt.confirm_visible) {
var label = new St.Label(({ style_class: 'prompt-dialog-password-label',
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.CENTER }));
var label = new St.Label(({ style_class: 'prompt-dialog-password-label' }));
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',
text: '',
can_focus: true,
x_expand: true });
can_focus: true });
this._confirmEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
ShellEntry.addContextMenu(this._confirmEntry, { isPassword: true });
this._confirmEntry.clutter_text.connect('activate', Lang.bind(this, this._onConfirmActivate));
if (rtl) {
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);
}
layout.pack(this._confirmEntry, 1, row);
row++;
} else {
this._confirmEntry = null;
@ -177,15 +130,15 @@ const KeyringDialog = new Lang.Class({
let choice = new CheckBox.CheckBox();
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);
layout.attach(choice.actor, rtl ? 0 : 1, row, 1, 1);
layout.pack(choice.actor, 1, row);
row++;
}
let warning = new St.Label({ style_class: 'prompt-dialog-error-label',
x_align: Clutter.ActorAlign.START });
let warning = new St.Label({ style_class: 'prompt-dialog-error-label' });
warning.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
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', warning, 'text', GObject.BindingFlags.SYNC_CREATE);
@ -211,7 +164,7 @@ const KeyringDialog = new Lang.Class({
this._continueButton.can_focus = sensitive;
this._continueButton.reactive = sensitive;
this._setWorking(!sensitive);
this.setWorking(!sensitive);
},
_ensureOpen: function() {

View File

@ -12,8 +12,6 @@ const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Config = imports.misc.config;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const ModalDialog = imports.ui.modalDialog;
const PopupMenu = imports.ui.popupMenu;
const ShellEntry = imports.ui.shellEntry;
@ -56,7 +54,7 @@ const NetworkSecretDialog = new Lang.Class({
mainContentBox.add(messageBox,
{ y_align: St.Align.START });
let subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline headline',
let subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline',
text: this._content.title });
messageBox.add(subjectLabel,
{ y_fill: false,
@ -74,28 +72,24 @@ const NetworkSecretDialog = new Lang.Class({
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',
layout_manager: layout });
layout.hookup_style(secretTable);
let rtl = secretTable.get_text_direction() == Clutter.TextDirection.RTL;
let initialFocusSet = false;
let pos = 0;
for (let i = 0; i < this._content.secrets.length; i++) {
let secret = this._content.secrets[i];
let label = new St.Label({ style_class: 'prompt-dialog-password-label',
text: secret.label,
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.CENTER });
text: secret.label });
label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
let reactive = secret.key != null;
secret.entry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: secret.value, can_focus: reactive,
reactive: reactive,
x_expand: true });
reactive: reactive });
ShellEntry.addContextMenu(secret.entry,
{ isPassword: secret.password });
@ -122,13 +116,10 @@ const NetworkSecretDialog = new Lang.Class({
} else
secret.valid = true;
if (rtl) {
layout.attach(secret.entry, 0, pos, 1, 1);
layout.attach(label, 1, pos, 1, 1);
} else {
layout.attach(label, 0, pos, 1, 1);
layout.attach(secret.entry, 1, pos, 1, 1);
}
layout.pack(label, 0, pos);
layout.child_set(label, { x_expand: false, y_fill: false,
x_align: Clutter.TableAlignment.START });
layout.pack(secret.entry, 1, pos);
pos++;
if (secret.password)
@ -340,7 +331,6 @@ const NetworkSecretDialog = new Lang.Class({
content.message = _("PIN code is needed for the mobile broadband device");
content.secrets.push({ label: _("PIN: "), key: 'pin',
value: gsmSetting.pin || '', password: true });
break;
}
// fall through
case 'cdma':
@ -383,12 +373,6 @@ const VPNRequestHandler = new Lang.Class({
argv.push('-i');
if (flags & NMClient.SecretAgentGetSecretsFlags.REQUEST_NEW)
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;
@ -607,13 +591,10 @@ const NetworkAgent = new Lang.Class({
Name: 'NetworkAgent',
_init: function() {
this._native = new Shell.NetworkAgent({ identifier: 'org.gnome.Shell.NetworkAgent',
capabilities: NMClient.SecretAgentCapabilities.VPN_HINTS
});
this._native = new Shell.NetworkAgent({ identifier: 'org.gnome.Shell.NetworkAgent' });
this._dialogs = { };
this._vpnRequests = { };
this._notifications = { };
this._native.connect('new-request', Lang.bind(this, this._newRequest));
this._native.connect('cancel-request', Lang.bind(this, this._cancelRequest));
@ -636,92 +617,21 @@ const NetworkAgent = new Lang.Class({
this._vpnRequests[requestId].cancel(true);
this._vpnRequests = { };
for (requestId in this._notifications)
this._notifications[requestId].destroy();
this._notifications = { };
this._enabled = false;
},
_showNotification: function(requestId, connection, settingName, hints, flags) {
let source = new MessageTray.Source(_("Network Manager"), 'network-transmit-receive');
source.policy = new MessageTray.NotificationApplicationPolicy('gnome-network-panel');
let title, body;
let connectionSetting = connection.get_setting_connection();
let connectionType = connectionSetting.get_connection_type();
switch (connectionType) {
case '802-11-wireless':
let wirelessSetting = connection.get_setting_wireless();
let ssid = NetworkManager.utils_ssid_to_utf8(wirelessSetting.get_ssid());
title = _("Authentication required by wireless network");
body = _("Passwords or encryption keys are required to access the wireless network “%s”.").format(ssid);
break;
case '802-3-ethernet':
title = _("Wired 802.1X authentication");
body = _("A password is required to connect to “%s”.".format(connection.get_id()));
break;
case 'pppoe':
title = _("DSL authentication");
body = _("A password is required to connect to “%s”.".format(connection.get_id()));
break;
case 'gsm':
if (hints.indexOf('pin') != -1) {
let gsmSetting = connection.get_setting_gsm();
title = _("PIN code required");
message = _("PIN code is needed for the mobile broadband device");
break;
}
// fall through
case 'cdma':
case 'bluetooth':
title = _("Mobile broadband network password");
message = _("A password is required to connect to “%s”.").format(connectionSetting.get_id());
break;
default:
log('Invalid connection type: ' + connectionType);
this._native.respond(requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
return;
}
let notification = new MessageTray.Notification(source, title, body);
notification.connect('activated', Lang.bind(this, function() {
notification.answered = true;
this._handleRequest(requestId, connection, settingName, hints, flags);
}));
this._notifications[requestId] = notification;
notification.connect('destroy', Lang.bind(this, function() {
if (!notification.answered)
this._native.respond(requestId, Shell.NetworkAgentResponse.USER_CANCELED);
delete this._notifications[requestId];
}));
Main.messageTray.add(source);
source.notify(notification);
},
_newRequest: function(agent, requestId, connection, settingName, hints, flags) {
if (!this._enabled) {
agent.respond(requestId, Shell.NetworkAgentResponse.USER_CANCELED);
return;
}
if (!(flags & NMClient.SecretAgentGetSecretsFlags.USER_REQUESTED))
this._showNotification(requestId, connection, settingName, hints, flags);
else
this._handleRequest(requestId, connection, settingName, hints, flags);
},
_handleRequest: function(requestId, connection, settingName, hints, flags) {
if (settingName == 'vpn') {
this._vpnRequest(requestId, connection, hints, flags);
return;
}
let dialog = new NetworkSecretDialog(this._native, requestId, connection, settingName, hints);
let dialog = new NetworkSecretDialog(agent, requestId, connection, settingName, hints);
dialog.connect('destroy', Lang.bind(this, function() {
delete this._dialogs[requestId];
}));
@ -781,33 +691,18 @@ const NetworkAgent = new Lang.Class({
let service = keyfile.get_string('VPN Connection', 'service');
let binary = keyfile.get_string('GNOME', 'auth-dialog');
let externalUIMode = false;
let hints = false;
try {
externalUIMode = keyfile.get_boolean('GNOME', 'supports-external-ui-mode');
} 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;
if (!GLib.path_is_absolute(path)) {
path = GLib.build_filenamev([Config.LIBEXECDIR, path]);
}
if (GLib.file_test(path, GLib.FileTest.IS_EXECUTABLE)) {
this._vpnBinaries[service] = { fileName: path, externalUIMode: externalUIMode, supportsHints: hints };
try {
let aliases = keyfile.get_string_list('VPN Connection', 'aliases');
for (let alias of aliases) {
this._vpnBinaries[alias] = { fileName: path, externalUIMode: externalUIMode, supportsHints: hints };
}
} catch(e) { } // ignore errors if key does not exist
} else {
if (GLib.file_test(path, GLib.FileTest.IS_EXECUTABLE))
this._vpnBinaries[service] = { fileName: path, externalUIMode: externalUIMode };
else
throw new Error('VPN plugin at %s is not executable'.format(path));
}
} catch(e) {
log('Error \'%s\' while processing VPN keyfile \'%s\''.
format(e.message, dir.get_child(name).get_path()));

View File

@ -13,19 +13,13 @@ const Mainloop = imports.mainloop;
const Polkit = imports.gi.Polkit;
const PolkitAgent = imports.gi.PolkitAgent;
const Animation = imports.ui.animation;
const Components = imports.ui.components;
const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry;
const UserWidget = imports.ui.userWidget;
const Tweener = imports.ui.tweener;
const DIALOG_ICON_SIZE = 48;
const WORK_SPINNER_ICON_SIZE = 16;
const WORK_SPINNER_ANIMATION_DELAY = 1.0;
const WORK_SPINNER_ANIMATION_TIME = 0.3;
const AuthenticationDialog = new Lang.Class({
Name: 'AuthenticationDialog',
Extends: ModalDialog.ModalDialog,
@ -56,7 +50,7 @@ const AuthenticationDialog = new Lang.Class({
mainContentBox.add(messageBox,
{ expand: true, y_align: St.Align.START });
this._subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline headline',
this._subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline',
text: _("Authentication Required") });
messageBox.add(this._subjectLabel,
@ -142,13 +136,6 @@ const AuthenticationDialog = new Lang.Class({
this._passwordEntry.clutter_text.connect('activate', Lang.bind(this, this._onEntryActivate));
this._passwordBox.add(this._passwordEntry,
{ expand: true });
let spinnerIcon = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE);
this._workSpinner.actor.opacity = 0;
this._passwordBox.add(this._workSpinner.actor);
this.setInitialKeyFocus(this._passwordEntry);
this._passwordBox.hide();
@ -178,10 +165,17 @@ const AuthenticationDialog = new Lang.Class({
this._cancelButton = this.addButton({ label: _("Cancel"),
action: Lang.bind(this, this.cancel),
key: Clutter.Escape });
key: Clutter.Escape },
{ expand: true, x_fill: false, x_align: St.Align.START });
this.placeSpinner({ expand: false,
x_fill: false,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.MIDDLE });
this._okButton = this.addButton({ label: _("Authenticate"),
action: Lang.bind(this, this._onAuthenticateButtonPressed),
default: true });
default: true },
{ expand: false, x_fill: false, x_align: St.Align.END });
this._doneEmitted = false;
@ -189,30 +183,6 @@ const AuthenticationDialog = new Lang.Class({
this._cookie = cookie;
},
_setWorking: function(working) {
Tweener.removeTweens(this._workSpinner.actor);
if (working) {
this._workSpinner.play();
Tweener.addTween(this._workSpinner.actor,
{ opacity: 255,
delay: WORK_SPINNER_ANIMATION_DELAY,
time: WORK_SPINNER_ANIMATION_TIME,
transition: 'linear'
});
} else {
Tweener.addTween(this._workSpinner.actor,
{ opacity: 0,
time: WORK_SPINNER_ANIMATION_TIME,
transition: 'linear',
onCompleteScope: this,
onComplete: function() {
if (this._workSpinner)
this._workSpinner.stop();
}
});
}
},
performAuthentication: function() {
this.destroySession();
this._session = new PolkitAgent.Session({ identity: this._identityToAuth,
@ -259,7 +229,7 @@ const AuthenticationDialog = new Lang.Class({
this._okButton.can_focus = sensitive;
this._okButton.reactive = sensitive;
this._setWorking(!sensitive);
this.setWorking(!sensitive);
},
_onEntryActivate: function() {

View File

@ -3,7 +3,6 @@
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell;
@ -14,11 +13,9 @@ const Tp = imports.gi.TelepathyGLib;
const History = imports.misc.history;
const Main = imports.ui.main;
const MessageList = imports.ui.messageList;
const MessageTray = imports.ui.messageTray;
const Params = imports.misc.params;
const PopupMenu = imports.ui.popupMenu;
const Util = imports.misc.util;
// See Notification.appendMessage
const SCROLLBACK_IMMEDIATE_TIME = 3 * 60; // 3 minutes
@ -32,15 +29,13 @@ const SCROLLBACK_HISTORY_LINES = 10;
// See Notification._onEntryChanged
const COMPOSING_STOP_TIMEOUT = 5;
const CHAT_EXPAND_LINES = 12;
const CLOCK_FORMAT_KEY = 'clock-format';
const NotificationDirection = {
SENT: 'chat-sent',
RECEIVED: 'chat-received'
};
const N_ = function(s) { return s; };
function makeMessageFromTpMessage(tpMessage, direction) {
let [text, flags] = tpMessage.to_text();
@ -121,7 +116,7 @@ const TelepathyClient = new Lang.Class({
}
if (!this._accountManager.is_prepared(Tp.AccountManager.get_feature_quark_core()))
this._accountManager.prepare_async(null, null);
this._accountManager.prepare_async(null, Lang.bind(this, this._accountManagerPrepared));
},
disable: function() {
@ -158,6 +153,14 @@ const TelepathyClient = new Lang.Class({
this._chatSources[channel.get_object_path()] = source;
source.connect('destroy', Lang.bind(this,
function() {
if (this._tpClient.is_handling_channel(channel)) {
// The chat box has been destroyed so it can't
// handle the channel any more.
channel.close_async(function(src, result) {
channel.close_finish(result);
});
}
delete this._chatSources[channel.get_object_path()];
}));
},
@ -223,29 +226,29 @@ const TelepathyClient = new Lang.Class({
_approveTextChannel: function(account, conn, channel, dispatchOp, context) {
let [targetHandle, targetHandleType] = channel.get_handle();
if (targetHandleType != Tp.HandleType.CONTACT) {
context.fail(new Tp.Error({ code: Tp.Error.INVALID_ARGUMENT,
message: 'Unsupported handle type' }));
return;
if (targetHandleType == Tp.HandleType.CONTACT) {
// Approve private text channels right away as we are going to handle it
dispatchOp.claim_with_async(this._tpClient,
Lang.bind(this, function(dispatchOp, result) {
try {
dispatchOp.claim_with_finish(result);
this._handlingChannels(account, conn, [channel], false);
} catch (err) {
throw new Error('Failed to Claim channel: ' + err);
}}));
context.accept();
}
// Approve private text channels right away as we are going to handle it
dispatchOp.claim_with_async(this._tpClient, Lang.bind(this, function(dispatchOp, result) {
try {
dispatchOp.claim_with_finish(result);
this._handlingChannels(account, conn, [channel], false);
} catch (err) {
log('Failed to Claim channel: ' + err);
}
}));
context.accept();
},
_delegatedChannelsCb: function(client, channels) {
// Nothing to do as we don't make a distinction between observed and
// handled channels.
},
_accountManagerPrepared: function(am, result) {
am.prepare_finish(result);
},
});
const ChatSource = new Lang.Class({
@ -266,8 +269,15 @@ const ChatSource = new Lang.Class({
this._channel = channel;
this._closedId = this._channel.connect('invalidated', Lang.bind(this, this._channelClosed));
this._notification = new ChatNotification(this);
this._notification.connect('clicked', Lang.bind(this, this.open));
this._notification.setUrgency(MessageTray.Urgency.HIGH);
this._notifyTimeoutId = 0;
// We ack messages when the user expands the new notification or views the summary
// notification, in which case the notification is also expanded.
this._notification.connect('expanded', Lang.bind(this, this._ackMessages));
this._presence = contact.get_presence_type();
this._sentId = this._channel.connect('message-sent', Lang.bind(this, this._messageSent));
@ -280,48 +290,31 @@ const ChatSource = new Lang.Class({
// Add ourselves as a source.
Main.messageTray.add(this);
this.pushNotification(this._notification);
this._getLogMessages();
},
_ensureNotification: function() {
if (this._notification)
return;
buildRightClickMenu: function() {
let item;
this._notification = new ChatNotification(this);
this._notification.connect('activated', Lang.bind(this, this.open));
this._notification.connect('updated', Lang.bind(this,
function() {
if (this._banner && this._banner.expanded)
this._ackMessages();
}));
this._notification.connect('destroy', Lang.bind(this,
function() {
this._notification = null;
}));
this.pushNotification(this._notification);
let rightClickMenu = this.parent();
item = new PopupMenu.PopupMenuItem('');
item.actor.connect('notify::mapped', Lang.bind(this, function() {
item.label.set_text(this.isMuted ? _("Unmute") : _("Mute"));
}));
item.connect('activate', Lang.bind(this, function() {
this.setMuted(!this.isMuted);
this.emit('done-displaying-content', false);
}));
rightClickMenu.add(item.actor);
return rightClickMenu;
},
_createPolicy: function() {
if (this._account.protocol_name == 'irc')
return new MessageTray.NotificationApplicationPolicy('org.gnome.Polari');
return new MessageTray.NotificationApplicationPolicy('empathy');
},
createBanner: function() {
this._banner = new ChatNotificationBanner(this._notification);
// We ack messages when the user expands the new notification
let id = this._banner.connect('expanded', Lang.bind(this, this._ackMessages));
this._banner.actor.connect('destroy', Lang.bind(this,
function() {
this._banner.disconnect(id);
this._banner = null;
}));
return this._banner;
},
_updateAlias: function() {
let oldAlias = this.title;
let newAlias = this._contact.get_alias();
@ -330,8 +323,7 @@ const ChatSource = new Lang.Class({
return;
this.setTitle(newAlias);
if (this._notification)
this._notification.appendAliasChange(oldAlias, newAlias);
this._notification.appendAliasChange(oldAlias, newAlias);
},
getIcon: function() {
@ -374,28 +366,15 @@ const ChatSource = new Lang.Class({
_updateAvatarIcon: function() {
this.iconUpdated();
if (this._notifiction)
this._notification.update(this._notification.title,
this._notification.bannerBodyText,
{ gicon: this.getIcon() });
this._notification.update(this._notification.title);
},
open: function() {
Main.overview.hide();
Main.panel.closeCalendar();
if (this._client.is_handling_channel(this._channel)) {
// We are handling the channel, try to pass it to Empathy or Polari
// (depending on the channel type)
// We don't check if either app is availble - mission control will
// fallback to something else if activation fails
let target;
if (this._channel.connection.protocol_name == 'irc')
target = 'org.freedesktop.Telepathy.Client.Polari';
else
target = 'org.freedesktop.Telepathy.Client.Empathy.Chat';
this._client.delegate_channels_async([this._channel], global.get_current_time(), target, null);
// We are handling the channel, try to pass it to Empathy
this._client.delegate_channels_async([this._channel],
global.get_current_time(),
'org.freedesktop.Telepathy.Client.Empathy.Chat', null);
} else {
// We are not the handler, just ask to present the channel
let dbus = Tp.DBusDaemon.dup();
@ -418,7 +397,6 @@ const ChatSource = new Lang.Class({
let [success, events] = logManager.get_filtered_events_finish(result);
let logMessages = events.map(makeMessageFromTplEvent);
this._ensureNotification();
let pendingTpMessages = this._channel.get_pending_messages();
let pendingMessages = [];
@ -468,24 +446,6 @@ const ChatSource = new Lang.Class({
},
destroy: function(reason) {
if (this._client.is_handling_channel(this._channel)) {
this._ackMessages();
// The chat box has been destroyed so it can't
// handle the channel any more.
this._channel.close_async(function(channel, result) {
channel.close_finish(result);
});
} else {
// Don't indicate any unread messages when the notification
// that represents them has been destroyed.
this._pendingMessages = [];
this.countUpdated();
}
// Keep source alive while the channel is open
if (reason != MessageTray.NotificationDestroyedReason.SOURCE_CLOSED)
return;
if (this._destroyed)
return;
@ -499,6 +459,9 @@ const ChatSource = new Lang.Class({
this._contact.disconnect(this._notifyAvatarId);
this._contact.disconnect(this._presenceChangedId);
if (this._timestampTimeoutId)
Mainloop.source_remove(this._timestampTimeoutId);
this.parent(reason);
},
@ -511,6 +474,10 @@ const ChatSource = new Lang.Class({
return this._pendingMessages.length;
},
get indicatorCount() {
return this.count;
},
get unseenCount() {
return this.count;
},
@ -523,7 +490,6 @@ const ChatSource = new Lang.Class({
if (message.get_message_type() == Tp.ChannelTextMessageType.DELIVERY_REPORT)
return;
this._ensureNotification();
this._pendingMessages.push(message);
this.countUpdated();
@ -551,7 +517,6 @@ const ChatSource = new Lang.Class({
// This is called for both messages we send from
// our client and other clients as well.
_messageSent: function(channel, message, flags, token) {
this._ensureNotification();
message = makeMessageFromTpMessage(message, NotificationDirection.SENT);
this._notification.appendMessage(message);
},
@ -589,10 +554,14 @@ const ChatSource = new Lang.Class({
},
_presenceChanged: function (contact, presence, status, message) {
if (this._notification)
this._notification.update(this._notification.title,
this._notification.bannerBodyText,
{ secondaryGIcon: this.getSecondaryIcon() });
let msg, title;
title = GLib.markup_escape_text(this.title, -1);
this._notification.update(this._notification.title, null, { secondaryGIcon: this.getSecondaryIcon() });
if (message)
msg += ' <i>(' + GLib.markup_escape_text(message, -1) + ')</i>';
},
_pendingRemoved: function(channel, message) {
@ -602,10 +571,6 @@ const ChatSource = new Lang.Class({
this._pendingMessages.splice(idx, 1);
this.countUpdated();
}
if (this._pendingMessages.length == 0 &&
this._banner && !this._banner.expanded)
this._banner.hide();
},
_ackMessages: function() {
@ -620,20 +585,43 @@ const ChatNotification = new Lang.Class({
Extends: MessageTray.Notification,
_init: function(source) {
this.parent(source, source.title, null,
{ secondaryGIcon: source.getSecondaryIcon() });
this.setUrgency(MessageTray.Urgency.HIGH);
this.setResident(true);
this.parent(source, source.title, null, { secondaryGIcon: source.getSecondaryIcon() });
this.messages = [];
this._timestampTimeoutId = 0;
},
this._responseEntry = new St.Entry({ style_class: 'chat-response',
can_focus: true });
this._responseEntry.clutter_text.connect('activate', Lang.bind(this, this._onEntryActivated));
this._responseEntry.clutter_text.connect('text-changed', Lang.bind(this, this._onEntryChanged));
this.setActionArea(this._responseEntry);
destroy: function(reason) {
if (this._timestampTimeoutId)
Mainloop.source_remove(this._timestampTimeoutId);
this._responseEntry.clutter_text.connect('key-focus-in', Lang.bind(this, function() {
this.focused = true;
}));
this._responseEntry.clutter_text.connect('key-focus-out', Lang.bind(this, function() {
this.focused = false;
this.emit('unfocused');
}));
this._lastGroup = null;
this._bodyBox = new St.BoxLayout({ style_class: 'chat-notification-body-box' });
this._bodyBin.child = this._bodyBox;
// 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
// bottom
this._oldMaxScrollValue = this._bodyScrollArea.vscroll.adjustment.value;
this._bodyScrollArea.add_style_class_name('chat-notification-scrollview');
this._bodyScrollArea.vscroll.adjustment.connect('changed', Lang.bind(this, function(adjustment) {
if (adjustment.value == this._oldMaxScrollValue)
this.scrollTo(St.Side.BOTTOM);
this._oldMaxScrollValue = Math.max(adjustment.lower, adjustment.upper - adjustment.page_size);
}));
this._inputHistory = new History.HistoryManager({ entry: this._responseEntry.clutter_text });
this._history = [];
this._timestampTimeoutId = 0;
this.parent(reason);
this._composingTimeoutId = 0;
},
/**
@ -659,8 +647,9 @@ const ChatNotification = new Lang.Class({
styles.push('chat-action');
}
if (message.direction == NotificationDirection.RECEIVED)
if (message.direction == NotificationDirection.RECEIVED) {
this.update(this.source.title, messageBody, { bannerMarkup: true });
}
let group = (message.direction == NotificationDirection.RECEIVED ?
'received' : 'sent');
@ -673,10 +662,10 @@ const ChatNotification = new Lang.Class({
},
_filterMessages: function() {
if (this.messages.length < 1)
if (this._history.length < 1)
return;
let lastMessageTime = this.messages[0].timestamp;
let lastMessageTime = this._history[0].time;
let currentTime = (Date.now() / 1000);
// Keep the scrollback from growing too long. If the most
@ -688,12 +677,19 @@ const ChatNotification = new Lang.Class({
let maxLength = (lastMessageTime < currentTime - SCROLLBACK_RECENT_TIME) ?
SCROLLBACK_IDLE_LENGTH : SCROLLBACK_RECENT_LENGTH;
let filteredHistory = this.messages.filter(function(item) { return item.realMessage });
let filteredHistory = this._history.filter(function(item) { return item.realMessage });
if (filteredHistory.length > maxLength) {
let lastMessageToKeep = filteredHistory[maxLength];
let expired = this.messages.splice(this.messages.indexOf(lastMessageToKeep));
let expired = this._history.splice(this._history.indexOf(lastMessageToKeep));
for (let i = 0; i < expired.length; i++)
this.emit('message-removed', expired[i]);
expired[i].actor.destroy();
}
let groups = this._bodyBox.get_children();
for (let i = 0; i < groups.length; i++) {
let group = groups[i];
if (group.get_n_children() == 0)
group.destroy();
}
},
@ -706,6 +702,7 @@ const ChatNotification = new Lang.Class({
* styles: Style class names for the message to have.
* timestamp: The timestamp of the message.
* noTimestamp: suppress timestamp signal?
* childProps: props to add the actor with.
*/
_append: function(props) {
let currentTime = (Date.now() / 1000);
@ -713,23 +710,43 @@ const ChatNotification = new Lang.Class({
group: null,
styles: [],
timestamp: currentTime,
noTimestamp: false });
noTimestamp: false,
childProps: null });
// Reset the old message timeout
if (this._timestampTimeoutId)
Mainloop.source_remove(this._timestampTimeoutId);
this._timestampTimeoutId = 0;
let message = { realMessage: props.group != 'meta',
showTimestamp: false };
Lang.copyProperties(props, message);
delete message.noTimestamp;
let highlighter = new MessageTray.URLHighlighter();
highlighter.actor.clutter_text.line_wrap = true;
highlighter.setMarkup(props.body, true);
this.messages.unshift(message);
this.emit('message-added', message);
let body = highlighter.actor;
let styles = props.styles;
for (let i = 0; i < styles.length; i++)
body.add_style_class_name(styles[i]);
let group = props.group;
if (group != this._lastGroup) {
this._lastGroup = group;
let emptyLine = new St.Label({ style_class: 'chat-empty-line' });
this._bodyBox.add_child(emptyLine);
}
this._lastMessageBox = new St.BoxLayout({ vertical: false });
let revealer = new MessageTray.Revealer(body);
this._lastMessageBox.add(revealer, props.childProps);
revealer.show(true);
this._bodyBox.add_child(this._lastMessageBox);
let timestamp = props.timestamp;
this._history.unshift({ actor: body, time: timestamp,
realMessage: group != 'meta' });
if (!props.noTimestamp) {
let timestamp = props.timestamp;
if (timestamp < currentTime - SCROLLBACK_IMMEDIATE_TIME) {
this.appendTimestamp();
} else {
@ -745,11 +762,101 @@ const ChatNotification = new Lang.Class({
this._filterMessages();
},
_formatTimestamp: function(date) {
let now = new Date();
var daysAgo = (now.getTime() - date.getTime()) / (24 * 60 * 60 * 1000);
let format;
let desktopSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
let clockFormat = desktopSettings.get_string(CLOCK_FORMAT_KEY);
let hasAmPm = date.toLocaleFormat('%p') != '';
if (clockFormat == '24h' || !hasAmPm) {
// Show only the time if date is on today
if(daysAgo < 1){
/* Translators: Time in 24h format */
format = _("%H\u2236%M");
}
// Show the word "Yesterday" and time if date is on yesterday
else if(daysAgo <2){
/* Translators: this is the word "Yesterday" followed by a
time string in 24h format. i.e. "Yesterday, 14:30" */
// 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) {
/* Translators: this is the week day name followed by a time
string in 24h format. i.e. "Monday, 14:30" */
// xgettext:no-c-format
format = _("%A, %H\u2236%M");
} else if (date.getYear() == now.getYear()) {
/* Translators: this is the month name and day number
followed by a time string in 24h format.
i.e. "May 25, 14:30" */
// xgettext:no-c-format
format = _("%B %d, %H\u2236%M");
} else {
/* Translators: this is the month name, day number, year
number followed by a time string in 24h format.
i.e. "May 25 2012, 14:30" */
// xgettext:no-c-format
format = _("%B %d %Y, %H\u2236%M");
}
} else {
// Show only the time if date is on today
if(daysAgo < 1){
/* Translators: Time in 24h format */
format = _("%l\u2236%M %p");
}
// Show the word "Yesterday" and time if date is on yesterday
else if(daysAgo <2){
/* Translators: this is the word "Yesterday" followed by a
time string in 12h format. i.e. "Yesterday, 2:30 pm" */
// xgettext:no-c-format
format = _("Yesterday, %l\u2236%M %p");
}
// Show a week day and time if date is in the last week
else if (daysAgo < 7) {
/* 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()) {
/* Translators: this is the month name and day number
followed by a time string in 12h format.
i.e. "May 25, 2:30 pm" */
// xgettext:no-c-format
format = _("%B %d, %l\u2236%M %p");
} else {
/* Translators: this is the month name, day number, year
number followed by a time string in 12h format.
i.e. "May 25 2012, 2:30 pm"*/
// xgettext:no-c-format
format = _("%B %d %Y, %l\u2236%M %p");
}
}
return date.toLocaleFormat(format);
},
appendTimestamp: function() {
this._timestampTimeoutId = 0;
this.messages[0].showTimestamp = true;
this.emit('timestamp-changed', this.messages[0]);
let lastMessageTime = this._history[0].time;
let lastMessageDate = new Date(lastMessageTime * 1000);
let timeLabel = new St.Label({ text: this._formatTimestamp(lastMessageDate),
style_class: 'chat-meta-message',
x_expand: true,
y_expand: true,
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.END });
this._lastMessageBox.add_actor(timeLabel);
this._filterMessages();
@ -764,154 +871,13 @@ const ChatNotification = new Lang.Class({
IM name. */
let message = '<i>' + _("%s is now known as %s").format(oldAlias, newAlias) + '</i>';
this._append({ body: message,
group: 'meta',
styles: ['chat-meta-message'] });
let label = this._append({ body: message,
group: 'meta',
styles: ['chat-meta-message'] });
this.update(newAlias);
this._filterMessages();
}
});
const ChatLineBox = new Lang.Class({
Name: 'ChatLineBox',
Extends: St.BoxLayout,
vfunc_get_preferred_height: function(forWidth) {
let [, natHeight] = this.parent(forWidth);
return [natHeight, natHeight];
}
});
const ChatNotificationBanner = new Lang.Class({
Name: 'ChatNotificationBanner',
Extends: MessageTray.NotificationBanner,
_init: function(notification) {
this.parent(notification);
this._responseEntry = new St.Entry({ style_class: 'chat-response',
x_expand: true,
can_focus: true });
this._responseEntry.clutter_text.connect('activate', Lang.bind(this, this._onEntryActivated));
this._responseEntry.clutter_text.connect('text-changed', Lang.bind(this, this._onEntryChanged));
this.setActionArea(this._responseEntry);
this._responseEntry.clutter_text.connect('key-focus-in', Lang.bind(this, function() {
this.focused = true;
}));
this._responseEntry.clutter_text.connect('key-focus-out', Lang.bind(this, function() {
this.focused = false;
this.emit('unfocused');
}));
this._scrollArea = new St.ScrollView({ style_class: 'chat-scrollview vfade',
vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
hscrollbar_policy: Gtk.PolicyType.NEVER,
visible: this.expanded });
this._contentArea = new St.BoxLayout({ style_class: 'chat-body',
vertical: true });
this._scrollArea.add_actor(this._contentArea);
this.setExpandedBody(this._scrollArea);
this.setExpandedLines(CHAT_EXPAND_LINES);
this._lastGroup = null;
// 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
// bottom
this._oldMaxScrollValue = this._scrollArea.vscroll.adjustment.value;
this._scrollArea.vscroll.adjustment.connect('changed', Lang.bind(this, function(adjustment) {
if (adjustment.value == this._oldMaxScrollValue)
this.scrollTo(St.Side.BOTTOM);
this._oldMaxScrollValue = Math.max(adjustment.lower, adjustment.upper - adjustment.page_size);
}));
this._inputHistory = new History.HistoryManager({ entry: this._responseEntry.clutter_text });
this._composingTimeoutId = 0;
this._messageActors = new Map();
this._messageAddedId = this.notification.connect('message-added',
Lang.bind(this, function(n, message) {
this._addMessage(message);
}));
this._messageRemovedId = this.notification.connect('message-removed',
Lang.bind(this, function(n, message) {
let actor = this._messageActors.get(message);
if (this._messageActors.delete(message))
actor.destroy();
}));
this._timestampChangedId = this.notification.connect('timestamp-changed',
Lang.bind(this, function(n, message) {
this._updateTimestamp(message);
}));
for (let i = this.notification.messages.length - 1; i >= 0; i--)
this._addMessage(this.notification.messages[i]);
},
_onDestroy: function() {
this.parent();
this.notification.disconnect(this._messageAddedId);
this.notification.disconnect(this._messageRemovedId);
this.notification.disconnect(this._timestampChangedId);
},
scrollTo: function(side) {
let adjustment = this._scrollArea.vscroll.adjustment;
if (side == St.Side.TOP)
adjustment.value = adjustment.lower;
else if (side == St.Side.BOTTOM)
adjustment.value = adjustment.upper;
},
hide: function() {
this.emit('done-displaying');
},
_addMessage: function(message) {
let highlighter = new MessageList.URLHighlighter(message.body, true, true);
let body = highlighter.actor;
let styles = message.styles;
for (let i = 0; i < styles.length; i++)
body.add_style_class_name(styles[i]);
let group = message.group;
if (group != this._lastGroup) {
this._lastGroup = group;
body.add_style_class_name('chat-new-group');
}
let lineBox = new ChatLineBox();
lineBox.add(body);
this._contentArea.add_actor(lineBox);
this._messageActors.set(message, lineBox);
this._updateTimestamp(message);
},
_updateTimestamp: function(message) {
let actor = this._messageActors.get(message);
if (!actor)
return;
while (actor.get_n_children() > 1)
actor.get_child_at_index(1).destroy();
if (message.showTimestamp) {
let lastMessageTime = message.timestamp;
let lastMessageDate = new Date(lastMessageTime * 1000);
let timeLabel = Util.createTimeLabel(lastMessageDate);
timeLabel.style_class = 'chat-meta-message';
timeLabel.x_expand = timeLabel.y_expand = true;
timeLabel.x_align = timeLabel.y_align = Clutter.ActorAlign.END;
actor.add_actor(timeLabel);
}
},
_onEntryActivated: function() {
@ -924,13 +890,13 @@ const ChatNotificationBanner = new Lang.Class({
// Telepathy sends out the Sent signal for us.
// see Source._messageSent
this._responseEntry.set_text('');
this.notification.source.respond(text);
this.source.respond(text);
},
_composingStopTimeout: function() {
this._composingTimeoutId = 0;
this.notification.source.setChatState(Tp.ChannelChatState.PAUSED);
this.source.setChatState(Tp.ChannelChatState.PAUSED);
return GLib.SOURCE_REMOVE;
},
@ -950,14 +916,14 @@ const ChatNotificationBanner = new Lang.Class({
}
if (text != '') {
this.notification.source.setChatState(Tp.ChannelChatState.COMPOSING);
this.source.setChatState(Tp.ChannelChatState.COMPOSING);
this._composingTimeoutId = Mainloop.timeout_add_seconds(
COMPOSING_STOP_TIMEOUT,
Lang.bind(this, this._composingStopTimeout));
GLib.Source.set_name_by_id(this._composingTimeoutId, '[gnome-shell] this._composingStopTimeout');
} else {
this.notification.source.setChatState(Tp.ChannelChatState.ACTIVE);
this.source.setChatState(Tp.ChannelChatState.ACTIVE);
}
}
});

View File

@ -27,8 +27,8 @@ const CtrlAltTabManager = new Lang.Class({
_init: function() {
this._items = [];
this.addGroup(global.window_group, _("Windows"),
'focus-windows-symbolic', { sortGroup: SortGroup.TOP,
focusCallback: Lang.bind(this, this._focusWindows) });
'emblem-documents-symbolic', { sortGroup: SortGroup.TOP,
focusCallback: Lang.bind(this, this._focusWindows) });
},
addGroup: function(root, name, icon, params) {
@ -100,7 +100,7 @@ const CtrlAltTabManager = new Lang.Class({
if (app)
icon = app.create_icon_texture(POPUP_APPICON_SIZE);
else
icon = textureCache.bind_cairo_surface_property(windows[i], 'icon');
icon = textureCache.bind_pixbuf_property(windows[i], 'icon');
}
items.push({ name: windows[i].title,
@ -140,17 +140,27 @@ const CtrlAltTabPopup = new Lang.Class({
Name: 'CtrlAltTabPopup',
Extends: SwitcherPopup.SwitcherPopup,
_init: function(items) {
this.parent(items);
_createSwitcher: function() {
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)
this._select(this._next());
this._select(backwards ? this._previous() : this._next());
else if (action == Meta.KeyBindingAction.SWITCH_PANELS_BACKWARD)
this._select(this._previous());
this._select(backwards ? this._next() : this._previous());
else if (keysym == Clutter.Left)
this._select(this._previous());
else if (keysym == Clutter.Right)

View File

@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Signals = imports.signals;
const Lang = imports.lang;
@ -259,7 +258,7 @@ const ShowAppsIcon = new Lang.Class({
},
_createIcon: function(size) {
this._iconActor = new St.Icon({ icon_name: 'view-app-grid-symbolic',
this._iconActor = new St.Icon({ icon_name: 'view-grid-symbolic',
icon_size: size,
style_class: 'show-apps-icon',
track_hover: true });
@ -270,9 +269,6 @@ const ShowAppsIcon = new Lang.Class({
if (app == null)
return false;
if (!global.settings.is_writable('favorite-apps'))
return false;
let id = app.get_id();
let isFavorite = AppFavorites.getAppFavorites().isFavorite(id);
return isFavorite;
@ -517,13 +513,10 @@ const Dash = new Lang.Class({
this._syncLabel(item, appIcon);
}));
let id = Main.overview.connect('hiding', Lang.bind(this, function() {
Main.overview.connect('hiding', Lang.bind(this, function() {
this._labelShowing = false;
item.hideLabel();
}));
item.child.connect('destroy', function() {
Main.overview.disconnect(id);
});
if (appIcon) {
appIcon.connect('sync-tooltip', Lang.bind(this, function() {
@ -536,17 +529,14 @@ const Dash = new Lang.Class({
let appIcon = new AppDisplay.AppIcon(app,
{ setSizeManually: true,
showLabel: false });
if (appIcon._draggable) {
appIcon._draggable.connect('drag-begin',
Lang.bind(this, function() {
appIcon.actor.opacity = 50;
}));
appIcon._draggable.connect('drag-end',
Lang.bind(this, function() {
appIcon.actor.opacity = 255;
}));
}
appIcon._draggable.connect('drag-begin',
Lang.bind(this, function() {
appIcon.actor.opacity = 50;
}));
appIcon._draggable.connect('drag-end',
Lang.bind(this, function() {
appIcon.actor.opacity = 255;
}));
appIcon.connect('menu-state-changed',
Lang.bind(this, function(appIcon, opened) {
this._itemMenuStateChanged(item, opened);
@ -644,14 +634,15 @@ const Dash = new Lang.Class({
let firstIcon = firstButton._delegate.icon;
let minHeight, natHeight;
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
// Enforce the current icon size during the size request
firstIcon.icon.ensure_style();
let [currentWidth, currentHeight] = firstIcon.icon.get_size();
firstIcon.icon.set_size(this.iconSize * scaleFactor, this.iconSize * scaleFactor);
firstIcon.setIconSize(this.iconSize);
[minHeight, natHeight] = firstButton.get_preferred_height(-1);
firstIcon.icon.set_size(currentWidth, currentHeight);
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let iconSizes = baseIconSizes.map(function(s) {
return s * scaleFactor;
});
// Subtract icon padding and box spacing from the available height
availHeight -= iconChildren.length * (natHeight - this.iconSize * scaleFactor) +
@ -659,10 +650,6 @@ const Dash = new Lang.Class({
let availSize = availHeight / iconChildren.length;
let iconSizes = baseIconSizes.map(function(s) {
return s * scaleFactor;
});
let newIconSize = baseIconSizes[0];
for (let i = 0; i < iconSizes.length; i++) {
if (iconSizes[i] < availSize)
@ -863,9 +850,6 @@ const Dash = new Lang.Class({
if (app == null || app.is_window_backed())
return DND.DragMotionResult.NO_DROP;
if (!global.settings.is_writable('favorite-apps'))
return DND.DragMotionResult.NO_DROP;
let favorites = AppFavorites.getAppFavorites().getFavorites();
let numFavorites = favorites.length;
@ -942,9 +926,6 @@ const Dash = new Lang.Class({
return false;
}
if (!global.settings.is_writable('favorite-apps'))
return false;
let id = app.get_id();
let favorites = AppFavorites.getAppFavorites().getFavoriteMap();

View File

@ -3,9 +3,6 @@
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const GnomeDesktop = imports.gi.GnomeDesktop;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const GWeather = imports.gi.GWeather;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Cairo = imports.cairo;
@ -21,292 +18,22 @@ const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const Calendar = imports.ui.calendar;
function _isToday(date) {
let now = new Date();
return now.getYear() == date.getYear() &&
now.getMonth() == date.getMonth() &&
now.getDate() == date.getDate();
}
const TodayButton = new Lang.Class({
Name: 'TodayButton',
_init: function(calendar) {
// 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.actor = new St.Button({ style_class: 'datemenu-today-button',
x_align: St.Align.START,
can_focus: true,
reactive: false
});
this.actor.connect('clicked', Lang.bind(this,
function() {
this._calendar.setDate(new Date(), false);
}));
let hbox = new St.BoxLayout({ vertical: true });
this.actor.add_actor(hbox);
this._dayLabel = new St.Label({ style_class: 'day-label',
x_align: Clutter.ActorAlign.START });
hbox.add_actor(this._dayLabel);
this._dateLabel = new St.Label({ style_class: 'date-label' });
hbox.add_actor(this._dateLabel);
this._calendar = calendar;
this._calendar.connect('selected-date-changed', Lang.bind(this,
function(calendar, date) {
// Make the button reactive only if the selected date is not the
// current date.
this.actor.reactive = !_isToday(date)
}));
},
setDate: function(date) {
this._dayLabel.set_text(date.toLocaleFormat('%A'));
/* 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 = Shell.util_translate_time_string (N_("%B %e %Y"));
this._dateLabel.set_text(date.toLocaleFormat(dateFormat));
/* Translators: This is the accessible name of the date button shown
* below the time in the shell; it should combine the weekday and the
* date, e.g. "Tuesday February 17 2015".
*/
let dateFormat = Shell.util_translate_time_string (N_("%A %B %e %Y"));
this.actor.accessible_name = date.toLocaleFormat(dateFormat);
}
});
const WorldClocksSection = new Lang.Class({
Name: 'WorldClocksSection',
_init: function() {
this._clock = new GnomeDesktop.WallClock();
this._settings = null;
this._clockNotifyId = 0;
this._changedId = 0;
this._locations = [];
this.actor = new St.Button({ style_class: 'world-clocks-button',
x_fill: true,
can_focus: true });
this.actor.connect('clicked', Lang.bind(this,
function() {
let app = this._getClockApp();
app.activate();
Main.overview.hide();
Main.panel.closeCalendar();
}));
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
this._grid = new St.Widget({ style_class: 'world-clocks-grid',
layout_manager: layout });
layout.hookup_style(this._grid);
this.actor.child = this._grid;
Shell.AppSystem.get_default().connect('installed-changed',
Lang.bind(this, this._sync));
this._sync();
},
_getClockApp: function() {
return Shell.AppSystem.get_default().lookup_app('org.gnome.clocks.desktop');
},
_sync: function() {
this.actor.visible = (this._getClockApp() != null);
if (this.actor.visible) {
if (!this._settings) {
this._settings = new Gio.Settings({ schema_id: 'org.gnome.clocks' });
this._changedId =
this._settings.connect('changed::world-clocks',
Lang.bind(this, this._clocksChanged));
this._clocksChanged();
}
} else {
if (this._settings)
this._settings.disconnect(this._changedId);
this._settings = null;
this._changedId = 0;
}
},
_clocksChanged: function() {
this._grid.destroy_all_children();
this._locations = [];
let world = GWeather.Location.get_world();
let clocks = this._settings.get_value('world-clocks').deep_unpack();
for (let i = 0; i < clocks.length; i++) {
let l = world.deserialize(clocks[i].location);
this._locations.push({ location: l });
}
this._locations.sort(function(a, b) {
return a.location.get_timezone().get_offset() -
b.location.get_timezone().get_offset();
});
let layout = this._grid.layout_manager;
let title = (this._locations.length == 0) ? _("Add world clocks…")
: _("World Clocks");
let header = new St.Label({ style_class: 'world-clocks-header',
x_align: Clutter.ActorAlign.START,
text: title });
layout.attach(header, 0, 0, 2, 1);
this.actor.label_actor = header;
for (let i = 0; i < this._locations.length; i++) {
let l = this._locations[i].location;
let label = new St.Label({ style_class: 'world-clocks-city',
text: l.get_city_name(),
x_align: Clutter.ActorAlign.START,
x_expand: true });
let time = new St.Label({ style_class: 'world-clocks-time',
x_align: Clutter.ActorAlign.END,
x_expand: true });
if (this._grid.text_direction == Clutter.TextDirection.RTL) {
layout.attach(time, 0, i + 1, 1, 1);
layout.attach(label, 1, i + 1, 1, 1);
} else {
layout.attach(label, 0, i + 1, 1, 1);
layout.attach(time, 1, i + 1, 1, 1);
}
this._locations[i].actor = time;
}
if (this._grid.get_n_children() > 1) {
if (!this._clockNotifyId)
this._clockNotifyId =
this._clock.connect('notify::clock', Lang.bind(this, this._updateLabels));
this._updateLabels();
} else {
if (this._clockNotifyId)
this._clock.disconnect(this._clockNotifyId);
this._clockNotifyId = 0;
}
},
_updateLabels: function() {
for (let i = 0; i < this._locations.length; i++) {
let l = this._locations[i];
let tz = GLib.TimeZone.new(l.location.get_timezone().get_tzid());
let now = GLib.DateTime.new_now(tz);
l.actor.text = Util.formatTime(now, { timeOnly: true });
}
}
});
const MessagesIndicator = new Lang.Class({
Name: 'MessagesIndicator',
_init: function() {
this.actor = new St.Label({ text: '⚫', visible: false, y_expand: true,
y_align: Clutter.ActorAlign.CENTER });
this._sources = [];
Main.messageTray.connect('source-added', Lang.bind(this, this._onSourceAdded));
Main.messageTray.connect('source-removed', Lang.bind(this, this._onSourceRemoved));
Main.messageTray.connect('queue-changed', Lang.bind(this, this._updateCount));
let sources = Main.messageTray.getSources();
sources.forEach(Lang.bind(this, function(source) { this._onSourceAdded(null, source); }));
},
_onSourceAdded: function(tray, source) {
source.connect('count-updated', Lang.bind(this, this._updateCount));
this._sources.push(source);
this._updateCount();
},
_onSourceRemoved: function(tray, source) {
this._sources.splice(this._sources.indexOf(source), 1);
this._updateCount();
},
_updateCount: function() {
let count = 0;
this._sources.forEach(Lang.bind(this,
function(source) {
count += source.unseenCount;
}));
count -= Main.messageTray.queueCount;
this.actor.visible = (count > 0);
}
});
const IndicatorPad = new Lang.Class({
Name: 'IndicatorPad',
Extends: St.Widget,
_init: function(actor) {
this._source = actor;
this._source.connect('notify::visible',
Lang.bind(this, this.queue_relayout));
this.parent();
},
vfunc_get_preferred_width: function(container, forHeight) {
if (this._source.visible)
return this._source.get_preferred_width(forHeight);
return [0, 0];
},
vfunc_get_preferred_height: function(container, forWidth) {
if (this._source.visible)
return this._source.get_preferred_height(forWidth);
return [0, 0];
}
});
const FreezableBinLayout = new Lang.Class({
Name: 'FreezableBinLayout',
Extends: Clutter.BinLayout,
_init: function() {
this.parent();
this._frozen = false;
this._savedWidth = [NaN, NaN];
this._savedHeight = [NaN, NaN];
},
set frozen(v) {
if (this._frozen == v)
return;
this._frozen = v;
if (!this._frozen)
this.layout_changed();
},
vfunc_get_preferred_width: function(container, forHeight) {
if (!this._frozen || this._savedWidth.some(isNaN))
this._savedWidth = this.parent(container, forHeight);
return this._savedWidth;
},
vfunc_get_preferred_height: function(container, forWidth) {
if (!this._frozen || this._savedHeight.some(isNaN))
this._savedHeight = this.parent(container, forWidth);
return this._savedHeight;
}
});
function _onVertSepRepaint (area)
{
let cr = area.get_context();
let themeNode = area.get_theme_node();
let [width, height] = area.get_surface_size();
let stippleColor = themeNode.get_color('-stipple-color');
let stippleWidth = themeNode.get_length('-stipple-width');
let x = Math.floor(width/2) + 0.5;
cr.moveTo(x, 0);
cr.lineTo(x, height);
Clutter.cairo_set_source_color(cr, stippleColor);
cr.setDash([1, 3], 1); // Hard-code for now
cr.setLineWidth(stippleWidth);
cr.stroke();
cr.$dispose();
};
const DateMenuButton = new Lang.Class({
Name: 'DateMenuButton',
@ -317,87 +44,128 @@ const DateMenuButton = new Lang.Class({
let hbox;
let vbox;
let menuAlignment = 0.5;
let menuAlignment = 0.25;
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
menuAlignment = 1.0 - menuAlignment;
this.parent(menuAlignment);
this._clockDisplay = new St.Label({ y_align: Clutter.ActorAlign.CENTER });
this._indicator = new MessagesIndicator();
let box = new St.BoxLayout();
box.add_actor(new IndicatorPad(this._indicator.actor));
box.add_actor(this._clockDisplay);
box.add_actor(this._indicator.actor);
this.actor.label_actor = this._clockDisplay;
this.actor.add_actor(box);
this.actor.add_actor(this._clockDisplay);
this.actor.add_style_class_name ('clock-display');
let layout = new FreezableBinLayout();
let bin = new St.Widget({ layout_manager: layout });
this.menu.box.add_child(bin);
hbox = new St.BoxLayout({ name: 'calendarArea' });
bin.add_actor(hbox);
this.menu.box.add_child(hbox);
// Fill up the first column
vbox = new St.BoxLayout({vertical: true});
hbox.add(vbox);
// 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',
reactive: false
});
this._date.connect('clicked',
Lang.bind(this, function() {
this._calendar.setDate(new Date(), false);
}));
vbox.add(this._date, { x_fill: false });
this._eventList = new Calendar.EventsList();
this._calendar = new Calendar.Calendar();
this._calendar.connect('selected-date-changed',
Lang.bind(this, function(calendar, date) {
layout.frozen = !_isToday(date);
this._messageList.setDate(date);
}));
// we know this._eventList is defined here, because selected-data-changed
// only gets emitted when the user clicks a date in the calendar,
// and the calender makes those dates unclickable when instantiated with
// a null event source
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);
let separator = new PopupMenu.PopupSeparatorMenuItem();
vbox.add(separator.actor, { y_align: St.Align.END, expand: true, y_fill: false });
this._openCalendarItem = new PopupMenu.PopupMenuItem(_("Open Calendar"));
this._openCalendarItem.connect('activate', Lang.bind(this, this._onOpenCalendarActivate));
vbox.add(this._openCalendarItem.actor, {y_align: St.Align.END, expand: true, y_fill: false});
this._openClocksItem = new PopupMenu.PopupMenuItem(_("Open Clocks"));
this._openClocksItem.connect('activate', Lang.bind(this, this._onOpenClocksActivate));
vbox.add(this._openClocksItem.actor, {y_align: St.Align.END, expand: true, y_fill: false});
Shell.AppSystem.get_default().connect('installed-changed',
Lang.bind(this, this._appInstalledChanged));
item = this.menu.addSettingsAction(_("Date & Time Settings"), 'gnome-datetime-panel.desktop');
if (item) {
item.actor.show_on_set_parent = false;
item.actor.reparent(vbox);
this._dateAndTimeSeparator = separator;
}
this._separator = new St.DrawingArea({ style_class: 'calendar-vertical-separator',
pseudo_class: 'highlighted' });
this._separator.connect('repaint', Lang.bind(this, _onVertSepRepaint));
hbox.add(this._separator);
// Fill up the second column
hbox.add(this._eventList.actor, { expand: true, y_fill: false, y_align: St.Align.START });
// Whenever the menu is opened, select today
this.menu.connect('open-state-changed', Lang.bind(this, function(menu, isOpen) {
// Whenever the menu is opened, select today
if (isOpen) {
let now = new Date();
this._calendar.setDate(now);
this._date.setDate(now);
this._messageList.setDate(now);
}
}));
// Fill up the first column
this._messageList = new Calendar.CalendarMessageList();
hbox.add(this._messageList.actor, { expand: true, y_fill: false, y_align: St.Align.START });
// Fill up the second column
vbox = new St.BoxLayout({ style_class: 'datemenu-calendar-column',
vertical: true });
hbox.add(vbox);
this._date = new TodayButton(this._calendar);
vbox.add_actor(this._date.actor);
vbox.add(this._calendar.actor);
this._displaysSection = new St.ScrollView({ style_class: 'datemenu-displays-section vfade',
x_expand: true, x_fill: true,
overlay_scrollbars: true });
this._displaysSection.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
vbox.add_actor(this._displaysSection);
let displaysBox = new St.BoxLayout({ vertical: true,
style_class: 'datemenu-displays-box' });
this._displaysSection.add_actor(displaysBox);
this._clocksItem = new WorldClocksSection();
displaysBox.add(this._clocksItem.actor, { x_fill: true });
// Done with hbox for calendar and event list
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));
this._sessionUpdated();
},
_getEventSource: function() {
return new Calendar.DBusEventSource();
_isToday: function(date) {
let now = new Date();
return now.getYear() == date.getYear() &&
now.getMonth() == date.getMonth() &&
now.getDay() == date.getDay();
},
_appInstalledChanged: function() {
this._calendarApp = undefined;
this._updateEventsVisibility();
},
_updateEventsVisibility: function() {
let visible = this._eventSource.hasCalendars;
this._openCalendarItem.actor.visible = visible &&
(this._getCalendarApp() != null);
this._openClocksItem.actor.visible = visible &&
(this._getClockApp() != null);
this._separator.visible = visible;
this._eventList.actor.visible = visible;
if (visible) {
let alignment = 0.25;
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
alignment = 1.0 - alignment;
this.menu._arrowAlignment = alignment;
} else {
this.menu._arrowAlignment = 0.5;
}
},
_setEventSource: function(eventSource) {
@ -405,24 +173,68 @@ const DateMenuButton = new Lang.Class({
this._eventSource.destroy();
this._calendar.setEventSource(eventSource);
this._messageList.setEventSource(eventSource);
this._eventList.setEventSource(eventSource);
this._eventSource = eventSource;
this._eventSource.connect('notify::has-calendars', Lang.bind(this, function() {
this._updateEventsVisibility();
}));
},
_sessionUpdated: function() {
let eventSource;
let showEvents = Main.sessionMode.showCalendarEvents;
if (showEvents) {
eventSource = this._getEventSource();
eventSource = new Calendar.DBusEventSource();
} else {
eventSource = new Calendar.EmptyEventSource();
}
this._setEventSource(eventSource);
this._updateEventsVisibility();
// Displays are not actually expected to launch Settings when activated
// but the corresponding app (clocks, weather); however we can consider
// that display-specific settings, so re-use "allowSettings" here ...
this._displaysSection.visible = Main.sessionMode.allowSettings;
// This needs to be handled manually, as the code to
// autohide separators doesn't work across the vbox
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() {
if (this._calendarApp !== undefined)
return this._calendarApp;
let apps = Gio.AppInfo.get_recommended_for_type('text/calendar');
if (apps && (apps.length > 0))
this._calendarApp = apps[0];
else
this._calendarApp = null;
return this._calendarApp;
},
_getClockApp: function() {
return Shell.AppSystem.get_default().lookup_app('org.gnome.clocks.desktop');
},
_onOpenCalendarActivate: function() {
this.menu.close();
let app = this._getCalendarApp();
if (app.get_id() == 'evolution.desktop')
app = Gio.DesktopAppInfo.new('evolution-calendar.desktop');
app.launch([], global.create_app_launch_context(0, -1));
},
_onOpenClocksActivate: function() {
this.menu.close();
let app = this._getClockApp();
app.activate();
}
});

View File

@ -79,12 +79,9 @@ const _Draggable = new Lang.Class({
dragActorOpacity: undefined });
this.actor = actor;
if (!params.manualMode) {
if (!params.manualMode)
this.actor.connect('button-press-event',
Lang.bind(this, this._onButtonPress));
this.actor.connect('touch-event',
Lang.bind(this, this._onTouchEvent));
}
this.actor.connect('destroy', Lang.bind(this, function() {
this._actorDestroyed = true;
@ -124,50 +121,8 @@ const _Draggable = new Lang.Class({
return Clutter.EVENT_PROPAGATE;
},
_onTouchEvent: function (actor, event) {
if (event.type() != Clutter.EventType.TOUCH_BEGIN ||
!global.display.is_pointer_emulating_sequence(event.get_event_sequence()))
return Clutter.EVENT_PROPAGATE;
if (Tweener.getTweenCount(actor))
return Clutter.EVENT_PROPAGATE;
this._touchSequence = event.get_event_sequence();
this._buttonDown = true;
this._grabActor();
let [stageX, stageY] = event.get_coords();
this._dragStartX = stageX;
this._dragStartY = stageY;
return Clutter.EVENT_PROPAGATE;
},
_grabDevice: function(actor) {
let manager = Clutter.DeviceManager.get_default();
let pointer = manager.get_core_device(Clutter.InputDeviceType.POINTER_DEVICE);
if (pointer && this._touchSequence)
pointer.sequence_grab(this._touchSequence, actor);
else if (pointer)
pointer.grab (actor);
this._grabbedDevice = pointer;
},
_ungrabDevice: function() {
if (this._touchSequence)
this._grabbedDevice.sequence_ungrab (this._touchSequence);
else
this._grabbedDevice.ungrab();
this._touchSequence = null;
this._grabbedDevice = null;
},
_grabActor: function() {
this._grabDevice(this.actor);
Clutter.grab_pointer(this.actor);
this._onEventId = this.actor.connect('event',
Lang.bind(this, this._onEvent));
},
@ -176,7 +131,7 @@ const _Draggable = new Lang.Class({
if (!this._onEventId)
return;
this._ungrabDevice();
Clutter.ungrab_pointer();
this.actor.disconnect(this._onEventId);
this._onEventId = null;
},
@ -185,13 +140,13 @@ const _Draggable = new Lang.Class({
if (!this._eventsGrabbed) {
this._eventsGrabbed = Main.pushModal(_getEventHandlerActor());
if (this._eventsGrabbed)
this._grabDevice(_getEventHandlerActor());
Clutter.grab_pointer(_getEventHandlerActor());
}
},
_ungrabEvents: function() {
if (this._eventsGrabbed) {
this._ungrabDevice();
Clutter.ungrab_pointer();
Main.popModal(_getEventHandlerActor());
this._eventsGrabbed = false;
}
@ -202,9 +157,7 @@ const _Draggable = new Lang.Class({
// didn't start the drag, to drop the draggable in case the drag was in progress, and
// to complete the drag and ensure that whatever happens to be under the pointer does
// not get triggered if the drag was cancelled with Esc.
if (event.type() == Clutter.EventType.BUTTON_RELEASE ||
(event.type() == Clutter.EventType.TOUCH_END &&
global.display.is_pointer_emulating_sequence(event.get_event_sequence()))) {
if (event.type() == Clutter.EventType.BUTTON_RELEASE) {
this._buttonDown = false;
if (this._dragInProgress) {
return this._dragActorDropped(event);
@ -219,9 +172,7 @@ const _Draggable = new Lang.Class({
}
// We intercept MOTION event to figure out if the drag has started and to draw
// this._dragActor under the pointer when dragging is in progress
} else if (event.type() == Clutter.EventType.MOTION ||
(event.type() == Clutter.EventType.TOUCH_UPDATE &&
global.display.is_pointer_emulating_sequence(event.get_event_sequence()))) {
} else if (event.type() == Clutter.EventType.MOTION) {
if (this._dragInProgress) {
return this._updateDragPosition(event);
} else if (this._dragActor == null) {
@ -263,7 +214,7 @@ const _Draggable = new Lang.Class({
* This function is useful to call if you've specified manualMode
* for the draggable.
*/
startDrag: function (stageX, stageY, time, sequence) {
startDrag: function (stageX, stageY, time) {
currentDraggable = this;
this._dragInProgress = true;
@ -277,8 +228,6 @@ const _Draggable = new Lang.Class({
this.emit('drag-begin', time);
if (this._onEventId)
this._ungrabActor();
this._touchSequence = sequence;
this._grabEvents();
global.screen.set_cursor(Meta.Cursor.DND_IN_DRAG);
@ -389,8 +338,8 @@ const _Draggable = new Lang.Class({
let threshold = Gtk.Settings.get_default().gtk_dnd_drag_threshold;
if ((Math.abs(stageX - this._dragStartX) > threshold ||
Math.abs(stageY - this._dragStartY) > threshold)) {
this.startDrag(stageX, stageY, event.get_time(), this._touchSequence);
this._updateDragPosition(event);
this.startDrag(stageX, stageY, event.get_time());
this._updateDragPosition(event);
}
return true;
@ -571,13 +520,20 @@ const _Draggable = new Lang.Class({
return;
}
this._animateDragEnd(eventTime,
{ x: snapBackX,
y: snapBackY,
scale_x: snapBackScale,
scale_y: snapBackScale,
time: SNAP_BACK_ANIMATION_TIME,
});
this._animationInProgress = true;
// No target, so snap back
Tweener.addTween(this._dragActor,
{ x: snapBackX,
y: snapBackY,
scale_x: snapBackScale,
scale_y: snapBackScale,
opacity: this._dragOrigOpacity,
time: SNAP_BACK_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._onAnimationComplete,
onCompleteScope: this,
onCompleteParams: [this._dragActor, eventTime]
});
},
_restoreDragActor: function(eventTime) {
@ -589,44 +545,18 @@ const _Draggable = new Lang.Class({
this._dragActor.set_scale(restoreScale, restoreScale);
this._dragActor.opacity = 0;
this._animateDragEnd(eventTime,
{ time: REVERT_ANIMATION_TIME });
},
_animateDragEnd: function (eventTime, params) {
this._animationInProgress = true;
// finish animation if the actor gets destroyed
// during it
this._dragActorDestroyId =
this._dragActor.connect('destroy',
Lang.bind(this, this._finishAnimation));
params['opacity'] = this._dragOrigOpacity;
params['transition'] = 'easeOutQuad';
params['onComplete'] = this._onAnimationComplete;
params['onCompleteScope'] = this;
params['onCompleteParams'] = [this._dragActor, eventTime];
// start the animation
Tweener.addTween(this._dragActor, params)
},
_finishAnimation : function () {
if (!this._animationInProgress)
return
this._animationInProgress = false;
if (!this._buttonDown)
this._dragComplete();
global.screen.set_cursor(Meta.Cursor.DEFAULT);
Tweener.addTween(this._dragActor,
{ opacity: this._dragOrigOpacity,
time: REVERT_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._onAnimationComplete,
onCompleteScope: this,
onCompleteParams: [this._dragActor, eventTime]
});
},
_onAnimationComplete : function (dragActor, eventTime) {
dragActor.disconnect(this._dragActorDestroyId);
this._dragActorDestroyId = 0;
if (this._dragOrigParent) {
Main.uiGroup.remove_child(this._dragActor);
this._dragOrigParent.add_actor(this._dragActor);
@ -635,9 +565,12 @@ const _Draggable = new Lang.Class({
} else {
dragActor.destroy();
}
global.screen.set_cursor(Meta.Cursor.DEFAULT);
this.emit('drag-end', eventTime, false);
this._finishAnimation();
this._animationInProgress = false;
if (!this._buttonDown)
this._dragComplete();
},
_dragComplete: function() {

View File

@ -1,84 +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 Main = imports.ui.main;
const EDGE_THRESHOLD = 20;
const DRAG_DISTANCE = 80;
const EdgeDragAction = new Lang.Class({
Name: 'EdgeDragAction',
Extends: Clutter.GestureAction,
_init : function(side, allowedModes) {
this.parent();
this._side = side;
this._allowedModes = allowedModes;
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;
if (!(this._allowedModes & Main.actionMode))
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

@ -1,6 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/*
* Copyright 2010-2016 Red Hat, Inc
* Copyright 2010 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -38,6 +38,8 @@ const UserWidget = imports.ui.userWidget;
let _endSessionDialog = null;
const TRIGGER_OFFLINE_UPDATE = '/usr/libexec/pk-trigger-offline-update';
const _ITEM_ICON_SIZE = 48;
const _DIALOG_ICON_SIZE = 48;
@ -114,7 +116,7 @@ const restartDialogContent = {
showOtherSessions: true,
};
const restartUpdateDialogContent = {
const restartInstallDialogContent = {
subject: C_("title", "Restart & Install Updates"),
description: function(seconds) {
@ -132,38 +134,11 @@ const restartUpdateDialogContent = {
showOtherSessions: true,
};
const restartUpgradeDialogContent = {
subject: C_("title", "Restart & Install Upgrade"),
upgradeDescription: function(distroName, distroVersion) {
/* Translators: This is the text displayed for system upgrades in the
shut down dialog. First %s gets replaced with the distro name and
second %s with the distro version to upgrade to */
return _("%s %s will be installed after restart. Upgrade installation can take a long time: ensure that you have backed up and that the computer is plugged in.").format(distroName, distroVersion);
},
disableTimer: true,
showBatteryWarning: false,
confirmButtons: [{ signal: 'ConfirmedReboot',
label: C_("button", "Restart &amp; Install") }],
iconName: 'view-refresh-symbolic',
iconStyleClass: 'end-session-dialog-shutdown-icon',
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,
UPGRADE_RESTART: 4
};
const DialogContent = {
0 /* DialogType.LOGOUT */: logoutDialogContent,
1 /* DialogType.SHUTDOWN */: shutdownDialogContent,
2 /* DialogType.RESTART */: restartDialogContent,
3 /* DialogType.UPDATE_RESTART */: restartUpdateDialogContent,
4 /* DialogType.UPGRADE_RESTART */: restartUpgradeDialogContent
0 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_LOGOUT */: logoutDialogContent,
1 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_SHUTDOWN */: shutdownDialogContent,
2 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_RESTART */: restartDialogContent,
3: restartInstallDialogContent
};
const MAX_USERS_IN_SESSION_DIALOG = 5;
@ -180,22 +155,6 @@ const LogindSessionIface = '<node> \
const LogindSession = Gio.DBusProxy.makeProxyWrapper(LogindSessionIface);
const PkOfflineIface = '<node> \
<interface name="org.freedesktop.PackageKit.Offline"> \
<property name="UpdatePrepared" type="b" access="read"/> \
<property name="UpdateTriggered" type="b" access="read"/> \
<property name="UpgradePrepared" type="b" access="read"/> \
<property name="UpgradeTriggered" type="b" access="read"/> \
<property name="PreparedUpgrade" type="a{sv}" 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> \
<interface name="org.freedesktop.UPower"> \
<property name="OnBattery" type="b" access="read"/> \
@ -286,14 +245,9 @@ const EndSessionDialog = new Lang.Class({
this._loginManager = LoginManager.getLoginManager();
this._userManager = AccountsService.UserManager.get_default();
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,
'org.freedesktop.UPower',
'/org/freedesktop/UPower',
@ -438,19 +392,11 @@ const EndSessionDialog = new Lang.Class({
if (dialogContent.descriptionWithUser)
description = dialogContent.descriptionWithUser(realName, displayTime);
else
description = dialogContent.description(displayTime);
}
}
// Use a different description when we are installing a system upgrade
if (dialogContent.upgradeDescription) {
let name = this._pkOfflineProxy.PreparedUpgrade['name'].deep_unpack();
let version = this._pkOfflineProxy.PreparedUpgrade['version'].deep_unpack();
if (name != null && version != null)
description = dialogContent.upgradeDescription(name, version);
}
// Fall back to regular description
if (!description)
description = dialogContent.description(displayTime);
@ -553,29 +499,31 @@ const EndSessionDialog = new Lang.Class({
},
_triggerOfflineUpdateReboot: function(callback) {
this._pkOfflineProxy.TriggerRemote('reboot',
function (result, error) {
if (error)
log(error.message);
callback();
});
this._pkexecSpawn([TRIGGER_OFFLINE_UPDATE, 'reboot'], callback);
},
_triggerOfflineUpdateShutdown: function(callback) {
this._pkOfflineProxy.TriggerRemote('power-off',
function (result, error) {
if (error)
log(error.message);
callback();
});
this._pkexecSpawn([TRIGGER_OFFLINE_UPDATE, 'power-off'], callback);
},
_triggerOfflineUpdateCancel: function(callback) {
this._pkOfflineProxy.CancelRemote(function (result, error) {
if (error)
log(error.message);
this._pkexecSpawn([TRIGGER_OFFLINE_UPDATE, '--cancel'], callback);
},
_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();
});
@ -729,12 +677,8 @@ const EndSessionDialog = new Lang.Class({
this._totalSecondsToStayOpen = totalSecondsToStayOpen;
this._type = type;
if (this._type == DialogType.RESTART) {
if (this._pkOfflineProxy.UpdateTriggered)
this._type = DialogType.UPDATE_RESTART;
else if (this._pkOfflineProxy.UpgradeTriggered)
this._type = DialogType.UPGRADE_RESTART;
}
if (this._type == 2 && this._updatesFile.query_exists(null))
this._type = 3;
this._applications = [];
this._applicationList.destroy_all_children();
@ -761,19 +705,19 @@ const EndSessionDialog = new Lang.Class({
if (dialogContent.showOtherSessions)
this._loadSessions();
let updateTriggered = this._pkOfflineProxy.UpdateTriggered;
let updatePrepared = this._pkOfflineProxy.UpdatePrepared;
let preparedUpdate = this._preparedUpdateFile.query_exists(null);
let updateAlreadyTriggered = this._updatesFile.query_exists(null);
let updatesAllowed = this._updatesPermission && this._updatesPermission.allowed;
_setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText);
this._checkBox.actor.visible = (dialogContent.checkBoxText && updatePrepared && updatesAllowed);
this._checkBox.actor.checked = (updatePrepared && updateTriggered);
this._checkBox.actor.visible = (dialogContent.checkBoxText && preparedUpdate && updatesAllowed);
this._checkBox.actor.checked = (preparedUpdate && updateAlreadyTriggered);
// We show the warning either together with the checkbox, or when
// updates have already been triggered, but the user doesn't have
// enough permissions to cancel them.
this._batteryWarning.visible = (dialogContent.showBatteryWarning &&
(this._checkBox.actor.visible || updatePrepared && updateTriggered && !updatesAllowed));
(this._checkBox.actor.visible || preparedUpdate && updateAlreadyTriggered && !updatesAllowed));
this._updateButtons();
@ -783,9 +727,7 @@ const EndSessionDialog = new Lang.Class({
return;
}
if (!dialogContent.disableTimer)
this._startTimer();
this._startTimer();
this._sync();
let signalId = this.connect('opened',

View File

@ -77,10 +77,10 @@ function init() {
window._ = Gettext.gettext;
window.C_ = Gettext.pgettext;
window.ngettext = Gettext.ngettext;
window.N_ = function(s) { return s; };
// Miscellaneous monkeypatching
_patchContainerClass(St.BoxLayout);
_patchContainerClass(St.Table);
_patchLayoutClass(Clutter.TableLayout, { row_spacing: 'spacing-rows',
column_spacing: 'spacing-columns' });

View File

@ -203,16 +203,14 @@ const InstallExtensionDialog = new Lang.Class({
let message = _("Download and install “%s” from extensions.gnome.org?").format(info.name);
let box = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout',
vertical: false });
let box = new St.BoxLayout();
this.contentLayout.add(box);
let gicon = new Gio.FileIcon({ file: Gio.File.new_for_uri(REPOSITORY_URL_BASE + info.icon) })
let icon = new St.Icon({ gicon: gicon });
box.add(icon);
let label = new St.Label({ style_class: 'prompt-dialog-headline headline',
text: message });
let label = new St.Label({ text: message });
box.add(label);
},

View File

@ -74,7 +74,7 @@ function disableExtension(uuid) {
if (extension.stylesheet) {
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
theme.unload_stylesheet(extension.stylesheet);
theme.unload_stylesheet(extension.stylesheet.get_path());
}
try {
@ -118,7 +118,7 @@ function enableExtension(uuid) {
let stylesheetFile = extension.dir.get_child(stylesheetNames[i]);
if (stylesheetFile.query_exists(null)) {
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
theme.load_stylesheet(stylesheetFile);
theme.load_stylesheet(stylesheetFile.get_path());
extension.stylesheet = stylesheetFile;
break;
}
@ -271,17 +271,10 @@ function onEnabledExtensionsChanged() {
}
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) {
enabledExtensions.forEach(function(uuid) {
enableExtension(uuid);
if (ExtensionUtils.extensions[uuid])
reloadExtension(ExtensionUtils.extensions[uuid]);
});
}
}
@ -334,7 +327,7 @@ function _sessionUpdated() {
// from allowExtensions in the future
if (Main.sessionMode.allowExtensions) {
if (initted)
enabledExtensions = getEnabledExtensions();
onEnabledExtensionsChanged();
enableAllExtensions();
} else {
disableAllExtensions();

View File

@ -32,9 +32,11 @@ const FocusCaretTracker = new Lang.Class({
Name: 'FocusCaretTracker',
_init: function() {
Atspi.init();
Atspi.set_timeout(250, 250);
this._atspiListener = Atspi.EventListener.new(Lang.bind(this, this._onChanged));
this._atspiInited = false;
this._focusListenerRegistered = false;
this._caretListenerRegistered = false;
},
@ -46,20 +48,12 @@ const FocusCaretTracker = new Lang.Class({
this.emit('caret-moved', event);
},
_initAtspi: function() {
if (!this._atspiInited) {
Atspi.init();
Atspi.set_timeout(250, 250);
this._atspiInited = true;
}
},
registerFocusListener: function() {
if (this._focusListenerRegistered)
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 + ':selected');
this._focusListenerRegistered = true;
@ -69,8 +63,6 @@ const FocusCaretTracker = new Lang.Class({
if (this._caretListenerRegistered)
return;
this._initAtspi();
this._atspiListener.register(CARETMOVED);
this._caretListenerRegistered = true;
},

View File

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

View File

@ -11,9 +11,6 @@ const Main = imports.ui.main;
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({
Name: 'CandidateArea',
@ -41,11 +38,11 @@ const CandidateArea = new Lang.Class({
this._buttonBox = new St.BoxLayout({ style_class: 'candidate-page-button-box' });
this._previousButton = new St.Button({ style_class: 'candidate-page-button candidate-page-button-previous button' });
this._previousButton = new St.Button({ style_class: 'candidate-page-button candidate-page-button-previous' });
this._previousButton.child = new St.Icon({ style_class: 'candidate-page-button-icon' });
this._buttonBox.add(this._previousButton, { expand: true });
this._nextButton = new St.Button({ style_class: 'candidate-page-button candidate-page-button-next button' });
this._nextButton = new St.Button({ style_class: 'candidate-page-button candidate-page-button-next' });
this._nextButton.child = new St.Icon({ style_class: 'candidate-page-button-icon' });
this._buttonBox.add(this._nextButton, { expand: true });
@ -92,7 +89,7 @@ const CandidateArea = new Lang.Class({
if (!visible)
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];
}
@ -158,22 +155,10 @@ const CandidatePopup = new Lang.Class({
panelService.connect('set-cursor-location',
Lang.bind(this, function(ps, x, y, w, h) {
this._setDummyCursorGeometry(x, y, w, h);
Main.layoutManager.setDummyCursorGeometry(x, y, w, h);
if (this._boxPointer.actor.visible)
this._boxPointer.setPosition(Main.layoutManager.dummyCursor, 0);
}));
try {
panelService.connect('set-cursor-location-relative',
Lang.bind(this, function(ps, x, y, w, h) {
if (!global.display.focus_window)
return;
let window = global.display.focus_window.get_compositor_private();
this._setDummyCursorGeometry(window.x + x, window.y + y, w, h);
}));
} catch(e) {
// Only recent IBus versions have support for this signal
// which is used for wayland clients. In order to work
// with older IBus versions we can silently ignore the
// signal's absence.
}
panelService.connect('update-preedit-text',
Lang.bind(this, function(ps, text, cursorPosition, visible) {
this._preeditText.visible = visible;
@ -258,12 +243,6 @@ const CandidatePopup = new Lang.Class({
}));
},
_setDummyCursorGeometry: function(x, y, w, h) {
Main.layoutManager.setDummyCursorGeometry(x, y, w, h);
if (this._boxPointer.actor.visible)
this._boxPointer.setPosition(Main.layoutManager.dummyCursor, 0);
},
_updateVisibility: function() {
let isVisible = (this._preeditText.visible ||
this._auxText.visible ||

View File

@ -10,30 +10,12 @@ const St = imports.gi.St;
const Lang = imports.lang;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const Main = imports.ui.main;
const ICON_SIZE = 96;
const MIN_ICON_SIZE = 16;
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({
Name: 'BaseIcon',
@ -191,55 +173,9 @@ const BaseIcon = new Lang.Class({
_onIconThemeChanged: function() {
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({
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) {
let [childMinWidth, childMinHeight, childNaturalWidth, childNaturalHeight] =
child.get_preferred_size();
/* Center the item in its allocation horizontally */
let [width, height, childXSpacing, childYSpacing] =
this._getAllocatedChildSizeAndSpacing(child);
let width = Math.min(this._getHItemSize(), childNaturalWidth);
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();
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._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);
}
Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
Lang.bind(this, this._updateIconSizes));
let scale = Math.min(this._fixedHItemSize, this._fixedVItemSize) / Math.max(this._hItemSize, this._vItemSize);
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
_updateIconSizes: function() {
let scale = Math.min(this._fixedHItemSize, this._fixedVItemSize) / Math.max(this._hItemSize, this._vItemSize);
let newIconSize = Math.floor(ICON_SIZE * scale);
_updateChildrenScale: function(scale) {
for (let i in this._items) {
let newIconSize = Math.floor(ICON_SIZE * scale);
this._items[i].icon.setIconSize(newIconSize);
}
}
@ -797,7 +550,6 @@ const PaginatedIconGrid = new Lang.Class({
_init: function(params) {
this.parent(params);
this._nPages = 0;
this.currentPage = 0;
this._rowsPerPage = 0;
this._spaceBetweenPages = 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) {
let [nColumns, usedWidth] = this._computeLayout(availWidthPerPage);
let nRows;

View File

@ -6,11 +6,9 @@ const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
const InputSourceManager = imports.ui.status.keyboard;
const BoxPointer = imports.ui.boxpointer;
const Layout = imports.ui.layout;
@ -25,9 +23,6 @@ const KEYBOARD_TYPE = 'keyboard-type';
const A11Y_APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications';
const SHOW_KEYBOARD = 'screen-keyboard-enabled';
const CARIBOU_BUS_NAME = 'org.gnome.Caribou.Daemon';
const CARIBOU_OBJECT_PATH = '/org/gnome/Caribou/Daemon';
const CaribouKeyboardIface = '<node> \
<interface name="org.gnome.Caribou.Keyboard"> \
<method name="Show"> \
@ -52,22 +47,13 @@ const CaribouKeyboardIface = '<node> \
</interface> \
</node>';
const CaribouDaemonIface = '<node> \
<interface name="org.gnome.Caribou.Daemon"> \
<method name="Run" /> \
<method name="Quit" /> \
</interface> \
</node>';
const CaribouDaemonProxy = Gio.DBusProxy.makeProxyWrapper(CaribouDaemonIface);
const Key = new Lang.Class({
Name: 'Key',
_init : function(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_keyboard = null;
@ -90,55 +76,20 @@ const Key = new Lang.Class({
}
},
_onDestroy: function() {
if (this._boxPointer) {
this._boxPointer.actor.destroy();
this._boxPointer = null;
}
},
_makeKey: function (key, label) {
_makeKey: function () {
let label = GLib.markup_escape_text(this._key.label, -1);
let button = new St.Button ({ label: label,
style_class: 'keyboard-key' });
button.key_width = this._key.width;
button.connect('button-press-event', Lang.bind(this,
function () {
key.press();
this._key.press();
return Clutter.EVENT_PROPAGATE;
}));
button.connect('button-release-event', Lang.bind(this,
function () {
key.release();
return Clutter.EVENT_PROPAGATE;
}));
button.connect('touch-event', Lang.bind(this,
function (actor, event) {
let device = event.get_device();
let sequence = event.get_event_sequence();
// We only handle touch events here on wayland. On X11
// we do get emulated pointer events, which already works
// for single-touch cases. Besides, the X11 passive touch grab
// set up by Mutter will make us see first the touch events
// and later the pointer events, so it will look like two
// unrelated series of events, we want to avoid double handling
// in these cases.
if (!Meta.is_wayland_compositor())
return Clutter.EVENT_PROPAGATE;
if (!this._touchPressed &&
event.type() == Clutter.EventType.TOUCH_BEGIN) {
device.sequence_grab(sequence, actor);
this._touchPressed = true;
key.press();
} else if (this._touchPressed &&
event.type() == Clutter.EventType.TOUCH_END &&
device.sequence_get_grabbed_actor(sequence) == actor) {
device.sequence_ungrab(sequence);
this._touchPressed = false;
key.release();
}
this._key.release();
return Clutter.EVENT_PROPAGATE;
}));
@ -161,9 +112,18 @@ const Key = new Lang.Class({
for (let i = 0; i < this._extended_keys.length; ++i) {
let extended_key = this._extended_keys[i];
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.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._boxPointer.bin.add_actor(this._extended_keyboard);
@ -201,28 +161,11 @@ const Keyboard = new Lang.Class({
this._timestamp = global.display.get_current_time_roundtrip();
this._keyboardSettings = new Gio.Settings({ schema_id: KEYBOARD_SCHEMA });
this._keyboardSettings.connect('changed', Lang.bind(this, this._sync));
this._a11yApplicationsSettings = new Gio.Settings({ schema_id: A11Y_APPLICATIONS_SCHEMA });
this._a11yApplicationsSettings.connect('changed', Lang.bind(this, this._sync));
this._daemonProxy = null;
this._lastDeviceId = null;
if (Meta.is_wayland_compositor() &&
Caribou.DisplayAdapter.set_default)
Caribou.DisplayAdapter.set_default(new ShellWaylandAdapter());
Meta.get_backend().connect('last-device-changed', Lang.bind(this,
function (backend, deviceId) {
let manager = Clutter.DeviceManager.get_default();
let device = manager.get_device(deviceId);
if (device.get_device_name().indexOf('XTEST') < 0) {
this._lastDeviceId = deviceId;
this._sync();
}
}));
this._sync();
this._keyboardSettings = new Gio.Settings({ schema: KEYBOARD_SCHEMA });
this._keyboardSettings.connect('changed', Lang.bind(this, this._settingsChanged));
this._a11yApplicationsSettings = new Gio.Settings({ schema: A11Y_APPLICATIONS_SCHEMA });
this._a11yApplicationsSettings.connect('changed', Lang.bind(this, this._settingsChanged));
this._settingsChanged();
this._showIdleId = 0;
this._subkeysBoxPointer = null;
@ -240,22 +183,8 @@ const Keyboard = new Lang.Class({
this._redraw();
},
_lastDeviceIsTouchscreen: function () {
if (!this._lastDeviceId)
return false;
let manager = Clutter.DeviceManager.get_default();
let device = manager.get_device(this._lastDeviceId);
if (!device)
return false;
return device.get_device_type() == Clutter.InputDeviceType.TOUCHSCREEN_DEVICE;
},
_sync: function () {
this._enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD) ||
this._lastDeviceIsTouchscreen();
_settingsChanged: function (settings, key) {
this._enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD);
if (!this._enableKeyboard && !this._keyboard)
return;
if (this._enableKeyboard && this._keyboard &&
@ -285,35 +214,9 @@ const Keyboard = new Lang.Class({
this.actor = null;
this._destroySource();
if (this._daemonProxy) {
this._daemonProxy.QuitRemote(function (result, error) {
if (error) {
log(error.message);
return;
}
});
this._daemonProxy = null;
}
},
_setupKeyboard: function() {
if (!this._daemonProxy) {
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._daemonProxy.RunRemote(function (result, error) {
if (error) {
log(error.message);
return;
}
});
this.actor = new St.BoxLayout({ name: 'keyboard', vertical: true, reactive: true });
Main.layoutManager.keyboardBox.add_actor(this.actor);
Main.layoutManager.trackChrome(this.actor);
@ -652,7 +555,7 @@ const Keyboard = new Lang.Class({
_moveTemporarily: function () {
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 newY = 3 * this.actor.height / 2;
@ -753,53 +656,3 @@ const KeyboardSource = new Lang.Class({
this._keyboard.show(Main.layoutManager.bottomIndex);
}
});
const ShellWaylandAdapter = new Lang.Class({
Name: 'ShellWaylandAdapter',
Extends: Caribou.XAdapter,
_init: function () {
this.parent();
let deviceManager = Clutter.DeviceManager.get_default();
this._virtualDevice = deviceManager.create_virtual_device(Clutter.InputDeviceType.KEYBOARD_DEVICE);
this._inputSourceManager = InputSourceManager.getInputSourceManager();
this._sourceChangedId = this._inputSourceManager.connect('current-source-changed',
Lang.bind(this, this._onSourceChanged));
this._sourcesModifiedId = this._inputSourceManager.connect ('sources-changed',
Lang.bind(this, this._onSourcesModified));
},
_onSourcesModified: function () {
this.emit('config-changed');
},
_onSourceChanged: function (inputSourceManager, oldSource) {
let source = inputSourceManager.currentSource;
this.emit('group-changed', source.index, source.id, '');
},
vfunc_get_groups: function () {
let inputSources = this._inputSourceManager.inputSources;
let groups = []
let variants = [];
for (let i in inputSources) {
let is = inputSources[i];
groups[is.index] = is.id;
variants[is.index] = '';
}
return [groups, groups.length, variants, variants.length];
},
vfunc_keyval_press: function(keyval) {
this._virtualDevice.notify_keyval(Clutter.get_current_event_time(),
keyval, Clutter.KeyState.PRESSED);
},
vfunc_keyval_release: function(keyval) {
this._virtualDevice.notify_keyval(Clutter.get_current_event_time(),
keyval, Clutter.KeyState.RELEASED);
},
});

View File

@ -11,7 +11,6 @@ const St = imports.gi.St;
const Background = imports.ui.background;
const BackgroundMenu = imports.ui.backgroundMenu;
const LoginManager = imports.misc.loginManager;
const DND = imports.ui.dnd;
const Main = imports.ui.main;
@ -21,6 +20,7 @@ const Tweener = imports.ui.tweener;
const STARTUP_ANIMATION_TIME = 0.5;
const KEYBOARD_ANIMATION_TIME = 0.15;
const BACKGROUND_FADE_ANIMATION_TIME = 1.0;
const DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff);
const HOT_CORNER_PRESSURE_THRESHOLD = 100; // pixels
const HOT_CORNER_PRESSURE_TIMEOUT = 1000; // ms
@ -46,16 +46,11 @@ const MonitorConstraint = new Lang.Class({
'index': GObject.ParamSpec.int('index',
'Monitor index', 'Track specific monitor',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
-1, 64, -1),
'work-area': GObject.ParamSpec.boolean('work-area',
'Work-area', 'Track monitor\'s work-area',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
false)},
-1, 64, -1)},
_init: function(props) {
this._primary = false;
this._index = -1;
this._workArea = false;
this.parent(props);
},
@ -85,19 +80,6 @@ const MonitorConstraint = new Lang.Class({
this.notify('index');
},
get work_area() {
return this._workArea;
},
set work_area(v) {
if (v == this._workArea)
return;
this._workArea = v;
if (this.actor)
this.actor.queue_relayout();
this.notify('work-area');
},
vfunc_set_actor: function(actor) {
if (actor) {
if (!this._monitorsChangedId) {
@ -105,21 +87,10 @@ const MonitorConstraint = new Lang.Class({
this.actor.queue_relayout();
}));
}
if (!this._workareasChangedId) {
this._workareasChangedId = global.screen.connect('workareas-changed', Lang.bind(this, function() {
if (this._workArea)
this.actor.queue_relayout();
}));
}
} else {
if (this._monitorsChangedId)
Main.layoutManager.disconnect(this._monitorsChangedId);
this._monitorsChangedId = 0;
if (this._workareasChangedId)
global.screen.disconnect(this._workareasChangedId);
this._workareasChangedId = 0;
}
this.parent(actor);
@ -129,21 +100,15 @@ const MonitorConstraint = new Lang.Class({
if (!this._primary && this._index < 0)
return;
let index;
if (this._primary)
index = Main.layoutManager.primaryIndex;
else
index = Math.min(this._index, Main.layoutManager.monitors.length - 1);
let rect;
if (this._workArea) {
let ws = global.screen.get_workspace_by_index(0);
rect = ws.get_work_area_for_monitor(index);
let monitor;
if (this._primary) {
monitor = Main.layoutManager.primaryMonitor;
} else {
rect = Main.layoutManager.monitors[index];
let index = Math.min(this._index, Main.layoutManager.monitors.length - 1);
monitor = Main.layoutManager.monitors[index];
}
actorBox.init_rect(rect.x, rect.y, rect.width, rect.height);
actorBox.init_rect(monitor.x, monitor.y, monitor.width, monitor.height);
}
});
@ -166,7 +131,6 @@ const Monitor = new Lang.Class({
const defaultParams = {
trackFullscreen: false,
affectsStruts: false,
affectsInputRegion: true
};
const LayoutManager = new Lang.Class({
@ -190,10 +154,10 @@ const LayoutManager = new Lang.Class({
this._isPopupWindowVisible = false;
this._startingUp = true;
// We don't want to paint the stage background color because either
// the SystemBackground we create or the MetaBackgroundActor inside
// global.window_group covers the entirety of the screen.
global.stage.no_clear_hint = true;
// Normally, the stage is always covered so Clutter doesn't need to clear
// it; however it becomes visible during the startup animation
// See the comment below for a longer explanation
global.stage.color = DEFAULT_BACKGROUND_COLOR;
// Set up stage hierarchy to group all UI actors under one container.
this.uiGroup = new Shell.GenericContainer({ name: 'uiGroup' });
@ -220,8 +184,7 @@ const LayoutManager = new Lang.Class({
global.stage.add_child(this.uiGroup);
this.overviewGroup = new St.Widget({ name: 'overviewGroup',
visible: false,
reactive: true });
visible: false });
this.addChrome(this.overviewGroup);
this.screenShieldGroup = new St.Widget({ name: 'screenShieldGroup',
@ -238,6 +201,10 @@ const LayoutManager = new Lang.Class({
this.panelBox.connect('allocation-changed',
Lang.bind(this, this._panelBoxChanged));
this.trayBox = new St.Widget({ name: 'trayBox',
layout_manager: new Clutter.BinLayout() });
this.addChrome(this.trayBox);
this.modalDialogGroup = new St.Widget({ name: 'modalDialogGroup',
layout_manager: new Clutter.BinLayout() });
this.uiGroup.add_actor(this.modalDialogGroup);
@ -250,16 +217,12 @@ const LayoutManager = new Lang.Class({
// A dummy actor that tracks the mouse or text cursor, based on the
// 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);
global.stage.remove_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();
global.window_group.add_child(this._backgroundGroup);
this._backgroundGroup.lower_bottom();
@ -275,18 +238,6 @@ const LayoutManager = new Lang.Class({
global.screen.connect('in-fullscreen-changed',
Lang.bind(this, this._updateFullscreen));
this._monitorsChanged();
// NVIDIA drivers don't preserve FBO contents across
// suspend/resume, see
// https://bugzilla.gnome.org/show_bug.cgi?id=739178
if (Shell.util_need_background_refresh()) {
LoginManager.getLoginManager().connect('prepare-for-sleep',
function(lm, suspending) {
if (suspending)
return;
Meta.Background.refresh_all();
});
}
},
// This is called by Main after everything else is constructed
@ -301,6 +252,7 @@ const LayoutManager = new Lang.Class({
this._inOverview = true;
this._updateVisibility();
this._updateRegions();
},
hideOverview: function() {
@ -308,6 +260,7 @@ const LayoutManager = new Lang.Class({
this._inOverview = false;
this._updateVisibility();
this._queueUpdateRegions();
},
_sessionUpdated: function() {
@ -401,7 +354,7 @@ const LayoutManager = new Lang.Class({
},
_addBackgroundMenu: function(bgManager) {
BackgroundMenu.addBackgroundMenu(bgManager.backgroundActor, this);
BackgroundMenu.addBackgroundMenu(bgManager.background.actor, this);
},
_createBackgroundManager: function(monitorIndex) {
@ -418,10 +371,10 @@ const LayoutManager = new Lang.Class({
_showSecondaryBackgrounds: function() {
for (let i = 0; i < this.monitors.length; i++) {
if (i != this.primaryIndex) {
let backgroundActor = this._bgManagers[i].backgroundActor;
backgroundActor.show();
backgroundActor.opacity = 0;
Tweener.addTween(backgroundActor,
let background = this._bgManagers[i].background;
background.actor.show();
background.actor.opacity = 0;
Tweener.addTween(background.actor,
{ opacity: 255,
time: BACKGROUND_FADE_ANIMATION_TIME,
transition: 'easeOutQuad' });
@ -444,16 +397,10 @@ const LayoutManager = new Lang.Class({
this._bgManagers.push(bgManager);
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() {
this.screenShieldGroup.set_position(0, 0);
this.screenShieldGroup.set_size(global.screen_width, global.screen_height);
@ -461,7 +408,12 @@ const LayoutManager = new Lang.Class({
this.panelBox.set_position(this.primaryMonitor.x, this.primaryMonitor.y);
this.panelBox.set_size(this.primaryMonitor.width, -1);
this.keyboardIndex = this.primaryIndex;
if (this.keyboardIndex < 0)
this.keyboardIndex = this.primaryIndex;
this.trayBox.set_position(this.bottomMonitor.x,
this.bottomMonitor.y + this.bottomMonitor.height);
this.trayBox.set_size(this.bottomMonitor.width, -1);
},
_panelBoxChanged: function() {
@ -541,7 +493,9 @@ const LayoutManager = new Lang.Class({
set 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() {
@ -581,6 +535,10 @@ const LayoutManager = new Lang.Class({
//
// When starting a normal user session, we want to grow it out of the middle
// 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() {
// During the initial transition, add a simple actor to block all events,
@ -591,12 +549,7 @@ const LayoutManager = new Lang.Class({
reactive: true });
this.addChrome(this._coverPane);
if (Meta.is_restart()) {
// On restart, we don't do an animation. Force an update of the
// regions immediately so that maximized windows restore to the
// right size taking struts into account.
this._updateRegions();
} else if (Main.sessionMode.isGreeter) {
if (Main.sessionMode.isGreeter) {
this.panelBox.translation_y = -this.panelBox.height;
} else {
this._updateBackgrounds();
@ -605,6 +558,7 @@ const LayoutManager = new Lang.Class({
// the UI group to get the correct allocation for the struts.
this._updateRegions();
this.trayBox.hide();
this.keyboardBox.hide();
let monitor = this.primaryMonitor;
@ -634,9 +588,7 @@ const LayoutManager = new Lang.Class({
},
_startupAnimation: function() {
if (Meta.is_restart())
this._startupAnimationComplete();
else if (Main.sessionMode.isGreeter)
if (Main.sessionMode.isGreeter)
this._startupAnimationGreeter();
else
this._startupAnimationSession();
@ -663,6 +615,10 @@ const LayoutManager = new Lang.Class({
},
_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 = null;
@ -671,6 +627,7 @@ const LayoutManager = new Lang.Class({
this._startingUp = false;
this.trayBox.show();
this.keyboardBox.show();
if (!Main.sessionMode.isGreeter) {
@ -743,11 +700,10 @@ const LayoutManager = new Lang.Class({
// @actor: an actor to add to the chrome
// @params: (optional) additional params
//
// Adds @actor to the chrome, and (unless %affectsInputRegion in
// @params is %false) extends the input region to include it.
// Changes in @actor's size, position, and visibility will
// automatically result in appropriate changes to the input
// region.
// Adds @actor to the chrome, and extends the input region
// to include it. Changes in @actor's size, position, and
// visibility will automatically result in appropriate changes
// to the input region.
//
// If %affectsStruts in @params is %true (and @actor is along a
// screen edge), then @actor's size and position will also affect
@ -841,7 +797,6 @@ const LayoutManager = new Lang.Class({
// need to connect to 'destroy' too.
this._trackedActors.push(actorData);
this._updateActorVisibility(actorData);
this._queueUpdateRegions();
},
@ -860,23 +815,25 @@ const LayoutManager = new Lang.Class({
this._queueUpdateRegions();
},
_updateActorVisibility: function(actorData) {
if (!actorData.trackFullscreen)
return;
let monitor = this.findMonitorForActor(actorData.actor);
actorData.actor.visible = !(global.window_group.visible &&
monitor &&
monitor.inFullscreen);
},
_updateVisibility: function() {
let windowsVisible = Main.sessionMode.hasWindows && !this._inOverview;
global.window_group.visible = windowsVisible;
global.top_window_group.visible = windowsVisible;
this._trackedActors.forEach(Lang.bind(this, this._updateActorVisibility));
for (let i = 0; i < this._trackedActors.length; i++) {
let actorData = this._trackedActors[i], visible;
if (!actorData.trackFullscreen)
continue;
if (!windowsVisible)
visible = true;
else if (this.findMonitorForActor(actorData.actor).inFullscreen)
visible = false;
else
visible = true;
actorData.actor.visible = visible;
}
},
getWorkAreaForMonitor: function(monitorIndex) {
@ -900,6 +857,9 @@ const LayoutManager = new Lang.Class({
},
_queueUpdateRegions: function() {
if (Main.sessionMode.isGreeter)
return;
if (this._startingUp)
return;
@ -933,27 +893,19 @@ const LayoutManager = new Lang.Class({
},
_updateRegions: function() {
let rects = [], struts = [], i;
if (this._updateRegionIdle) {
Meta.later_remove(this._updateRegionIdle);
delete this._updateRegionIdle;
}
// No need to update when we have a modal.
if (Main.modalCount > 0)
return GLib.SOURCE_REMOVE;
// Bug workaround - get_transformed_position()/get_transformed_size() don't work after
// a change in stage size until the first pick or paint.
// https://bugzilla.gnome.org/show_bug.cgi?id=761565
global.stage.get_actor_at_pos(Clutter.PickMode.ALL, 0, 0);
let rects = [], struts = [], i;
let isPopupMenuVisible = global.top_window_group.get_children().some(isPopupMetaWindow);
let wantsInputRegion = !isPopupMenuVisible;
for (i = 0; i < this._trackedActors.length; i++) {
let actorData = this._trackedActors[i];
if (!(actorData.affectsInputRegion && wantsInputRegion) && !actorData.affectsStruts)
if (!wantsInputRegion && !actorData.affectsStruts)
continue;
let [x, y] = actorData.actor.get_transformed_position();
@ -963,7 +915,7 @@ const LayoutManager = new Lang.Class({
w = Math.round(w);
h = Math.round(h);
if (actorData.affectsInputRegion && wantsInputRegion && actorData.actor.get_paint_visibility())
if (wantsInputRegion && actorData.actor.get_paint_visibility())
rects.push(new Meta.Rectangle({ x: x, y: y, width: w, height: h }));
if (actorData.affectsStruts) {
@ -973,43 +925,87 @@ const LayoutManager = new Lang.Class({
let y1 = Math.max(y, 0);
let y2 = Math.min(y + h, global.screen_height);
// Metacity wants to know what side of the monitor the
// strut is considered to be attached to. First, we find
// the monitor that contains the strut. If the actor is
// NetWM struts are not really powerful enought to handle
// a multi-monitor scenario, they only describe what happens
// around the outer sides of the full display region. However
// it can describe a partial region along each side, so
// we can support having the struts only affect the
// primary monitor. This should be enough as we only have
// chrome affecting the struts on the primary monitor so
// far.
//
// Metacity wants to know what side of the screen the
// strut is considered to be attached to. If the actor is
// only touching one edge, or is touching the entire
// border of that monitor, then it's obvious which side
// to call it. If it's in a corner, we pick a side
// arbitrarily. If it doesn't touch any edges, or it
// spans the width/height across the middle of the
// screen, then we don't create a strut for it at all.
let monitor = this.findMonitorForActor(actorData.actor);
// border of the primary monitor, then it's obvious which
// side to call it. If it's in a corner, we pick a side
// arbitrarily. If it doesn't touch any edges, or it spans
// the width/height across the middle of the screen, then
// we don't create a strut for it at all.
let side;
if (x1 <= monitor.x && x2 >= monitor.x + monitor.width) {
if (y1 <= monitor.y)
let primary = this.primaryMonitor;
if (x1 <= primary.x && x2 >= primary.x + primary.width) {
if (y1 <= primary.y)
side = Meta.Side.TOP;
else if (y2 >= monitor.y + monitor.height)
else if (y2 >= primary.y + primary.height)
side = Meta.Side.BOTTOM;
else
continue;
} else if (y1 <= monitor.y && y2 >= monitor.y + monitor.height) {
if (x1 <= monitor.x)
} else if (y1 <= primary.y && y2 >= primary.y + primary.height) {
if (x1 <= 0)
side = Meta.Side.LEFT;
else if (x2 >= monitor.x + monitor.width)
else if (x2 >= primary.x + primary.width)
side = Meta.Side.RIGHT;
else
continue;
} else if (x1 <= monitor.x)
} else if (x1 <= 0)
side = Meta.Side.LEFT;
else if (y1 <= monitor.y)
else if (y1 <= 0)
side = Meta.Side.TOP;
else if (x2 >= monitor.x + monitor.width)
else if (x2 >= global.screen_width)
side = Meta.Side.RIGHT;
else if (y2 >= monitor.y + monitor.height)
else if (y2 >= global.screen_height)
side = Meta.Side.BOTTOM;
else
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 strut = new Meta.Strut({ rect: strutRect, side: side });
struts.push(strut);
@ -1026,13 +1022,7 @@ const LayoutManager = new Lang.Class({
}
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);
@ -1058,10 +1048,10 @@ const HotCorner = new Lang.Class({
this._setupFallbackCornerIfNeeded(layoutManager);
this._pressureBarrier = new PressureBarrier(HOT_CORNER_PRESSURE_THRESHOLD,
HOT_CORNER_PRESSURE_TIMEOUT,
Shell.ActionMode.NORMAL |
Shell.ActionMode.OVERVIEW);
this._pressureBarrier = new TriggerablePressureBarrier(HOT_CORNER_PRESSURE_THRESHOLD,
HOT_CORNER_PRESSURE_TIMEOUT,
Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW);
this._pressureBarrier.connect('trigger', Lang.bind(this, this._toggleOverview));
// Cache the three ripples instead of dynamically creating and destroying them.
@ -1238,15 +1228,13 @@ const HotCorner = new Lang.Class({
const PressureBarrier = new Lang.Class({
Name: 'PressureBarrier',
_init: function(threshold, timeout, actionMode) {
this._threshold = threshold;
this._timeout = timeout;
this._actionMode = actionMode;
_init: function(threshold, timeout, keybindingMode) {
this.threshold = threshold;
this.timeout = timeout;
this._keybindingMode = keybindingMode;
this._barriers = [];
this._eventFilter = null;
this._isTriggered = false;
this._reset();
this.reset();
},
addBarrier: function(barrier) {
@ -1275,10 +1263,10 @@ const PressureBarrier = new Lang.Class({
this._eventFilter = filter;
},
_reset: function() {
reset: function() {
this._barrierEvents = [];
this._currentPressure = 0;
this._lastTime = 0;
this.currentPressure = 0;
},
_isHorizontal: function(barrier) {
@ -1299,12 +1287,21 @@ const PressureBarrier = new Lang.Class({
return Math.abs(event.dy);
},
get currentPressure() {
return this._currentPressure;
},
set currentPressure(value) {
this._currentPressure = value;
this.emit('pressure-changed');
},
_trimBarrierEvents: function() {
// Events are guaranteed to be sorted in time order from
// oldest to newest, so just look for the first old event,
// and then chop events after that off.
let i = 0;
let threshold = this._lastTime - this._timeout;
let threshold = this._lastTime - this.timeout;
while (i < this._barrierEvents.length) {
let [time, distance] = this._barrierEvents[i];
@ -1317,54 +1314,38 @@ const PressureBarrier = new Lang.Class({
for (i = 0; i < firstNewEvent; i++) {
let [time, distance] = this._barrierEvents[i];
this._currentPressure -= distance;
this.currentPressure = distance;
}
this._barrierEvents = this._barrierEvents.slice(firstNewEvent);
},
_onBarrierLeft: function(barrier, event) {
barrier._isHit = false;
if (this._barriers.every(function(b) { return !b._isHit; })) {
this._reset();
this._isTriggered = false;
}
this.reset();
},
_trigger: function() {
this._isTriggered = true;
this.emit('trigger');
this._reset();
},
_onBarrierHit: function(barrier, event) {
barrier._isHit = true;
// If we've triggered the barrier, wait until the pointer has the
// left the barrier hitbox until we trigger it again.
if (this._isTriggered)
return;
_shouldUseEvent: function(barrier, event) {
if (this._eventFilter && this._eventFilter(event))
return;
return false;
// Throw out all events not in the proper keybinding mode
if (!(this._actionMode & Main.actionMode))
return;
if (!(this._keybindingMode & Main.keybindingMode))
return false;
let slide = this._getDistanceAlongBarrier(barrier, event);
let distance = this._getDistanceAcrossBarrier(barrier, event);
if (distance >= this._threshold) {
this._trigger();
return;
}
// Throw out events where the cursor is move more
// along the axis of the barrier than moving with
// the barrier.
if (slide > distance)
return;
return false;
return true;
},
_appendEvent: function(barrier, event) {
let distance = this._getDistanceAcrossBarrier(barrier, event);
this._lastTime = event.time;
@ -1372,10 +1353,55 @@ const PressureBarrier = new Lang.Class({
distance = Math.min(15, distance);
this._barrierEvents.push([event.time, distance]);
this._currentPressure += distance;
this.currentPressure += distance;
},
if (this._currentPressure >= this._threshold)
this._trigger();
_onBarrierHit: function(barrier, event) {
if (!this._shouldUseEvent(barrier, event))
return;
this._appendEvent(barrier, event);
}
});
Signals.addSignalMethods(PressureBarrier.prototype);
const TriggerablePressureBarrier = new Lang.Class({
Name: 'TriggerablePressureBarrier',
Extends: PressureBarrier,
_init: function(threshold, timeout, keybindingMode) {
this.parent(threshold, timeout, keybindingMode);
this._isTriggered = false;
},
_trigger: function() {
this._isTriggered = true;
this.emit('trigger');
this.reset();
},
_onBarrierLeft: function() {
this.parent();
this._isTriggered = false;
},
_onBarrierHit: function(barrier, event) {
// If we've triggered the barrier, wait until the pointer has the
// left the barrier hitbox until we trigger it again.
if (this._isTriggered)
return;
if (!this._shouldUseEvent(barrier, event))
return;
if (distance >= this.threshold) {
this._trigger();
return;
}
this._appendEvent(barrier, event);
if (this.currentPressure >= this.threshold)
this._trigger();
},
});

View File

@ -1,272 +0,0 @@
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const CtrlAltTab = imports.ui.ctrlAltTab;
const Lang = imports.lang;
const Layout = imports.ui.layout;
const Main = imports.ui.main;
const Overview = imports.ui.overview;
const OverviewControls = imports.ui.overviewControls;
const Tweener = imports.ui.tweener;
const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
'bluetooth-applet': 'bluetooth',
'gnome-volume-control-applet': 'volume', // renamed to gnome-sound-applet
// when moved to control center
'gnome-sound-applet': 'volume',
'nm-applet': 'network',
'gnome-power-manager': 'battery',
'keyboard': 'keyboard',
'a11y-keyboard': 'a11y',
'kbd-scrolllock': 'keyboard',
'kbd-numlock': 'keyboard',
'kbd-capslock': 'keyboard',
'ibus-ui-gtk': 'keyboard'
};
// Offset of the original position from the bottom-right corner
const CONCEALED_WIDTH = 3;
const REVEAL_ANIMATION_TIME = 0.2;
const TEMP_REVEAL_TIME = 2;
const BARRIER_THRESHOLD = 70;
const BARRIER_TIMEOUT = 1000;
const LegacyTray = new Lang.Class({
Name: 'LegacyTray',
_init: function() {
this.actor = new St.Widget({ clip_to_allocation: true,
layout_manager: new Clutter.BinLayout() });
let constraint = new Layout.MonitorConstraint({ primary: true,
work_area: true });
this.actor.add_constraint(constraint);
this._slideLayout = new OverviewControls.SlideLayout();
this._slideLayout.translationX = 0;
this._slideLayout.slideDirection = OverviewControls.SlideDirection.LEFT;
this._slider = new St.Widget({ x_expand: true, y_expand: true,
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.END,
layout_manager: this._slideLayout });
this.actor.add_actor(this._slider);
this._slider.connect('notify::allocation', Lang.bind(this, this._syncBarrier));
this._box = new St.BoxLayout({ style_class: 'legacy-tray' });
this._slider.add_actor(this._box);
this._concealHandle = new St.Button({ style_class: 'legacy-tray-handle',
/* translators: 'Hide' is a verb */
accessible_name: _("Hide tray"),
can_focus: true });
this._concealHandle.child = new St.Icon({ icon_name: 'go-previous-symbolic' });
this._box.add_child(this._concealHandle);
this._iconBox = new St.BoxLayout({ style_class: 'legacy-tray-icon-box' });
this._box.add_actor(this._iconBox);
this._revealHandle = new St.Button({ style_class: 'legacy-tray-handle' });
this._revealHandle.child = new St.Icon({ icon_name: 'go-next-symbolic' });
this._box.add_child(this._revealHandle);
this._revealHandle.bind_property('visible',
this._concealHandle, 'visible',
GObject.BindingFlags.BIDIRECTIONAL |
GObject.BindingFlags.INVERT_BOOLEAN);
this._revealHandle.connect('notify::visible',
Lang.bind(this, this._sync));
this._revealHandle.connect('notify::hover',
Lang.bind(this ,this._sync));
this._revealHandle.connect('clicked', Lang.bind(this,
function() {
this._concealHandle.show();
}));
this._concealHandle.connect('clicked', Lang.bind(this,
function() {
this._revealHandle.show();
}));
this._horizontalBarrier = null;
this._pressureBarrier = new Layout.PressureBarrier(BARRIER_THRESHOLD,
BARRIER_TIMEOUT,
Shell.ActionMode.NORMAL);
this._pressureBarrier.connect('trigger', Lang.bind(this, function() {
this._concealHandle.show();
}));
Main.layoutManager.addChrome(this.actor, { affectsInputRegion: false });
Main.layoutManager.trackChrome(this._slider, { affectsInputRegion: true });
Main.uiGroup.set_child_below_sibling(this.actor, Main.layoutManager.modalDialogGroup);
Main.ctrlAltTabManager.addGroup(this.actor,
_("Status Icons"), 'focus-legacy-systray-symbolic',
{ sortGroup: CtrlAltTab.SortGroup.BOTTOM });
this._trayManager = new Shell.TrayManager();
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._trayManager.manage_screen(global.screen, this.actor);
Main.overview.connect('showing', Lang.bind(this,
function() {
Tweener.removeTweens(this._slider);
Tweener.addTween(this._slider, { opacity: 0,
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad' });
}));
Main.overview.connect('shown', Lang.bind(this, this._sync));
Main.overview.connect('hiding', Lang.bind(this,
function() {
this._sync();
Tweener.removeTweens(this._slider);
Tweener.addTween(this._slider, { opacity: 255,
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad' });
}));
Main.layoutManager.connect('monitors-changed',
Lang.bind(this, this._sync));
global.screen.connect('in-fullscreen-changed',
Lang.bind(this, this._sync));
Main.sessionMode.connect('updated', Lang.bind(this, this._sync));
this._sync();
},
_onTrayIconAdded: function(tm, icon) {
let wmClass = icon.wm_class ? icon.wm_class.toLowerCase() : '';
if (STANDARD_TRAY_ICON_IMPLEMENTATIONS[wmClass] !== undefined)
return;
let button = new St.Button({ child: icon,
style_class: 'legacy-tray-icon',
button_mask: St.ButtonMask.ONE |
St.ButtonMask.TWO |
St.ButtonMask.THREE,
can_focus: true,
x_fill: true, y_fill: true });
let app = Shell.WindowTracker.get_default().get_app_from_pid(icon.pid);
if (!app)
app = Shell.AppSystem.get_default().lookup_startup_wmclass(wmClass);
if (!app)
app = Shell.AppSystem.get_default().lookup_desktop_wmclass(wmClass);
if (app)
button.accessible_name = app.get_name();
else
button.accessible_name = icon.title;
button.connect('clicked',
function() {
icon.click(Clutter.get_current_event());
});
button.connect('key-press-event',
function() {
icon.click(Clutter.get_current_event());
return Clutter.EVENT_PROPAGATE;
});
button.connect('key-focus-in', Lang.bind(this,
function() {
this._concealHandle.show();
}));
this._iconBox.add_actor(button);
if (!this._concealHandle.visible) {
this._concealHandle.show();
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, TEMP_REVEAL_TIME,
Lang.bind(this, function() {
this._concealHandle.hide();
return GLib.SOURCE_REMOVE;
}));
}
},
_onTrayIconRemoved: function(tm, icon) {
if (!this.actor.contains(icon))
return;
icon.get_parent().destroy();
this._sync();
},
_syncBarrier: function() {
let rtl = (this._slider.get_text_direction() == Clutter.TextDirection.RTL);
let [x, y] = this._slider.get_transformed_position();
let [w, h] = this._slider.get_transformed_size();
let x1 = Math.round(x);
if (rtl)
x1 += Math.round(w);
let x2 = x1;
let y1 = Math.round(y);
let y2 = y1 + Math.round(h);
if (this._horizontalBarrier &&
this._horizontalBarrier.x1 == x1 &&
this._horizontalBarrier.y1 == y1 &&
this._horizontalBarrier.x2 == x2 &&
this._horizontalBarrier.y2 == y2)
return;
this._unsetBarrier();
let directions = (rtl ? Meta.BarrierDirection.NEGATIVE_X : Meta.BarrierDirection.POSITIVE_X);
this._horizontalBarrier = new Meta.Barrier({ display: global.display,
x1: x1, x2: x2,
y1: y1, y2: y2,
directions: directions });
this._pressureBarrier.addBarrier(this._horizontalBarrier);
},
_unsetBarrier: function() {
if (this._horizontalBarrier == null)
return;
this._pressureBarrier.removeBarrier(this._horizontalBarrier);
this._horizontalBarrier.destroy();
this._horizontalBarrier = null;
},
_sync: function() {
// FIXME: we no longer treat tray icons as notifications
let allowed = Main.sessionMode.hasNotifications;
let hasIcons = this._iconBox.get_n_children() > 0;
let inOverview = Main.overview.visible && !Main.overview.animationInProgress;
let inFullscreen = Main.layoutManager.primaryMonitor.inFullscreen;
this.actor.visible = allowed && hasIcons && !inOverview && !inFullscreen;
if (!hasIcons)
this._concealHandle.hide();
let targetSlide;
if (this._concealHandle.visible) {
targetSlide = 1.0;
} else if (!hasIcons) {
targetSlide = 0.0;
} else {
let [, boxWidth] = this._box.get_preferred_width(-1);
let [, handleWidth] = this._revealHandle.get_preferred_width(-1);
if (this._revealHandle.hover)
targetSlide = handleWidth / boxWidth;
else
targetSlide = CONCEALED_WIDTH / boxWidth;
}
if (this.actor.visible) {
Tweener.addTween(this._slideLayout,
{ slideX: targetSlide,
time: REVEAL_ANIMATION_TIME,
transition: 'easeOutQuad' });
} else {
this._slideLayout.slideX = targetSlide;
this._unsetBarrier();
}
}
});

View File

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

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