Compare commits

..

8 Commits

Author SHA1 Message Date
Giovanni Campagna
6e448a2711 ScreenShield: fix spacing of notifications and sources
Reduce padding around persistent sources, and ensure that spacing
around resident notifications is only applied once.
Also, add some padding to the clock.

https://bugzilla.gnome.org/show_bug.cgi?id=681143
2012-08-06 21:43:54 +02:00
Giovanni Campagna
1d484e2278 ScreenSheild: make notification view scrollable
Place a maximum height on the notification view, and show scrollbars
if the list of persistent sources would overflow.

https://bugzilla.gnome.org/show_bug.cgi?id=681143
2012-08-06 21:43:54 +02:00
Giovanni Campagna
0b7ca098ad ScreenShield: update the displayed title when the source changes
Notifications in the lock screen need to watch signals on source
and react accordingly.

https://bugzilla.gnome.org/show_bug.cgi?id=681143
2012-08-06 21:43:54 +02:00
Jasper St. Pierre
5cb9aa9cf3 messageTray: Hook SourceActor up to source icon changes automatically
Instead of manually tracking source icon changes, or requiring a manual
call to _setSummaryIcon, add a way to emit a signal when we're guaranteed
the icon has been changed, and then the source actor will automatically
update the icon.
_setSummaryIcon is still available for sources such as the notification
daemon, that require special treatment for the summary icon (to be used
with tray icons)

https://bugzilla.gnome.org/show_bug.cgi?id=680426
2012-08-06 21:43:54 +02:00
Giovanni Campagna
0171e561f2 ScreenShield: bump the lock screen slightly when pressing a key
When pressing a key different from escape (one thus that has no
effect), bump the screen up, to indicate that it eats keyboard
input and it must be lifted up.

https://bugzilla.gnome.org/show_bug.cgi?id=681143
2012-08-06 21:43:54 +02:00
Giovanni Campagna
82f7431a28 ScreenShield: handle Escape on the stage, not on the lock screen
This allows to press esc to unlock even if the focus is not on
the lock screen (for example after dismissing the auth failure
notification).

https://bugzilla.gnome.org/show_bug.cgi?id=681143
2012-08-06 21:43:54 +02:00
Giovanni Campagna
29958df7e7 ScreenShield: when explicitly locking, tween the shield from the top
The curtain should appear to be an overlay on top of the system,
and since it is lifted by dragging up, it makes sense to slide it
down on lock.

https://bugzilla.gnome.org/show_bug.cgi?id=681143
2012-08-06 21:43:54 +02:00
Giovanni Campagna
2f990346df ScreenShield: blur and desaturate the screenshield background
The background is the same as the normal desktop, so we blur and
desaturate it to clearly show that it's not the normal system state.

Includes a noticeable slowdown due to GLSL shading and FBO redirection.

https://bugzilla.gnome.org/show_bug.cgi?id=681143
2012-08-06 21:43:54 +02:00
123 changed files with 12408 additions and 12362 deletions

140
NEWS
View File

@@ -1,143 +1,3 @@
3.5.91
======
* Improve modal dialog styling of network secret prompts [Jasper; #682412]
* Fix visibility of non-active workspaces during overview transition
[Florian; #682002]
* Improve scrollbar theming [Cosimo; #682476]
* Make sure the app menu remains hidden in locked state [Florian; #682475]
* Add tooltip to show-applications icon [Jasper; #682445]
* Do not add duplicate remote search providers [Florian; #682470]
* Handle 'popup-menu' signal on summary items [Florian; #682486]
* Fix dwelling during mouse-down [Owen; #682385]
* Set label actor for endSessionDialog.ListItem [Alejandro; #677503]
* Don't match on comments when searching applications [Florian; #682529]
* Make workspace selector more similar to the mockup [Stefano; #662087]
* Fix extension installation and reloading [Jasper; #682578]
* Hide removable devices in the lock screen [Giovanni; #681143]
* Reset cancellable after hitting Escape on login screen [Alban; #681537]
* Fix suspend from the user menu [Giovanni; #682746]
* Set label actor for summary items in message tray [Alejandro; #677229]
* Set label for the "Show applications" dash button [Alejandro; #682366]
* Load extensions as late as possible [Jasper; #682822]
* Improve mount operation dialogs [Jon; #682645]
* Remove "Connect to ..." item from places search [Florian; #682817]
* Don't auto-expand notifications with actions [Giovanni; #682738]
* Add a new lock screen menu to combine volume network and power
[Giovanni; #682540]
* Add support for pre-edit to StIMText [Daiki; #664041]
* Remove StIconType [Jasper, Florian, Rui, Giovanni, Debarshi; #682540]
* Use monitor geometry for dwelling [Florian; #683044]
* Add support for surrounding-text to StIMText [Daiki; #683015]
* Improve the placement and style of the "No results" text [Jasper; #683135]
* Remove broken network device activation policy [Giovanni; #683136]
* Hide power status icon when no battery is present [Tim; #683080]
* Ensure summary items are square and have spacing [Debarshi; #682248]
* Fix close buttons overlapping screen edge [Debarshi; #682343]
* Escape the tray when a legacy icon is clicked [Giovanni; #682244]
* Update arrow in the screen shield to match latest mockups [Giovanni; #682285]
* Allow lifting the screen shield with the mouse wheel [Giovanni; #683164]
* Make sure to show the app menu after unlocking the screen [Jasper; #683154]
* Misc bug fixes and cleanups [Debarshi, Florian, Giovanni, Jasper, Rui;
#582650, #667439, #682238, #682268, #682429, #682455, #682544, #682546,
#682683, #682710, #682998, #683073, #683137, #683156]
Contributors:
Alban Browaeys, Giovanni Campagna, Cosimo Cecchi, Stefano Facchini,
Adel Gadllah, Tim Lunn, Rui Matos, William Jon McCann, Florian Müllner,
Alejandro Piñeiro, Debarshi Ray, Jasper St. Pierre, Owen Taylor, Daiki Ueno
Translations:
Piotr Drąg [pl], Takayuki KUSANO [ja], Kjartan Maraas [nb],
Aurimas Černius [lt], Daniel Mustieles [es], Yuri Myasoedov [ru],
Khaled Hosny [ar], Yaron Shahrabani [he], Tom Tryfonidis [el],
Nilamdyuti Goswami [as], Fran Diéguez [gl], Nguyễn Thái Ngọc Duy [vi],
A S Alam [pa], Dr.T.Vasudevan [ta], Luca Ferretti [it]
3.5.90
======
* Use symbolic icons for workspace switch OSD [Jon; #680738]
* Lock screen improvements:
- Hide user menu and a11y menu in the screen lock [Giovanni; #681143]
- Bump the lock screen slightly when pressing a key [Giovanni; #681143]
- Constrain vertical movement of the screen shield [Giovanni; #681143]
- Return to lock screen on idle [Giovanni; #682041]
- Unlock screen automatically after fast-user switching [Giovanni; #682096]
- Fix "other user" label [Ray; #681750]
* Constrain content of system modals to primary monitor [#681743]
* Respect automatic lock setting on suspend/user-switch [Giovanni; #680231]
* Improve styling of keyring prompt [Jasper; #681821]
* Do not hard-code <super> as overlay-key [Florian; #665547]
* Update style of attached modal dialogs [Florian; #681601]
* a11y: allow navigation on non reactive items [Alejandro; #667439, #667439]
* Implement mode-less overview design [Joost, Florian; #682109]
* Implement message-tray redesign:
- Restyle the message tray [Ana, Allan, Florian; #677213, #682342]
- Move the desktop upwards when showing the tray [Debarshi; #681392]
- Add a close button to notifications [Ana, Jasper; #682253]
- Add a keybinding to toggle the tray [Debarshi; #681392]
- Make the tray keyboard navigable [Debarshi; #681519]
- Add dwelling at the bottom of the screen to open the tray [Owen; #682310]
- Don't time out banners when the user is inactive [Marina, Jasper]
- Misc fixes and cleanups [Jasper, Marina]
* Fix showing "Next Week" on Sundays [Sebastian; #682198]
* Delay restoring IM presence until the network comes up [Florian; #677982]
* Display enterprise login hint [Ray; #681975]
* Ignore unrecognized/irrelevant network devices/connections [Dan; #682364]
* Misc bug fixes and cleanups: [Dan, Florian, Jasper, Jiro, Piotr, Rico;
#643687, #682045, #682189]
Contributors:
Giovanni Campagna, Allan Day, Piotr Drąg, William Jon McCann,
Sebastian Keller, Jiro Matsuzawa, Florian Müllner, Alejandro Piñeiro,
Debarshi Ray, Ana Risteska, Jasper St. Pierre, Ray Strode, Owen Taylor,
Rico Tzschichholz, Joost Verdoorn, Dan Winship, Marina Zhurakhinskaya
Translations:
Nilamdyuti Goswami [as], Daniel Mustieles [es], Yaron Shahrabani [he],
Chao-Hsiung Liao [zh_HK, zh_TW], Tobias Endrigkeit [de], A S Alam [pa],
Sandeep Sheshrao Shedmake [mr], Fran Diéguez [gl],
Мирослав Николић [sr, sr@latin]
3.5.5
=====
* Update style to match mockups [Allan]
- improve calendar layout and legibility
- update notifications and menus
- use a common style for entries
- update scrollbars to match GTK+
- improve clock/unlock button in lock screen
- update polkit dialogs [Jasper]
* Fix login dialog growing when selecting different users [Florian; #675076]
* Implement screen lock in the shell [Giovanni]
- restructure login code to be shared with session unlock [#619955]
- add initial screen shield / unlock dialog implementation [#619955]
- implement (optional) notification list on lock shield [#619955]
- update login dialog style to match lock screen [#619955]
- filter notifications to only show new ones on the screen lock [#681143]
- make notifications scrollable if necessary [#681143]
- use correct application names in notifications [#681143]
- allow to return to the shield by pressing Escape [#681143]
* Minor login dialog improvements [Florian]
- update style to match the overall visuals [#660913]
- indicate whether users are logged in [#658185]
* Add support for background-repeat CSS property [Jasper; #680801]
* Add :active pseudo class on scroll handles [Florian]
* Remove markup from translated strings [Matthias; #681270]
* Misc bug fixes and cleanups: [Alban, Florian, Giovanni, Jasper, Jeremy,
Matthias, Piotr; #677893, #679944, #680064, #680170, #680216, #680426,
#681101, #681382]
Contributors:
Jeremy Bicha, Alban Browaeys, Giovanni Campagna, Matthias Clasen, Allan Day,
Piotr Drąg , Florian Müllner, Jasper St. Pierre
Translations:
Matej Urbančič [sl], Tom Tryfonidis [el], Yaron Shahrabani [he],
Kjartan Maraas [nb], Baurzhan Muftakhidinov [kk], Praveen Illa [te],
Khaled Hosny [ar], Daniel Mustieles [es], Gabor Kelemen [hu],
Fran Diéguez [gl], Sweta Kothari [gu], Aleksej Kabanov [ru],
Nilamdyuti Goswami [as], Arash Mousavi [fa], Мирослав Николић [sr, sr@latin]
3.5.4
=====
* Fix wrong result handling of remote calls [Florian; #678852]

View File

@@ -1,5 +1,5 @@
AC_PREREQ(2.63)
AC_INIT([gnome-shell],[3.5.91],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_INIT([gnome-shell],[3.5.4],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c])
@@ -60,10 +60,10 @@ fi
AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
CLUTTER_MIN_VERSION=1.11.11
CLUTTER_MIN_VERSION=1.9.16
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=1.33.2
MUTTER_MIN_VERSION=3.5.91
MUTTER_MIN_VERSION=3.5.4
GTK_MIN_VERSION=3.3.9
GIO_MIN_VERSION=2.31.6
LIBECAL_MIN_VERSION=3.5.3

View File

@@ -10,6 +10,11 @@ desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop
@INTLTOOL_DESKTOP_RULE@
searchprovidersdir = $(pkgdatadir)/open-search-providers
dist_searchproviders_DATA = \
open-search-providers/google.xml \
open-search-providers/wikipedia.xml
introspectiondir = $(datadir)/dbus-1/interfaces
introspection_DATA = org.gnome.ShellSearchProvider.xml
@@ -31,7 +36,6 @@ dist_theme_DATA = \
theme/filter-selected-rtl.svg \
theme/gnome-shell.css \
theme/logged-in-indicator.svg \
theme/message-tray-background.png \
theme/noise-texture.png \
theme/panel-button-border.svg \
theme/panel-button-highlight-narrow.svg \
@@ -43,8 +47,8 @@ dist_theme_DATA = \
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
theme/ws-switch-arrow-up.svg \
theme/ws-switch-arrow-down.svg
gsettings_SCHEMAS = org.gnome.shell.gschema.xml

View File

@@ -0,0 +1,7 @@
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>Google</ShortName>
<Description>Google Search</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image width="16" height="16">data:image/x-icon;base64,AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs9Pt8xetPtu9FsfFNtu%2BTzvb2%2B%2Fne4dFJeBw0egA%2FfAJAfAA8ewBBegAAAAD%2B%2FPtft98Mp%2BwWsfAVsvEbs%2FQeqvF8xO7%2F%2F%2F63yqkxdgM7gwE%2FggM%2BfQA%2BegBDeQDe7PIbotgQufcMufEPtfIPsvAbs%2FQvq%2Bfz%2Bf%2F%2B%2B%2FZKhR05hgBBhQI8hgBAgAI9ewD0%2B%2Fg3pswAtO8Cxf4Kw%2FsJvvYAqupKsNv%2B%2Fv7%2F%2FP5VkSU0iQA7jQA9hgBDgQU%2BfQH%2F%2Ff%2FQ6fM4sM4KsN8AteMCruIqqdbZ7PH8%2Fv%2Fg6Nc%2Fhg05kAA8jAM9iQI%2BhQA%2BgQDQu6b97uv%2F%2F%2F7V8Pqw3eiWz97q8%2Ff%2F%2F%2F%2F7%2FPptpkkqjQE4kwA7kAA5iwI8iAA8hQCOSSKdXjiyflbAkG7u2s%2F%2B%2F%2F39%2F%2F7r8utrqEYtjQE8lgA7kwA7kwA9jwA9igA9hACiWSekVRyeSgiYSBHx6N%2F%2B%2Fv7k7OFRmiYtlAA5lwI7lwI4lAA7kgI9jwE9iwI4iQCoVhWcTxCmb0K%2BooT8%2Fv%2F7%2F%2F%2FJ2r8fdwI1mwA3mQA3mgA8lAE8lAE4jwA9iwE%2BhwGfXifWvqz%2B%2Ff%2F58u%2Fev6Dt4tr%2B%2F%2F2ZuIUsggA7mgM6mAM3lgA5lgA6kQE%2FkwBChwHt4dv%2F%2F%2F728ei1bCi7VAC5XQ7kz7n%2F%2F%2F6bsZkgcB03lQA9lgM7kwA2iQktZToPK4r9%2F%2F%2F9%2F%2F%2FSqYK5UwDKZAS9WALIkFn%2B%2F%2F3%2F%2BP8oKccGGcIRJrERILYFEMwAAuEAAdX%2F%2Ff7%2F%2FP%2B%2BfDvGXQLIZgLEWgLOjlf7%2F%2F%2F%2F%2F%2F9QU90EAPQAAf8DAP0AAfMAAOUDAtr%2F%2F%2F%2F7%2B%2Fu2bCTIYwDPZgDBWQDSr4P%2F%2Fv%2F%2F%2FP5GRuABAPkAA%2FwBAfkDAPAAAesAAN%2F%2F%2B%2Fz%2F%2F%2F64g1C5VwDMYwK8Yg7y5tz8%2Fv%2FV1PYKDOcAAP0DAf4AAf0AAfYEAOwAAuAAAAD%2F%2FPvi28ymXyChTATRrIb8%2F%2F3v8fk6P8MAAdUCAvoAAP0CAP0AAfYAAO4AAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAA</Image>
<Url type="text/html" method="GET" template="http://www.google.com/search?q={searchTerms}"/>
</OpenSearchDescription>

View File

@@ -0,0 +1,44 @@
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>Wikipedia</ShortName>
<Description>Wikipedia, the free encyclopedia</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image width="16" height="16">data:image/x-icon;base64,AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAEAgQAhIOEAMjHyABIR0gA6ejpAGlqaQCpqKkAKCgoAPz9%2FAAZGBkAmJiYANjZ2ABXWFcAent6ALm6uQA8OjwAiIiIiIiIiIiIiI4oiL6IiIiIgzuIV4iIiIhndo53KIiIiB%2FWvXoYiIiIfEZfWBSIiIEGi%2FfoqoiIgzuL84i9iIjpGIoMiEHoiMkos3FojmiLlUipYliEWIF%2BiDe0GoRa7D6GPbjcu1yIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA</Image>
<Url type="text/html" method="GET" template="http://{language}.wikipedia.org/wiki/Special:Search?search={searchTerms}"/>
<!-- The criterion for being below is being listed with more than 100,000
articles on http://meta.wikimedia.org/wiki/List_of_Wikipedias -->
<Language>ar</Language>
<Language>bg</Language>
<Language>ca</Language>
<Language>cs</Language>
<Language>da</Language>
<Language>de</Language>
<Language>en</Language>
<Language>eo</Language>
<Language>es</Language>
<Language>fa</Language>
<Language>fi</Language>
<Language>fr</Language>
<Language>he</Language>
<Language>hu</Language>
<Language>id</Language>
<Language>it</Language>
<Language>ja</Language>
<Language>ko</Language>
<Language>lt</Language>
<Language>nl</Language>
<Language>no</Language>
<Language>pl</Language>
<Language>pt</Language>
<Language>ro</Language>
<Language>ru</Language>
<Language>sk</Language>
<Language>sl</Language>
<Language>sr</Language>
<Language>sv</Language>
<Language>tr</Language>
<Language>uk</Language>
<Language>vi</Language>
<Language>vo</Language>
<Language>war</Language>
<Language>zh</Language>
</OpenSearchDescription>

View File

@@ -87,13 +87,6 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
Keybinding to open the application menu.
</_description>
</key>
<key name="toggle-message-tray" type="as">
<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="toggle-recording" type="as">
<default><![CDATA[['<Control><Shift><Alt>r']]]></default>
<_summary>Keybinding to toggle the screen recorder</_summary>

View File

@@ -48,8 +48,9 @@ stage {
.dash-label,
.window-caption,
.switcher-list,
.source-title,
.app-well-app > .overview-icon,
.show-apps > .overview-icon,
.remove-favorite > .overview-icon,
.search-result-content > .overview-icon {
font-size: 9pt;
font-weight: bold;
@@ -80,25 +81,25 @@ StScrollBar StBin#trough {
}
StScrollBar StButton#vhandle {
background-color: #5d6464;
background-color: #959797;
border: 2px solid #242424;
border-radius: 8px;
}
StScrollBar StButton#hhandle {
background-color: #5d6464;
background-color: #959797;
border: 2px solid #242424;
border-radius: 8px;
}
StScrollBar StButton#hhandle:hover,
StScrollBar StButton#vhandle:hover {
background-color: #777d7c;
background-color: #c2c3c3;
}
StScrollBar StButton#hhandle:active,
StScrollBar StButton#vhandle:active {
background-color: #3465a4;
background-color: #729fcf;
}
/* Check Boxes */
@@ -502,7 +503,7 @@ StButton.popup-menu-item:insensitive {
-boxpointer-gap: 4px
}
.panel-status-button-box {
#networkMenu {
spacing: 4px;
}
@@ -578,24 +579,22 @@ StButton.popup-menu-item:insensitive {
border-right: 0px;
border-radius: 9px 0px 0px 9px;
background-color: rgba(0, 0, 0, 0.5);
padding: 11px 7px 11px 11px;
padding: 8px;
}
.workspace-thumbnails-background:rtl {
border-right: 1px;
border-left: 0px;
border-radius: 0px 9px 9px 0px;
padding: 11px 11px 11px 7px;
}
.workspace-thumbnails {
spacing: 11px;
spacing: 7px;
}
.workspace-thumbnail-indicator {
border: 4px solid rgba(255,255,255,0.7);
border-radius: 4px;
padding: 1px;
outline: 2px solid white;
border: 1px solid #888;
}
.window-caption {
@@ -605,30 +604,14 @@ StButton.popup-menu-item:insensitive {
-shell-caption-spacing: 12px;
}
.window-close, .notification-close {
.window-close {
background-image: url("close-window.svg");
background-size: 34px;
height: 34px;
width: 34px;
}
.window-close {
-shell-close-overlap: 20px;
}
.notification-close {
/* we start out in the top right of the
* notification, inset.
*
* center is 32px/2 = 17px
*
* adjust left 2px
* adjust down 8px */
-shell-close-overlap-x: 15px;
-shell-close-overlap-y: 12px;
}
.window-close:rtl {
-st-background-image-shadow: 2px 2px 6px rgba(0,0,0,0.5);
}
@@ -666,11 +649,19 @@ StButton.popup-menu-item:insensitive {
spacing: 1em;
}
#viewSelectorTabBar {
padding: 1em;
}
/* Search Box */
#searchArea {
padding: 0px 24px;
}
#searchEntry {
border-radius: 17px;
width: 320px;
width: 250px;
}
.search-entry-icon {
@@ -678,6 +669,26 @@ StButton.popup-menu-item:insensitive {
color: #8d8f8a;
}
/* View Tabs */
.view-tab-title {
color: #888a85;
font-size: 12pt;
font-weight: bold;
padding: 0px 0.75em;
height: 1.5em;
}
.view-tab-title:hover {
color: #bbb;
}
.view-tab-title:selected {
color: #000000;
background-color: #c2c7cd;
border-radius: 0.25em;
}
/* Search Results */
#searchResults {
@@ -695,6 +706,7 @@ StButton.popup-menu-item:insensitive {
padding-left: 20px;
}
.search-statustext,
.search-section-header {
padding: 4px 12px;
spacing: 4px;
@@ -702,12 +714,6 @@ StButton.popup-menu-item:insensitive {
font-size: .8em;
}
.search-statustext {
color: #efefef;
font-size: 2em;
font-weight: bold;
}
.search-section-results {
padding: 6px;
}
@@ -798,12 +804,21 @@ StButton.popup-menu-item:insensitive {
outline: 1px solid #aaa;
}
.dash-item-container > StButton {
.dash-item-container > .app-well-app {
padding: 4px 8px;
}
.remove-favorite-icon {
color: #a0a0a0;
}
.remove-favorite-icon:hover {
color: white;
icon-shadow: black 0px 2px 2px;
}
.app-well-app > .overview-icon,
.show-apps > .overview-icon,
.remove-favorite > .overview-icon,
.search-result-content > .overview-icon {
border-radius: 4px;
padding: 3px;
@@ -819,44 +834,15 @@ StButton.popup-menu-item:insensitive {
}
.app-well-app:hover > .overview-icon,
.show-apps:hover > .overview-icon,
.remove-favorite:hover > .overview-icon,
.search-result-content:hover > .overview-icon {
background-color: rgba(255,255,255,0.1);
text-shadow: black 0px 2px 2px;
transition-duration: 100;
color:white;
}
.show-apps {
padding: 4px 0;
}
.show-apps-icon {
color: #a0a0a0;
}
.show-apps:hover .show-apps-icon {
color: white;
}
.show-apps:checked > .overview-icon {
background-gradient-start: rgba(255, 255, 255, .05);
background-gradient-end: rgba(255, 255, 255, .15);
background-gradient-direction: vertical;
border-radius: 4px;
box-shadow: inset 0px 1px 2px 0px rgba(0, 0, 0, 1);
transition-duration: 100;
}
.show-apps:checked .show-apps-icon,
.show-apps:focus .show-apps-icon {
color: white;
transition-duration: 100;
}
.app-well-app:focus > .overview-icon,
.search-result-content:focus > .overview-icon,
.show-apps:focus > .overview-icon,
.app-well-app:selected > .overview-icon,
.search-result-content:selected > .overview-icon {
background-color: rgba(255,255,255,0.33);
@@ -1187,27 +1173,19 @@ StButton.popup-menu-item:insensitive {
/* Message Tray */
#message-tray {
background: #2e3436 url(message-tray-background.png);
background-repeat: repeat;
transition-duration: 250;
height: 72px;
}
#message-tray:overview {
background: rgba(0, 0, 0, 0.1);
border-top: 1px solid rgba(128, 128, 128, 0.3);
background-gradient-direction: vertical;
background-gradient-start: rgba(0,0,0,0.01);
background-gradient-end: rgba(0,0,0,0.82);
height: 36px;
}
.notification {
font-size: 11pt;
border-radius: 10px 10px 0px 0px;
background: rgba(0,0,0,0.8);
padding: 8px 8px 4px 8px;
spacing-rows: 10px;
spacing-columns: 10px;
}
.notification, #notification-container {
font-size: 11pt;
width: 34em;
}
@@ -1215,13 +1193,6 @@ StButton.popup-menu-item:insensitive {
padding-bottom: 8px;
}
.notification-unexpanded {
/* We want to force the actor at a specific size, irrespective
of its minimum and preferred size, so we override both */
min-height: 36px;
height: 36px;
}
/* We use row-span = 2 for the image cell, which prevents its height preferences to be
taken into account during allocation, so its height ends up being limited by the height
of the content in the other rows. To avoid showing a stretched image, we set the minimum
@@ -1236,7 +1207,6 @@ StButton.popup-menu-item:insensitive {
-arrow-base: 36px;
-arrow-rise: 18px;
color: white;
-boxpointer-gap: 4px;
}
.summary-boxpointer .notification {
@@ -1416,29 +1386,68 @@ StButton.popup-menu-item:insensitive {
border-radius: 4px;
}
/* The spacing and padding on the summary is tricky; we want to keep
* the icons from touching each other or the edges of the screen, but
* we also want them to be "Fitts"-y with respect to the edges, so the
* summary area's bottom and right padding must actually be part of
* the icons. However, we can't put *all* of the padding into the
* icons, because then the summary would be 0x0 when there were no
* icons in it, and so you wouldn't be able to hover over it to
* activate it.
*
* Also, the spacing between a summary-source's icon and title is
* actually specified as padding-left in source-title, because we
* want the spacing to collapse along with the title.
*/
#summary-mode {
padding: 0px 6px 0px 6px; /* same as the values in .summary-source */
height: 60px;
spacing: 10px;
padding: 2px 0px 0px 4px;
height: 36px;
}
#summary-mode:rtl {
padding: 2px 4px 0px 0px;
}
.summary-source-button {
border-radius: 4px;
transition-duration: 100;
text-shadow: black 0px 2px 2px;
}
.summary-source-button:hover {
background-color: rgba(255,255,255,0.1);
.summary-source-button:ltr {
padding-right: 12px;
}
.summary-source-button:focus,
.summary-source-button:selected {
background-color: rgba(255,255,255,0.33);
.summary-source-button:selected .summary-source {
background-image: url("panel-button-highlight-narrow.svg");
background-size: contain;
border-image: url("source-button-border.svg") 10 10 0 1;
}
.summary-source-button:expanded:selected .summary-source {
background-image: none;
border-image: none;
}
.summary-source-button:expanded:selected {
background-image: url("panel-button-highlight-wide.svg");
background-size: contain;
border-image: url("source-button-border.svg") 10 10 0 1;
}
.summary-source-button:rtl {
padding-left: 12px;
}
.summary-source-button:last-child:ltr {
padding-right: 12px;
}
.summary-source-button:last-child:rtl {
padding-left: 12px;
}
.summary-source {
padding-right: 6px;
padding-left: 6px;
padding-right: 4px;
padding-left: 4px;
}
.summary-source-counter {
@@ -1451,6 +1460,15 @@ StButton.popup-menu-item:insensitive {
min-width: 1em;
}
.source-title {
padding-left: 4px;
}
.source-title:rtl {
padding-left: 0px;
padding-right: 4px;
}
/* App Switcher */
#altTabPopup {
padding: 8px;
@@ -1561,7 +1579,7 @@ StButton.popup-menu-item:insensitive {
height: 100px;
border: 0px;
background: rgba(255,255,255,0.5);
background-image: url("ws-switch-arrow-up.png");
background-image: url("ws-switch-arrow-up.svg");
border-radius: 8px;
}
@@ -1569,7 +1587,7 @@ StButton.popup-menu-item:insensitive {
height: 100px;
border: 0px;
background: rgba(255,255,255,0.5);
background-image: url("ws-switch-arrow-down.png");
background-image: url("ws-switch-arrow-down.svg");
border-radius: 8px;
}
@@ -1683,7 +1701,6 @@ StButton.popup-menu-item:insensitive {
border-radius: 5px;
width: 32px;
height: 32px;
background-size: contain;
}
.end-session-dialog-shutdown-icon {
@@ -1844,7 +1861,6 @@ StButton.popup-menu-item:insensitive {
.prompt-dialog-password-box {
spacing: 1em;
padding-bottom: 1em;
}
.prompt-dialog-error-label {
@@ -1883,24 +1899,14 @@ StButton.popup-menu-item:insensitive {
color: #ff0000;
}
.polkit-dialog-user-icon {
border: 2px solid #8b8b8b;
border-radius: 5px;
background-size: contain;
width: 48px;
height: 48px;
}
/* Network Agent Dialog */
.network-dialog-secret-table {
spacing-rows: 15px;
spacing-columns: 1em;
}
.keyring-dialog-control-table {
spacing-rows: 15px;
spacing-columns: 1em;
}
/* Magnifier */
@@ -2010,7 +2016,7 @@ StButton.popup-menu-item:insensitive {
min-width: 350px;
}
.login-dialog-prompt-login-hint-message {
.login-dialog-prompt-fingerprint-message {
font-size: 10.5pt;
}
@@ -2086,7 +2092,6 @@ StButton.popup-menu-item:insensitive {
font-size: 10.5pt;
font-weight: bold;
color: #666666;
padding-top: 1em;
}
.login-dialog-not-listed-button:hover .login-dialog-not-listed-label {
@@ -2166,7 +2171,7 @@ StButton.popup-menu-item:insensitive {
.login-dialog .modal-dialog-button {
border: 1px solid #666666;
border: 1px solid white;
border-radius: 5px;
padding: 3px 18px;
}
@@ -2178,13 +2183,13 @@ StButton.popup-menu-item:insensitive {
border: 2px solid #16335d;
}
.login-dialog .modal-dialog-button:default:hover {
.login-dialog .modal-dialog-button:hover {
background-gradient-start: #74a0d0;
background-gradient-end: #436d9f;
}
.login-dialog .modal-dialog-button:default:active,
.login-dialog .modal-dialog-button:default:pressed {
.login-dialog .modal-dialog-button:active,
.login-dialog .modal-dialog-button:pressed {
background-gradient-start: #436d9f;
background-gradient-end: #74a0d0;
}
@@ -2195,21 +2200,15 @@ StButton.popup-menu-item:insensitive {
/* Screen shield */
#lockDialogGroup {
#screenShieldGroup {
background: #2e3436 url(noise-texture.png);
background-repeat: repeat;
}
.screen-shield-arrows {
padding-bottom: 3em;
}
.screen-shield-arrows Gjs_Arrow {
color: white;
width: 80px;
height: 48px;
-arrow-thickness: 12px;
-arrow-shadow: 0 1px 1px rgba(0,0,0,0.4);
#screenShieldGroup .arrow {
color: #333333;
width: 100px;
height: 50px;
}
.screen-shield-clock {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 850 B

View File

@@ -0,0 +1,376 @@
<?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"
version="1.1"
width="96"
height="96"
id="svg25070"
inkscape:version="0.48.0 r9654"
sodipodi:docname="ws-switch-arrow-down.svg">
<metadata
id="metadata3353">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="718"
inkscape:window-height="480"
id="namedview3351"
showgrid="false"
inkscape:zoom="2.6979167"
inkscape:cx="48"
inkscape:cy="48"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="0"
inkscape:current-layer="svg25070" />
<defs
id="defs25072">
<linearGradient
x1="-86.552246"
y1="185.439"
x2="-83.37072"
y2="197.31261"
id="linearGradient24957"
xlink:href="#linearGradient4034-0-4"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(6,0)" />
<linearGradient
id="linearGradient4034-0-4">
<stop
id="stop4036-5-7"
style="stop-color:#eeeeec;stop-opacity:1"
offset="0" />
<stop
id="stop4038-9-6"
style="stop-color:#babdb6;stop-opacity:1"
offset="1" />
</linearGradient>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter24765">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix24767" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix24769" />
</filter>
<linearGradient
x1="-74.520325"
y1="169.06032"
x2="-74.520325"
y2="205.94189"
id="linearGradient24955"
xlink:href="#linearGradient4632-1-3-9-3-2"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-5,0)" />
<linearGradient
id="linearGradient4632-1-3-9-3-2">
<stop
id="stop4634-1-8-3-9-0"
style="stop-color:#eeeeec;stop-opacity:1"
offset="0" />
<stop
id="stop4636-1-9-9-8-8"
style="stop-color:#ffffff;stop-opacity:1"
offset="0.0274937" />
<stop
id="stop4638-8-3-9-6-6"
style="stop-color:#f2f2f2;stop-opacity:1"
offset="0.274937" />
<stop
id="stop4640-8-5-7-8-9"
style="stop-color:#eeeeec;stop-opacity:1"
offset="0.38707438" />
<stop
id="stop4642-5-41-9-6-9"
style="stop-color:#d9dad8;stop-opacity:1"
offset="0.66528589" />
<stop
id="stop4644-5-2-7-9-2"
style="stop-color:#dfe0dd;stop-opacity:1"
offset="0.76745707" />
<stop
id="stop4646-3-2-3-7-3"
style="stop-color:#f0f0f0;stop-opacity:1"
offset="1" />
</linearGradient>
<radialGradient
cx="-33.412369"
cy="185.74171"
r="2.3554697"
fx="-33.412369"
fy="185.74171"
id="radialGradient24959"
xlink:href="#linearGradient4869-4-1"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0075,0,0,1.0075,-5.4544,-1.25141)" />
<linearGradient
id="linearGradient4869-4-1">
<stop
id="stop4871-6-2"
style="stop-color:#ffffff;stop-opacity:1"
offset="0" />
<stop
id="stop4879-7-4"
style="stop-color:#eeeeec;stop-opacity:1"
offset="0.31807542" />
<stop
id="stop4877-6-1"
style="stop-color:#c8c9c6;stop-opacity:1"
offset="0.74691135" />
<stop
id="stop4873-1-0"
style="stop-color:#d3d7cf;stop-opacity:1"
offset="1" />
</linearGradient>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter25011">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix25013" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix25015" />
</filter>
<radialGradient
cx="-33.412369"
cy="185.74171"
r="2.3554697"
fx="-33.412369"
fy="185.74171"
id="radialGradient24961"
xlink:href="#linearGradient4869-4-0"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0075,0,0,1.0075,-5.4544,-1.25141)" />
<linearGradient
id="linearGradient4869-4-0">
<stop
id="stop4871-6-8"
style="stop-color:#ffffff;stop-opacity:1"
offset="0" />
<stop
id="stop4879-7-5"
style="stop-color:#eeeeec;stop-opacity:1"
offset="0.31807542" />
<stop
id="stop4877-6-5"
style="stop-color:#c8c9c6;stop-opacity:1"
offset="0.74691135" />
<stop
id="stop4873-1-4"
style="stop-color:#d3d7cf;stop-opacity:1"
offset="1" />
</linearGradient>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter25023">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix25025" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix25027" />
</filter>
<linearGradient
x1="-39.858727"
y1="184.61784"
x2="-38.244785"
y2="188.84898"
id="linearGradient24963"
xlink:href="#linearGradient4941"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient4941">
<stop
id="stop4943"
style="stop-color:#ffffff;stop-opacity:1"
offset="0" />
<stop
id="stop4945"
style="stop-color:#ffffff;stop-opacity:0"
offset="1" />
</linearGradient>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter25033">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix25035" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix25037" />
</filter>
<linearGradient
x1="-39.858727"
y1="184.61784"
x2="-38.244785"
y2="188.84898"
id="linearGradient24965"
xlink:href="#linearGradient4941-7"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient4941-7">
<stop
id="stop4943-2"
style="stop-color:#ffffff;stop-opacity:1"
offset="0" />
<stop
id="stop4945-5"
style="stop-color:#ffffff;stop-opacity:0"
offset="1" />
</linearGradient>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter25043">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix25045" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix25047" />
</filter>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter25049">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix25051" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix25053" />
</filter>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter25055">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix25057" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix25059" />
</filter>
</defs>
<g
transform="matrix(0,1,-1,0,48.0003,4.1307112e-7)"
id="layer1">
<g
transform="matrix(-2,0,0,2,-97.2497,-374.967)"
id="g4030-1-8"
style="stroke:#000000;stroke-opacity:1;display:inline">
<path
d="m -72.5,173.5 -14,14 14,14"
id="path3165-7-3"
style="color:#000000;fill:none;stroke:#000000;stroke-width:7;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"
inkscape:connector-curvature="0" />
</g>
<path
d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z"
transform="matrix(-3.34328,0,0,3.34328,-89.2797,-623.176)"
id="path4050-2-7-9-4"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52343899;marker:none;visibility:visible;display:inline;overflow:visible"
inkscape:connector-curvature="0" />
<path
d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z"
transform="matrix(-3.34328,0,0,3.34328,-111.2797,-623.176)"
id="path4050-2-7-9-4-8"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52343899;marker:none;visibility:visible;display:inline;overflow:visible"
inkscape:connector-curvature="0" />
<path
d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z"
transform="matrix(-2.86565,0,0,2.86565,-70.8457,-534.143)"
id="path4050-2-7-9-4-0"
style="color:#000000;fill:none;stroke:#000000;stroke-width:0.69792098;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"
inkscape:connector-curvature="0" />
<path
d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z"
transform="matrix(-2.86565,0,0,2.86565,-92.8457,-534.143)"
id="path4050-2-7-9-4-0-9"
style="color:#000000;fill:none;stroke:#000000;stroke-width:0.69792098;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"
inkscape:connector-curvature="0" />
<path
d="m 47.87528,-34.0295 c 1.53896,0.0448 3.0511,0.70928 4.125,1.8125 l 32.25,32.25 -32.25,32.25 c -2.2253,2.2253 -6.2747,2.2253 -8.5,0 -2.2253,-2.22528 -2.2253,-6.2747 0,-8.5 l 23.75,-23.75 -23.75,-23.75 c -1.73168,-1.6731 -2.295,-4.44228 -1.3546,-6.65894 0.94042,-2.21668 3.32312,-3.73604 5.7296,-3.65356 z"
id="path3165-7-3-1"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0pt;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;text-anchor:start;opacity:0.35;color:#000000;fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans"
inkscape:connector-curvature="0" />
<path
d="m 41.8316,28.09418 c -0.014,-1.58898 0.54158,-3.18406 1.66868,-4.31118 l 23.75,-23.75 m -25.1046,-30.40894 c 0.94042,-2.21668 3.32312,-3.73604 5.7296,-3.65356 1.53896,0.0448 3.0511,0.70928 4.125,1.8125 l 32.25,32.25"
id="path3165-7-3-1-9"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0pt;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;text-anchor:start;color:#000000;fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 841 B

View File

@@ -0,0 +1,447 @@
<?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="96"
height="96"
id="svg25070"
version="1.1"
inkscape:version="0.48.0 r9654"
sodipodi:docname="ws-switch-arrow-up.svg">
<defs
id="defs25072">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 24 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="48 : 24 : 1"
inkscape:persp3d-origin="24 : 16 : 1"
id="perspective25078" />
<inkscape:perspective
id="perspective24985"
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="#linearGradient4034-0-4"
id="linearGradient24957"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(6)"
x1="-86.552246"
y1="185.439"
x2="-83.37072"
y2="197.31261" />
<linearGradient
inkscape:collect="always"
id="linearGradient4034-0-4">
<stop
style="stop-color: rgb(238, 238, 236); stop-opacity: 1;"
offset="0"
id="stop4036-5-7" />
<stop
style="stop-color: rgb(186, 189, 182); stop-opacity: 1;"
offset="1"
id="stop4038-9-6" />
</linearGradient>
<filter
id="filter24765"
inkscape:label="Invert"
x="0"
y="0"
width="1"
height="1"
inkscape:menu="Color"
inkscape:menu-tooltip="Invert colors"
color-interpolation-filters="sRGB">
<feColorMatrix
id="feColorMatrix24767"
type="saturate"
values="1"
result="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix24769"
in="fbSourceGraphic"
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" />
</filter>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4632-1-3-9-3-2"
id="linearGradient24955"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-5)"
x1="-74.520325"
y1="169.06032"
x2="-74.520325"
y2="205.94189" />
<linearGradient
id="linearGradient4632-1-3-9-3-2">
<stop
style="stop-color: rgb(238, 238, 236); stop-opacity: 1;"
offset="0"
id="stop4634-1-8-3-9-0" />
<stop
id="stop4636-1-9-9-8-8"
offset="0.0274937"
style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" />
<stop
id="stop4638-8-3-9-6-6"
offset="0.274937"
style="stop-color: rgb(242, 242, 242); stop-opacity: 1;" />
<stop
id="stop4640-8-5-7-8-9"
offset="0.38707438"
style="stop-color: rgb(238, 238, 236); stop-opacity: 1;" />
<stop
id="stop4642-5-41-9-6-9"
offset="0.66528589"
style="stop-color: rgb(217, 218, 216); stop-opacity: 1;" />
<stop
id="stop4644-5-2-7-9-2"
offset="0.76745707"
style="stop-color: rgb(223, 224, 221); stop-opacity: 1;" />
<stop
style="stop-color: rgb(240, 240, 240); stop-opacity: 1;"
offset="1"
id="stop4646-3-2-3-7-3" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4869-4-1"
id="radialGradient24959"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0075, 0, 0, 1.0075, -5.4544, -1.25141)"
cx="-33.412369"
cy="185.74171"
fx="-33.412369"
fy="185.74171"
r="2.3554697" />
<linearGradient
id="linearGradient4869-4-1">
<stop
style="stop-color: rgb(255, 255, 255); stop-opacity: 1;"
offset="0"
id="stop4871-6-2" />
<stop
id="stop4879-7-4"
offset="0.31807542"
style="stop-color: rgb(238, 238, 236); stop-opacity: 1;" />
<stop
id="stop4877-6-1"
offset="0.74691135"
style="stop-color: rgb(200, 201, 198); stop-opacity: 1;" />
<stop
style="stop-color: rgb(211, 215, 207); stop-opacity: 1;"
offset="1"
id="stop4873-1-0" />
</linearGradient>
<filter
id="filter25011"
inkscape:label="Invert"
x="0"
y="0"
width="1"
height="1"
inkscape:menu="Color"
inkscape:menu-tooltip="Invert colors"
color-interpolation-filters="sRGB">
<feColorMatrix
id="feColorMatrix25013"
type="saturate"
values="1"
result="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix25015"
in="fbSourceGraphic"
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" />
</filter>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4869-4-0"
id="radialGradient24961"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0075, 0, 0, 1.0075, -5.4544, -1.25141)"
cx="-33.412369"
cy="185.74171"
fx="-33.412369"
fy="185.74171"
r="2.3554697" />
<linearGradient
id="linearGradient4869-4-0">
<stop
style="stop-color: rgb(255, 255, 255); stop-opacity: 1;"
offset="0"
id="stop4871-6-8" />
<stop
id="stop4879-7-5"
offset="0.31807542"
style="stop-color: rgb(238, 238, 236); stop-opacity: 1;" />
<stop
id="stop4877-6-5"
offset="0.74691135"
style="stop-color: rgb(200, 201, 198); stop-opacity: 1;" />
<stop
style="stop-color: rgb(211, 215, 207); stop-opacity: 1;"
offset="1"
id="stop4873-1-4" />
</linearGradient>
<filter
id="filter25023"
inkscape:label="Invert"
x="0"
y="0"
width="1"
height="1"
inkscape:menu="Color"
inkscape:menu-tooltip="Invert colors"
color-interpolation-filters="sRGB">
<feColorMatrix
id="feColorMatrix25025"
type="saturate"
values="1"
result="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix25027"
in="fbSourceGraphic"
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" />
</filter>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4941"
id="linearGradient24963"
gradientUnits="userSpaceOnUse"
x1="-39.858727"
y1="184.61784"
x2="-38.244785"
y2="188.84898" />
<linearGradient
inkscape:collect="always"
id="linearGradient4941">
<stop
style="stop-color: rgb(255, 255, 255); stop-opacity: 1;"
offset="0"
id="stop4943" />
<stop
style="stop-color: rgb(255, 255, 255); stop-opacity: 0;"
offset="1"
id="stop4945" />
</linearGradient>
<filter
id="filter25033"
inkscape:label="Invert"
x="0"
y="0"
width="1"
height="1"
inkscape:menu="Color"
inkscape:menu-tooltip="Invert colors"
color-interpolation-filters="sRGB">
<feColorMatrix
id="feColorMatrix25035"
type="saturate"
values="1"
result="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix25037"
in="fbSourceGraphic"
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" />
</filter>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4941-7"
id="linearGradient24965"
gradientUnits="userSpaceOnUse"
x1="-39.858727"
y1="184.61784"
x2="-38.244785"
y2="188.84898" />
<linearGradient
inkscape:collect="always"
id="linearGradient4941-7">
<stop
style="stop-color: rgb(255, 255, 255); stop-opacity: 1;"
offset="0"
id="stop4943-2" />
<stop
style="stop-color: rgb(255, 255, 255); stop-opacity: 0;"
offset="1"
id="stop4945-5" />
</linearGradient>
<filter
id="filter25043"
inkscape:label="Invert"
x="0"
y="0"
width="1"
height="1"
inkscape:menu="Color"
inkscape:menu-tooltip="Invert colors"
color-interpolation-filters="sRGB">
<feColorMatrix
id="feColorMatrix25045"
type="saturate"
values="1"
result="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix25047"
in="fbSourceGraphic"
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" />
</filter>
<filter
id="filter25049"
inkscape:label="Invert"
x="0"
y="0"
width="1"
height="1"
inkscape:menu="Color"
inkscape:menu-tooltip="Invert colors"
color-interpolation-filters="sRGB">
<feColorMatrix
id="feColorMatrix25051"
type="saturate"
values="1"
result="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix25053"
in="fbSourceGraphic"
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" />
</filter>
<filter
id="filter25055"
inkscape:label="Invert"
x="0"
y="0"
width="1"
height="1"
inkscape:menu="Color"
inkscape:menu-tooltip="Invert colors"
color-interpolation-filters="sRGB">
<feColorMatrix
id="feColorMatrix25057"
type="saturate"
values="1"
result="fbSourceGraphic" />
<feColorMatrix
id="feColorMatrix25059"
in="fbSourceGraphic"
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.8284271"
inkscape:cx="-12.356322"
inkscape:cy="57.536221"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1200"
inkscape:window-height="840"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="0" />
<metadata
id="metadata25075">
<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
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0, 48)">
<g
id="g3181"
transform="matrix(0,1,-1,0,48.0003,-48)">
<g
style="stroke:#000000;stroke-opacity:1;display:inline"
transform="matrix(2,0,0,2,193.25,-374.967)"
id="g4030-1-8">
<path
style="color:#000000;fill:none;stroke:#000000;stroke-width:7;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"
d="m -72.5,173.5 -14,14 14,14"
id="path3165-7-3"
sodipodi:nodetypes="ccc"
inkscape:connector-curvature="0" />
</g>
<path
transform="matrix(3.34328,0,0,3.34328,185.28,-623.176)"
d="m -36.5,186.40625 c 0,1.15635 -0.937404,2.09375 -2.09375,2.09375 -1.156346,0 -2.09375,-0.9374 -2.09375,-2.09375 0,-1.15635 0.937404,-2.09375 2.09375,-2.09375 1.156346,0 2.09375,0.9374 2.09375,2.09375 z"
sodipodi:ry="2.09375"
sodipodi:rx="2.09375"
sodipodi:cy="186.40625"
sodipodi:cx="-38.59375"
id="path4050-2-7-9-4"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52343899;marker:none;visibility:visible;display:inline;overflow:visible"
sodipodi:type="arc" />
<path
transform="matrix(3.34328,0,0,3.34328,207.28,-623.176)"
d="m -36.5,186.40625 c 0,1.15635 -0.937404,2.09375 -2.09375,2.09375 -1.156346,0 -2.09375,-0.9374 -2.09375,-2.09375 0,-1.15635 0.937404,-2.09375 2.09375,-2.09375 1.156346,0 2.09375,0.9374 2.09375,2.09375 z"
sodipodi:ry="2.09375"
sodipodi:rx="2.09375"
sodipodi:cy="186.40625"
sodipodi:cx="-38.59375"
id="path4050-2-7-9-4-8"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52343899;marker:none;visibility:visible;display:inline;overflow:visible"
sodipodi:type="arc" />
<path
transform="matrix(2.86565,0,0,2.86565,166.846,-534.143)"
d="m -36.5,186.40625 c 0,1.15635 -0.937404,2.09375 -2.09375,2.09375 -1.156346,0 -2.09375,-0.9374 -2.09375,-2.09375 0,-1.15635 0.937404,-2.09375 2.09375,-2.09375 1.156346,0 2.09375,0.9374 2.09375,2.09375 z"
sodipodi:ry="2.09375"
sodipodi:rx="2.09375"
sodipodi:cy="186.40625"
sodipodi:cx="-38.59375"
id="path4050-2-7-9-4-0"
style="color:#000000;fill:none;stroke:#000000;stroke-width:0.69792098;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"
sodipodi:type="arc" />
<path
transform="matrix(2.86565,0,0,2.86565,188.846,-534.143)"
d="m -36.5,186.40625 c 0,1.15635 -0.937404,2.09375 -2.09375,2.09375 -1.156346,0 -2.09375,-0.9374 -2.09375,-2.09375 0,-1.15635 0.937404,-2.09375 2.09375,-2.09375 1.156346,0 2.09375,0.9374 2.09375,2.09375 z"
sodipodi:ry="2.09375"
sodipodi:rx="2.09375"
sodipodi:cy="186.40625"
sodipodi:cx="-38.59375"
id="path4050-2-7-9-4-0-9"
style="color:#000000;fill:none;stroke:#000000;stroke-width:0.69792098;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"
sodipodi:type="arc" />
<path
transform="matrix(2,0,0,2,-586,-765.967)"
sodipodi:nodetypes="ccccscccsc"
id="path3165-7-3-1"
d="m 317.06251,365.96875 c -0.76948,0.0224 -1.52555,0.35464 -2.0625,0.90625 l -16.125,16.125 16.125,16.125 c 1.11265,1.11265 3.13735,1.11265 4.25,0 1.11265,-1.11264 1.11265,-3.13735 0,-4.25 l -11.875,-11.875 11.875,-11.875 c 0.86584,-0.83655 1.1475,-2.22114 0.6773,-3.32947 -0.47021,-1.10834 -1.66156,-1.86802 -2.8648,-1.82678 z"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0pt;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;text-anchor:start;opacity:0.35;color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans"
inkscape:connector-curvature="0" />
<path
transform="matrix(2,0,0,2,-586,-765.967)"
sodipodi:nodetypes="ccccccc"
id="path3165-7-3-1-9"
d="m 320.08435,397.03059 c 0.007,-0.79449 -0.27079,-1.59203 -0.83434,-2.15559 L 307.37501,383 m 12.5523,-15.20447 c -0.47021,-1.10834 -1.66156,-1.86802 -2.8648,-1.82678 -0.76948,0.0224 -1.52555,0.35464 -2.0625,0.90625 L 298.87501,383"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0pt;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;text-anchor:start;color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -17,10 +17,11 @@ jsdir = $(pkgdatadir)/js
nobase_dist_js_DATA = \
gdm/batch.js \
gdm/consoleKit.js \
gdm/fingerprint.js \
gdm/loginDialog.js \
gdm/powerMenu.js \
gdm/realmd.js \
gdm/systemd.js \
gdm/util.js \
extensionPrefs/main.js \
misc/config.js \
@@ -29,7 +30,6 @@ nobase_dist_js_DATA = \
misc/gnomeSession.js \
misc/history.js \
misc/jsParse.js \
misc/loginManager.js \
misc/modemManager.js \
misc/params.js \
misc/util.js \
@@ -52,7 +52,6 @@ nobase_dist_js_DATA = \
ui/extensionDownloader.js \
ui/flashspot.js \
ui/ibusCandidatePopup.js\
ui/grabHelper.js \
ui/iconGrid.js \
ui/keyboard.js \
ui/keyringPrompt.js \
@@ -73,7 +72,6 @@ nobase_dist_js_DATA = \
ui/panel.js \
ui/panelMenu.js \
ui/placeDisplay.js \
ui/pointerWatcher.js \
ui/polkitAuthenticationAgent.js \
ui/popupMenu.js \
ui/remoteSearch.js \
@@ -85,7 +83,6 @@ nobase_dist_js_DATA = \
ui/shellDBus.js \
ui/status/accessibility.js \
ui/status/keyboard.js \
ui/status/lockScreenMenu.js \
ui/status/network.js \
ui/status/power.js \
ui/status/volume.js \

22
js/gdm/consoleKit.js Normal file
View File

@@ -0,0 +1,22 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const ConsoleKitManagerIface = <interface name='org.freedesktop.ConsoleKit.Manager'>
<method name='CanRestart'>
<arg type='b' direction='out'/>
</method>
<method name='CanStop'>
<arg type='b' direction='out'/>
</method>
<method name='Restart' />
<method name='Stop' />
</interface>;
const ConsoleKitProxy = Gio.DBusProxy.makeProxyWrapper(ConsoleKitManagerIface);
function ConsoleKitManager() {
return new ConsoleKitProxy(Gio.DBus.system,
'org.freedesktop.ConsoleKit',
'/org/freedesktop/ConsoleKit/Manager');
};

View File

@@ -39,7 +39,6 @@ const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
const Tweener = imports.ui.tweener;
const UserMenu = imports.ui.userMenu;
const _RESIZE_ANIMATION_TIME = 0.25;
const _SCROLL_ANIMATION_TIME = 0.5;
@@ -97,14 +96,14 @@ const UserListItem = new Lang.Class({
x_align: St.Align.START,
x_fill: true });
this._userAvatar = new UserMenu.UserAvatarWidget(this.user,
{ styleClass: 'login-dialog-user-list-item-icon' });
layout.add(this._userAvatar.actor);
this._iconBin = new St.Bin();
layout.add(this._iconBin);
let textLayout = new St.BoxLayout({ style_class: 'login-dialog-user-list-item-text-box',
vertical: true });
layout.add(textLayout, { expand: true });
this._nameLabel = new St.Label({ style_class: 'login-dialog-user-list-item-name' });
this._nameLabel = new St.Label({ text: this.user.get_real_name(),
style_class: 'login-dialog-user-list-item-name' });
textLayout.add(this._nameLabel,
{ y_fill: false,
y_align: St.Align.MIDDLE,
@@ -118,16 +117,63 @@ const UserListItem = new Lang.Class({
y_fill: false,
y_align: St.Align.END });
this._updateIcon();
this._updateLoggedIn();
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
this._onUserChanged();
},
_onUserChanged: function() {
this._nameLabel.set_text(this.user.get_real_name());
this._userAvatar.update();
this._updateIcon();
this._updateLoggedIn();
},
_setIconFromFile: function(iconFile, styleClass) {
if (styleClass)
this._iconBin.set_style_class_name(styleClass);
this._iconBin.set_style(null);
this._iconBin.child = null;
if (iconFile) {
this._iconBin.show();
// We use background-image instead of, say, St.TextureCache
// so the theme writers can add a rounded frame around the image
// and so theme writers can pick the icon size.
this._iconBin.set_style('background-image: url("' + iconFile + '");' +
'background-size: contain;');
} else {
this._iconBin.hide();
}
},
_setIconFromName: function(iconName, styleClass) {
if (styleClass)
this._iconBin.set_style_class_name(styleClass);
this._iconBin.set_style(null);
if (iconName != null) {
let icon = new St.Icon();
icon.set_icon_name(iconName)
this._iconBin.child = icon;
this._iconBin.show();
} else {
this._iconBin.child = null;
this._iconBin.hide();
}
},
_updateIcon: function() {
let iconFileName = this.user.get_icon_file();
let gicon = null;
if (GLib.file_test(iconFileName, GLib.FileTest.EXISTS))
this._setIconFromFile(iconFileName, 'login-dialog-user-list-item-icon');
else
this._setIconFromName('avatar-default', 'login-dialog-user-list-item-icon');
},
syncStyleClasses: function() {
this._updateLoggedIn();
@@ -650,8 +696,8 @@ const LoginDialog = new Lang.Class({
this._userVerifier.connect('verification-failed', Lang.bind(this, this._onVerificationFailed));
this._userVerifier.connect('reset', Lang.bind(this, this._onReset));
this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint));
this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._hideLoginHint));
this._userVerifier.connect('show-fingerprint-prompt', Lang.bind(this, this._showFingerprintPrompt));
this._userVerifier.connect('hide-fingerprint-prompt', Lang.bind(this, this._hideFingerprintPrompt));
this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA });
@@ -715,9 +761,12 @@ const LoginDialog = new Lang.Class({
x_fill: true,
y_fill: false,
x_align: St.Align.START });
this._promptLoginHint = new St.Label({ style_class: 'login-dialog-prompt-login-hint-message' });
this._promptLoginHint.hide();
this._promptBox.add(this._promptLoginHint);
// Translators: this message is shown below the password entry field
// to indicate the user can swipe their finger instead
this._promptFingerprintMessage = new St.Label({ text: _("(or swipe finger)"),
style_class: 'login-dialog-prompt-fingerprint-message' });
this._promptFingerprintMessage.hide();
this._promptBox.add(this._promptFingerprintMessage);
this._sessionList = new SessionList();
this._sessionList.connect('session-activated',
@@ -805,7 +854,7 @@ const LoginDialog = new Lang.Class({
function() {
this._sessionList.close();
this._promptLoginHint.hide();
this._promptFingerprintMessage.hide();
this._userList.actor.show();
this._userList.actor.opacity = 255;
return this._userList.showItems();
@@ -826,14 +875,12 @@ const LoginDialog = new Lang.Class({
this._sessionList.setActiveSession(sessionId);
},
_showLoginHint: function(verifier, message) {
this._promptLoginHint.set_text(message)
GdmUtil.fadeInActor(this._promptLoginHint);
_showFingerprintPrompt: function() {
GdmUtil.fadeInActor(this._promptFingerprintMessage);
},
_hideLoginHint: function() {
GdmUtil.fadeOutActor(this._promptLoginHint);
this._promptLoginHint.set_text('');
_hideFingerprintPrompt: function() {
GdmUtil.fadeOutActor(this._promptFingerprintMessage);
},
cancel: function() {
@@ -852,8 +899,8 @@ const LoginDialog = new Lang.Class({
function() {
// Show it with 0 opacity so we preallocate space for it
// in the event we need to fade in the message
this._promptLoginHint.opacity = 0;
this._promptLoginHint.show();
this._promptFingerprintMessage.opacity = 0;
this._promptFingerprintMessage.show();
},
function() {
@@ -925,8 +972,9 @@ const LoginDialog = new Lang.Class({
},
function() {
this._promptLoginHint.hide();
this._promptFingerprintMessage.hide();
this._promptEntry.reactive = true;
this._promptEntry.remove_style_pseudo_class('insensitive');
this._promptEntry.set_text('');
}];
@@ -946,6 +994,7 @@ const LoginDialog = new Lang.Class({
function() {
let _text = this._promptEntry.get_text();
this._promptEntry.reactive = false;
this._promptEntry.add_style_pseudo_class('insensitive');
this._userVerifier.answerQuery(serviceName, _text);
}];

View File

@@ -21,7 +21,8 @@
const Lang = imports.lang;
const UPowerGlib = imports.gi.UPowerGlib;
const LoginManager = imports.misc.loginManager;
const ConsoleKit = imports.gdm.consoleKit;
const Systemd = imports.gdm.systemd;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
@@ -31,10 +32,13 @@ const PowerMenuButton = new Lang.Class({
Extends: PanelMenu.SystemStatusButton,
_init: function() {
this.parent('system-shutdown-symbolic', null);
this.parent('system-shutdown', null);
this._upClient = new UPowerGlib.Client();
this._loginManager = LoginManager.getLoginManager();
if (Systemd.haveSystemd())
this._systemdLoginManager = new Systemd.SystemdLoginManager();
else
this._consoleKitManager = new ConsoleKit.ConsoleKitManager();
this._createSubMenu();
@@ -61,19 +65,57 @@ const PowerMenuButton = new Lang.Class({
},
_updateHaveShutdown: function() {
this._loginManager.canPowerOff(Lang.bind(this, function(result) {
this._haveShutdown = result;
this._powerOffItem.actor.visible = this._haveShutdown;
this._updateVisibility();
}));
if (Systemd.haveSystemd()) {
this._systemdLoginManager.CanPowerOffRemote(Lang.bind(this,
function(result, error) {
if (!error)
this._haveShutdown = result[0] != 'no';
else
this._haveShutdown = false;
this._powerOffItem.actor.visible = this._haveShutdown;
this._updateVisibility();
}));
} else {
this._consoleKitManager.CanStopRemote(Lang.bind(this,
function(result, error) {
if (!error)
this._haveShutdown = result[0];
else
this._haveShutdown = false;
this._powerOffItem.actor.visible = this._haveShutdown;
this._updateVisibility();
}));
}
},
_updateHaveRestart: function() {
this._loginManager.canReboot(Lang.bind(this, function(result) {
this._haveRestart = result;
this._restartItem.actor.visible = this._haveRestart;
this._updateVisibility();
}));
if (Systemd.haveSystemd()) {
this._systemdLoginManager.CanRebootRemote(Lang.bind(this,
function(result, error) {
if (!error)
this._haveRestart = result[0] != 'no';
else
this._haveRestart = false;
this._restartItem.actor.visible = this._haveRestart;
this._updateVisibility();
}));
} else {
this._consoleKitManager.CanRestartRemote(Lang.bind(this,
function(result, error) {
if (!error)
this._haveRestart = result[0];
else
this._haveRestart = false;
this._restartItem.actor.visible = this._haveRestart;
this._updateVisibility();
}));
}
},
_updateHaveSuspend: function() {
@@ -110,13 +152,19 @@ const PowerMenuButton = new Lang.Class({
if (!this._haveRestart)
return;
this._loginManager.reboot();
if (Systemd.haveSystemd())
this._systemdLoginManager.RebootRemote(true);
else
this._consoleKitManager.RestartRemote();
},
_onActivatePowerOff: function() {
if (!this._haveShutdown)
return;
this._loginManager.powerOff();
if (Systemd.haveSystemd())
this._systemdLoginManager.PowerOffRemote(true);
else
this._consoleKitManager.StopRemote();
}
});

View File

@@ -1,139 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const ProviderIface = <interface name='org.freedesktop.realmd.Provider'>
<property name="Name" type="s" access="read"/>
<property name="Version" type="s" access="read"/>
<property name="Realms" type="ao" access="read"/>
<method name="Discover">
<arg name="string" type="s" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="relevance" type="i" direction="out"/>
<arg name="realm" type="ao" direction="out"/>
</method>
</interface>;
const Provider = Gio.DBusProxy.makeProxyWrapper(ProviderIface);
const ServiceIface = <interface name="org.freedesktop.realmd.Service">
<method name="Cancel">
<arg name="operation" type="s" direction="in"/>
</method>
<method name="Release" />
<method name="SetLocale">
<arg name="locale" type="s" direction="in"/>
</method>
<signal name="Diagnostics">
<arg name="data" type="s"/>
<arg name="operation" type="s"/>
</signal>
</interface>;
const Service = Gio.DBusProxy.makeProxyWrapper(ServiceIface);
const RealmIface = <interface name="org.freedesktop.realmd.Realm">
<property name="Name" type="s" access="read"/>
<property name="Configured" type="s" access="read"/>
<property name="Details" type="a(ss)" access="read"/>
<property name="LoginFormats" type="as" access="read"/>
<property name="LoginPolicy" type="s" access="read"/>
<property name="PermittedLogins" type="as" access="read"/>
<property name="SupportedInterfaces" type="as" access="read"/>
<method name="ChangeLoginPolicy">
<arg name="login_policy" type="s" direction="in"/>
<arg name="permitted_add" type="as" direction="in"/>
<arg name="permitted_remove" type="as" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
</method>
<method name="Deconfigure">
<arg name="options" type="a{sv}" direction="in"/>
</method>
</interface>;
const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface);
const Manager = new Lang.Class({
Name: 'Manager',
_init: function(parentActor) {
this._aggregateProvider = Provider(Gio.DBus.system,
'org.freedesktop.realmd',
'/org/freedesktop/realmd',
Lang.bind(this, this._reloadRealms))
this._realms = {};
this._aggregateProvider.connect('g-properties-changed',
Lang.bind(this, function(proxy, properties) {
if ('Realms' in properties.deep_unpack())
this._reloadRealms();
}));
},
_reloadRealms: function() {
let realmPaths = this._aggregateProvider.Realms;
if (!realmPaths)
return;
for (let i = 0; i < realmPaths.length; i++) {
let realm = Realm(Gio.DBus.system,
'org.freedesktop.realmd',
realmPaths[i],
Lang.bind(this, this._onRealmLoaded));
}
},
_reloadRealm: function(realm) {
if (!realm.Configured) {
if (this._realms[realm.get_object_path()])
delete this._realms[realm.get_object_path()];
return;
}
this._realms[realm.get_object_path()] = realm;
this._updateLoginFormat();
},
_onRealmLoaded: function(realm, error) {
if (error)
return;
this._reloadRealm(realm);
realm.connect('g-properties-changed',
Lang.bind(this, function(proxy, properties) {
if ('Configured' in properties.deep_unpack())
this._reloadRealm();
}));
},
_updateLoginFormat: function() {
let newLoginFormat;
for (let realmPath in this._realms) {
let realm = this._realms[realmPath];
if (realm.LoginFormats && realm.LoginFormats.length > 0) {
newLoginFormat = realm.LoginFormats[0];
break;
}
}
if (this._loginFormat != newLoginFormat) {
this._loginFormat = newLoginFormat;
this.emit('login-format-changed', newLoginFormat);
}
},
get loginFormat() {
if (this._loginFormat !== undefined)
return this._loginFormat;
this._updateLoginFormat();
return this._loginFormat;
}
});
Signals.addSignalMethods(Manager.prototype)

31
js/gdm/systemd.js Normal file
View File

@@ -0,0 +1,31 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const SystemdLoginManagerIface = <interface name='org.freedesktop.login1.Manager'>
<method name='PowerOff'>
<arg type='b' direction='in'/>
</method>
<method name='Reboot'>
<arg type='b' direction='in'/>
</method>
<method name='CanPowerOff'>
<arg type='s' direction='out'/>
</method>
<method name='CanReboot'>
<arg type='s' direction='out'/>
</method>
</interface>;
const SystemdLoginManagerProxy = Gio.DBusProxy.makeProxyWrapper(SystemdLoginManagerIface);
function SystemdLoginManager() {
return new SystemdLoginManagerProxy(Gio.DBus.system,
'org.freedesktop.login1',
'/org/freedesktop/login1');
};
function haveSystemd() {
return GLib.access("/sys/fs/cgroup/systemd", 0) >= 0;
}

View File

@@ -6,7 +6,6 @@ const Signals = imports.signals;
const Batch = imports.gdm.batch;
const Fprint = imports.gdm.fingerprint;
const Realmd = imports.gdm.realmd;
const Main = imports.ui.main;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
@@ -79,17 +78,16 @@ const ShellUserVerifier = new Lang.Class({
this._settings = new Gio.Settings({ schema: LOGIN_SCREEN_SCHEMA });
this._cancellable = new Gio.Cancellable();
this._fprintManager = new Fprint.FprintManager();
this._realmManager = new Realmd.Manager();
this._checkForFingerprintReader();
},
begin: function(userName, hold) {
this._cancellable = new Gio.Cancellable();
this._hold = hold;
this._userName = userName;
this._checkForFingerprintReader();
if (userName) {
// If possible, reauthenticate an already running session,
// so any session specific credentials get updated appropriately
@@ -101,18 +99,14 @@ const ShellUserVerifier = new Lang.Class({
},
cancel: function() {
if (this._cancellable)
this._cancellable.cancel();
this._cancellable.cancel();
if (this._userVerifier)
this._userVerifier.call_cancel_sync(null);
},
clear: function() {
if (this._cancellable) {
this._cancellable.cancel();
this._cancellable = null;
}
this._cancellable.cancel();
if (this._userVerifier) {
this._userVerifier.run_dispose();
@@ -146,12 +140,11 @@ const ShellUserVerifier = new Lang.Class({
this._hold.release();
} catch (e) {
if (this._reauthOnly) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
logError(e, 'Failed to open reauthentication channel');
this.emit('verification-failed');
this._hold.release();
this.emit('verification-failed');
return;
}
@@ -162,14 +155,10 @@ const ShellUserVerifier = new Lang.Class({
},
_userVerifierGot: function(client, result) {
try {
this._userVerifier = client.get_user_verifier_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.ErrorEnum.CANCELLED)) {
return;
}
this._userVerifier = client.get_user_verifier_finish(result);
this._connectSignals();
this._beginVerification();
this._hold.release();
},
@@ -191,12 +180,7 @@ const ShellUserVerifier = new Lang.Class({
this._userName,
this._cancellable,
Lang.bind(this, function(obj, result) {
try {
obj.call_begin_verification_for_user_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return;
}
obj.call_begin_verification_for_user_finish(result);
this._hold.release();
}));
@@ -207,12 +191,7 @@ const ShellUserVerifier = new Lang.Class({
this._userName,
this._cancellable,
Lang.bind(this, function(obj, result) {
try {
obj.call_begin_verification_for_user_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return;
}
obj.call_begin_verification_for_user_finish(result);
this._hold.release();
}));
}
@@ -220,12 +199,7 @@ const ShellUserVerifier = new Lang.Class({
this._userVerifier.call_begin_verification(PASSWORD_SERVICE_NAME,
this._cancellable,
Lang.bind(this, function(obj, result) {
try {
obj.call_begin_verification_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return;
}
obj.call_begin_verification_finish(result);
this._hold.release();
}));
}
@@ -237,10 +211,7 @@ const ShellUserVerifier = new Lang.Class({
// as a cue to display our own message.
if (serviceName == FINGERPRINT_SERVICE_NAME &&
this._haveFingerprintReader) {
// Translators: this message is shown below the password entry field
// to indicate the user can swipe their finger instead
this.emit('show-login-hint', _("(or swipe finger)"));
this.emit('show-fingerprint-prompt');
} else if (serviceName == PASSWORD_SERVICE_NAME) {
Main.notifyError(info);
}
@@ -254,30 +225,11 @@ const ShellUserVerifier = new Lang.Class({
Main.notifyError(problem);
},
_showRealmLoginHint: function() {
if (this._realmManager.loginFormat) {
let hint = this._realmManager.loginFormat;
hint = hint.replace(/%U/g, 'user');
hint = hint.replace(/%D/g, 'DOMAIN');
hint = hint.replace(/%[^UD]/g, '');
// Translators: this message is shown below the username entry field
// to clue the user in on how to login to the local network realm
this.emit('show-login-hint',
_("(e.g., user or %s)").format(hint));
}
},
_onInfoQuery: function(client, serviceName, question) {
// We only expect questions to come from the main auth service
if (serviceName != PASSWORD_SERVICE_NAME)
return;
this._showRealmLoginHint();
this._realmLoginHintSignalId = this._realmManager.connect('login-format-changed',
Lang.bind(this, this._showRealmLoginHint));
this.emit('ask-question', serviceName, question, '');
},
@@ -293,6 +245,8 @@ const ShellUserVerifier = new Lang.Class({
this._userVerifier.run_dispose();
this._userVerifier = null;
this._checkForFingerprintReader();
this.emit('reset');
},
@@ -306,13 +260,8 @@ const ShellUserVerifier = new Lang.Class({
// password authentication a chance to succeed
if (serviceName == PASSWORD_SERVICE_NAME) {
this.emit('verification-failed');
}
this.emit('hide-login-hint');
if (this._realmLoginHintSignalId) {
this._realmManager.disconnect(this._realmLoginHintSignalId);
this._realmLoginHintSignalId = 0;
} else if (serviceName == FINGERPRINT_SERVICE_NAME) {
this.emit('hide-fingerprint-prompt');
}
},
});

View File

@@ -1,197 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const SystemdLoginManagerIface = <interface name='org.freedesktop.login1.Manager'>
<method name='PowerOff'>
<arg type='b' direction='in'/>
</method>
<method name='Reboot'>
<arg type='b' direction='in'/>
</method>
<method name='CanPowerOff'>
<arg type='s' direction='out'/>
</method>
<method name='CanReboot'>
<arg type='s' direction='out'/>
</method>
</interface>;
const SystemdLoginSessionIface = <interface name='org.freedesktop.login1.Session'>
<signal name='Lock' />
<signal name='Unlock' />
</interface>;
const SystemdLoginManager = Gio.DBusProxy.makeProxyWrapper(SystemdLoginManagerIface);
const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIface);
const ConsoleKitManagerIface = <interface name='org.freedesktop.ConsoleKit.Manager'>
<method name='CanRestart'>
<arg type='b' direction='out'/>
</method>
<method name='CanStop'>
<arg type='b' direction='out'/>
</method>
<method name='Restart' />
<method name='Stop' />
<method name='GetCurrentSession'>
<arg type='o' direction='out' />
</method>
</interface>;
const ConsoleKitSessionIface = <interface name='org.freedesktop.ConsoleKit.Session'>
<method name='IsActive'>
<arg type='b' direction='out' />
</method>
<signal name='ActiveChanged'>
<arg type='b' direction='out' />
</signal>
<signal name='Lock' />
<signal name='Unlock' />
</interface>;
const ConsoleKitSession = Gio.DBusProxy.makeProxyWrapper(ConsoleKitSessionIface);
const ConsoleKitManager = Gio.DBusProxy.makeProxyWrapper(ConsoleKitManagerIface);
function haveSystemd() {
return GLib.access("/sys/fs/cgroup/systemd", 0) >= 0;
}
let _loginManager = null;
/**
* LoginManager:
* An abstraction over systemd/logind and ConsoleKit.
*
*/
function getLoginManager() {
if (_loginManager == null) {
if (haveSystemd())
_loginManager = new LoginManagerSystemd();
else
_loginManager = new LoginManagerConsoleKit();
}
return _loginManager;
}
const LoginManagerSystemd = new Lang.Class({
Name: 'LoginManagerSystemd',
_init: function() {
this._proxy = new SystemdLoginManager(Gio.DBus.system,
'org.freedesktop.login1',
'/org/freedesktop/login1');
},
// Having this function is a bit of a hack since the Systemd and ConsoleKit
// session objects have different interfaces - but in both cases there are
// Lock/Unlock signals, and that's all we count upon at the moment.
getCurrentSessionProxy: function() {
if (!this._currentSession) {
this._currentSession = new SystemdLoginSession(Gio.DBus.system,
'org.freedesktop.login1',
'/org/freedesktop/login1/session/' +
GLib.getenv('XDG_SESSION_ID'));
}
return this._currentSession;
},
get sessionActive() {
return Shell.session_is_active_for_systemd();
},
canPowerOff: function(asyncCallback) {
this._proxy.CanPowerOffRemote(function(result, error) {
if (error)
asyncCallback(false);
else
asyncCallback(result[0] != 'no');
});
},
canReboot: function(asyncCallback) {
this._proxy.CanRebootRemote(function(result, error) {
if (error)
asyncCallback(false);
else
asyncCallback(result[0] != 'no');
});
},
powerOff: function() {
this._proxy.PowerOffRemote(true);
},
reboot: function() {
this._proxy.RebootRemote(true);
}
});
const LoginManagerConsoleKit = new Lang.Class({
Name: 'LoginManagerConsoleKit',
_init: function() {
this._proxy = new ConsoleKitManager(Gio.DBus.system,
'org.freedesktop.ConsoleKit',
'/org/freedesktop/ConsoleKit/Manager');
},
// Having this function is a bit of a hack since the Systemd and ConsoleKit
// session objects have different interfaces - but in both cases there are
// Lock/Unlock signals, and that's all we count upon at the moment.
getCurrentSessionProxy: function() {
if (!this._currentSession) {
let [currentSessionId] = this._proxy.GetCurrentSessionSync();
this._currentSession = new ConsoleKitSession(Gio.DBus.system,
'org.freedesktop.ConsoleKit',
currentSessionId);
}
return this._currentSession;
},
get sessionActive() {
if (this._sessionActive !== undefined)
return this._sessionActive;
let session = this.getCurrentSessionProxy();
session.connectSignal('ActiveChanged', Lang.bind(this, function(object, senderName, [isActive]) {
this._sessionActive = isActive;
}));
[this._sessionActive] = session.IsActiveSync();
return this._sessionActive;
},
canPowerOff: function(asyncCallback) {
this._proxy.CanStopRemote(function(result, error) {
if (error)
asyncCallback(false);
else
asyncCallback(result[0]);
});
},
canReboot: function(asyncCallback) {
this._proxy.CanRestartRemote(function(result, error) {
if (error)
asyncCallback(false);
else
asyncCallback(result[0]);
});
},
powerOff: function() {
this._proxy.StopRemote();
},
reboot: function() {
this._proxy.RestartRemote();
}
});

View File

@@ -84,7 +84,7 @@ function trySpawn(argv)
try {
[success, pid] = GLib.spawn_async(null, argv, null,
GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD,
null);
null, null);
} catch (err) {
/* Rewrite the error in case of ENOENT */
if (err.matches(GLib.SpawnError, GLib.SpawnError.NOENT)) {

View File

@@ -115,10 +115,10 @@ function run() {
for (let i = 0; i < 2; i++) {
Scripting.scriptEvent('applicationsShowStart');
Main.overview._dash.showAppsButton.checked = true;
Main.overview._viewSelector.switchTab('applications');
yield Scripting.waitLeisure();
Scripting.scriptEvent('applicationsShowDone');
Main.overview._dash.showAppsButton.checked = false;
Main.overview._viewSelector.switchTab('windows');
yield Scripting.waitLeisure();
}
}

View File

@@ -5,12 +5,11 @@ const Mainloop = imports.mainloop;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Params = imports.misc.params;
const Shell = imports.gi.Shell;
const GnomeSession = imports.misc.gnomeSession;
const LoginManager = imports.misc.loginManager;
const Shell = imports.gi.Shell;
const Main = imports.ui.main;
const ShellMountOperation = imports.ui.shellMountOperation;
const GnomeSession = imports.misc.gnomeSession;
const GNOME_SESSION_AUTOMOUNT_INHIBIT = 16;
@@ -20,6 +19,62 @@ const SETTING_ENABLE_AUTOMOUNT = 'automount';
const AUTORUN_EXPIRE_TIMEOUT_SECS = 10;
const ConsoleKitSessionIface = <interface name="org.freedesktop.ConsoleKit.Session">
<method name="IsActive">
<arg type="b" direction="out" />
</method>
<signal name="ActiveChanged">
<arg type="b" direction="out" />
</signal>
</interface>;
const ConsoleKitSessionProxy = Gio.DBusProxy.makeProxyWrapper(ConsoleKitSessionIface);
const ConsoleKitManagerIface = <interface name="org.freedesktop.ConsoleKit.Manager">
<method name="GetCurrentSession">
<arg type="o" direction="out" />
</method>
</interface>;
const ConsoleKitManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(ConsoleKitManagerIface);
function ConsoleKitManager() {
var self = new Gio.DBusProxy({ g_connection: Gio.DBus.system,
g_interface_name: ConsoleKitManagerInfo.name,
g_interface_info: ConsoleKitManagerInfo,
g_name: 'org.freedesktop.ConsoleKit',
g_object_path: '/org/freedesktop/ConsoleKit/Manager',
g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START |
Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
self._updateSessionActive = function() {
if (self.g_name_owner) {
self.GetCurrentSessionRemote(function([session]) {
self._ckSession = new ConsoleKitSessionProxy(Gio.DBus.system, 'org.freedesktop.ConsoleKit', session);
self._ckSession.connectSignal('ActiveChanged', function(object, senderName, [isActive]) {
self.sessionActive = isActive;
});
self._ckSession.IsActiveRemote(function([isActive]) {
self.sessionActive = isActive;
});
});
} else {
self.sessionActive = true;
}
};
self.connect('notify::g-name-owner',
Lang.bind(self, self._updateSessionActive));
self._updateSessionActive();
self.init(null);
return self;
}
function haveSystemd() {
return GLib.access("/sys/fs/cgroup/systemd", 0) >= 0;
}
const AutomountManager = new Lang.Class({
Name: 'AutomountManager',
@@ -33,7 +88,8 @@ const AutomountManager = new Lang.Class({
Lang.bind(this, this._InhibitorsChanged));
this._inhibited = false;
this._loginManager = LoginManager.getLoginManager();
if (!haveSystemd())
this.ckListener = new ConsoleKitManager();
Main.screenShield.connect('lock-status-changed', Lang.bind(this, this._lockStatusChanged));
@@ -90,10 +146,21 @@ const AutomountManager = new Lang.Class({
return false;
},
isSessionActive: function() {
// Return whether the current session is active, using the
// right mechanism: either systemd if available or ConsoleKit
// as fallback.
if (haveSystemd())
return Shell.session_is_active_for_systemd();
return this.ckListener.sessionActive;
},
_onDriveConnected: function() {
// if we're not in the current ConsoleKit session,
// or screensaver is active, don't play sounds
if (!this._loginManager.sessionActive)
if (!this.isSessionActive())
return;
if (Main.screenShield.locked)
@@ -105,7 +172,7 @@ const AutomountManager = new Lang.Class({
_onDriveDisconnected: function() {
// if we're not in the current ConsoleKit session,
// or screensaver is active, don't play sounds
if (!this._loginManager.sessionActive)
if (!this.isSessionActive())
return;
if (Main.screenShield.locked)
@@ -117,7 +184,7 @@ const AutomountManager = new Lang.Class({
_onDriveEjectButton: function(monitor, drive) {
// TODO: this code path is not tested, as the GVfs volume monitor
// doesn't emit this signal just yet.
if (!this._loginManager.sessionActive)
if (!this.isSessionActive())
return;
// we force stop/eject in this case, so we don't have to pass a
@@ -157,7 +224,7 @@ const AutomountManager = new Lang.Class({
if (params.checkSession) {
// if we're not in the current ConsoleKit session,
// don't attempt automount
if (!this._loginManager.sessionActive)
if (!this.isSessionActive())
return;
if (Main.screenShield.locked) {

View File

@@ -4,7 +4,6 @@ const Lang = imports.lang;
const Gio = imports.gi.Gio;
const St = imports.gi.St;
const LoginManager = imports.misc.loginManager;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const ShellMountOperation = imports.ui.shellMountOperation;
@@ -143,8 +142,6 @@ const AutorunManager = new Lang.Class({
Name: 'AutorunManager',
_init: function() {
this._loginManager = LoginManager.getLoginManager();
this._volumeMonitor = Gio.VolumeMonitor.get();
this._volumeMonitor.connect('mount-added',
@@ -179,7 +176,7 @@ const AutorunManager = new Lang.Class({
_onMountAdded: function(monitor, mount) {
// don't do anything if our session is not the currently
// active one
if (!this._loginManager.sessionActive)
if (!Main.automountManager.isSessionActive())
return;
let discoverer = new ContentTypeDiscoverer(Lang.bind (this,
@@ -261,8 +258,7 @@ const AutorunResidentSource = new Lang.Class({
Extends: MessageTray.Source,
_init: function() {
this.parent(_("Removable Devices"), 'media-removable');
this.showInLockScreen = false;
this.parent(_("Removable Devices"), 'media-removable', St.IconType.FULLCOLOR);
this._mounts = [];

View File

@@ -410,7 +410,6 @@ const BoxPointer = new Lang.Class({
let themeNode = this.actor.get_theme_node();
let gap = themeNode.get_length('-boxpointer-gap');
let padding = themeNode.get_length('-arrow-rise');
let resX, resY;
@@ -436,8 +435,8 @@ const BoxPointer = new Lang.Class({
case St.Side.BOTTOM:
resX = sourceCenterX - (halfMargin + (natWidth - margin) * alignment);
resX = Math.max(resX, monitor.x + padding);
resX = Math.min(resX, monitor.x + monitor.width - (padding + natWidth));
resX = Math.max(resX, monitor.x + 10);
resX = Math.min(resX, monitor.x + monitor.width - (10 + natWidth));
this.setArrowOrigin(sourceCenterX - resX);
break;
@@ -445,8 +444,8 @@ const BoxPointer = new Lang.Class({
case St.Side.RIGHT:
resY = sourceCenterY - (halfMargin + (natHeight - margin) * alignment);
resY = Math.max(resY, monitor.y + padding);
resY = Math.min(resY, monitor.y + monitor.height - (padding + natHeight));
resY = Math.max(resY, monitor.y + 10);
resY = Math.min(resY, monitor.y + monitor.height - (10 + natHeight));
this.setArrowOrigin(sourceCenterY - resY);
break;

View File

@@ -204,11 +204,12 @@ const CalendarServerInfo = Gio.DBusInterfaceInfo.new_for_xml(CalendarServerIfac
function CalendarServer() {
var self = new Gio.DBusProxy({ g_connection: Gio.DBus.session,
g_interface_name: CalendarServerInfo.name,
g_interface_info: CalendarServerInfo,
g_name: 'org.gnome.Shell.CalendarServer',
g_object_path: '/org/gnome/Shell/CalendarServer',
g_flags: Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES });
g_interface_name: CalendarServerInfo.name,
g_interface_info: CalendarServerInfo,
g_name: 'org.gnome.Shell.CalendarServer',
g_object_path: '/org/gnome/Shell/CalendarServer',
g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START |
Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
self.init(null);
return self;
@@ -716,15 +717,13 @@ const EventsList = new Lang.Class({
let tomorrowEnd = new Date(dayEnd.getTime() + 86400 * 1000);
this._addPeriod(_("Tomorrow"), tomorrowBegin, tomorrowEnd, false, true);
let dayInWeek = (dayEnd.getDay() - this._weekStart + 7) % 7;
if (dayInWeek < 5) {
if (dayEnd.getDay() <= 4 + this._weekStart) {
/* If now is within the first 5 days we show "This week" and
* include events up until and including Saturday/Sunday
* (depending on whether a week starts on Sunday/Monday).
*/
let thisWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000);
let thisWeekEnd = new Date(dayEnd.getTime() + (6 - dayInWeek) * 86400 * 1000);
let thisWeekEnd = new Date(dayEnd.getTime() + (6 + this._weekStart - dayEnd.getDay()) * 86400 * 1000);
this._addPeriod(_("This week"), thisWeekBegin, thisWeekEnd, true, false);
} else {
/* otherwise it's one of the two last days of the week ... show
@@ -732,7 +731,7 @@ const EventsList = new Lang.Class({
* Saturday/Sunday
*/
let nextWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000);
let nextWeekEnd = new Date(dayEnd.getTime() + (13 - dayInWeek) * 86400 * 1000);
let nextWeekEnd = new Date(dayEnd.getTime() + (13 + this._weekStart - dayEnd.getDay()) * 86400 * 1000);
this._addPeriod(_("Next week"), nextWeekBegin, nextWeekEnd, true, false);
}
},

View File

@@ -27,6 +27,7 @@ const CtrlAltTabManager = new Lang.Class({
_init: function() {
this._items = [];
this._focusManager = St.FocusManager.get_for_stage(global.stage);
},
addGroup: function(root, name, icon, params) {
@@ -40,11 +41,11 @@ const CtrlAltTabManager = new Lang.Class({
this._items.push(item);
root.connect('destroy', Lang.bind(this, function() { this.removeGroup(root); }));
global.focus_manager.add_group(root);
this._focusManager.add_group(root);
},
removeGroup: function(root) {
global.focus_manager.remove_group(root);
this._focusManager.remove_group(root);
for (let i = 0; i < this._items.length; i++) {
if (this._items[i].root == root) {
this._items.splice(i, 1);
@@ -318,6 +319,7 @@ const CtrlAltTabSwitcher = new Lang.Class({
let icon = item.iconActor;
if (!icon) {
icon = new St.Icon({ icon_name: item.iconName,
icon_type: St.IconType.SYMBOLIC,
icon_size: POPUP_APPICON_SIZE });
}
box.add(icon, { x_fill: false, y_fill: false } );

View File

@@ -124,19 +124,15 @@ const DashItemContainer = new Lang.Class({
},
setLabelText: function(text) {
if (this.label == null) {
if (this.label == null)
this.label = new St.Label({ style_class: 'dash-label'});
Main.layoutManager.addChrome(this.label);
this.label.hide();
}
this.label.set_text(text);
Main.layoutManager.addChrome(this.label);
this.label.hide();
},
hideLabel: function () {
if (this.label == null)
return;
Tweener.addTween(this.label,
{ opacity: 0,
time: DASH_ITEM_LABEL_HIDE_TIME,
@@ -230,47 +226,36 @@ const DashItemContainer = new Lang.Class({
}
});
const ShowAppsIcon = new Lang.Class({
Name: 'ShowAppsIcon',
const RemoveFavoriteIcon = new Lang.Class({
Name: 'RemoveFavoriteIcon',
Extends: DashItemContainer,
_init: function() {
this.parent();
this.toggleButton = new St.Button({ style_class: 'show-apps',
track_hover: true,
can_focus: true,
toggle_mode: true });
this._iconBin = new St.Bin({ style_class: 'remove-favorite' });
this._iconActor = null;
this.icon = new IconGrid.BaseIcon(_("Show Applications"),
this.icon = new IconGrid.BaseIcon(_("Remove"),
{ setSizeManually: true,
showLabel: false,
createIcon: Lang.bind(this, this._createIcon) });
this.toggleButton.add_actor(this.icon.actor);
this.toggleButton._delegate = this;
this._iconBin.set_child(this.icon.actor);
this._iconBin._delegate = this;
this.setChild(this.toggleButton);
this.setHover(false);
this.toggleButton.label_actor = this.label;
this.setChild(this._iconBin);
},
_createIcon: function(size) {
this._iconActor = new St.Icon({ icon_name: 'view-grid-symbolic',
icon_size: size,
style_class: 'show-apps-icon',
track_hover: true });
this._iconActor = new St.Icon({ icon_name: 'user-trash',
style_class: 'remove-favorite-icon',
icon_size: size });
return this._iconActor;
},
setHover: function(hovered) {
this.toggleButton.set_hover(hovered);
this._iconBin.set_hover(hovered);
if (this._iconActor)
this._iconActor.set_hover(hovered);
if (hovered)
this.setLabelText(_("Remove from Favorites"));
else
this.setLabelText(_("Show Applications"));
},
// Rely on the dragged item being a favorite
@@ -321,28 +306,17 @@ const Dash = new Lang.Class({
this._dragPlaceholder = null;
this._dragPlaceholderPos = -1;
this._animatingPlaceholdersCount = 0;
this._favRemoveTarget = null;
this._showLabelTimeoutId = 0;
this._resetHoverTimeoutId = 0;
this._labelShowing = false;
this._container = new St.BoxLayout({ name: 'dash',
vertical: true,
clip_to_allocation: true });
this._box = new St.BoxLayout({ vertical: true,
this._box = new St.BoxLayout({ name: 'dash',
vertical: true,
clip_to_allocation: true });
this._box._delegate = this;
this._container.add(this._box);
this._showAppsIcon = new ShowAppsIcon();
this._showAppsIcon.icon.setIconSize(this.iconSize);
this._hookUpLabel(this._showAppsIcon);
this.showAppsButton = this._showAppsIcon.toggleButton;
this._container.add(this._showAppsIcon.actor);
this.actor = new St.Bin({ child: this._container });
this.actor = new St.Bin({ y_align: St.Align.START, child: this._box });
this.actor.connect('notify::height', Lang.bind(this,
function() {
if (this._maxHeight != this.actor.height)
@@ -395,6 +369,14 @@ const Dash = new Lang.Class({
_endDrag: function() {
this._clearDragPlaceholder();
if (this._favRemoveTarget) {
this._favRemoveTarget.animateOutAndDestroy();
this._favRemoveTarget.actor.connect('destroy', Lang.bind(this,
function() {
this._favRemoveTarget = null;
}));
this._adjustIconSize();
}
DND.removeDragMonitor(this._dragMonitor);
},
@@ -413,13 +395,28 @@ const Dash = new Lang.Class({
let srcIsFavorite = (id in favorites);
let showAppsHovered =
this._showAppsIcon.actor.contains(dragEvent.targetActor);
if (srcIsFavorite &&
app.get_state() != Shell.AppState.RUNNING &&
dragEvent.source.actor &&
this.actor.contains (dragEvent.source.actor) &&
this._favRemoveTarget == null) {
this._favRemoveTarget = new RemoveFavoriteIcon();
this._favRemoveTarget.icon.setIconSize(this.iconSize);
this._box.add(this._favRemoveTarget.actor);
this._adjustIconSize();
this._favRemoveTarget.animateIn();
}
if (!this._box.contains(dragEvent.targetActor) || showAppsHovered)
let favRemoveHovered = false;
if (this._favRemoveTarget)
favRemoveHovered =
this._favRemoveTarget.actor.contains(dragEvent.targetActor);
if (!this._box.contains(dragEvent.targetActor) || favRemoveHovered)
this._clearDragPlaceholder();
this._showAppsIcon.setHover(showAppsHovered);
if (this._favRemoveTarget)
this._favRemoveTarget.setHover(favRemoveHovered);
return DND.DragMotionResult.CONTINUE;
},
@@ -435,17 +432,6 @@ const Dash = new Lang.Class({
Main.queueDeferredWork(this._workId);
},
_hookUpLabel: function(item) {
item.child.connect('notify::hover', Lang.bind(this, function() {
this._onHover(item);
}));
Main.overview.connect('hiding', Lang.bind(this, function() {
this._labelShowing = false;
item.hideLabel();
}));
},
_createAppItem: function(app) {
let display = new AppDisplay.AppWellIcon(app,
{ setSizeManually: true,
@@ -465,14 +451,25 @@ const Dash = new Lang.Class({
item.setLabelText(app.get_name());
// Override default AppWellIcon label_actor
display.actor.label_actor = item.label;
display.icon.setIconSize(this.iconSize);
this._hookUpLabel(item);
display.actor.connect('notify::hover',
Lang.bind(this, function() {
this._onHover(item, display)
}));
Main.overview.connect('hiding',
Lang.bind(this, function() {
this._labelShowing = false;
item.hideLabel();
}));
return item;
},
_onHover: function (item) {
if (item.child.get_hover() && !item.child._delegate.isMenuUp) {
_onHover: function (item, display) {
if (display.actor.get_hover() && !display.isMenuUp) {
if (this._showLabelTimeoutId == 0) {
let timeout = this._labelShowing ? 0 : DASH_ITEM_HOVER_TIMEOUT;
this._showLabelTimeoutId = Mainloop.timeout_add(timeout,
@@ -513,12 +510,18 @@ const Dash = new Lang.Class({
!actor._delegate.animatingOut;
});
iconChildren.push(this._showAppsIcon.actor);
if (iconChildren.length == 0) {
this._box.add_style_pseudo_class('empty');
return;
}
this._box.remove_style_pseudo_class('empty');
if (this._maxHeight == -1)
return;
let themeNode = this._container.get_theme_node();
let themeNode = this._box.get_theme_node();
let maxAllocation = new Clutter.ActorBox({ x1: 0, y1: 0,
x2: 42 /* whatever */,
y2: this._maxHeight });
@@ -544,6 +547,7 @@ const Dash = new Lang.Class({
[minHeight, natHeight] = iconChildren[0].get_preferred_height(-1);
}
// Subtract icon padding and box spacing from the available height
availHeight -= iconChildren.length * (natHeight - this.iconSize) +
(iconChildren.length - 1) * spacing;

View File

@@ -34,7 +34,6 @@ const GnomeSession = imports.misc.gnomeSession;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
const Tweener = imports.ui.tweener;
const UserMenu = imports.ui.userMenu;
let _endSessionDialog = null;
@@ -90,7 +89,7 @@ const shutdownDialogContent = {
label: C_("button", "Restart") },
{ signal: 'ConfirmedShutdown',
label: C_("button", "Power Off") }],
iconName: 'system-shutdown-symbolic',
iconName: 'system-shutdown',
iconStyleClass: 'end-session-dialog-shutdown-icon'
};
@@ -105,7 +104,7 @@ const restartDialogContent = {
endDescription: _("Restarting the system."),
confirmButtons: [{ signal: 'ConfirmedReboot',
label: C_("button", "Restart") }],
iconName: 'system-shutdown-symbolic',
iconName: 'system-shutdown',
iconStyleClass: 'end-session-dialog-shutdown-icon'
};
@@ -161,7 +160,6 @@ const ListItem = new Lang.Class({
this._descriptionLabel = new St.Label({ text: this._reason,
style_class: 'end-session-dialog-app-list-item-description' });
this.actor.label_actor = this._nameLabel;
textLayout.add(this._descriptionLabel,
{ expand: true,
x_fill: true });
@@ -304,6 +302,41 @@ const EndSessionDialog = new Lang.Class({
this._user.disconnect(this._userChangedId);
},
_setIconFromFile: function(iconFile, styleClass) {
if (styleClass)
this._iconBin.set_style_class_name(styleClass);
this._iconBin.set_style(null);
this._iconBin.child = null;
if (iconFile) {
this._iconBin.show();
this._iconBin.set_style('background-image: url("' + iconFile + '");' +
'background-size: contain;');
} else {
this._iconBin.hide();
}
},
_setIconFromName: function(iconName, styleClass) {
if (styleClass)
this._iconBin.set_style_class_name(styleClass);
this._iconBin.set_style(null);
if (iconName != null) {
let textureCache = St.TextureCache.get_default();
let icon = textureCache.load_icon_name(this._iconBin.get_theme_node(),
iconName,
St.IconType.SYMBOLIC,
_DIALOG_ICON_SIZE);
this._iconBin.child = icon;
this._iconBin.show();
} else {
this._iconBin.child = null;
this._iconBin.hide();
}
},
_updateDescription: function() {
if (this.state != ModalDialog.State.OPENING &&
this.state != ModalDialog.State.OPENED)
@@ -352,16 +385,16 @@ const EndSessionDialog = new Lang.Class({
return;
let dialogContent = DialogContent[this._type];
if (dialogContent.iconName) {
this._iconBin.child = new St.Icon({ icon_name: dialogContent.iconName,
icon_size: _DIALOG_ICON_SIZE,
style_class: dialogContent.iconStyleClass });
} else {
let avatarWidget = new UserMenu.UserAvatarWidget(this._user,
{ iconSize: _DIALOG_ICON_SIZE,
styleClass: dialogContent.iconStyleClass });
this._iconBin.child = avatarWidget.actor;
avatarWidget.update();
if (this._user.is_loaded && !dialogContent.iconName) {
let iconFile = this._user.get_icon_file();
if (GLib.file_test(iconFile, GLib.FileTest.EXISTS))
this._setIconFromFile(iconFile, dialogContent.iconStyleClass);
else
this._setIconFromName('avatar-default', dialogContent.iconStyleClass);
} else if (dialogContent.iconName) {
this._setIconFromName(dialogContent.iconName,
dialogContent.iconStyleClass);
}
this._updateDescription();

View File

@@ -60,7 +60,7 @@ function uninstallExtension(uuid) {
if (extension.type != ExtensionUtils.ExtensionType.PER_USER)
return false;
if (!ExtensionSystem.unloadExtension(extension))
if (!ExtensionSystem.unloadExtension(uuid))
return false;
FileUtils.recursivelyDeleteDir(extension.dir, true);
@@ -82,7 +82,7 @@ function gotExtensionZipFile(session, message, uuid, dir, callback, errback) {
}
let [file, stream] = Gio.File.new_tmp('XXXXXX.shell-extension.zip');
let contents = message.response_body.flatten().get_as_bytes();
let contents = message.response_body.flatten().as_bytes();
stream.output_stream.write_bytes(contents, null);
stream.close(null);
let [success, pid] = GLib.spawn_async(null,
@@ -124,7 +124,7 @@ function updateExtension(uuid) {
let oldExtension = ExtensionUtils.extensions[uuid];
let extensionDir = oldExtension.dir;
if (!ExtensionSystem.unloadExtension(oldExtension))
if (!ExtensionSystem.unloadExtension(uuid))
return;
FileUtils.recursivelyMoveDir(extensionDir, oldExtensionTmpDir);
@@ -135,7 +135,7 @@ function updateExtension(uuid) {
try {
ExtensionSystem.loadExtension(extension);
} catch(e) {
ExtensionSystem.unloadExtension(extension);
ExtensionSystem.unloadExtension(uuid);
logError(e, 'Error loading extension %s'.format(uuid));

View File

@@ -158,32 +158,23 @@ function loadExtension(extension) {
_signals.emit('extension-state-changed', extension);
}
function unloadExtension(extension) {
function unloadExtension(uuid) {
let extension = ExtensionUtils.extensions[uuid];
if (!extension)
return false;
// Try to disable it -- if it's ERROR'd, we can't guarantee that,
// but it will be removed on next reboot, and hopefully nothing
// broke too much.
disableExtension(extension.uuid);
disableExtension(uuid);
extension.state = ExtensionState.UNINSTALLED;
_signals.emit('extension-state-changed', extension);
delete ExtensionUtils.extensions[extension.uuid];
delete ExtensionUtils.extensions[uuid];
return true;
}
function reloadExtension(oldExtension) {
// Grab the things we'll need to pass to createExtensionObject
// to reload it.
let { uuid: uuid, dir: dir, type: type } = oldExtension;
// Then unload the old extension.
unloadExtension(oldExtension);
// Now, recreate the extension and load it.
let newExtension = ExtensionUtils.createExtensionObject(uuid, dir, type);
loadExtension(newExtension);
}
function initExtension(uuid) {
let extension = ExtensionUtils.extensions[uuid];
let dir = extension.dir;

View File

@@ -1,355 +0,0 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
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 Params = imports.misc.params;
function _navigateActor(actor, needsGrab) {
if (!actor)
return;
if (needsGrab && actor instanceof St.Widget)
needsGrab = !actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
if (needsGrab)
actor.grab_key_focus();
}
// GrabHelper:
// @owner: the actor that owns the GrabHelper
//
// Creates a new GrabHelper object, for dealing with keyboard and pointer grabs
// associated with a set of actors.
//
// Note that the grab can be automatically dropped at any time by the user, and
// your code just needs to deal with it; you shouldn't adjust behavior directly
// after you call ungrab(), but instead pass an 'onUngrab' callback when you
// call grab().
const GrabHelper = new Lang.Class({
Name: 'GrabHelper',
_init: function(owner) {
this._owner = owner;
this._grabStack = [];
this._actors = [];
this._capturedEventId = 0;
this._eventId = 0;
this._keyFocusNotifyId = 0;
this._focusWindowChangedId = 0;
this._ignoreRelease = false;
this._modalCount = 0;
this._grabFocusCount = 0;
},
// addActor:
// @actor: an actor
//
// Adds @actor to the set of actors that are allowed to process events
// during a grab.
addActor: function(actor) {
actor.__grabHelperDestroyId = actor.connect('destroy', Lang.bind(this, function() { this.removeActor(actor); }));
this._actors.push(actor);
},
// removeActor:
// @actor: an actor
//
// Removes @actor from the set of actors that are allowed to
// process events during a grab.
removeActor: function(actor) {
let index = this._actors.indexOf(actor);
if (index != -1)
this._actors.splice(index, 1);
if (actor.__grabHelperDestroyId) {
actor.disconnect(actor.__grabHelperDestroyId);
delete actor.__grabHelperDestroyId;
}
},
_isWithinGrabbedActor: function(actor) {
while (actor) {
if (this._actors.indexOf(actor) != -1)
return true;
actor = actor.get_parent();
}
return false;
},
get currentGrab() {
let idx = this._grabStack.length - 1;
while (idx >= 0 && this._grabStack[idx].untracked)
idx--;
return this._grabStack[idx] || {};
},
_findStackIndex: function(actor) {
if (!actor)
return -1;
for (let i = 0; i < this._grabStack.length; i++) {
if (this._grabStack[i].actor === actor)
return i;
}
return -1;
},
isActorGrabbed: function(actor) {
return this._findStackIndex(actor) >= 0;
},
// grab:
// @params: A bunch of parameters, see below
//
// Grabs the mouse and keyboard, according to the GrabHelper's
// parameters. If @newFocus is not %null, then the keyboard focus
// is moved to the first #StWidget:can-focus widget inside it.
//
// The grab will automatically be dropped if:
// - The user clicks outside the grabbed actors
// - The user types Escape
// - The keyboard focus is moved outside the grabbed actors
// - A window is focused
//
// If @params.actor is not null, then it will be focused as the
// new actor. If you attempt to grab an already focused actor, the
// request to be focused will be ignored. The actor will not be
// added to the grab stack, so do not call a paired ungrab().
//
// If @params contains { modal: true }, then grab() will push a modal
// on the owner of the GrabHelper. As long as there is at least one
// { modal: true } actor on the grab stack, the grab will be kept.
// When the last { modal: true } actor is ungrabbed, then the modal
// will be dropped. A modal grab can fail if there is already a grab
// in effect from aother application; in this case the function returns
// false and nothing happens. Non-modal grabs can never fail.
//
// If @params contains { grabFocus: true }, then if you call grab()
// while the shell is outside the overview, it will set the stage
// input mode to %Shell.StageInputMode.FOCUSED, and ungrab() will
// revert it back, and re-focus the previously-focused window (if
// another window hasn't been explicitly focused before then).
//
// If @params contains { untracked: true }, then it will be skipped
// when the grab helper ungrabs for you, or when calculating
// currentGrab.
grab: function(params) {
params = Params.parse(params, { actor: null,
modal: false,
untracked: false,
grabFocus: false,
onUngrab: null });
let focus = global.stage.key_focus;
let hadFocus = focus && this._isWithinGrabbedActor(focus);
let newFocus = params.actor;
if (this.isActorGrabbed(params.actor))
return true;
if (this._grabFocusCount == 0 && this._modalCount == 0) {
if (!this._fullGrab(hadFocus, params.modal, params.grabFocus))
return false;
}
params.savedFocus = focus;
this._grabStack.push(params);
if (params.modal)
this._modalCount++;
if (params.grabFocus)
this._grabFocusCount++;
_navigateActor(newFocus, hadFocus);
return true;
},
_fullGrab: function(hadFocus, modal, grabFocus) {
let metaDisplay = global.screen.get_display();
if (modal) {
if (!Main.pushModal(this._owner))
return false;
}
this._grabbedFromKeynav = hadFocus;
this._preGrabInputMode = global.stage_input_mode;
this._prevFocusedWindow = null;
if (grabFocus) {
this._prevFocusedWindow = metaDisplay.focus_window;
if (this._preGrabInputMode == Shell.StageInputMode.NONREACTIVE ||
this._preGrabInputMode == Shell.StageInputMode.NORMAL) {
global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
}
}
if (modal || grabFocus) {
this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
this._eventId = global.stage.connect('event', Lang.bind(this, this._onEvent));
this._keyFocusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged));
this._focusWindowChangedId = metaDisplay.connect('notify::focus-window', Lang.bind(this, this._focusWindowChanged));
}
return true;
},
// ignoreRelease:
//
// Make sure that the next button release event evaluated by the
// capture event handler returns false. This is designed for things
// like the ComboBoxMenu that go away on press, but need to eat
// the next release event.
ignoreRelease: function() {
this._ignoreRelease = true;
},
// ungrab:
// @params: The parameters for the grab; see below.
//
// Pops an actor from the grab stack, potentially dropping the grab.
//
// If the actor that was popped from the grab stack was not the actor
// That was passed in, this call is ignored.
ungrab: function(params) {
params = Params.parse(params, { actor: this.currentGrab.actor });
let grabStackIndex = this._findStackIndex(params.actor);
if (grabStackIndex < 0)
return;
let poppedGrabs = this._grabStack.slice(grabStackIndex);
// "Pop" all newly ungrabbed actors off the grab stack
// by truncating the array.
this._grabStack.length = grabStackIndex;
let wasModal = this._modalCount > 0;
for (let i = poppedGrabs.length - 1; i >= 0; i--) {
let poppedGrab = poppedGrabs[i];
if (poppedGrab.onUngrab)
poppedGrab.onUngrab();
if (poppedGrab.modal)
this._modalCount--;
if (poppedGrab.grabFocus)
this._grabFocusCount--;
}
let focus = global.stage.key_focus;
let hadFocus = focus && this._isWithinGrabbedActor(focus);
if (this._grabFocusCount == 0 && this._modalCount == 0)
this._fullUngrab(wasModal);
let poppedGrab = poppedGrabs[0];
_navigateActor(poppedGrab.savedFocus, hadFocus);
},
_fullUngrab: function(wasModal) {
if (this._capturedEventId > 0) {
global.stage.disconnect(this._capturedEventId);
this._capturedEventId = 0;
}
if (this._eventId > 0) {
global.stage.disconnect(this._eventId);
this._eventId = 0;
}
if (this._keyFocusNotifyId > 0) {
global.stage.disconnect(this._keyFocusNotifyId);
this._keyFocusNotifyId = 0;
}
if (!this._focusWindowChanged > 0) {
let metaDisplay = global.screen.get_display();
metaDisplay.disconnect(this._focusWindowChangedId);
this._focusWindowChangedId = 0;
}
let prePopInputMode = global.stage_input_mode;
if (wasModal) {
Main.popModal(this._owner);
global.sync_pointer();
}
if (this._grabbedFromKeynav) {
if (this._preGrabInputMode == Shell.StageInputMode.FOCUSED &&
prePopInputMode != Shell.StageInputMode.FULLSCREEN)
global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
}
if (this._prevFocusedWindow) {
let metaDisplay = global.screen.get_display();
if (!metaDisplay.focus_window) {
metaDisplay.set_input_focus_window(this._prevFocusedWindow,
false, global.get_current_time());
}
}
},
_onCapturedEvent: function(actor, event) {
let type = event.type();
let press = type == Clutter.EventType.BUTTON_PRESS;
let release = type == Clutter.EventType.BUTTON_RELEASE;
let button = press || release;
if (release && this._ignoreRelease) {
this._ignoreRelease = false;
return false;
}
if (!button && this._modalCount == 0)
return false;
if (this._isWithinGrabbedActor(event.get_source()))
return false;
if (button) {
// If we have a press event, ignore the next event,
// which should be a release event.
if (press)
this._ignoreRelease = true;
this.ungrab();
}
return this._modalCount > 0;
},
// We catch 'event' rather than 'key-press-event' so that we get
// a chance to run before the overview's own Escape check
_onEvent: function(actor, event) {
if (event.type() == Clutter.EventType.KEY_PRESS &&
event.get_key_symbol() == Clutter.KEY_Escape) {
this.ungrab();
return true;
}
return false;
},
_onKeyFocusChanged: function() {
let focus = global.stage.key_focus;
if (!focus || !this._isWithinGrabbedActor(focus))
this.ungrab();
},
_focusWindowChanged: function() {
let metaDisplay = global.screen.get_display();
if (metaDisplay.focus_window != null)
this.ungrab();
}
});

View File

@@ -542,7 +542,7 @@ const KeyboardSource = new Lang.Class({
_init: function(keyboard) {
this._keyboard = keyboard;
this.parent(_("Keyboard"), 'input-keyboard-symbolic');
this.parent(_("Keyboard"), 'input-keyboard', St.IconType.SYMBOLIC);
},
handleSummaryClick: function() {

View File

@@ -84,10 +84,7 @@ const KeyringDialog = new Lang.Class({
if (this.prompt.password_visible) {
let label = new St.Label(({ style_class: 'prompt-dialog-password-label' }));
label.set_text(_("Password:"));
table.add(label, { row: row, col: 0,
x_expand: false, x_fill: true,
x_align: St.Align.START,
y_fill: false, y_align: St.Align.MIDDLE });
table.add(label, { row: row, col: 0, x_expand: false, x_fill: true, x_align: St.Align.START });
this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: '',
can_focus: true});
@@ -103,10 +100,7 @@ const KeyringDialog = new Lang.Class({
if (this.prompt.confirm_visible) {
var label = new St.Label(({ style_class: 'prompt-dialog-password-label' }));
label.set_text(_("Type again:"));
table.add(label, { row: row, col: 0,
x_expand: false, x_fill: true,
x_align: St.Align.START,
y_fill: false, y_align: St.Align.MIDDLE });
table.add(label, { row: row, col: 0, x_expand: false, x_fill: true, x_align: St.Align.START });
this._confirmEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: '',
can_focus: true});

View File

@@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const GObject = imports.gi.GObject;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
@@ -18,79 +17,6 @@ const HOT_CORNER_ACTIVATION_TIMEOUT = 0.5;
const STARTUP_ANIMATION_TIME = 0.2;
const KEYBOARD_ANIMATION_TIME = 0.5;
const MonitorConstraint = new Lang.Class({
Name: 'MonitorConstraint',
Extends: Clutter.Constraint,
Properties: {'primary': GObject.ParamSpec.boolean('primary',
'Primary', 'Track primary monitor',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
false),
'index': GObject.ParamSpec.int('index',
'Monitor index', 'Track specific monitor',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
-1, 64, -1)},
_init: function(props) {
this._primary = false;
this._index = -1;
this.parent(props);
},
get primary() {
return this._primary;
},
set primary(v) {
this._primary = v;
if (this.actor)
this.actor.queue_relayout();
this.notify('primary');
},
get index() {
return this._index;
},
set index(v) {
this._index = v;
if (this.actor)
this.actor.queue_relayout();
this.notify('index');
},
vfunc_set_actor: function(actor) {
if (actor) {
if (!this._monitorsChangedId) {
this._monitorsChangedId = Main.layoutManager.connect('monitors-changed', Lang.bind(this, function() {
this.actor.queue_relayout();
}));
}
} else {
if (this._monitorsChangedId)
Main.layoutManager.disconnect(this._monitorsChangedId);
this._monitorsChangedId = 0;
}
this.parent(actor);
},
vfunc_update_allocation: function(actor, actorBox) {
if (!this._primary && this._index < 0)
return;
let monitor;
if (this._primary) {
monitor = Main.layoutManager.primaryMonitor;
} else {
let index = Math.min(this._index, Main.layoutManager.monitors.length - 1);
monitor = Main.layoutManager.monitors[index];
}
actorBox.init_rect(monitor.x, monitor.y, monitor.width, monitor.height);
}
});
const LayoutManager = new Lang.Class({
Name: 'LayoutManager',
@@ -109,7 +35,6 @@ const LayoutManager = new Lang.Class({
this.screenShieldGroup = new St.Widget({ name: 'screenShieldGroup',
visible: false,
clip_to_allocation: true,
layout_manager: new Clutter.BinLayout(),
});
this.addChrome(this.screenShieldGroup);
@@ -314,7 +239,7 @@ const LayoutManager = new Lang.Class({
get currentMonitor() {
let index = global.screen.get_current_monitor();
return this.monitors[index];
return Main.layoutManager.monitors[index];
},
_startupAnimation: function() {

View File

@@ -38,6 +38,7 @@ var commandHeader = 'const Clutter = imports.gi.Clutter; ' +
/* Utility functions...we should probably be able to use these
* in the shell core code too. */
'const stage = global.stage; ' +
'const color = function(pixel) { let c= new Clutter.Color(); c.from_pixel(pixel); return c; }; ' +
/* Special lookingGlass functions */
'const it = Main.lookingGlass.getIt(); ' +
'const r = Lang.bind(Main.lookingGlass, Main.lookingGlass.getResult); ';
@@ -868,6 +869,7 @@ const LookingGlass = new Lang.Class({
let toolbar = new St.BoxLayout({ name: 'Toolbar' });
this.actor.add_actor(toolbar);
let inspectIcon = new St.Icon({ icon_name: 'gtk-color-picker',
icon_type: St.IconType.FULLCOLOR,
icon_size: 24 });
toolbar.add_actor(inspectIcon);
inspectIcon.reactive = true;

View File

@@ -12,7 +12,7 @@ const Signals = imports.signals;
const Main = imports.ui.main;
const MagnifierDBus = imports.ui.magnifierDBus;
const Params = imports.misc.params;
const PointerWatcher = imports.ui.pointerWatcher;
const MOUSE_POLL_FREQUENCY = 50;
const CROSSHAIRS_CLIP_SIZE = [100, 100];
@@ -56,7 +56,7 @@ const Magnifier = new Lang.Class({
let xfixesCursor = Shell.XFixesCursor.get_for_stage(global.stage);
this._mouseSprite = new Clutter.Texture();
xfixesCursor.update_texture_image(this._mouseSprite);
this._cursorRoot = new Clutter.Actor();
this._cursorRoot = new Clutter.Group();
this._cursorRoot.add_actor(this._mouseSprite);
// Create the first ZoomRegion and initialize it according to the
@@ -136,8 +136,11 @@ const Magnifier = new Lang.Class({
* Turn on mouse tracking, if not already doing so.
*/
startTrackingMouse: function() {
if (!this._pointerWatch)
this._pointerWatch = PointerWatcher.getPointerWatcher().addWatch(MOUSE_POLL_FREQUENCY, Lang.bind(this, this.scrollToMousePos));
if (!this._mouseTrackingId)
this._mouseTrackingId = Mainloop.timeout_add(
MOUSE_POLL_FREQUENCY,
Lang.bind(this, this.scrollToMousePos)
);
},
/**
@@ -145,10 +148,10 @@ const Magnifier = new Lang.Class({
* Turn off mouse tracking, if not already doing so.
*/
stopTrackingMouse: function() {
if (this._pointerWatch)
this._pointerWatch.remove();
if (this._mouseTrackingId)
Mainloop.source_remove(this._mouseTrackingId);
this._pointerWatch = null;
this._mouseTrackingId = null;
},
/**
@@ -300,7 +303,8 @@ const Magnifier = new Lang.Class({
*/
setCrosshairsColor: function(color) {
if (this._crossHairs) {
let [res, clutterColor] = Clutter.Color.from_string(color);
let clutterColor = new Clutter.Color();
clutterColor.from_string(color);
this._crossHairs.setColor(clutterColor);
}
},
@@ -1077,21 +1081,21 @@ const ZoomRegion = new Lang.Class({
// hide the magnified region from CLUTTER_PICK_ALL
Shell.util_set_hidden_from_pick (this._magView, true);
// Add a group to clip the contents of the magnified view.
let mainGroup = new Clutter.Actor({ clip_to_allocation: true });
// Append a Clutter.Group to clip the contents of the magnified view.
let mainGroup = new Clutter.Group({ clip_to_allocation: true });
this._magView.set_child(mainGroup);
// Add a background for when the magnified uiGroup is scrolled
// out of view (don't want to see desktop showing through).
this._background = new Clutter.Actor({ background_color: Main.DEFAULT_BACKGROUND_COLOR,
width: global.screen_width,
height: global.screen_height });
this._background = new Clutter.Rectangle({ color: Main.DEFAULT_BACKGROUND_COLOR });
mainGroup.add_actor(this._background);
// Clone the group that contains all of UI on the screen. This is the
// chrome, the windows, etc.
this._uiGroupClone = new Clutter.Clone({ source: Main.uiGroup });
mainGroup.add_actor(this._uiGroupClone);
Main.uiGroup.set_size(global.screen_width, global.screen_height);
this._background.set_size(global.screen_width, global.screen_height);
// Add either the given mouseSourceActor to the ZoomRegion, or a clone of
// it.
@@ -1325,7 +1329,7 @@ const ZoomRegion = new Lang.Class({
this._mouseActor.set_scale(this._xMagFactor, this._yMagFactor);
let [x, y] = this._screenToViewPort(0, 0);
this._uiGroupClone.set_position(Math.round(x), Math.round(y));
this._uiGroupClone.set_position(x, y);
this._updateMousePosition();
},
@@ -1353,6 +1357,7 @@ const ZoomRegion = new Lang.Class({
if (!this.isActive())
return;
Main.uiGroup.set_size(global.screen_width, global.screen_height);
this._background.set_size(global.screen_width, global.screen_height);
if (this._screenPosition == GDesktopEnums.MagnifierScreenPosition.NONE)
@@ -1376,15 +1381,15 @@ const Crosshairs = new Lang.Class({
let groupWidth = global.screen_width * 3;
let groupHeight = global.screen_height * 3;
this._actor = new Clutter.Actor({
this._actor = new Clutter.Group({
clip_to_allocation: false,
width: groupWidth,
height: groupHeight
});
this._horizLeftHair = new Clutter.Actor();
this._horizRightHair = new Clutter.Actor();
this._vertTopHair = new Clutter.Actor();
this._vertBottomHair = new Clutter.Actor();
this._horizLeftHair = new Clutter.Rectangle();
this._horizRightHair = new Clutter.Rectangle();
this._vertTopHair = new Clutter.Rectangle();
this._vertBottomHair = new Clutter.Rectangle();
this._actor.add_actor(this._horizLeftHair);
this._actor.add_actor(this._horizRightHair);
this._actor.add_actor(this._vertTopHair);
@@ -1455,10 +1460,10 @@ const Crosshairs = new Lang.Class({
* @clutterColor: The color as a Clutter.Color.
*/
setColor: function(clutterColor) {
this._horizLeftHair.background_color = clutterColor;
this._horizRightHair.background_color = clutterColor;
this._vertTopHair.background_color = clutterColor;
this._vertBottomHair.background_color = clutterColor;
this._horizLeftHair.set_color(clutterColor);
this._horizRightHair.set_color(clutterColor);
this._vertTopHair.set_color(clutterColor);
this._vertBottomHair.set_color(clutterColor);
},
/**
@@ -1467,7 +1472,9 @@ const Crosshairs = new Lang.Class({
* @color: The color as a Clutter.Color.
*/
getColor: function() {
return this._horizLeftHair.get_color();
let clutterColor = new Clutter.Color();
this._horizLeftHair.get_color(clutterColor);
return clutterColor;
},
/**

View File

@@ -43,11 +43,13 @@ const XdndHandler = imports.ui.xdndHandler;
const Util = imports.misc.util;
const OVERRIDES_SCHEMA = 'org.gnome.shell.overrides';
const DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2266bbff);
const DEFAULT_BACKGROUND_COLOR = new Clutter.Color();
DEFAULT_BACKGROUND_COLOR.from_pixel(0x2266bbff);
let automountManager = null;
let autorunManager = null;
let panel = null;
let hotCorners = [];
let overview = null;
let runDialog = null;
let lookingGlass = null;
@@ -79,6 +81,10 @@ let _overridesSettings = null;
let background = null;
function createUserSession() {
// Load the calendar server. Note that we are careful about
// not loading any events until the user presses the clock
global.launch_calendar_server();
telepathyClient = new TelepathyClient.Client();
automountManager = new AutomountManager.AutomountManager();
autorunManager = new AutorunManager.AutorunManager();
@@ -217,7 +223,8 @@ function start() {
sessionMode.createSession();
panel.init();
panel.startStatusArea();
layoutManager.init();
keyboard.init();
overview.init();
@@ -226,6 +233,11 @@ function start() {
global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT,
false, -1, 1);
if (sessionMode.allowExtensions) {
ExtensionDownloader.init();
ExtensionSystem.loadExtensions();
}
if (sessionMode.hasRunDialog) {
Meta.keybindings_set_custom_handler('panel-run-dialog', function() {
getRunDialog().open();
@@ -274,11 +286,6 @@ function start() {
global.screen.connect('restacked', _windowsRestacked);
_nWorkspacesChanged();
if (sessionMode.allowExtensions) {
ExtensionDownloader.init();
ExtensionSystem.loadExtensions();
}
}
let _workspaces = [];
@@ -502,6 +509,9 @@ function loadTheme() {
let theme = new St.Theme ({ application_stylesheet: cssStylesheet });
if (sessionMode.extraStylesheet)
theme.load_stylesheet(sessionMode.extraStylesheet);
if (previousTheme) {
let customStylesheets = previousTheme.get_custom_stylesheets();
@@ -578,6 +588,12 @@ function _globalKeyPressHandler(actor, event) {
// This relies on the fact that Clutter.ModifierType is the same as Gdk.ModifierType
let action = global.display.get_keybinding_action(keyCode, modifierState);
// This isn't a Meta.KeyBindingAction yet
if (symbol == Clutter.Super_L || symbol == Clutter.Super_R) {
overview.hide();
return true;
}
if (action == Meta.KeyBindingAction.SWITCH_PANELS) {
ctrlAltTabManager.popup(modifierState & Clutter.ModifierType.SHIFT_MASK,
modifierState);
@@ -620,7 +636,6 @@ function _globalKeyPressHandler(actor, event) {
getRunDialog().open();
return true;
case Meta.KeyBindingAction.PANEL_MAIN_MENU:
case Meta.KeyBindingAction.OVERLAY_KEY:
overview.hide();
return true;
}

File diff suppressed because it is too large Load Diff

View File

@@ -14,7 +14,6 @@ const Atk = imports.gi.Atk;
const Params = imports.misc.params;
const Layout = imports.ui.layout;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
@@ -60,14 +59,12 @@ const ModalDialog = new Lang.Class({
this._group.connect('key-release-event', Lang.bind(this, this._onKeyReleaseEvent));
this._backgroundBin = new St.Bin();
this._monitorConstraint = new Layout.MonitorConstraint();
this._backgroundBin.add_constraint(this._monitorConstraint);
this._group.add_actor(this._backgroundBin);
this.dialogLayout = new St.BoxLayout({ style_class: 'modal-dialog',
vertical: true });
this._dialogLayout = new St.BoxLayout({ style_class: 'modal-dialog',
vertical: true });
if (params.styleClass != null) {
this.dialogLayout.add_style_class_name(params.styleClass);
this._dialogLayout.add_style_class_name(params.styleClass);
}
if (!this._shellReactive) {
@@ -80,29 +77,29 @@ const ModalDialog = new Lang.Class({
this._eventBlocker = new Clutter.Group({ reactive: true });
stack.add_actor(this._eventBlocker);
stack.add_actor(this.dialogLayout);
stack.add_actor(this._dialogLayout);
} else {
this._backgroundBin.child = this.dialogLayout;
this._backgroundBin.child = this._dialogLayout;
}
this.contentLayout = new St.BoxLayout({ vertical: true });
this.dialogLayout.add(this.contentLayout,
{ x_fill: true,
y_fill: true,
x_align: St.Align.MIDDLE,
y_align: St.Align.START });
this._dialogLayout.add(this.contentLayout,
{ x_fill: true,
y_fill: true,
x_align: St.Align.MIDDLE,
y_align: St.Align.START });
this._buttonLayout = new St.BoxLayout({ style_class: 'modal-dialog-button-box',
visible: false,
vertical: false });
this.dialogLayout.add(this._buttonLayout,
{ expand: true,
x_align: St.Align.MIDDLE,
y_align: St.Align.END });
this._dialogLayout.add(this._buttonLayout,
{ expand: true,
x_align: St.Align.MIDDLE,
y_align: St.Align.END });
global.focus_manager.add_group(this.dialogLayout);
this._initialKeyFocus = this.dialogLayout;
global.focus_manager.add_group(this._dialogLayout);
this._initialKeyFocus = this._dialogLayout;
this._initialKeyFocusDestroyId = 0;
this._savedKeyFocus = null;
},
@@ -199,11 +196,14 @@ const ModalDialog = new Lang.Class({
},
_fadeOpen: function() {
this._monitorConstraint.index = global.screen.get_current_monitor();
let monitor = Main.layoutManager.currentMonitor;
this._backgroundBin.set_position(monitor.x, monitor.y);
this._backgroundBin.set_size(monitor.width, monitor.height);
this.state = State.OPENING;
this.dialogLayout.opacity = 255;
this._dialogLayout.opacity = 255;
if (this._lightbox)
this._lightbox.show();
this._group.opacity = 0;
@@ -227,7 +227,7 @@ const ModalDialog = new Lang.Class({
this._initialKeyFocus = actor;
this._initialKeyFocusDestroyId = actor.connect('destroy', Lang.bind(this, function() {
this._initialKeyFocus = this.dialogLayout;
this._initialKeyFocus = this._dialogLayout;
this._initialKeyFocusDestroyId = 0;
}));
},
@@ -320,7 +320,7 @@ const ModalDialog = new Lang.Class({
return;
this.popModal(timestamp);
Tweener.addTween(this.dialogLayout,
Tweener.addTween(this._dialogLayout,
{ opacity: 0,
time: FADE_OUT_DIALOG_TIME,
transition: 'easeOutQuad',

View File

@@ -135,10 +135,7 @@ const NetworkSecretDialog = new Lang.Class({
} else
secret.valid = true;
secretTable.add(label, { row: pos, col: 0,
x_expand: false, x_fill: true,
x_align: St.Align.START,
y_fill: false, y_align: St.Align.MIDDLE });
secretTable.add(label, { row: pos, col: 0, x_expand: false, x_fill: true, x_align: St.Align.START, y_align: St.Align.START });
secretTable.add(secret.entry, { row: pos, col: 1, x_expand: true, x_fill: true, y_align: St.Align.END });
pos++;
@@ -168,7 +165,6 @@ const NetworkSecretDialog = new Lang.Class({
}
this._okButton.button.reactive = valid;
this._okButton.button.can_focus = valid;
},
_onOk: function() {

View File

@@ -256,7 +256,6 @@ const NotificationDaemon = new Lang.Class({
Mainloop.idle_add(Lang.bind(this,
function () {
this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
return false;
}));
return invocation.return_value(GLib.Variant.new('(u)', [id]));
}
@@ -357,7 +356,8 @@ const NotificationDaemon = new Lang.Class({
let gicon = this._iconForNotificationData(icon, hints);
let iconActor = new St.Icon({ gicon: gicon,
icon_size: MessageTray.NOTIFICATION_ICON_SIZE });
icon_type: St.IconType.FULLCOLOR,
icon_size: source.ICON_SIZE });
if (notification == null) {
notification = new MessageTray.Notification(source, summary, body,
@@ -583,12 +583,18 @@ const Source = new Lang.Class({
this.notifications.length > 0)
return false;
let id = global.connect('notify::stage-input-mode', Lang.bind(this, function () {
global.disconnect(id);
if (Main.overview.visible) {
// We can't just connect to Main.overview's 'hidden' signal,
// because it's emitted *before* it calls popModal()...
let id = global.connect('notify::stage-input-mode', Lang.bind(this,
function () {
global.disconnect(id);
this.trayIcon.click(event);
}));
Main.overview.hide();
} else {
this.trayIcon.click(event);
}));
Main.overview.hide();
}
return true;
},
@@ -624,16 +630,6 @@ const Source = new Lang.Class({
}
},
setTitle: function(title) {
// Do nothing if .app is set, we don't want to override the
// app name with whatever is provided through libnotify (usually
// garbage)
if (this.app)
return;
this.parent(title);
},
open: function(notification) {
this.destroyNonResidentNotifications();
this.openApp();

View File

@@ -10,14 +10,19 @@ const St = imports.gi.St;
const Shell = imports.gi.Shell;
const Gdk = imports.gi.Gdk;
const AppDisplay = imports.ui.appDisplay;
const Dash = imports.ui.dash;
const DND = imports.ui.dnd;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const Panel = imports.ui.panel;
const Params = imports.misc.params;
const PlaceDisplay = imports.ui.placeDisplay;
const RemoteSearch = imports.ui.remoteSearch;
const Tweener = imports.ui.tweener;
const ViewSelector = imports.ui.viewSelector;
const Wanda = imports.ui.wanda;
const WorkspacesView = imports.ui.workspacesView;
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
// Time for initial animation going into Overview mode
@@ -70,13 +75,14 @@ const ShellInfo = new Lang.Class({
let notification = null;
if (this._source.notifications.length == 0) {
notification = new MessageTray.Notification(this._source, text, null);
notification.setTransient(true);
notification.setShowWhenLocked(true);
} else {
notification = this._source.notifications[0];
notification.update(text, null, { clear: true });
}
notification.setTransient(true);
this._undoCallback = undoCallback;
if (undoCallback) {
notification.addButton('system-undo',
@@ -138,6 +144,8 @@ const Overview = new Lang.Class({
this._capturedEventId = 0;
this._buttonPressId = 0;
this._workspacesDisplay = null;
this.visible = false; // animating to overview, in overview, animating out
this._shown = false; // show() and not hide()
this._shownTemporarily = false; // showTemporarily() and not hideTemporarily()
@@ -184,23 +192,29 @@ const Overview = new Lang.Class({
this._shellInfo = new ShellInfo();
this._searchEntry = new St.Entry({ name: 'searchEntry',
/* Translators: this is the text displayed
in the search entry when no search is
active; it should not exceed ~30
characters. */
hint_text: _("Type to search..."),
track_hover: true,
can_focus: true });
this._group.add_actor(this._searchEntry);
this._dash = new Dash.Dash();
this._viewSelector = new ViewSelector.ViewSelector(this._searchEntry,
this._dash.showAppsButton);
this._viewSelector = new ViewSelector.ViewSelector();
this._group.add_actor(this._viewSelector.actor);
this._group.add_actor(this._dash.actor);
this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
this._viewSelector.addViewTab('windows', _("Windows"), this._workspacesDisplay.actor, 'text-x-generic');
let appView = new AppDisplay.AllAppDisplay();
this._viewSelector.addViewTab('applications', _("Applications"), appView.actor, 'system-run');
// Default search providers
// Wanda comes obviously first
this.addSearchProvider(new Wanda.WandaSearchProvider());
this.addSearchProvider(new AppDisplay.AppSearchProvider());
this.addSearchProvider(new AppDisplay.SettingsSearchProvider());
this.addSearchProvider(new PlaceDisplay.PlaceSearchProvider());
// Load remote search providers provided by applications
RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, this.addSearchProvider));
// TODO - recalculate everything when desktop size changes
this._dash = new Dash.Dash();
this._group.add_actor(this._dash.actor);
this._dash.actor.add_constraint(this._viewSelector.constrainY);
this._dash.actor.add_constraint(this._viewSelector.constrainHeight);
this.dashIconSize = this._dash.iconSize;
this._dash.connect('icon-size-changed',
@@ -210,7 +224,7 @@ const Overview = new Lang.Class({
// Translators: this is the name of the dock/favorites area on
// the left of the overview
Main.ctrlAltTabManager.addGroup(this._dash.actor, _("Dash"), 'user-bookmarks-symbolic');
Main.ctrlAltTabManager.addGroup(this._dash.actor, _("Dash"), 'user-bookmarks');
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._relayout));
this._relayout();
@@ -486,13 +500,13 @@ const Overview = new Lang.Class({
this._coverPane.set_position(0, contentY);
this._coverPane.set_size(primary.width, contentHeight);
let searchWidth = this._searchEntry.get_width();
let searchHeight = this._searchEntry.get_height();
let searchX = (primary.width - searchWidth) / 2;
let searchY = contentY + this._spacing;
let dashWidth = Math.round(DASH_SPLIT_FRACTION * primary.width);
let dashY = searchY + searchHeight + this._spacing;
let viewWidth = primary.width - dashWidth - this._spacing;
let viewHeight = contentHeight - 2 * this._spacing;
let viewY = contentY + this._spacing;
let viewX = rtl ? 0 : dashWidth + this._spacing;
// Set the dash's x position - y is handled by a constraint
let dashX;
if (rtl) {
this._dash.actor.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
@@ -500,14 +514,8 @@ const Overview = new Lang.Class({
} else {
dashX = 0;
}
this._dash.actor.set_x(dashX);
let viewX = rtl ? 0 : dashWidth + this._spacing;
let viewY = searchY + searchHeight + this._spacing;
let viewWidth = primary.width - dashWidth - this._spacing;
let viewHeight = contentHeight - this._spacing - viewY;
this._searchEntry.set_position(searchX, searchY);
this._dash.actor.set_position(dashX, dashY);
this._viewSelector.actor.set_position(viewX, viewY);
this._viewSelector.actor.set_size(viewWidth, viewHeight);
},
@@ -557,28 +565,6 @@ const Overview = new Lang.Class({
Lang.bind(this, this._onButtonPress));
},
fadeInDesktop: function() {
this._desktopFade.opacity = 0;
this._desktopFade.show();
Tweener.addTween(this._desktopFade,
{ opacity: 255,
time: ANIMATION_TIME,
transition: 'easeOutQuad' });
},
fadeOutDesktop: function() {
if (!this._desktopFade.child)
this._desktopFade.child = this._getDesktopClone();
this._desktopFade.opacity = 255;
this._desktopFade.show();
Tweener.addTween(this._desktopFade,
{ opacity: 0,
time: ANIMATION_TIME,
transition: 'easeOutQuad'
});
},
_animateVisible: function() {
if (this.visible || this.animationInProgress)
return;
@@ -599,7 +585,21 @@ const Overview = new Lang.Class({
global.window_group.hide();
this._group.show();
this._background.show();
this._viewSelector.show();
this._workspacesDisplay.show();
if (!this._desktopFade.child)
this._desktopFade.child = this._getDesktopClone();
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows()) {
this._desktopFade.opacity = 255;
this._desktopFade.show();
Tweener.addTween(this._desktopFade,
{ opacity: 0,
time: ANIMATION_TIME,
transition: 'easeOutQuad'
});
}
this._group.opacity = 0;
Tweener.addTween(this._group,
@@ -726,7 +726,16 @@ const Overview = new Lang.Class({
this.animationInProgress = true;
this._hideInProgress = true;
this._viewSelector.zoomFromOverview();
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows()) {
this._desktopFade.opacity = 0;
this._desktopFade.show();
Tweener.addTween(this._desktopFade,
{ opacity: 255,
time: ANIMATION_TIME,
transition: 'easeOutQuad' });
}
this._workspacesDisplay.zoomFromOverview();
// Make other elements fade out.
Tweener.addTween(this._group,
@@ -768,7 +777,8 @@ const Overview = new Lang.Class({
global.window_group.show();
this._viewSelector.hide();
this._workspacesDisplay.hide();
this._desktopFade.hide();
this._background.hide();
this._group.hide();

View File

@@ -14,14 +14,13 @@ const St = imports.gi.St;
const Signals = imports.signals;
const Atk = imports.gi.Atk;
const Config = imports.misc.config;
const CtrlAltTab = imports.ui.ctrlAltTab;
const DND = imports.ui.dnd;
const Layout = imports.ui.layout;
const Overview = imports.ui.overview;
const PopupMenu = imports.ui.popupMenu;
const PanelMenu = imports.ui.panelMenu;
const DateMenu = imports.ui.dateMenu;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
@@ -222,14 +221,14 @@ const AppMenuButton = new Lang.Class({
Name: 'AppMenuButton',
Extends: PanelMenu.Button,
_init: function(panel) {
_init: function(menuManager) {
this.parent(0.0, null, true);
this.actor.accessible_role = Atk.Role.MENU;
this._startingApps = [];
this._menuManager = panel.menuManager;
this._menuManager = menuManager;
this._targetApp = null;
this._appMenuNotifyId = 0;
this._actionGroupNotifyId = 0;
@@ -286,7 +285,7 @@ const AppMenuButton = new Lang.Class({
},
show: function() {
if (this._visible || Main.screenShield.locked)
if (this._visible)
return;
this._visible = true;
@@ -469,12 +468,10 @@ const AppMenuButton = new Lang.Class({
},
setLockedState: function(locked) {
if (locked) {
if (locked)
this.hide();
} else {
this.show();
else
this._sync();
}
},
_sync: function() {
@@ -902,29 +899,6 @@ const PanelCorner = new Lang.Class({
}
});
const PANEL_ITEM_IMPLEMENTATIONS = {
'activities': ActivitiesButton,
'appMenu': AppMenuButton,
'dateMenu': imports.ui.dateMenu.DateMenuButton,
'a11y': imports.ui.status.accessibility.ATIndicator,
'volume': imports.ui.status.volume.Indicator,
'battery': imports.ui.status.power.Indicator,
'lockScreen': imports.ui.status.lockScreenMenu.Indicator,
'keyboard': imports.ui.status.keyboard.InputSourceIndicator,
'powerMenu': imports.gdm.powerMenu.PowerMenuButton,
'userMenu': imports.ui.userMenu.UserMenuButton
};
if (Config.HAVE_BLUETOOTH)
PANEL_ITEM_IMPLEMENTATIONS['bluetooth'] =
imports.ui.status.bluetooth.Indicator;
try {
PANEL_ITEM_IMPLEMENTATIONS['network'] =
imports.ui.status.network.NMApplet;
} catch(e) {
log('NMApplet is not supported. It is possible that your NetworkManager version is too old');
}
const Panel = new Lang.Class({
Name: 'Panel',
@@ -934,7 +908,7 @@ const Panel = new Lang.Class({
reactive: true });
this.actor._delegate = this;
this.statusArea = {};
this._statusArea = {};
Main.overview.connect('shown', Lang.bind(this, function () {
this.actor.add_style_class_name('in-overview');
@@ -945,7 +919,7 @@ const Panel = new Lang.Class({
Main.screenShield.connect('lock-status-changed', Lang.bind(this, this._onLockStateChanged));
this.menuManager = new PopupMenu.PopupMenuManager(this);
this._menus = new PopupMenu.PopupMenuManager(this);
this._leftBox = new St.BoxLayout({ name: 'panelLeft' });
this.actor.add_actor(this._leftBox);
@@ -972,8 +946,29 @@ const Panel = new Lang.Class({
this.actor.connect('allocate', Lang.bind(this, this._allocate));
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
/* Button on the left side of the panel. */
if (Main.sessionMode.hasOverview) {
this._activitiesButton = new ActivitiesButton();
this._activities = this._activitiesButton.actor;
this._leftBox.add(this._activities);
// The activities button has a pretend menu, so as to integrate
// more cleanly with the rest of the panel
this._menus.addMenu(this._activitiesButton.menu);
}
if (Main.sessionMode.hasAppMenu) {
this._appMenu = new AppMenuButton(this._menus);
this._leftBox.add(this._appMenu.actor);
}
/* center */
this._dateMenu = new DateMenu.DateMenuButton();
this._centerBox.add(this._dateMenu.actor, { y_fill: true });
this._menus.addMenu(this._dateMenu.menu);
Main.layoutManager.panelBox.add(this.actor);
Main.ctrlAltTabManager.addGroup(this.actor, _("Top Bar"), 'start-here-symbolic',
Main.ctrlAltTabManager.addGroup(this.actor, _("Top Bar"), 'start-here',
{ sortGroup: CtrlAltTab.SortGroup.TOP });
},
@@ -1091,71 +1086,76 @@ const Panel = new Lang.Class({
},
openAppMenu: function() {
let indicator = this.statusArea.appMenu;
if (!indicator) // appMenu not supported by current session mode
return;
let menu = indicator.menu;
if (!indicator.actor.reactive || menu.isOpen)
let menu = this._appMenu.menu;
if (!this._appMenu.actor.reactive || menu.isOpen)
return;
menu.open();
menu.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
},
init: function() {
let panel = Main.sessionMode.panel;
this._initBox(panel.left, this._leftBox);
this._initBox(panel.center, this._centerBox);
this._initBox(panel.right, this._rightBox);
},
_initBox: function(elements, box) {
for (let i = 0; i < elements.length; i++) {
let role = elements[i];
let constructor = PANEL_ITEM_IMPLEMENTATIONS[role];
startStatusArea: function() {
for (let i = 0; i < Main.sessionMode.statusArea.order.length; i++) {
let role = Main.sessionMode.statusArea.order[i];
let constructor = Main.sessionMode.statusArea.implementation[role];
if (!constructor) {
// panel icon is not supported (can happen for
// bluetooth or network)
// This icon is not implemented (this is a bug)
continue;
}
let indicator = new constructor(this);
this._addToPanelBox(role, indicator, i, box);
let indicator = new constructor();
this.addToStatusArea(role, indicator, i);
}
},
_addToPanelBox: function(role, indicator, position, box) {
box.insert_child_at_index(indicator.actor, position);
if (indicator.menu)
this.menuManager.addMenu(indicator.menu);
this.statusArea[role] = indicator;
let destroyId = indicator.connect('destroy', Lang.bind(this, function(emitter) {
delete this.statusArea[role];
emitter.disconnect(destroyId);
}));
_insertStatusItem: function(actor, position) {
let children = this._rightBox.get_children();
let i;
for (i = children.length - 1; i >= 0; i--) {
let rolePosition = children[i]._rolePosition;
if (position > rolePosition) {
this._rightBox.insert_child_at_index(actor, i + 1);
break;
}
}
if (i == -1) {
// If we didn't find a position, we must be first
this._rightBox.insert_child_at_index(actor, 0);
}
actor._rolePosition = position;
},
addToStatusArea: function(role, indicator, position, box) {
if (this.statusArea[role])
addToStatusArea: function(role, indicator, position) {
if (this._statusArea[role])
throw new Error('Extension point conflict: there is already a status indicator for role ' + role);
if (!(indicator instanceof PanelMenu.Button))
throw new TypeError('Status indicator must be an instance of PanelMenu.Button');
position = position || 0;
let boxes = {
left: this._leftBox,
center: this._centerBox,
right: this._rightBox
};
let boxContainer = boxes[box] || this._rightBox;
this._addToPanelBox(role, indicator, position, boxContainer);
if (!position)
position = 0;
this._insertStatusItem(indicator.actor, position);
if (indicator.menu)
this._menus.addMenu(indicator.menu);
this._statusArea[role] = indicator;
let destroyId = indicator.connect('destroy', Lang.bind(this, function(emitter) {
delete this._statusArea[role];
emitter.disconnect(destroyId);
}));
return indicator;
},
_onLockStateChanged: function(shield, locked) {
for (let id in this.statusArea)
this.statusArea[id].setLockedState(locked);
if (this._activitiesButton)
this._activitiesButton.setLockedState(locked);
if (this._appMenu)
this._appMenu.setLockedState(locked);
if (this._dateMenu)
this._dateMenu.setLockedState(locked);
for (let id in this._statusArea)
this._statusArea[id].setLockedState(locked);
},
});

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 Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
@@ -183,7 +182,8 @@ const Button = new Lang.Class({
_onMenuKeyPress: function(actor, event) {
let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_Left || symbol == Clutter.KEY_Right) {
let group = global.focus_manager.get_group(this.actor);
let focusManager = St.FocusManager.get_for_stage(global.stage);
let group = focusManager.get_group(this.actor);
if (group) {
let direction = (symbol == Clutter.KEY_Left) ? Gtk.DirectionType.LEFT : Gtk.DirectionType.RIGHT;
group.navigate_focus(this.actor, direction, false);
@@ -231,36 +231,19 @@ const SystemStatusButton = new Lang.Class({
_init: function(iconName, nameText) {
this.parent(0.0, nameText);
this._iconActor = new St.Icon({ icon_name: iconName,
icon_type: St.IconType.SYMBOLIC,
style_class: 'system-status-icon' });
this.actor.add_actor(this._iconActor);
this.actor.add_style_class_name('panel-status-button');
this._box = new St.BoxLayout({ style_class: 'panel-status-button-box' });
this.actor.add_actor(this._box);
if (iconName)
this.setIcon(iconName);
},
addIcon: function(gicon) {
let icon = new St.Icon({ gicon: gicon,
style_class: 'system-status-icon' });
this._box.add_actor(icon);
return icon;
},
setIcon: function(iconName) {
// Need to first add a NULL GIcon and then set icon_name, to ensure
// compatibility with -symbolic fallbacks
if (!this.mainIcon)
this.mainIcon = this.addIcon(null);
this.mainIcon.icon_name = iconName;
this._iconActor.icon_name = iconName;
},
setGIcon: function(gicon) {
if (this.mainIcon)
this.mainIcon.gicon = gicon;
else
this.mainIcon = this.addIcon(gicon);
this._iconActor.gicon = gicon;
}
});

View File

@@ -153,8 +153,26 @@ const PlacesManager = new Lang.Class({
Gio.app_info_launch_default_for_uri(desktopUri, _makeLaunchContext(params));
});
this._connect = new PlaceInfo('special:connect', _("Connect to..."),
function (size) {
// do NOT use St.Icon here, it crashes the shell
// see wanda.js for details
return St.TextureCache.get_default().load_icon_name(null,
'applications-internet',
St.IconType.FULLCOLOR,
size);
},
function (params) {
// BUG: nautilus-connect-server doesn't have a desktop file, so we can't
// launch it with the workspace from params. It's probably pretty rare
// and odd to drag this place onto a workspace in any case
Util.spawn(['nautilus-connect-server']);
});
this._defaultPlaces.push(this._home);
this._defaultPlaces.push(this._desktopMenu);
this._defaultPlaces.push(this._connect);
/*
* Show devices, code more or less ported from nautilus-places-sidebar.c

View File

@@ -1,126 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell;
// We stop polling if the user is idle for more than this amount of time
const IDLE_TIME = 1000;
// This file implements a reasonably efficient system for tracking the position
// of the mouse pointer. We simply query the pointer from the X server in a loop,
// but we turn off the polling when the user is idle.
let _pointerWatcher = null;
function getPointerWatcher() {
if (_pointerWatcher == null)
_pointerWatcher = new PointerWatcher();
return _pointerWatcher;
}
const PointerWatch = new Lang.Class({
Name: 'PointerWatch',
_init: function(watcher, interval, callback) {
this.watcher = watcher;
this.interval = interval;
this.callback = callback;
},
// remove:
// remove this watch. This function may safely be called
// while the callback is executing.
remove: function() {
this.watcher._removeWatch(this);
}
});
const PointerWatcher = new Lang.Class({
Name: 'PointerWatcher',
_init: function() {
let idleMonitor = Shell.IdleMonitor.get();
idleMonitor.add_watch(IDLE_TIME,
Lang.bind(this, this._onIdleMonitorWatch));
this._idle = idleMonitor.get_idletime() > IDLE_TIME;
this._watches = [];
this.pointerX = null;
this.pointerY = null;
},
// addWatch:
// @interval: hint as to the time resolution needed. When the user is
// not idle, the position of the pointer will be queried at least
// once every this many milliseconds.
// @callback: function to call when the pointer position changes - takes
// two arguments, X and Y.
//
// Set up a watch on the position of the mouse pointer. Returns a
// PointerWatch object which has a remove() method to remove the watch.
addWatch: function(interval, callback) {
// Avoid unreliably calling the watch for the current position
this._updatePointer();
let watch = new PointerWatch(this, interval, callback);
this._watches.push(watch);
this._updateTimeout();
return watch;
},
_removeWatch: function(watch) {
for (let i = 0; i < this._watches.length; i++) {
if (this._watches[i] == watch) {
this._watches.splice(i, 1);
this._updateTimeout();
return;
}
}
},
_onIdleMonitorWatch: function(monitor, id, userBecameIdle) {
this._idle = userBecameIdle;
if (!userBecameIdle)
this._updatePointer();
this._updateTimeout();
},
_updateTimeout: function() {
if (this._timeoutId) {
Mainloop.source_remove(this._timeoutId);
this._timeoutId = 0;
}
if (this._idle || this._watches.length == 0)
return;
let minInterval = this._watches[0].interval;
for (let i = 1; i < this._watches.length; i++)
minInterval = Math.min(this._watches[i].interval, minInterval);
this._timeoutId = Mainloop.timeout_add(minInterval,
Lang.bind(this, this._onTimeout));
},
_onTimeout: function() {
this._updatePointer();
return true;
},
_updatePointer: function() {
let [x, y, mods] = global.get_pointer();
if (this.pointerX == x && this.pointerY == y)
return;
this.pointerX = x;
this.pointerY = y;
for (let i = 0; i < this._watches.length;) {
let watch = this._watches[i];
watch.callback(x, y);
if (watch == this._watches[i]) // guard against self-removal
i++;
}
}
});

View File

@@ -35,9 +35,6 @@ const PolkitAgent = imports.gi.PolkitAgent;
const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry;
const UserMenu = imports.ui.userMenu;
const DIALOG_ICON_SIZE = 48;
const AuthenticationDialog = new Lang.Class({
Name: 'AuthenticationDialog',
@@ -120,11 +117,9 @@ const AuthenticationDialog = new Lang.Class({
let userBox = new St.BoxLayout({ style_class: 'polkit-dialog-user-layout',
vertical: false });
messageBox.add(userBox);
this._userAvatar = new UserMenu.UserAvatarWidget(this._user,
{ iconSize: DIALOG_ICON_SIZE,
styleClass: 'polkit-dialog-user-icon' });
this._userAvatar.actor.hide();
userBox.add(this._userAvatar.actor,
this._userIcon = new St.Icon();
this._userIcon.hide();
userBox.add(this._userIcon,
{ x_fill: true,
y_fill: false,
x_align: St.Align.END,
@@ -319,8 +314,18 @@ const AuthenticationDialog = new Lang.Class({
_onUserChanged: function() {
if (this._user.is_loaded) {
this._userAvatar.update();
this._userAvatar.actor.show();
if (this._userIcon) {
let iconFileName = this._user.get_icon_file();
let iconFile = Gio.file_new_for_path(iconFileName);
let icon;
if (iconFile.query_exists(null)) {
icon = new Gio.FileIcon({file: iconFile});
} else {
icon = new Gio.ThemedIcon({name: 'avatar-default'});
}
this._userIcon.set_gicon (icon);
this._userIcon.show();
}
}
},

View File

@@ -37,13 +37,12 @@ const PopupBaseMenuItem = new Lang.Class({
activate: true,
hover: true,
sensitive: true,
style_class: null,
can_focus: true
style_class: null
});
this.actor = new Shell.GenericContainer({ style_class: 'popup-menu-item',
reactive: params.reactive,
track_hover: params.reactive,
can_focus: params.can_focus,
can_focus: params.reactive,
accessible_role: Atk.Role.MENU_ITEM});
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
@@ -70,9 +69,10 @@ const PopupBaseMenuItem = new Lang.Class({
}
if (params.reactive && params.hover)
this.actor.connect('notify::hover', Lang.bind(this, this._onHoverChanged));
this.actor.connect('key-focus-in', Lang.bind(this, this._onKeyFocusIn));
this.actor.connect('key-focus-out', Lang.bind(this, this._onKeyFocusOut));
if (params.reactive) {
this.actor.connect('key-focus-in', Lang.bind(this, this._onKeyFocusIn));
this.actor.connect('key-focus-out', Lang.bind(this, this._onKeyFocusOut));
}
},
_onStyleChanged: function (actor) {
@@ -134,7 +134,6 @@ const PopupBaseMenuItem = new Lang.Class({
this.sensitive = sensitive;
this.actor.reactive = sensitive;
this.actor.can_focus = sensitive;
this.emit('sensitive-changed', sensitive);
},
@@ -180,14 +179,12 @@ const PopupBaseMenuItem = new Lang.Class({
this._dot = new St.DrawingArea({ style_class: 'popup-menu-item-dot' });
this._dot.connect('repaint', Lang.bind(this, this._onRepaintDot));
this.actor.add_actor(this._dot);
this.actor.add_accessible_state (Atk.StateType.CHECKED);
} else {
if (!this._dot)
return;
this._dot.destroy();
this._dot = null;
this.actor.remove_accessible_state (Atk.StateType.CHECKED);
}
},
@@ -398,8 +395,7 @@ const PopupSeparatorMenuItem = new Lang.Class({
Extends: PopupBaseMenuItem,
_init: function () {
this.parent({ reactive: false,
can_focus: false});
this.parent({ reactive: false });
this._drawingArea = new St.DrawingArea({ style_class: 'popup-separator-menu-item' });
this.addActor(this._drawingArea, { span: -1, expand: true });
@@ -718,8 +714,7 @@ const Switch = new Lang.Class({
_init: function(state) {
this.actor = new St.Bin({ style_class: 'toggle-switch',
accessible_role: Atk.Role.CHECK_BOX,
can_focus: true });
accessible_role: Atk.Role.CHECK_BOX});
// Translators: this MUST be either "toggle-switch-us"
// (for toggle switches containing the English words
// "ON" and "OFF") or "toggle-switch-intl" (for toggle
@@ -867,6 +862,10 @@ const PopupMenuBase = new Lang.Class({
// for the menu which causes its prelight state to freeze
this.blockSourceEvents = false;
// Can be set while a menu is up to let all events through without special
// menu handling useful for scrollbars in menus, and probably not otherwise.
this.passEvents = false;
this._activeMenuItem = null;
this._childMenus = [];
this._settingsActions = { };
@@ -1052,17 +1051,14 @@ const PopupMenuBase = new Lang.Class({
if (menuItem instanceof PopupMenuSection) {
this._connectSubMenuSignals(menuItem, menuItem);
menuItem._parentOpenStateChangedId = this.connect('open-state-changed',
menuItem._closingId = this.connect('open-state-changed',
function(self, open) {
if (open)
menuItem.open();
else
menuItem.close();
if (!open)
menuItem.close(BoxPointer.PopupAnimation.FADE);
});
menuItem.connect('destroy', Lang.bind(this, function() {
menuItem.disconnect(menuItem._subMenuActivateId);
menuItem.disconnect(menuItem._subMenuActiveChangeId);
this.disconnect(menuItem._parentOpenStateChangedId);
this.length--;
}));
@@ -1288,6 +1284,24 @@ const PopupSubMenu = new Lang.Class({
hscrollbar_policy: Gtk.PolicyType.NEVER,
vscrollbar_policy: Gtk.PolicyType.NEVER });
// StScrollbar plays dirty tricks with events, calling
// clutter_set_motion_events_enabled (FALSE) during the scroll; this
// confuses our event tracking, so we just turn it off during the
// scroll.
let vscroll = this.actor.get_vscroll_bar();
vscroll.connect('scroll-start',
Lang.bind(this, function() {
let topMenu = this._getTopMenu();
if (topMenu)
topMenu.passEvents = true;
}));
vscroll.connect('scroll-stop',
Lang.bind(this, function() {
let topMenu = this._getTopMenu();
if (topMenu)
topMenu.passEvents = false;
}));
this.actor.add_actor(this.box);
this.actor._delegate = this;
this.actor.clip_to_allocation = true;
@@ -1443,7 +1457,7 @@ const PopupMenuSection = new Lang.Class({
// deliberately ignore any attempt to open() or close(), but emit the
// corresponding signal so children can still pick it up
open: function() { this.emit('open-state-changed', true); },
open: function(animate) { this.emit('open-state-changed', true); },
close: function() { this.emit('open-state-changed', false); },
destroy: function() {
@@ -1881,7 +1895,7 @@ const RemoteMenu = new Lang.Class({
}));
}
item.actor.reactive = item.actor.can_focus = action.enabled;
item.actor.reactive = action.enabled;
destroyId = item.connect('destroy', Lang.bind(this, function() {
item.disconnect(destroyId);
@@ -2013,7 +2027,7 @@ const RemoteMenu = new Lang.Class({
if (action.items.length) {
for (let i = 0; i < action.items.length; i++) {
let item = action.items[i];
item.actor.reactive = item.actor.can_focus = action.enabled;
item.actor.reactive = action.enabled;
}
}
}
@@ -2264,6 +2278,9 @@ const PopupMenuManager = new Lang.Class({
this._owner.menuEventFilter(event))
return true;
if (this._activeMenu != null && this._activeMenu.passEvents)
return false;
if (this._didPop) {
this._didPop = false;
return true;

View File

@@ -34,17 +34,16 @@ var SearchProviderProxy = Gio.DBusProxy.makeProxyWrapper(SearchProviderIface);
function loadRemoteSearchProviders(addProviderCallback) {
let dataDirs = GLib.get_system_data_dirs();
let loadedProviders = {};
for (let i = 0; i < dataDirs.length; i++) {
let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', 'search-providers']);
let dir = Gio.file_new_for_path(path);
if (!dir.query_exists(null))
continue;
loadRemoteSearchProvidersFromDir(dir, loadedProviders, addProviderCallback);
loadRemoteSearchProvidersFromDir(dir, addProviderCallback);
}
};
function loadRemoteSearchProvidersFromDir(dir, loadedProviders, addProviderCallback) {
function loadRemoteSearchProvidersFromDir(dir, addProviderCallback) {
let dirPath = dir.get_path();
FileUtils.listDirAsync(dir, Lang.bind(this, function(files) {
for (let i = 0; i < files.length; i++) {
@@ -66,9 +65,6 @@ function loadRemoteSearchProvidersFromDir(dir, loadedProviders, addProviderCallb
let busName = keyfile.get_string(group, 'BusName');
let objectPath = keyfile.get_string(group, 'ObjectPath');
if (loadedProviders[objectPath])
continue;
let appInfo = null;
try {
let desktopId = keyfile.get_string(group, 'DesktopId');
@@ -90,7 +86,6 @@ function loadRemoteSearchProvidersFromDir(dir, loadedProviders, addProviderCallb
icon,
busName,
objectPath);
loadedProviders[objectPath] = remoteProvider;
} catch(e) {
log('Failed to add search provider "%s": %s'.format(title, e.toString()));
continue;
@@ -117,7 +112,8 @@ const RemoteSearchProvider = new Lang.Class({
createIcon: function(size, meta) {
if (meta['gicon']) {
return new St.Icon({ gicon: Gio.icon_new_for_string(meta['gicon']),
icon_size: size });
icon_size: size,
icon_type: St.IconType.FULLCOLOR });
} else if (meta['icon-data']) {
let [width, height, rowStride, hasAlpha,
bitsPerSample, nChannels, data] = meta['icon-data'];
@@ -128,7 +124,8 @@ const RemoteSearchProvider = new Lang.Class({
// Ugh, but we want to fall back to something ...
return new St.Icon({ icon_name: 'text-x-generic',
icon_size: size });
icon_size: size,
icon_type: St.IconType.FULLCOLOR });
},
_getResultsFinished: function(results, error) {

View File

@@ -1,20 +1,14 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Cairo = imports.cairo;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GnomeDesktop = imports.gi.GnomeDesktop;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Signals = imports.signals;
const St = imports.gi.St;
const TweenerEquations = imports.tweener.equations;
const GnomeSession = imports.misc.gnomeSession;
const Layout = imports.ui.layout;
const LoginManager = imports.misc.loginManager;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
@@ -23,16 +17,11 @@ const Tweener = imports.ui.tweener;
const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
const LOCK_ENABLED_KEY = 'lock-enabled';
const CURTAIN_SLIDE_TIME = 0.5;
const CURTAIN_SLIDE_TIME = 0.8;
// fraction of screen height the arrow must reach before completing
// the slide up automatically
const ARROW_DRAG_TRESHOLD = 0.1;
// Parameters for the arrow animation
const N_ARROWS = 3;
const ARROW_ANIMATION_TIME = 0.6;
const ARROW_ANIMATION_PEAK_OPACITY = 0.4;
// The distance in px that the lock screen will move to when pressing
// a key that has no effect in the lock screen (bumping it)
const BUMP_SIZE = 25;
@@ -88,8 +77,8 @@ const NotificationsBox = new Lang.Class({
_init: function() {
this.actor = new St.BoxLayout({ vertical: true,
name: 'screenShieldNotifications',
style_class: 'screen-shield-notifications-box' });
name: 'screenShieldNotifications',
style_class: 'screen-shield-notifications-box' });
this._residentNotificationBox = new St.BoxLayout({ vertical: true,
style_class: 'screen-shield-notifications-box' });
@@ -103,9 +92,8 @@ const NotificationsBox = new Lang.Class({
this._items = [];
Main.messageTray.getSummaryItems().forEach(Lang.bind(this, function(item) {
this._summaryItemAdded(Main.messageTray, item, true);
this._summaryItemAdded(Main.messageTray, item);
}));
this._updateVisibility();
this._summaryAddedId = Main.messageTray.connect('summary-item-added', Lang.bind(this, this._summaryItemAdded));
},
@@ -129,7 +117,7 @@ const NotificationsBox = new Lang.Class({
return;
}
let children = this._persistentNotificationBox.get_children();
let children = this._persistentNotificationBox.get_children()
this.actor.visible = children.some(function(a) { return a.visible; });
},
@@ -137,11 +125,11 @@ const NotificationsBox = new Lang.Class({
return source.hasResidentNotification() && !source.isChat;
},
_makeNotificationCountText: function(count, isChat) {
if (isChat)
return ngettext("%d new message", "%d new messages", count).format(count);
_makeNotificationCountText: function(source) {
if (source.isChat)
return ngettext("%d new message", "%d new messages", source.count).format(source.count);
else
return ngettext("%d new notification", "%d new notifications", count).format(count);
return ngettext("%d new notification", "%d new notifications", source.count).format(source.count);
},
_makeNotificationSource: function(source) {
@@ -157,19 +145,17 @@ const NotificationsBox = new Lang.Class({
style_class: 'screen-shield-notification-label' });
textBox.add(label);
let count = source.unseenCount;
let countLabel = new St.Label({ text: this._makeNotificationCountText(count, source.isChat),
let countLabel = new St.Label({ text: this._makeNotificationCountText(source),
style_class: 'screen-shield-notification-count-text' });
textBox.add(countLabel);
box.visible = count != 0;
box.visible = source.count != 0;
return [box, countLabel];
},
_summaryItemAdded: function(tray, item, dontUpdateVisibility) {
// Ignore transient sources, or sources explicitly marked not to show
// in the lock screen
if (item.source.isTransient || !item.source.showInLockScreen)
_summaryItemAdded: function(tray, item) {
// Ignore transient sources
if (item.source.isTransient)
return;
let obj = {
@@ -183,22 +169,20 @@ const NotificationsBox = new Lang.Class({
};
if (obj.resident) {
this._residentNotificationBox.add(item.notificationStackWidget);
item.closeButtonVisible = false;
item.prepareNotificationStackForShowing();
this._residentNotificationBox.add(item.notificationStackView);
} else {
[obj.sourceBox, obj.countLabel] = this._makeNotificationSource(item.source);
this._persistentNotificationBox.add(obj.sourceBox, { x_fill: false, x_align: St.Align.MIDDLE });
}
obj.contentUpdatedId = item.connect('content-updated', Lang.bind(this, this._onItemContentUpdated));
obj.sourceCountChangedId = item.source.connect('count-updated', Lang.bind(this, this._onSourceChanged));
obj.sourceCountChangedId = item.source.connect('count-changed', Lang.bind(this, this._onSourceChanged));
obj.sourceTitleChangedId = item.source.connect('title-changed', Lang.bind(this, this._onSourceChanged));
obj.sourceDestroyId = item.source.connect('destroy', Lang.bind(this, this._onSourceDestroy));
this._items.push(obj);
if (!dontUpdateVisibility)
this._updateVisibility();
this._updateVisibility();
},
_findSource: function(source) {
@@ -230,8 +214,7 @@ const NotificationsBox = new Lang.Class({
if (obj.resident && !itemShouldBeResident) {
// make into a regular item
obj.item.doneShowingNotificationStack();
this._residentNotificationBox.remove_actor(obj.item.notificationStackWidget);
this._residentNotificationBox.remove_actor(obj.item.notificationStackView);
[obj.sourceBox, obj.countLabel] = this._makeNotificationSource(obj.source);
this._persistentNotificationBox.add(obj.sourceBox);
@@ -239,16 +222,13 @@ const NotificationsBox = new Lang.Class({
// make into a resident item
obj.sourceBox.destroy();
obj.sourceBox = obj.countLabel = null;
obj.resident = true;
this._residentNotificationBox.add(obj.item.notificationStackWidget);
obj.item.closeButtonVisible = false;
obj.item.prepareNotificationStackForShowing();
this._residentNotificationBox.add(obj.item.notificationStackView);
} else {
// just update the counter
let count = obj.source.unseenCount;
obj.countLabel.text = this._makeNotificationCountText(count, obj.source.isChat);
obj.sourceBox.visible = count != 0;
obj.countLabel.text = this._makeNotificationCountText(obj.item.source);
obj.sourceBox.visible = obj.source.count != 0;
}
this._updateVisibility();
@@ -265,8 +245,8 @@ const NotificationsBox = new Lang.Class({
_removeItem: function(obj) {
if (obj.resident) {
this._residentNotificationBox.remove_actor(obj.item.notificationStackView);
obj.item.doneShowingNotificationStack();
this._residentNotificationBox.remove_actor(obj.item.notificationStackWidget);
} else {
obj.sourceBox.destroy();
}
@@ -277,62 +257,6 @@ const NotificationsBox = new Lang.Class({
},
});
const Arrow = new Lang.Class({
Name: 'Arrow',
Extends: St.Bin,
_init: function(params) {
this.parent(params);
this.x_fill = this.y_fill = true;
this.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
this._drawingArea = new St.DrawingArea();
this._drawingArea.connect('repaint', Lang.bind(this, this._drawArrow));
this.child = this._drawingArea;
this._shadowHelper = null;
this._shadowWidth = this._shadowHeight = 0;
},
_drawArrow: function(arrow) {
let cr = arrow.get_context();
let [w, h] = arrow.get_surface_size();
let node = this.get_theme_node();
let thickness = node.get_length('-arrow-thickness');
Clutter.cairo_set_source_color(cr, node.get_foreground_color());
cr.setLineCap(Cairo.LineCap.ROUND);
cr.setLineWidth(thickness);
cr.moveTo(thickness / 2, h - thickness / 2);
cr.lineTo(w/2, thickness);
cr.lineTo(w - thickness / 2, h - thickness / 2);
cr.stroke();
},
vfunc_style_changed: function() {
let node = this.get_theme_node();
this._shadow = node.get_shadow('-arrow-shadow');
if (this._shadow)
this._shadowHelper = St.ShadowHelper.new(this._shadow);
else
this._shadowHelper = null;
},
vfunc_paint: function() {
if (this._shadowHelper) {
this._shadowHelper.update(this._drawingArea);
let allocation = this._drawingArea.get_allocation_box();
let paintOpacity = this._drawingArea.get_paint_opacity();
this._shadowHelper.paint(allocation, paintOpacity);
}
this._drawingArea.paint();
}
});
/**
* To test screen shield, make sure to kill gnome-screensaver.
*
@@ -349,53 +273,38 @@ const ScreenShield = new Lang.Class({
_init: function() {
this.actor = Main.layoutManager.screenShieldGroup;
this._lockScreenState = MessageTray.State.HIDDEN;
this._lockScreenGroup = new St.Widget({ x_expand: true,
y_expand: true,
reactive: true,
can_focus: true,
name: 'lockScreenGroup',
layout_manager: new Clutter.BinLayout()
});
this._lockScreenGroup.connect('key-release-event',
Lang.bind(this, this._onLockScreenKeyRelease));
this._lockScreenGroup.connect('scroll-event',
Lang.bind(this, this._onLockScreenScroll));
this._lockScreenContents = new St.Widget({ layout_manager: new Clutter.BinLayout(),
name: 'lockScreenContents' });
this._lockScreenContents.add_constraint(new Layout.MonitorConstraint({ primary: true }));
this._background = Meta.BackgroundActor.new_for_screen(global.screen);
this._background.add_effect(new Clutter.BlurEffect());
this._background.add_effect(new Clutter.DesaturateEffect({ factor: 0.6 }));
this._lockScreenGroup.add_actor(this._background);
this._lockScreenGroup.add_actor(this._lockScreenContents);
this._arrowContainer = new St.BoxLayout({ style_class: 'screen-shield-arrows',
vertical: true,
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.END,
// HACK: without these, ClutterBinLayout
// ignores alignment properties on the actor
x_expand: true,
y_expand: true });
this._arrow = new St.DrawingArea({ style_class: 'arrow',
reactive: true,
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.END,
// HACK: without these, ClutterBinLayout
// ignores alignment properties on the actor
x_expand: true,
y_expand: true
});
this._arrow.connect('repaint', Lang.bind(this, this._drawArrow));
this._lockScreenGroup.add_actor(this._arrow);
for (let i = 0; i < N_ARROWS; i++) {
let arrow = new Arrow({ opacity: 0 });
this._arrowContainer.add_actor(arrow);
}
this._lockScreenContents.add_actor(this._arrowContainer);
let dragArea = new Clutter.Rect({ origin: new Clutter.Point({ x: 0, y: -global.screen_height, }),
size: new Clutter.Size({ width: global.screen_width,
height: global.screen_height }) });
let action = new Clutter.DragAction({ drag_axis: Clutter.DragAxis.Y_AXIS,
drag_area: dragArea });
let action = new Clutter.DragAction({ drag_axis: Clutter.DragAxis.Y_AXIS });
action.connect('drag-begin', Lang.bind(this, this._onDragBegin));
action.connect('drag-end', Lang.bind(this, this._onDragEnd));
this._lockScreenGroup.add_action(action);
this._lockDialogGroup = new St.Widget({ x_expand: true,
y_expand: true,
name: 'lockDialogGroup' });
y_expand: true });
this.actor.add_actor(this._lockDialogGroup);
this.actor.add_actor(this._lockScreenGroup);
@@ -412,11 +321,6 @@ const ScreenShield = new Lang.Class({
this._onStatusChanged(status);
}));
this._loginManager = LoginManager.getLoginManager();
this._loginSession = this._loginManager.getCurrentSessionProxy();
this._loginSession.connectSignal('Lock', Lang.bind(this, function() { this.lock(false); }));
this._loginSession.connectSignal('Unlock', Lang.bind(this, function() { this.unlock(); }));
this._settings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA });
this._isModal = false;
@@ -429,74 +333,40 @@ const ScreenShield = new Lang.Class({
fadeFactor: 1 });
},
_onLockScreenKeyRelease: function(actor, event) {
_onStageKeyRelease: function(actor, event) {
if (!this._isLocked)
return false;
if (event.get_key_symbol() == Clutter.KEY_Escape) {
this._ensureUnlockDialog();
this._hideLockScreen(true);
this._showUnlockDialog(true);
return true;
}
// Don't bump if the lock screen is not showing or is
// animating, as the bump overrides the animation and would
// remove any onComplete handler
if (this._lockScreenState == MessageTray.State.SHOWN)
this._bumpLockScreen();
this._bumpLockScreen();
return true;
},
_onLockScreenScroll: function(actor, event) {
if (this._lockScreenState != MessageTray.State.SHOWN)
return false;
_drawArrow: function() {
let cr = this._arrow.get_context();
let [w, h] = this._arrow.get_surface_size();
let node = this._arrow.get_theme_node();
let delta = 0;
if (event.get_scroll_direction() == Clutter.ScrollDirection.UP)
delta = 5;
else if (event.get_scroll_direction() == Clutter.ScrollDirection.SMOOTH)
delta = Math.max(0, event.get_scroll_delta()[0]);
Clutter.cairo_set_source_color(cr, node.get_foreground_color());
this._lockScreenScrollCounter += delta;
// 7 standard scrolls to lift up
if (this._lockScreenScrollCounter > 35) {
this._ensureUnlockDialog();
this._hideLockScreen(0);
}
return true;
},
_animateArrows: function() {
let arrows = this._arrowContainer.get_children();
let unitaryDelay = ARROW_ANIMATION_TIME / (arrows.length + 1);
let maxOpacity = 255 * ARROW_ANIMATION_PEAK_OPACITY;
for (let i = 0; i < arrows.length; i++) {
arrows.opacity = 0;
Tweener.addTween(arrows[i],
{ opacity: 0,
delay: unitaryDelay * (N_ARROWS - (i + 1)),
time: ARROW_ANIMATION_TIME,
transition: function(t, b, c, d) {
if (t < d/2)
return TweenerEquations.easeOutQuad(t, 0, maxOpacity, d/2);
else
return TweenerEquations.easeInQuad(t - d/2, maxOpacity, -maxOpacity, d/2);
}
});
}
return true;
cr.moveTo(0, h);
cr.lineTo(w/2, 0);
cr.lineTo(w, h);
cr.fill();
},
_onDragBegin: function() {
Tweener.removeTweens(this._lockScreenGroup);
this._lockScreenState = MessageTray.State.HIDING;
this._ensureUnlockDialog();
},
_onDragEnd: function(action, actor, eventX, eventY, modifiers) {
if (this._lockScreenGroup.y < -(ARROW_DRAG_TRESHOLD * global.stage.height)) {
// Complete motion automatically
this._hideLockScreen(true);
this._showUnlockDialog(true);
} else {
// restore the lock screen to its original place
// try to use the same speed as the normal animation
@@ -508,19 +378,9 @@ const ScreenShield = new Lang.Class({
time: time,
transition: 'linear',
onComplete: function() {
this._lockScreenGroup.fixed_position_set = false;
this._lockScreenState = MessageTray.State.SHOWN;
},
onCompleteScope: this,
this.fixed_position_set = false;
}
});
// If we have a unlock dialog, cancel it
if (this._dialog) {
this._dialog.cancel();
if (!this._keepDialog) {
this._dialog = null;
}
}
}
},
@@ -555,8 +415,7 @@ const ScreenShield = new Lang.Class({
showDialog: function() {
this.lock(true);
this._ensureUnlockDialog();
this._hideLockScreen(false);
this._showUnlockDialog(false);
},
_bumpLockScreen: function() {
@@ -574,9 +433,7 @@ const ScreenShield = new Lang.Class({
});
},
_hideLockScreen: function(animate) {
this._lockScreenState = MessageTray.State.HIDING;
_showUnlockDialog: function(animate) {
if (animate) {
// Tween the lock screen out of screen
// try to use the same speed regardless of original position
@@ -587,22 +444,12 @@ const ScreenShield = new Lang.Class({
{ y: -h,
time: time,
transition: 'linear',
onComplete: function() {
this._lockScreenHidden();
},
onCompleteScope: this,
onComplete: Lang.bind(this, this._hideLockScreen),
});
} else {
this._lockScreenHidden();
this._hideLockScreen();
}
},
_lockScreenHidden: function() {
this._lockScreenState = MessageTray.State.HIDDEN;
this._lockScreenGroup.hide();
},
_ensureUnlockDialog: function() {
if (!this._dialog) {
[this._dialog, this._keepDialog] = Main.sessionMode.createUnlockDialog(this._lockDialogGroup);
if (!this._dialog) {
@@ -643,9 +490,14 @@ const ScreenShield = new Lang.Class({
this.unlock();
},
_hideLockScreen: function() {
this._arrow.hide();
this._lockScreenGroup.hide();
},
_resetLockScreen: function(animate) {
this._lockScreenGroup.show();
this._lockScreenState = MessageTray.State.SHOWING;
this._arrow.show();
if (animate) {
this._lockScreenGroup.y = -global.screen_height;
@@ -655,36 +507,19 @@ const ScreenShield = new Lang.Class({
time: SHORT_FADE_TIME,
transition: 'linear',
onComplete: function() {
this._lockScreenShown();
this._lockScreenGroup.fixed_position_set = false;
this.emit('lock-screen-shown');
},
onCompleteScope: this
});
this._lockDialogGroup.opacity = 0;
Tweener.removeTweens(this._lockDialogGroup);
Tweener.addTween(this._lockDialogGroup,
{ opacity: 255,
time: SHORT_FADE_TIME,
transition: 'easeOutQuad' });
} else {
this._lockDialogGroup.opacity = 255;
this._lockScreenShown();
this._lockScreenGroup.fixed_position_set = false;
this.emit('lock-screen-shown');
}
this._lockScreenGroup.grab_key_focus();
},
_lockScreenShown: function() {
if (this._arrowAnimationId)
Mainloop.source_remove(this._arrowAnimationId);
this._arrowAnimationId = Mainloop.timeout_add(6000, Lang.bind(this, this._animateArrows));
this._animateArrows();
this._lockScreenState = MessageTray.State.SHOWN;
this._lockScreenGroup.fixed_position_set = false;
this._lockScreenScrollCounter = 0;
this.emit('lock-screen-shown');
if (!this._stageKeyHandler)
this._stageKeyHandler = global.stage.connect('key-release-event',
Lang.bind(this, this._onStageKeyRelease));
},
// Some of the actors in the lock screen are heavy in
@@ -699,7 +534,7 @@ const ScreenShield = new Lang.Class({
this._lockScreenContentsBox.add(this._clock.actor, { x_fill: true,
y_fill: true });
this._lockScreenContents.add_actor(this._lockScreenContentsBox);
this._lockScreenGroup.add_actor(this._lockScreenContentsBox);
if (this._settings.get_boolean('show-notifications')) {
this._notificationsBox = new NotificationsBox();
@@ -722,11 +557,6 @@ const ScreenShield = new Lang.Class({
this._lockScreenContentsBox.destroy();
if (this._arrowAnimationId) {
Mainloop.source_remove(this._arrowAnimationId);
this._arrowAnimationId = 0;
}
this._hasLockScreen = false;
},
@@ -738,11 +568,16 @@ const ScreenShield = new Lang.Class({
if (this._hasLockScreen)
this._clearLockScreen();
if (this._stageKeyHandler) {
global.stage.disconnect(this._stageKeyHandler);
this._stageKeyHandler = 0;
}
if (this._keepDialog) {
// The dialog must be kept alive,
// so immediately go back to it
// This will also reset _isLocked
this._ensureUnlockDialog();
this._showUnlockDialog(false);
return;
}
@@ -753,14 +588,12 @@ const ScreenShield = new Lang.Class({
this._lightbox.hide();
if (this._isModal) {
Main.popModal(this.actor);
this._isModal = false;
}
this._isLocked = false;
Main.popModal(this.actor);
this.actor.hide();
this._isModal = false;
this._isLocked = false;
this.emit('lock-status-changed', false);
},

View File

@@ -10,6 +10,8 @@ const Util = imports.misc.util;
const FileUtils = imports.misc.fileUtils;
const Main = imports.ui.main;
const DISABLED_OPEN_SEARCH_PROVIDERS_KEY = 'disabled-open-search-providers';
// Not currently referenced by the search API, but
// this enumeration can be useful for provider
// implementations.
@@ -167,6 +169,99 @@ const SearchProvider = new Lang.Class({
});
Signals.addSignalMethods(SearchProvider.prototype);
const OpenSearchSystem = new Lang.Class({
Name: 'OpenSearchSystem',
_init: function() {
this._providers = [];
global.settings.connect('changed::' + DISABLED_OPEN_SEARCH_PROVIDERS_KEY, Lang.bind(this, this._refresh));
this._refresh();
},
getProviders: function() {
let res = [];
for (let i = 0; i < this._providers.length; i++)
res.push({ id: i, name: this._providers[i].name });
return res;
},
setSearchTerms: function(terms) {
this._terms = terms;
},
_checkSupportedProviderLanguage: function(provider) {
if (provider.url.search(/{language}/) == -1)
return true;
let langs = GLib.get_language_names();
langs.push('en');
let lang = null;
for (let i = 0; i < langs.length; i++) {
for (let k = 0; k < provider.langs.length; k++) {
if (langs[i] == provider.langs[k])
lang = langs[i];
}
if (lang)
break;
}
provider.lang = lang;
return lang != null;
},
activateResult: function(id, params) {
let searchTerms = this._terms.join(' ');
let url = this._providers[id].url.replace('{searchTerms}', encodeURIComponent(searchTerms));
if (url.match('{language}'))
url = url.replace('{language}', this._providers[id].lang);
try {
Gio.app_info_launch_default_for_uri(url, global.create_app_launch_context());
} catch (e) {
// TODO: remove this after glib will be removed from moduleset
// In the default jhbuild, gio is in our prefix but gvfs is not
Util.spawn(['gvfs-open', url])
}
Main.overview.hide();
},
_addProvider: function(fileName) {
let path = global.datadir + '/open-search-providers/' + fileName;
let source = Shell.get_file_contents_utf8_sync(path);
let [success, name, url, langs, icon_uri] = Shell.parse_search_provider(source);
let provider ={ name: name,
url: url,
id: this._providers.length,
icon_uri: icon_uri,
langs: langs };
if (this._checkSupportedProviderLanguage(provider)) {
this._providers.push(provider);
this.emit('changed');
}
},
_refresh: function() {
this._providers = [];
let names = global.settings.get_strv(DISABLED_OPEN_SEARCH_PROVIDERS_KEY);
let file = Gio.file_new_for_path(global.datadir + '/open-search-providers');
FileUtils.listDirAsync(file, Lang.bind(this, function(files) {
for (let i = 0; i < files.length; i++) {
let enabled = true;
let name = files[i].get_name();
for (let k = 0; k < names.length; k++)
if (names[k] == name)
enabled = false;
if (enabled)
this._addProvider(name);
}
}));
}
});
Signals.addSignalMethods(OpenSearchSystem.prototype);
const SearchSystem = new Lang.Class({
Name: 'SearchSystem',

View File

@@ -173,9 +173,10 @@ const GridSearchResults = new Lang.Class({
const SearchResults = new Lang.Class({
Name: 'SearchResults',
_init: function(searchSystem) {
_init: function(searchSystem, openSearchSystem) {
this._searchSystem = searchSystem;
this._searchSystem.connect('search-updated', Lang.bind(this, this._updateResults));
this._openSearchSystem = openSearchSystem;
this.actor = new St.BoxLayout({ name: 'searchResults',
vertical: true });
@@ -190,7 +191,7 @@ const SearchResults = new Lang.Class({
scrollView.add_actor(this._content);
this.actor.add(scrollView, { x_fill: true,
y_fill: true,
y_fill: false,
expand: true,
x_align: St.Align.START,
y_align: St.Align.START });
@@ -205,10 +206,7 @@ const SearchResults = new Lang.Class({
}));
this._statusText = new St.Label({ style_class: 'search-statustext' });
this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE });
this._content.add(this._statusBin, { expand: true });
this._statusBin.add_actor(this._statusText);
this._content.add(this._statusText);
this._providers = this._searchSystem.getProviders();
this._providerMeta = [];
for (let i = 0; i < this._providers.length; i++) {
@@ -217,10 +215,55 @@ const SearchResults = new Lang.Class({
this._searchProvidersBox = new St.BoxLayout({ style_class: 'search-providers-box' });
this.actor.add(this._searchProvidersBox);
this._openSearchProviders = [];
this._openSearchSystem.connect('changed', Lang.bind(this, this._updateOpenSearchProviderButtons));
this._updateOpenSearchProviderButtons();
this._highlightDefault = false;
this._defaultResult = null;
},
_updateOpenSearchProviderButtons: function() {
for (let i = 0; i < this._openSearchProviders.length; i++)
this._openSearchProviders[i].actor.destroy();
this._openSearchProviders = this._openSearchSystem.getProviders();
for (let i = 0; i < this._openSearchProviders.length; i++)
this._createOpenSearchProviderButton(this._openSearchProviders[i]);
},
_createOpenSearchProviderButton: function(provider) {
let button = new St.Button({ style_class: 'dash-search-button',
reactive: true,
can_focus: true,
x_fill: true,
y_align: St.Align.MIDDLE });
let bin = new St.Bin({ x_fill: false,
x_align:St.Align.MIDDLE });
button.connect('clicked', Lang.bind(this, function() {
this._openSearchSystem.activateResult(provider.id);
}));
let title = new St.Label({ text: provider.name,
style_class: 'dash-search-button-label' });
button.label_actor = title;
bin.set_child(title);
button.set_child(bin);
provider.actor = button;
button.setSelected = function(selected) {
if (selected)
button.add_style_pseudo_class('selected');
else
button.remove_style_pseudo_class('selected');
};
button.activate = Lang.bind(this, function() {
this._openSearchSystem.activateResult(provider.id);
});
button.actor = button;
this._searchProvidersBox.add(button);
},
createProviderMeta: function(provider) {
let providerBox = new St.BoxLayout({ style_class: 'search-section',
vertical: true });
@@ -268,18 +311,20 @@ const SearchResults = new Lang.Class({
reset: function() {
this._searchSystem.reset();
this._statusBin.hide();
this._statusText.hide();
this._clearDisplay();
},
startingSearch: function() {
this.reset();
this._statusText.set_text(_("Searching..."));
this._statusBin.show();
this._statusText.show();
},
doSearch: function (searchString) {
this._searchSystem.updateSearch(searchString);
let terms = this._searchSystem.getTerms();
this._openSearchSystem.setSearchTerms(terms);
},
_metaForProvider: function(provider) {
@@ -325,10 +370,10 @@ const SearchResults = new Lang.Class({
}
if (!haveResults) {
this._statusText.set_text(_("No results."));
this._statusBin.show();
this._statusText.set_text(_("No matching results."));
this._statusText.show();
} else {
this._statusBin.hide();
this._statusText.hide();
}
},

View File

@@ -2,13 +2,36 @@
const Lang = imports.lang;
const Config = imports.misc.config;
const Main = imports.ui.main;
const Params = imports.misc.params;
const STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION = {
'a11y': imports.ui.status.accessibility.ATIndicator,
'volume': imports.ui.status.volume.Indicator,
'battery': imports.ui.status.power.Indicator,
'keyboard': imports.ui.status.keyboard.InputSourceIndicator,
'userMenu': imports.ui.userMenu.UserMenuButton
};
if (Config.HAVE_BLUETOOTH)
STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION['bluetooth'] =
imports.ui.status.bluetooth.Indicator;
try {
STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION['network'] =
imports.ui.status.network.NMApplet;
} catch(e) {
log('NMApplet is not supported. It is possible that your NetworkManager version is too old');
}
const DEFAULT_MODE = 'user';
const _modes = {
'gdm': { hasOverview: false,
hasAppMenu: false,
showCalendarEvents: false,
allowSettings: false,
allowExtensions: false,
@@ -17,15 +40,24 @@ const _modes = {
hasWorkspaces: false,
createSession: Main.createGDMSession,
createUnlockDialog: Main.createGDMLoginDialog,
panel: {
left: [],
center: ['dateMenu'],
right: ['a11y', 'display', 'keyboard',
'volume', 'battery', 'lockScreen', 'powerMenu']
extraStylesheet: null,
statusArea: {
order: [
'a11y', 'display', 'keyboard',
'volume', 'battery', 'powerMenu'
],
implementation: {
'a11y': imports.ui.status.accessibility.ATIndicator,
'volume': imports.ui.status.volume.Indicator,
'battery': imports.ui.status.power.Indicator,
'keyboard': imports.ui.status.keyboard.InputSourceIndicator,
'powerMenu': imports.gdm.powerMenu.PowerMenuButton
}
}
},
'initial-setup': { hasOverview: false,
hasAppMenu: false,
showCalendarEvents: false,
allowSettings: false,
allowExtensions: false,
@@ -33,14 +65,21 @@ const _modes = {
hasRunDialog: false,
hasWorkspaces: false,
createSession: Main.createInitialSetupSession,
panel: {
left: [],
center: ['dateMenu'],
right: ['a11y', 'keyboard', 'volume', 'lockScreen']
}
},
extraStylesheet: null,
statusArea: {
order: [
'a11y', 'keyboard', 'volume'
],
implementation: {
'a11y': imports.ui.status.accessibility.ATIndicator,
'keyboard': imports.ui.status.keyboard.XKBIndicator,
'volume': imports.ui.status.volume.Indicator
}
}
},
'user': { hasOverview: true,
hasAppMenu: true,
showCalendarEvents: true,
allowSettings: true,
allowExtensions: true,
@@ -49,11 +88,13 @@ const _modes = {
hasWorkspaces: true,
createSession: Main.createUserSession,
createUnlockDialog: Main.createSessionUnlockDialog,
panel: {
left: ['activities', 'appMenu'],
center: ['dateMenu'],
right: ['a11y', 'keyboard', 'volume', 'bluetooth',
'network', 'battery', 'lockScreen', 'userMenu']
extraStylesheet: null,
statusArea: {
order: [
'input-method', 'a11y', 'keyboard', 'volume', 'bluetooth',
'network', 'battery', 'userMenu'
],
implementation: STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION
}
}
};

View File

@@ -318,11 +318,8 @@ const GnomeShellExtensions = new Lang.Class({
},
ReloadExtension: function(uuid) {
let extension = ExtensionUtils.extensions[uuid];
if (!extension)
return;
ExtensionSystem.reloadExtension(extension);
ExtensionSystem.unloadExtension(uuid);
ExtensionSystem.loadExtension(uuid);
},
CheckForUpdates: function() {

View File

@@ -240,7 +240,7 @@ const ShellUnmountNotifier = new Lang.Class({
Extends: MessageTray.Source,
_init: function() {
this.parent('', 'media-removable');
this.parent('', 'media-removable', St.IconType.FULLCOLOR);
this._notification = null;
Main.messageTray.add(this);
@@ -361,12 +361,12 @@ const ShellMountPasswordDialog = new Lang.Class({
if (strings[1])
description.set_text(strings[1]);
this._passwordBox = new St.BoxLayout({ vertical: false, style_class: 'prompt-dialog-password-box' });
this._passwordBox = new St.BoxLayout({ vertical: false });
this._messageBox.add(this._passwordBox);
this._passwordLabel = new St.Label(({ style_class: 'prompt-dialog-password-label',
text: _("Password") }));
this._passwordBox.add(this._passwordLabel, { y_fill: false, y_align: St.Align.MIDDLE });
text: _("Passphrase") }));
this._passwordBox.add(this._passwordLabel);
this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: "",
@@ -386,7 +386,7 @@ const ShellMountPasswordDialog = new Lang.Class({
if (flags & Gio.AskPasswordFlags.SAVING_SUPPORTED) {
this._rememberChoice = new CheckBox.CheckBox();
this._rememberChoice.getLabelActor().text = _("Remember Password");
this._rememberChoice.getLabelActor().text = _("Remember Passphrase");
this._rememberChoice.actor.checked = true;
this._messageBox.add(this._rememberChoice.actor);
} else {

View File

@@ -36,7 +36,7 @@ const ATIndicator = new Lang.Class({
Extends: PanelMenu.SystemStatusButton,
_init: function() {
this.parent('preferences-desktop-accessibility-symbolic', _("Accessibility"));
this.parent('preferences-desktop-accessibility', _("Accessibility"));
let highContrast = this._buildHCItem();
this.menu.addMenuItem(highContrast);
@@ -76,7 +76,7 @@ const ATIndicator = new Lang.Class({
},
setLockedState: function(locked) {
this.actor.visible = !locked;
this.menu.setSettingsVisibility(!locked);
},
_buildItemExtended: function(string, initial_value, writable, on_set) {

View File

@@ -24,7 +24,7 @@ const Indicator = new Lang.Class({
Extends: PanelMenu.SystemStatusButton,
_init: function() {
this.parent('bluetooth-disabled-symbolic', _("Bluetooth"));
this.parent('bluetooth-disabled', _("Bluetooth"));
this._applet = new GnomeBluetoothApplet.Applet();
@@ -111,10 +111,10 @@ const Indicator = new Lang.Class({
if (on) {
this._discoverable.actor.show();
this.setIcon('bluetooth-active-symbolic');
this.setIcon('bluetooth-active');
} else {
this._discoverable.actor.hide();
this.setIcon('bluetooth-disabled-symbolic');
this.setIcon('bluetooth-disabled');
}
},
@@ -306,7 +306,7 @@ const Indicator = new Lang.Class({
_ensureSource: function() {
if (!this._source) {
this._source = new MessageTray.Source(_("Bluetooth"), 'bluetooth-active');
this._source = new MessageTray.Source(_("Bluetooth"), 'bluetooth-active', St.IconType.SYMBOLIC);
Main.messageTray.add(this._source);
}
},

View File

@@ -178,9 +178,7 @@ const InputSourceIndicator = new Lang.Class({
},
setLockedState: function(locked) {
if (Main.sessionMode.allowSettings) {
this._showLayoutItem.actor.visible = !locked;
}
this._showLayoutItem.actor.visible = !locked;
this.menu.setSettingsVisibility(!locked);
},

View File

@@ -1,62 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const GObject = imports.gi.GObject;
const Lang = imports.lang;
const St = imports.gi.St;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const VolumeMenu = imports.ui.status.volume;
const Indicator = new Lang.Class({
Name: 'LockScreenMenuIndicator',
Extends: PanelMenu.SystemStatusButton,
_init: function() {
this.parent(null, _("Volume, network, battery"));
this.actor.hide();
this._volume = Main.panel.statusArea.volume;
if (this._volume) {
this._volumeIcon = this.addIcon(null);
this._volume.mainIcon.bind_property('gicon', this._volumeIcon, 'gicon',
GObject.BindingFlags.SYNC_CREATE);
this._volume.mainIcon.bind_property('visible', this._volumeIcon, 'visible',
GObject.BindingFlags.SYNC_CREATE);
this._volumeControl = VolumeMenu.getMixerControl();
this._volumeMenu = new VolumeMenu.VolumeMenu(this._volumeControl);
this.menu.addMenuItem(this._volumeMenu);
}
this._network = Main.panel.statusArea.network;
if (this._network) {
this._networkIcon = this.addIcon(null);
this._network.mainIcon.bind_property('gicon', this._networkIcon, 'gicon',
GObject.BindingFlags.SYNC_CREATE);
this._network.mainIcon.bind_property('visible', this._networkIcon, 'visible',
GObject.BindingFlags.SYNC_CREATE);
this._networkSecondaryIcon = this.addIcon(null);
this._network.secondaryIcon.bind_property('gicon', this._networkSecondaryIcon, 'gicon',
GObject.BindingFlags.SYNC_CREATE);
this._network.secondaryIcon.bind_property('visible', this._networkSecondaryIcon, 'visible',
GObject.BindingFlags.SYNC_CREATE);
}
this._battery = Main.panel.statusArea.battery;
if (this._battery) {
this._batteryIcon = this.addIcon(null);
this._battery.mainIcon.bind_property('gicon', this._batteryIcon, 'gicon',
GObject.BindingFlags.SYNC_CREATE);
this._battery.mainIcon.bind_property('visible', this._batteryIcon, 'visible',
GObject.BindingFlags.SYNC_CREATE);
}
},
setLockedState: function(locked) {
this.actor.visible = locked;
}
});

View File

@@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const NetworkManager = imports.gi.NetworkManager;
const NMClient = imports.gi.NMClient;
@@ -122,7 +121,7 @@ const NMNetworkMenuItem = new Lang.Class({
this._secureIcon = new St.Icon({ style_class: 'popup-menu-icon' });
if (this.bestAP._secType != NMAccessPointSecurity.UNKNOWN &&
this.bestAP._secType != NMAccessPointSecurity.NONE)
this._secureIcon.icon_name = 'network-wireless-encrypted-symbolic';
this._secureIcon.icon_name = 'network-wireless-encrypted';
this._icons.add_actor(this._secureIcon);
},
@@ -133,9 +132,9 @@ const NMNetworkMenuItem = new Lang.Class({
_getIcon: function() {
if (this.bestAP.mode == NM80211Mode.ADHOC)
return 'network-workgroup-symbolic';
return 'network-workgroup';
else
return 'network-wireless-signal-' + signalToIcon(this.bestAP.strength) + '-symbolic';
return 'network-wireless-signal-' + signalToIcon(this.bestAP.strength);
}
});
@@ -168,14 +167,15 @@ const NMWiredSectionTitleMenuItem = new Lang.Class({
let newState = this._switch.state;
let ok;
if (newState)
ok = this._device.activate();
else
ok = this._device.deactivate();
// Immediately reset the switch to false, it will be updated appropriately
// by state-changed signals in devices (but fixes the VPN not being in sync
// if the ActiveConnection object is never seen by libnm-glib)
this._switch.setToggleState(false);
if (!ok)
this._switch.setToggleState(false);
if (newState)
this._device.activate();
else
this._device.deactivate();
}
});
@@ -272,14 +272,11 @@ const NMDevice = new Lang.Class({
if (this.device) {
this.statusItem = new PopupMenu.PopupSwitchMenuItem(this._getDescription(), this.connected, { style_class: 'popup-subtitle-menu-item' });
this._statusChanged = this.statusItem.connect('toggled', Lang.bind(this, function(item, state) {
let ok;
if (state)
ok = this.activate();
this.activate();
else
ok = this.deactivate();
if (!ok)
item.setToggleState(!state);
this.deactivate();
this.emit('enabled-changed');
}));
this._updateStatusItem();
@@ -317,35 +314,22 @@ const NMDevice = new Lang.Class({
deactivate: function() {
this.device.disconnect(null);
return true;
},
activate: function() {
if (this._activeConnection)
// nothing to do
return true;
return;
// If there is only one connection available, use that
// Otherwise, if no connection is currently configured,
// try automatic configuration (or summon the config dialog)
if (this._connections.length == 1) {
// pick the most recently used connection and connect to that
// or if no connections ever set, create an automatic one
if (this._connections.length > 0) {
this._client.activate_connection(this._connections[0].connection, this.device, null, null);
return true;
} else if (this._connections.length == 0) {
return this._activateAutomaticConnection();
} else if (this._autoConnectionName) {
let connection = this._createAutomaticConnection();
if (connection)
this._client.add_and_activate_connection(connection, this.device, null, null);
}
return false;
},
_activateAutomaticConnection: function() {
let connection = this._createAutomaticConnection();
if (connection) {
this._client.add_and_activate_connection(connection, this.device, null, null);
return true;
}
return false;
},
get connected() {
@@ -776,7 +760,7 @@ const NMDeviceModem = new Lang.Class({
},
_getSignalIcon: function() {
return 'network-cellular-signal-' + signalToIcon(this.mobileDevice.signal_quality) + '-symbolic';
return 'network-cellular-signal-' + signalToIcon(this.mobileDevice.signal_quality);
},
_createSection: function() {
@@ -802,13 +786,13 @@ const NMDeviceModem = new Lang.Class({
this.parent();
},
_activateAutomaticConnection: function() {
_createAutomaticConnection: function() {
// Mobile wizard is too complex for the shell UI and
// is handled by the network panel
Util.spawn(['gnome-control-center', 'network',
'connect-3g', this.device.get_path()]);
return true;
},
return null;
}
});
const NMDeviceBluetooth = new Lang.Class({
@@ -837,16 +821,6 @@ const NMDeviceBluetooth = new Lang.Class({
return connection;
},
_activateAutomaticConnection: function() {
// FIXME: DUN devices are configured like modems, so
// we need to spawn the mobile wizard
// but the network panel doesn't support bluetooth at the moment
// so we just create an empty connection and hope
// that this phone supports PAN
return this.parent();
},
_makeConnectionName: function(device) {
let name = device.name;
if (name)
@@ -1067,13 +1041,44 @@ const NMDeviceWireless = new Lang.Class({
activate: function() {
if (this._activeConnection)
// nothing to do
return true;
return;
// All possible policy we can have here is just broken
// NM autoconnects when wifi devices are enabled, and if it
// didn't, there is a good reason
// User, pick a connection from the list, thank you
return false;
// among all visible networks, pick the last recently used connection
let best = null;
let bestApObj = null;
let bestTime = 0;
for (let i = 0; i < this._networks.length; i++) {
let apObj = this._networks[i];
for (let j = 0; j < apObj.connections.length; j++) {
let connection = apObj.connections[j];
if (connection._timestamp > bestTime) {
best = connection;
bestTime = connection._timestamp;
bestApObj = apObj;
}
}
}
if (best) {
for (let i = 0; i < bestApObj.accessPoints.length; i++) {
let ap = bestApObj.accessPoints[i];
if (ap.connection_valid(best)) {
this._client.activate_connection(best, this.device, ap.dbus_path, null);
break;
}
}
return;
}
// XXX: what else to do?
// for now, just pick a random network
// (this function is called in a corner case anyway, that is, only when
// the user toggles the switch and has more than one wireless device)
if (this._networks.length > 0) {
let connection = this._createAutomaticConnection(this._networks[0]);
let accessPoints = this._networks[0].accessPoints;
this._client.add_and_activate_connection(connection, this.device, accessPoints[0].dbus_path, null);
}
},
_notifySsidCb: function(accessPoint) {
@@ -1463,7 +1468,7 @@ const NMDeviceWireless = new Lang.Class({
{ reactive: false });
else
this._activeConnectionItem = new PopupMenu.PopupImageMenuItem(title,
'network-wireless-connected-symbolic',
'network-wireless-connected',
{ reactive: false });
this._activeConnectionItem.setShowDot(true);
},
@@ -1559,15 +1564,26 @@ const NMDeviceWireless = new Lang.Class({
const NMApplet = new Lang.Class({
Name: 'NMApplet',
Extends: PanelMenu.SystemStatusButton,
Extends: PanelMenu.Button,
_init: function() {
this.parent('network-offline', _('Network'));
this.parent(0.0, _('Network'));
this.secondaryIcon = this.addIcon(new Gio.ThemedIcon({ name: 'network-vpn-symbolic' }));
this.secondaryIcon.hide();
this._box = new St.BoxLayout({ name: 'networkMenu' });
this.actor.add_actor (this._box);
this.actor.add_style_class_name('panel-status-button');
this._primaryIcon = new St.Icon({ icon_name: 'network-offline',
icon_type: St.IconType.SYMBOLIC,
style_class: 'system-status-icon' });
this._box.add_actor(this._primaryIcon);
this._secondaryIcon = new St.Icon({ icon_name: 'network-vpn',
icon_type: St.IconType.SYMBOLIC,
style_class: 'system-status-icon',
visible: false });
this._box.add_actor(this._secondaryIcon);
this._isLocked = false;
this._client = NMClient.Client.new();
this._statusSection = new PopupMenu.PopupMenuSection();
@@ -1675,15 +1691,24 @@ const NMApplet = new Lang.Class({
}));
},
setIcon: function(iconName) {
this._primaryIcon.icon_name = iconName;
},
setLockedState: function(locked) {
this._isLocked = locked;
this._syncNMState();
// FIXME: more design discussion is needed before we can
// expose part of this menu
if (locked)
this.menu.close();
this.actor.reactive = !locked;
},
_ensureSource: function() {
if (!this._source) {
this._source = new MessageTray.Source(_("Network Manager"),
'network-transmit-receive');
'network-transmit-receive',
St.IconType.SYMBOLIC);
this._source.connect('destroy', Lang.bind(this, function() {
this._source = null;
@@ -1754,7 +1779,9 @@ const NMApplet = new Lang.Class({
this._ensureSource();
let icon = new St.Icon({ icon_name: iconName,
icon_size: MessageTray.NOTIFICATION_ICON_SIZE });
icon_type: St.IconType.SYMBOLIC,
icon_size: this._source.ICON_SIZE
});
device._notification = new MessageTray.Notification(this._source, title, text,
{ icon: icon });
device._notification.setUrgency(urgency);
@@ -1771,7 +1798,7 @@ const NMApplet = new Lang.Class({
wrapper._activationFailedId = wrapper.connect('activation-failed', Lang.bind(this, function(device, reason) {
// XXX: nm-applet has no special text depending on reason
// but I'm not sure of this generic message
this._notifyForDevice(device, 'network-error-symbolic',
this._notifyForDevice(device, 'network-error',
_("Connection failed"),
_("Activation of network connection failed"),
MessageTray.Urgency.HIGH);
@@ -1796,6 +1823,7 @@ const NMApplet = new Lang.Class({
let wrapperClass = this._dtypes[device.get_device_type()];
if (wrapperClass) {
let wrapper = this._makeWrapperDevice(wrapperClass, device);
let section = this._devices[wrapper.category].section;
let devices = this._devices[wrapper.category].devices;
@@ -1804,7 +1832,8 @@ const NMApplet = new Lang.Class({
devices.push(wrapper);
this._syncSectionTitle(wrapper.category);
}
} else
log('Invalid network device type, is ' + device.get_device_type());
},
_deviceRemoved: function(client, device) {
@@ -1823,32 +1852,9 @@ const NMApplet = new Lang.Class({
this._syncSectionTitle(wrapper.category)
},
_getSupportedActiveConnections: function() {
let activeConnections = this._client.get_active_connections() || [ ];
let supportedConnections = [];
for (let i = 0; i < activeConnections.length; i++) {
let devices = activeConnections[i].get_devices();
if (!devices || !devices[0])
continue;
// Ignore connections via unrecognized device types
if (!this._dtypes[devices[0].device_type])
continue;
// Ignore slave connections
let connectionPath = activeConnections[i].connection;
let connection = this._settings.get_connection_by_path(connectionPath)
if (this._ignoreConnection(connection))
continue;
supportedConnections.push(activeConnections[i]);
}
return supportedConnections;
},
_syncActiveConnections: function() {
let closedConnections = [ ];
let newActiveConnections = this._getSupportedActiveConnections();
let newActiveConnections = this._client.get_active_connections() || [ ];
for (let i = 0; i < this._activeConnections.length; i++) {
let a = this._activeConnections[i];
if (newActiveConnections.indexOf(a) == -1) // connection is removed
@@ -1952,24 +1958,10 @@ const NMApplet = new Lang.Class({
this._updateIcon();
},
_ignoreConnection: function(connection) {
let setting = connection.get_setting_connection();
if (!setting)
return true;
// Ignore slave connections
if (setting.get_master())
return true;
return false;
},
_readConnections: function() {
let connections = this._settings.list_connections();
for (let i = 0; i < connections.length; i++) {
let connection = connections[i];
if (this._ignoreConnection(connection))
continue;
if (connection._updatedId) {
// connection was already seen (for example because NetworkManager was restarted)
continue;
@@ -1983,8 +1975,6 @@ const NMApplet = new Lang.Class({
},
_newConnection: function(settings, connection) {
if (this._ignoreConnection(connection))
return;
if (connection._updatedId) {
// connection was already seen
return;
@@ -2062,11 +2052,16 @@ const NMApplet = new Lang.Class({
},
_syncNMState: function() {
this.mainIcon.visible = this._client.manager_running;
this.actor.visible = this.mainIcon.visible && !this._isLocked;
if (!this._client.manager_running) {
log('NetworkManager is not running, hiding...');
this.menu.close();
this.actor.hide();
return;
} else
this.actor.show();
if (!this._client.networking_enabled) {
this.setIcon('network-offline-symbolic');
this.setIcon('network-offline');
this._hideDevices();
this._statusItem.label.text = _("Networking is disabled");
this._statusSection.actor.show();
@@ -2084,22 +2079,22 @@ const NMApplet = new Lang.Class({
let hasMobileIcon = false;
if (!mc) {
this.setIcon('network-offline-symbolic');
this.setIcon('network-offline');
} else if (mc.state == NetworkManager.ActiveConnectionState.ACTIVATING) {
switch (mc._section) {
case NMConnectionCategory.WWAN:
this.setIcon('network-cellular-acquiring-symbolic');
this.setIcon('network-cellular-acquiring');
break;
case NMConnectionCategory.WIRELESS:
this.setIcon('network-wireless-acquiring-symbolic');
this.setIcon('network-wireless-acquiring');
break;
case NMConnectionCategory.WIRED:
this.setIcon('network-wired-acquiring-symbolic');
this.setIcon('network-wired-acquiring');
break;
default:
// fallback to a generic connected icon
// (it could be a private connection of some other user)
this.setIcon('network-wired-acquiring-symbolic');
this.setIcon('network-wired-acquiring');
}
} else {
let dev;
@@ -2114,17 +2109,17 @@ const NMApplet = new Lang.Class({
log('An active wireless connection, in infrastructure mode, involves no access point?');
break;
}
this.setIcon('network-wireless-connected-symbolic');
this.setIcon('network-wireless-connected');
} else {
if (this._activeAccessPoint != ap) {
if (this._accessPointUpdateId)
this._activeAccessPoint.disconnect(this._accessPointUpdateId);
this._activeAccessPoint = ap;
this._activeAccessPointUpdateId = ap.connect('notify::strength', Lang.bind(this, function() {
this.setIcon('network-wireless-signal-' + signalToIcon(ap.strength) + '-symbolic');
this.setIcon('network-wireless-signal-' + signalToIcon(ap.strength));
}));
}
this.setIcon('network-wireless-signal-' + signalToIcon(ap.strength) + '-symbolic');
this.setIcon('network-wireless-signal-' + signalToIcon(ap.strength));
hasApIcon = true;
}
break;
@@ -2133,7 +2128,7 @@ const NMApplet = new Lang.Class({
break;
}
case NMConnectionCategory.WIRED:
this.setIcon('network-wired-symbolic');
this.setIcon('network-wired');
break;
case NMConnectionCategory.WWAN:
dev = mc._primaryDevice;
@@ -2143,7 +2138,7 @@ const NMApplet = new Lang.Class({
}
if (!dev.mobileDevice) {
// this can happen for bluetooth in PAN mode
this.setIcon('network-cellular-connected-symbolic');
this.setIcon('network-cellular-connected');
break;
}
@@ -2152,37 +2147,37 @@ const NMApplet = new Lang.Class({
this._mobileUpdateDevice.disconnect(this._mobileUpdateId);
this._mobileUpdateDevice = dev.mobileDevice;
this._mobileUpdateId = dev.mobileDevice.connect('notify::signal-quality', Lang.bind(this, function() {
this.setIcon('network-cellular-signal-' + signalToIcon(dev.mobileDevice.signal_quality) + '-symbolic');
this.setIcon('network-cellular-signal-' + signalToIcon(dev.mobileDevice.signal_quality));
}));
}
this.setIcon('network-cellular-signal-' + signalToIcon(dev.mobileDevice.signal_quality) + '-symbolic');
this.setIcon('network-cellular-signal-' + signalToIcon(dev.mobileDevice.signal_quality));
hasMobileIcon = true;
break;
default:
// fallback to a generic connected icon
// (it could be a private connection of some other user)
this.setIcon('network-wired-symbolic');
this.setIcon('network-wired');
break;
}
}
// update VPN indicator
if (this._vpnConnection) {
let vpnIconName = 'network-vpn-symbolic';
let vpnIconName = 'network-vpn';
if (this._vpnConnection.state == NetworkManager.ActiveConnectionState.ACTIVATING)
vpnIconName = 'network-vpn-acquiring-symbolic';
vpnIconName = 'network-vpn-acquiring';
// only show a separate icon when we're using a wireless/3g connection
if (mc._section == NMConnectionCategory.WIRELESS ||
mc._section == NMConnectionCategory.WWAN) {
this.secondaryIcon.icon_name = vpnIconName;
this.secondaryIcon.show();
this._secondaryIcon.icon_name = vpnIconName;
this._secondaryIcon.visible = true;
} else {
this.setIcon(vpnIconName);
this.secondaryIcon.hide();
this._secondaryIcon.visible = false;
}
} else {
this.secondaryIcon.hide();
this._secondaryIcon.visible = false;
}
// cleanup stale signal connections

View File

@@ -52,11 +52,10 @@ const Indicator = new Lang.Class({
Extends: PanelMenu.SystemStatusButton,
_init: function() {
this.parent('battery-missing-symbolic', _("Battery"));
this.parent('battery-missing', _("Battery"));
this._proxy = new PowerManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH);
this._isLocked = false;
this._deviceItems = [ ];
this._hasPrimary = false;
this._primaryDeviceId = null;
@@ -78,8 +77,9 @@ const Indicator = new Lang.Class({
},
setLockedState: function(locked) {
this._isLocked = locked;
this._syncIcon();
if (locked)
this.menu.close();
this.actor.reactive = !locked;
},
_readPrimaryDevice: function() {
@@ -150,21 +150,16 @@ const Indicator = new Lang.Class({
}));
},
_syncIcon: function() {
_devicesChanged: function() {
let icon = this._proxy.Icon;
let hasIcon = false;
if (icon) {
let gicon = Gio.icon_new_for_string(icon);
this.setGIcon(gicon);
hasIcon = true;
this.actor.show();
} else {
this.menu.close();
this.actor.hide();
}
this.mainIcon.visible = hasIcon;
this.actor.visible = hasIcon && !this._isLocked;
},
_devicesChanged: function() {
this._syncIcon();
this._readPrimaryDevice();
this._readOtherDevices();
}
@@ -183,6 +178,7 @@ const DeviceItem = new Lang.Class({
this._label = new St.Label({ text: this._deviceTypeToString(device_type) });
this._icon = new St.Icon({ gicon: Gio.icon_new_for_string(icon),
icon_type: St.IconType.SYMBOLIC,
style_class: 'popup-menu-icon' });
this._box.add_actor(this._icon);
@@ -191,8 +187,6 @@ const DeviceItem = new Lang.Class({
let percentLabel = new St.Label({ text: C_("percent of battery remaining", "%d%%").format(Math.round(percentage)) });
this.addActor(percentLabel, { align: St.Align.END });
//FIXME: ideally we would like to expose this._label and percentLabel
this.actor.label_actor = percentLabel;
},
_deviceTypeToString: function(type) {

View File

@@ -12,27 +12,14 @@ const VOLUME_ADJUSTMENT_STEP = 0.05; /* Volume adjustment step in % */
const VOLUME_NOTIFY_ID = 1;
// Each Gvc.MixerControl is a connection to PulseAudio,
// so it's better to make it a singleton
let _mixerControl;
function getMixerControl() {
if (_mixerControl)
return _mixerControl;
const Indicator = new Lang.Class({
Name: 'VolumeIndicator',
Extends: PanelMenu.SystemStatusButton,
_mixerControl = new Gvc.MixerControl({ name: 'GNOME Shell Volume Control' });
_mixerControl.open();
_init: function() {
this.parent('audio-volume-muted', _("Volume"));
return _mixerControl;
}
const VolumeMenu = new Lang.Class({
Name: 'VolumeMenu',
Extends: PopupMenu.PopupMenuSection,
_init: function(control) {
this.parent();
this._control = control;
this._control = new Gvc.MixerControl({ name: 'GNOME Shell Volume Control' });
this._control.connect('state-changed', Lang.bind(this, this._onControlStateChanged));
this._control.connect('default-sink-changed', Lang.bind(this, this._readOutput));
this._control.connect('default-source-changed', Lang.bind(this, this._readInput));
@@ -48,10 +35,10 @@ const VolumeMenu = new Lang.Class({
this._outputSlider = new PopupMenu.PopupSliderMenuItem(0);
this._outputSlider.connect('value-changed', Lang.bind(this, this._sliderChanged, '_output'));
this._outputSlider.connect('drag-end', Lang.bind(this, this._notifyVolumeChange));
this.addMenuItem(this._outputTitle);
this.addMenuItem(this._outputSlider);
this.menu.addMenuItem(this._outputTitle);
this.menu.addMenuItem(this._outputSlider);
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this._input = null;
this._inputVolumeId = 0;
@@ -60,11 +47,22 @@ const VolumeMenu = new Lang.Class({
this._inputSlider = new PopupMenu.PopupSliderMenuItem(0);
this._inputSlider.connect('value-changed', Lang.bind(this, this._sliderChanged, '_input'));
this._inputSlider.connect('drag-end', Lang.bind(this, this._notifyVolumeChange));
this.addMenuItem(this._inputTitle);
this.addMenuItem(this._inputSlider);
this.menu.addMenuItem(this._inputTitle);
this.menu.addMenuItem(this._inputSlider);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addSettingsAction(_("Sound Settings"), 'gnome-sound-panel.desktop');
this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
this._control.open();
},
scroll: function(direction) {
setLockedState: function(locked) {
this.menu.setSettingsVisibility(!locked);
},
_onScrollEvent: function(actor, event) {
let direction = event.get_scroll_direction();
let currentVolume = this._output.volume;
if (direction == Clutter.ScrollDirection.DOWN) {
@@ -90,8 +88,9 @@ const VolumeMenu = new Lang.Class({
if (this._control.get_state() == Gvc.MixerControlState.READY) {
this._readOutput();
this._readInput();
this.actor.show();
} else {
this.emit('icon-changed', null);
this.actor.hide();
}
},
@@ -110,7 +109,7 @@ const VolumeMenu = new Lang.Class({
this._volumeChanged (null, null, '_output');
} else {
this._outputSlider.setValue(0);
this.emit('icon-changed', 'audio-volume-muted-symbolic');
this.setIcon('audio-volume-muted-symbolic');
}
},
@@ -156,14 +155,14 @@ const VolumeMenu = new Lang.Class({
_volumeToIcon: function(volume) {
if (volume <= 0) {
return 'audio-volume-muted-symbolic';
return 'audio-volume-muted';
} else {
let n = Math.floor(3 * volume / this._volumeMax) + 1;
if (n < 2)
return 'audio-volume-low-symbolic';
return 'audio-volume-low';
if (n >= 3)
return 'audio-volume-high-symbolic';
return 'audio-volume-medium-symbolic';
return 'audio-volume-high';
return 'audio-volume-medium';
}
},
@@ -197,55 +196,15 @@ const VolumeMenu = new Lang.Class({
slider.setValue(muted ? 0 : (this[property].volume / this._volumeMax));
if (property == '_output') {
if (muted)
this.emit('icon-changed', 'audio-volume-muted-symbolic');
this.setIcon('audio-volume-muted');
else
this.emit('icon-changed', this._volumeToIcon(this._output.volume));
this.setIcon(this._volumeToIcon(this._output.volume));
}
},
_volumeChanged: function(object, param_spec, property) {
this[property+'Slider'].setValue(this[property].volume / this._volumeMax);
if (property == '_output' && !this._output.is_muted)
this.emit('icon-changed', this._volumeToIcon(this._output.volume));
}
});
const Indicator = new Lang.Class({
Name: 'VolumeIndicator',
Extends: PanelMenu.SystemStatusButton,
_init: function() {
this.parent('audio-volume-muted-symbolic', _("Volume"));
this._isLocked = false;
this._control = getMixerControl();
this._volumeMenu = new VolumeMenu(this._control);
this._volumeMenu.connect('icon-changed', Lang.bind(this, function(menu, icon) {
this._hasPulseAudio = (icon != null);
this.setIcon(icon);
this._syncVisibility();
}));
this.menu.addMenuItem(this._volumeMenu);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addSettingsAction(_("Sound Settings"), 'gnome-sound-panel.desktop');
this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
},
setLockedState: function(locked) {
this._isLocked = locked;
this._syncVisibility();
},
_syncVisibility: function() {
this.actor.visible = this._hasPulseAudio && !this._isLocked;
this.mainIcon.visible = this._hasPulseAudio;
},
_onScrollEvent: function(actor, event) {
this._volumeMenu.scroll(event.get_scroll_direction());
this.setIcon(this._volumeToIcon(this._output.volume));
}
});

View File

@@ -132,7 +132,7 @@ const Client = new Lang.Class({
let channel = channels[i];
let [targetHandle, targetHandleType] = channel.get_handle();
if (channel.get_invalidated())
if (Shell.is_channel_invalidated(channel))
continue;
/* Only observe contact text channels */
@@ -184,7 +184,7 @@ const Client = new Lang.Class({
continue;
}
if (channel.get_invalidated())
if (Shell.is_channel_invalidated(channel))
continue;
// 'notify' will be true when coming from an actual HandleChannels
@@ -211,15 +211,13 @@ const Client = new Lang.Class({
// We can only approve the rooms if we have been invited to it
let selfContact = channel.group_get_self_contact();
if (selfContact == null) {
context.fail(new Tp.Error({ code: Tp.Error.INVALID_ARGUMENT,
message: 'Not invited to the room' }));
Shell.decline_dispatch_op(context, 'Not invited to the room');
return;
}
let [invited, inviter, reason, msg] = channel.group_get_local_pending_contact_info(selfContact);
if (!invited) {
context.fail(new Tp.Error({ code: Tp.Error.INVALID_ARGUMENT,
message: 'Not invited to the room' }));
Shell.decline_dispatch_op(context, 'Not invited to the room');
return;
}
@@ -239,9 +237,8 @@ const Client = new Lang.Class({
let channel = channels[0];
let chanType = channel.get_channel_type();
if (channel.get_invalidated()) {
context.fail(new Tp.Error({ code: Tp.Error.INVALID_ARGUMENT,
message: 'Channel is invalidated' }));
if (Shell.is_channel_invalidated(channel)) {
Shell.decline_dispatch_op(context, 'Channel is invalidated');
return;
}
@@ -252,8 +249,7 @@ const Client = new Lang.Class({
else if (chanType == Tp.IFACE_CHANNEL_TYPE_FILE_TRANSFER)
this._approveFileTransfer(account, conn, channel, dispatchOp, context);
else
context.fail(new Tp.Error({ code: Tp.Error.INVALID_ARGUMENT,
message: 'Unsupported channel type' }));
Shell.decline_dispatch_op(context, 'Unsupported channel type');
},
_approveTextChannel: function(account, conn, channel, dispatchOp, context) {
@@ -383,7 +379,8 @@ const Client = new Lang.Class({
_ensureSubscriptionSource: function() {
if (this._subscriptionSource == null) {
this._subscriptionSource = new MessageTray.Source(_("Subscription request"),
'gtk-dialog-question');
'gtk-dialog-question',
St.IconType.FULLCOLOR);
Main.messageTray.add(this._subscriptionSource);
this._subscriptionSource.connect('destroy', Lang.bind(this, function () {
this._subscriptionSource = null;
@@ -419,7 +416,8 @@ const Client = new Lang.Class({
_ensureAccountSource: function() {
if (this._accountSource == null) {
this._accountSource = new MessageTray.Source(_("Connection error"),
'gtk-dialog-error');
'gtk-dialog-error',
St.IconType.FULLCOLOR);
Main.messageTray.add(this._accountSource);
this._accountSource.connect('destroy', Lang.bind(this, function () {
this._accountSource = null;
@@ -495,6 +493,7 @@ const ChatSource = new Lang.Class({
this._iconBox.child = textureCache.load_uri_async(uri, this._iconBox._size, this._iconBox._size);
} else {
this._iconBox.child = new St.Icon({ icon_name: 'avatar-default',
icon_type: St.IconType.FULLCOLOR,
icon_size: this._iconBox._size });
}
@@ -503,7 +502,8 @@ const ChatSource = new Lang.Class({
createSecondaryIcon: function() {
let iconBox = new St.Bin();
iconBox.child = new St.Icon({ style_class: 'secondary-icon' });
iconBox.child = new St.Icon({ style_class: 'secondary-icon',
icon_type: St.IconType.FULLCOLOR });
let presenceType = this._contact.get_presence_type();
switch (presenceType) {
@@ -578,7 +578,7 @@ const ChatSource = new Lang.Class({
this._pendingMessages.push(message);
}
this.countUpdated();
this._updateCount();
let showTimestamp = false;
@@ -624,17 +624,8 @@ const ChatSource = new Lang.Class({
this.destroy();
},
/* All messages are new messages for Telepathy sources */
get count() {
return this._pendingMessages.length;
},
get unseenCount() {
return this.count;
},
get countVisible() {
return this.count > 0;
_updateCount: function() {
this._setCount(this._pendingMessages.length, this._pendingMessages.length > 0);
},
_messageReceived: function(channel, message) {
@@ -642,7 +633,7 @@ const ChatSource = new Lang.Class({
return;
this._pendingMessages.push(message);
this.countUpdated();
this._updateCount();
message = makeMessageFromTpMessage(message, NotificationDirection.RECEIVED);
this._notification.appendMessage(message);
@@ -719,7 +710,7 @@ const ChatSource = new Lang.Class({
if (idx >= 0) {
this._pendingMessages.splice(idx, 1);
this.countUpdated();
this._updateCount();
}
else
throw new Error('Message not in our pending list: ' + message);
@@ -1193,6 +1184,7 @@ const SubscriptionRequestNotification = new Lang.Class({
}
else {
iconBox.child = new St.Icon({ icon_name: 'avatar-default',
icon_type: St.IconType.FULLCOLOR,
icon_size: iconBox._size });
}
@@ -1337,14 +1329,15 @@ const AccountNotification = new Lang.Class({
case 'reconnect':
// If it fails again, a new notification should pop up with the
// new error.
account.reconnect_async(null);
account.reconnect_async(null, null);
break;
case 'edit':
let cmd = '/usr/bin/empathy-accounts'
+ ' --select-account=%s'
.format(account.get_path_suffix());
let app_info = Gio.app_info_create_from_commandline(cmd, null, 0);
app_info.launch([], global.create_app_launch_context());
let app_info = Gio.app_info_create_from_commandline(cmd, null, 0,
null);
app_info.launch([], null, null);
break;
}
this.destroy();

View File

@@ -20,9 +20,6 @@ const UserMenu = imports.ui.userMenu;
const Batch = imports.gdm.batch;
const GdmUtil = imports.gdm.util;
// The timeout before going back automatically to the lock screen (in seconds)
const IDLE_TIMEOUT = 2 * 60;
// A widget showing the user avatar and name
const UserWidget = new Lang.Class({
Name: 'UserWidget',
@@ -97,14 +94,14 @@ const UnlockDialog = new Lang.Class({
this._userVerifier.connect('verification-complete', Lang.bind(this, this._onVerificationComplete));
this._userVerifier.connect('verification-failed', Lang.bind(this, this._onVerificationFailed));
this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint));
this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._hideLoginHint));
this._userVerifier.connect('show-fingerprint-prompt', Lang.bind(this, this._showFingerprintPrompt));
this._userVerifier.connect('hide-fingerprint-prompt', Lang.bind(this, this._hideFingerprintPrompt));
this._userWidget = new UserWidget(this._user);
this.contentLayout.add_actor(this._userWidget.actor);
this._promptLayout = new St.BoxLayout({ style_class: 'login-dialog-prompt-layout',
vertical: true });
vertical: false });
this._promptLabel = new St.Label({ style_class: 'login-dialog-prompt-label' });
this._promptLayout.add(this._promptLabel,
@@ -122,22 +119,14 @@ const UnlockDialog = new Lang.Class({
this.contentLayout.add_actor(this._promptLayout);
this._promptLoginHint = new St.Label({ style_class: 'login-dialog-prompt-login-hint' });
this._promptLoginHint.hide();
this.contentLayout.add_actor(this._promptLoginHint);
// Translators: this message is shown below the password entry field
// to indicate the user can swipe their finger instead
this._promptFingerprintMessage = new St.Label({ text: _("(or swipe finger)"),
style_class: 'login-dialog-prompt-fingerprint-message' });
this._promptFingerprintMessage.hide();
this.contentLayout.add_actor(this._promptFingerprintMessage);
let cancelButton = { label: _("Cancel"),
action: Lang.bind(this, this._escape),
key: Clutter.KEY_Escape };
this._okButton = { label: _("Unlock"),
action: Lang.bind(this, this._doUnlock),
default: true };
this.setButtons([cancelButton, this._okButton]);
this._updateOkButton(false);
this._reset();
let otherUserLabel = new St.Label({ text: _("Log in as another user"),
let otherUserLabel = new St.Label({ text: _("Login as another user"),
style_class: 'login-dialog-not-listed-label' });
this._otherUserButton = new St.Button({ style_class: 'login-dialog-not-listed-button',
can_focus: true,
@@ -146,19 +135,23 @@ const UnlockDialog = new Lang.Class({
x_align: St.Align.START,
x_fill: true });
this._otherUserButton.connect('clicked', Lang.bind(this, this._otherUserClicked));
this.dialogLayout.add(this._otherUserButton,
{ x_align: St.Align.START,
x_fill: false });
this.contentLayout.add(this._otherUserButton,
{ x_align: St.Align.START,
x_fill: false });
this._okButton = { label: _("Unlock"),
action: Lang.bind(this, this._doUnlock),
default: true };
this.setButtons([this._okButton]);
this.setActionKey(Clutter.KEY_Escape, Lang.bind(this, this._escape));
this._updateOkButton(false);
this._reset();
GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
this.emit('loaded');
return false;
}));
this._idleMonitor = Shell.IdleMonitor.get();
// this dialog is only created after user activity (curtain drag or
// escape key press), so the timeout will fire after IDLE_TIMEOUT seconds of inactivity
this._idleWatchId = this._idleMonitor.add_watch(IDLE_TIMEOUT * 1000, Lang.bind(this, this._escape));
},
_updateOkButton: function(sensitive) {
@@ -166,7 +159,6 @@ const UnlockDialog = new Lang.Class({
},
_reset: function() {
this._userVerifier.clear();
this._userVerifier.begin(this._userName, new Batch.Hold());
},
@@ -181,13 +173,12 @@ const UnlockDialog = new Lang.Class({
this._updateOkButton(true);
},
_showLoginHint: function(verifier, message) {
this._promptLoginHint.set_text(message)
GdmUtil.fadeInActor(this._promptLoginHint);
_showFingerprintPrompt: function() {
GdmUtil.fadeInActor(this._promptFingerprintMessage);
},
_hideLoginHint: function() {
GdmUtil.fadeOutActor(this._promptLoginHint);
_hideFingerprintPrompt: function() {
GdmUtil.fadeOutActor(this._promptFingerprintMessage);
},
_doUnlock: function() {
@@ -217,7 +208,7 @@ const UnlockDialog = new Lang.Class({
},
_otherUserClicked: function(button, event) {
Gdm.goto_login_session_sync(null);
this._userManager.goto_login_session();
this._userVerifier.cancel();
this.emit('failed');
@@ -225,12 +216,6 @@ const UnlockDialog = new Lang.Class({
destroy: function() {
this._userVerifier.clear();
if (this._idleWatchId) {
this._idleMonitor.remove_watch(this._idleWatchId);
this._idleWatchId = 0;
}
this.parent();
},

View File

@@ -16,15 +16,12 @@ const GnomeSession = imports.misc.gnomeSession;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const Params = imports.misc.params;
const Util = imports.misc.util;
const LOCKDOWN_SCHEMA = 'org.gnome.desktop.lockdown';
const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
const DISABLE_USER_SWITCH_KEY = 'disable-user-switching';
const DISABLE_LOCK_SCREEN_KEY = 'disable-lock-screen';
const DISABLE_LOG_OUT_KEY = 'disable-log-out';
const LOCK_ENABLED_KEY = 'lock-enabled';
const DIALOG_ICON_SIZE = 64;
@@ -46,16 +43,12 @@ const IMStatus = {
const UserAvatarWidget = new Lang.Class({
Name: 'UserAvatarWidget',
_init: function(user, params) {
_init: function(user) {
this._user = user;
params = Params.parse(params, { reactive: false,
iconSize: DIALOG_ICON_SIZE,
styleClass: 'status-chooser-user-icon' });
this._iconSize = params.iconSize;
this.actor = new St.Bin({ style_class: params.styleClass,
track_hover: params.reactive,
reactive: params.reactive });
this.actor = new St.Bin({ style_class: 'status-chooser-user-icon',
track_hover: true,
reactive: true });
},
update: function() {
@@ -69,8 +62,9 @@ const UserAvatarWidget = new Lang.Class({
this.actor.style = 'background-image: url("%s");'.format(iconFile);
} else {
this.actor.style = null;
this.actor.child = new St.Icon({ icon_name: 'avatar-default-symbolic',
icon_size: this._iconSize });
this.actor.child = new St.Icon({ icon_name: 'avatar-default',
icon_type: St.IconType.SYMBOLIC,
icon_size: DIALOG_ICON_SIZE });
}
}
});
@@ -102,7 +96,6 @@ const IMUserNameItem = new Lang.Class({
_init: function() {
this.parent({ reactive: false,
can_focus: false,
style_class: 'status-chooser-user-name' });
this._wrapper = new Shell.GenericContainer();
@@ -140,13 +133,12 @@ const IMStatusChooserItem = new Lang.Class({
_init: function() {
this.parent({ reactive: false,
can_focus: false,
style_class: 'status-chooser' });
this._userManager = AccountsService.UserManager.get_default();
this._user = this._userManager.get_user(GLib.get_user_name());
this._avatar = new UserAvatarWidget(this._user, { reactive: true });
this._avatar = new UserAvatarWidget(this._user);
this._iconBin = new St.Button({ child: this._avatar.actor });
this.addActor(this._iconBin);
@@ -166,22 +158,22 @@ const IMStatusChooserItem = new Lang.Class({
let item;
item = new IMStatusItem(_("Available"), 'user-available-symbolic');
item = new IMStatusItem(_("Available"), 'user-available');
this._combo.addMenuItem(item, IMStatus.AVAILABLE);
item = new IMStatusItem(_("Busy"), 'user-busy-symbolic');
item = new IMStatusItem(_("Busy"), 'user-busy');
this._combo.addMenuItem(item, IMStatus.BUSY);
item = new IMStatusItem(_("Invisible"), 'user-invisible-symbolic');
item = new IMStatusItem(_("Invisible"), 'user-invisible');
this._combo.addMenuItem(item, IMStatus.HIDDEN);
item = new IMStatusItem(_("Away"), 'user-away-symbolic');
item = new IMStatusItem(_("Away"), 'user-away');
this._combo.addMenuItem(item, IMStatus.AWAY);
item = new IMStatusItem(_("Idle"), 'user-idle-symbolic');
item = new IMStatusItem(_("Idle"), 'user-idle');
this._combo.addMenuItem(item, IMStatus.IDLE);
item = new IMStatusItem(_("Unavailable"), 'user-offline-symbolic');
item = new IMStatusItem(_("Unavailable"), 'user-offline');
this._combo.addMenuItem(item, IMStatus.OFFLINE);
this._combo.connect('active-item-changed',
@@ -209,21 +201,20 @@ const IMStatusChooserItem = new Lang.Class({
Lang.bind(this, this._IMAccountsChanged));
this._accountMgr.prepare_async(null, Lang.bind(this,
function(mgr) {
let [presence, status, msg] = mgr.get_most_available_presence();
let savedPresence = global.settings.get_int('saved-im-presence');
this._IMAccountsChanged(mgr);
if (this._networkMonitor.network_available)
this._restorePresence();
else
this._setComboboxPresence(Tp.ConnectionPresenceType.OFFLINE);
}));
this._networkMonitor = Gio.NetworkMonitor.get_default();
this._networkMonitor.connect('network-changed',
Lang.bind(this, function(monitor, available) {
this._IMAccountsChanged(this._accountMgr);
if (available && !this._imPresenceRestored)
this._restorePresence();
if (savedPresence == presence) {
this._IMStatusChanged(mgr, presence, status, msg);
} else {
this._setComboboxPresence(savedPresence);
status = this._statusForPresence(savedPresence);
msg = msg ? msg : '';
mgr.set_all_requested_presences(savedPresence, status, msg);
}
}));
this._userLoadedId = this._user.connect('notify::is-loaded',
@@ -238,21 +229,6 @@ const IMStatusChooserItem = new Lang.Class({
}));
},
_restorePresence: function() {
let [presence, status, msg] = this._accountMgr.get_most_available_presence();
let savedPresence = global.settings.get_int('saved-im-presence');
if (savedPresence == presence) {
this._IMStatusChanged(this._accountMgr, presence, status, msg);
} else {
this._setComboboxPresence(savedPresence);
status = this._statusForPresence(savedPresence);
msg = msg ? msg : '';
this._accountMgr.set_all_requested_presences(savedPresence, status, msg);
}
},
destroy: function() {
// clean up signal handlers
if (this._userLoadedId != 0) {
@@ -309,8 +285,7 @@ const IMStatusChooserItem = new Lang.Class({
let accounts = mgr.get_valid_accounts().filter(function(account) {
return account.enabled;
});
let sensitive = accounts.length > 0 && this._networkMonitor.network_available;
this._combo.setSensitive(sensitive);
this._combo.setSensitive(accounts.length > 0);
},
_IMStatusChanged: function(accountMgr, presence, status, message) {
@@ -463,7 +438,6 @@ const UserMenuButton = new Lang.Class({
let box = new St.BoxLayout({ name: 'panelUserMenu' });
this.actor.add_actor(box);
this._screenSaverSettings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA });
this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA });
this._userManager = AccountsService.UserManager.get_default();
@@ -482,19 +456,19 @@ const UserMenuButton = new Lang.Class({
box.add(this._iconBox, { y_align: St.Align.MIDDLE, y_fill: false });
let textureCache = St.TextureCache.get_default();
this._offlineIcon = new St.Icon({ icon_name: 'user-offline-symbolic',
this._offlineIcon = new St.Icon({ icon_name: 'user-offline',
style_class: 'popup-menu-icon' });
this._availableIcon = new St.Icon({ icon_name: 'user-available-symbolic',
this._availableIcon = new St.Icon({ icon_name: 'user-available',
style_class: 'popup-menu-icon' });
this._busyIcon = new St.Icon({ icon_name: 'user-busy-symbolic',
this._busyIcon = new St.Icon({ icon_name: 'user-busy',
style_class: 'popup-menu-icon' });
this._invisibleIcon = new St.Icon({ icon_name: 'user-invisible-symbolic',
this._invisibleIcon = new St.Icon({ icon_name: 'user-invisible',
style_class: 'popup-menu-icon' });
this._awayIcon = new St.Icon({ icon_name: 'user-away-symbolic',
this._awayIcon = new St.Icon({ icon_name: 'user-away',
style_class: 'popup-menu-icon' });
this._idleIcon = new St.Icon({ icon_name: 'user-idle-symbolic',
this._idleIcon = new St.Icon({ icon_name: 'user-idle',
style_class: 'popup-menu-icon' });
this._pendingIcon = new St.Icon({ icon_name: 'user-status-pending-symbolic',
this._pendingIcon = new St.Icon({ icon_name: 'user-status-pending',
style_class: 'popup-menu-icon' });
this._accountMgr.connect('most-available-presence-changed',
@@ -563,7 +537,9 @@ const UserMenuButton = new Lang.Class({
},
setLockedState: function(locked) {
this.actor.visible = !locked;
if (locked)
this.menu.close();
this.actor.reactive = !locked;
},
_onDestroy: function() {
@@ -678,10 +654,8 @@ const UserMenuButton = new Lang.Class({
},
_onAccountRemoved: function(accountMgr, account) {
if (account._changingId) {
account.disconnect(account._changingId);
account._changingId = 0;
}
account.disconnect(account._changingId);
account._changingId = 0;
this._updateChangingPresence();
},
@@ -798,9 +772,8 @@ const UserMenuButton = new Lang.Class({
_onLoginScreenActivate: function() {
Main.overview.hide();
if (this._screenSaverSettings.get_boolean(LOCK_ENABLED_KEY))
Main.screenShield.lock(false);
Gdm.goto_login_session_sync(null);
Main.screenShield.lock(false);
this._userManager.goto_login_session();
},
_onQuitSessionActivate: function() {
@@ -822,17 +795,13 @@ const UserMenuButton = new Lang.Class({
this._suspendOrPowerOffItem.state == PopupMenu.PopupAlternatingMenuItemState.DEFAULT) {
this._session.ShutdownRemote();
} else {
if (this._screenSaverSettings.get_boolean(LOCK_ENABLED_KEY)) {
let tmpId = Main.screenShield.connect('lock-screen-shown', Lang.bind(this, function() {
Main.screenShield.disconnect(tmpId);
let tmpId = Main.screenShield.connect('lock-screen-shown', Lang.bind(this, function() {
Main.screenShield.disconnect(tmpId);
this._upClient.suspend_sync(null);
}));
Main.screenShield.lock(true);
} else {
this._upClient.suspend_sync(null);
}
}));
Main.screenShield.lock(true);
}
}
});

View File

@@ -9,258 +9,176 @@ const Lang = imports.lang;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const AppDisplay = imports.ui.appDisplay;
const Main = imports.ui.main;
const PlaceDisplay = imports.ui.placeDisplay;
const RemoteSearch = imports.ui.remoteSearch;
const Search = imports.ui.search;
const SearchDisplay = imports.ui.searchDisplay;
const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const Wanda = imports.ui.wanda;
const WorkspacesView = imports.ui.workspacesView;
const BaseTab = new Lang.Class({
Name: 'BaseTab',
_init: function(titleActor, pageActor, name, a11yIcon) {
this.title = titleActor;
this.page = new St.Bin({ child: pageActor,
x_align: St.Align.START,
y_align: St.Align.START,
x_fill: true,
y_fill: true,
style_class: 'view-tab-page' });
if (this.title.can_focus) {
Main.ctrlAltTabManager.addGroup(this.title, name, a11yIcon);
} else {
Main.ctrlAltTabManager.addGroup(this.page, name, a11yIcon,
{ proxy: this.title,
focusCallback: Lang.bind(this, this._a11yFocus) });
}
this.visible = false;
},
show: function(animate) {
this.visible = true;
this.page.show();
if (!animate)
return;
this.page.opacity = 0;
Tweener.addTween(this.page,
{ opacity: 255,
time: 0.1,
transition: 'easeOutQuad' });
},
hide: function() {
this.visible = false;
Tweener.addTween(this.page,
{ opacity: 0,
time: 0.1,
transition: 'easeOutQuad',
onComplete: Lang.bind(this,
function() {
this.page.hide();
})
});
},
_a11yFocus: function() {
this._activate();
this.page.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
},
_activate: function() {
this.emit('activated');
}
});
Signals.addSignalMethods(BaseTab.prototype);
const FocusTrap = new Lang.Class({
Name: 'FocusTrap',
Extends: St.Widget,
const ViewTab = new Lang.Class({
Name: 'ViewTab',
Extends: BaseTab,
vfunc_navigate_focus: function(from, direction) {
if (direction == Gtk.DirectionType.TAB_FORWARD ||
direction == Gtk.DirectionType.TAB_BACKWARD)
return this.parent(from, direction);
return false;
_init: function(id, label, pageActor, a11yIcon) {
this.id = id;
let titleActor = new St.Button({ label: label,
style_class: 'view-tab-title' });
titleActor.connect('clicked', Lang.bind(this, this._activate));
this.parent(titleActor, pageActor, label, a11yIcon);
}
});
const ViewSelector = new Lang.Class({
Name: 'ViewSelector',
_init : function(searchEntry, showAppsButton) {
this.actor = new St.BoxLayout({ name: 'viewSelector',
vertical: true });
this._showAppsButton = showAppsButton;
this._showAppsButton.connect('notify::checked', Lang.bind(this, this._onShowAppsButtonToggled));
this._pageArea = new Shell.Stack();
this.actor.add(this._pageArea, { x_fill: true,
y_fill: true,
expand: true });
this._activePage = null;
const SearchTab = new Lang.Class({
Name: 'SearchTab',
Extends: BaseTab,
_init: function() {
this.active = false;
this._searchPending = false;
this._searchTimeoutId = 0;
this._searchSystem = new Search.SearchSystem();
this._openSearchSystem = new Search.OpenSearchSystem();
this._entry = searchEntry;
this._entry = new St.Entry({ name: 'searchEntry',
/* Translators: this is the text displayed
in the search entry when no search is
active; it should not exceed ~30
characters. */
hint_text: _("Type to search..."),
track_hover: true,
can_focus: true });
ShellEntry.addContextMenu(this._entry);
this._text = this._entry.clutter_text;
this._text.connect('text-changed', Lang.bind(this, this._onTextChanged));
this._text.connect('key-press-event', Lang.bind(this, this._onKeyPress));
this._inactiveIcon = new St.Icon({ style_class: 'search-entry-icon',
icon_name: 'edit-find',
icon_type: St.IconType.SYMBOLIC });
this._activeIcon = new St.Icon({ style_class: 'search-entry-icon',
icon_name: 'edit-clear',
icon_type: St.IconType.SYMBOLIC });
this._entry.set_secondary_icon(this._inactiveIcon);
this._iconClickedId = 0;
this._searchResults = new SearchDisplay.SearchResults(this._searchSystem, this._openSearchSystem);
this.parent(this._entry, this._searchResults.actor, _("Search"), 'edit-find');
this._text.connect('text-changed', Lang.bind(this, this._onTextChanged));
this._text.connect('key-press-event', Lang.bind(this, function (o, e) {
// We can't connect to 'activate' here because search providers
// might want to do something with the modifiers in activateDefault.
let symbol = e.get_key_symbol();
if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
if (this._searchTimeoutId > 0) {
Mainloop.source_remove(this._searchTimeoutId);
this._doSearch();
}
this._searchResults.activateDefault();
return true;
}
return false;
}));
this._entry.connect('notify::mapped', Lang.bind(this, this._onMapped));
global.stage.connect('notify::key-focus', Lang.bind(this, this._onStageKeyFocusChanged));
this._capturedEventId = 0;
this._text.connect('key-focus-in', Lang.bind(this, function() {
this._searchResults.highlightDefault(true);
}));
this._text.connect('key-focus-out', Lang.bind(this, function() {
this._searchResults.highlightDefault(false);
}));
this._entry.connect('notify::mapped', Lang.bind(this, this._onMapped));
global.stage.connect('notify::key-focus', Lang.bind(this, this._onStageKeyFocusChanged));
this._inactiveIcon = new St.Icon({ style_class: 'search-entry-icon',
icon_name: 'edit-find-symbolic' });
this._activeIcon = new St.Icon({ style_class: 'search-entry-icon',
icon_name: 'edit-clear-symbolic' });
this._entry.set_secondary_icon(this._inactiveIcon);
this._iconClickedId = 0;
this._capturedEventId = 0;
this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
this._workspacesPage = this._addPage(this._workspacesDisplay.actor, null,
_("Windows"), 'text-x-generic-symbolic');
this._appDisplay = new AppDisplay.AllAppDisplay();
this._appsPage = this._addPage(this._appDisplay.actor, null,
_("Applications"), 'system-run-symbolic');
this._searchResults = new SearchDisplay.SearchResults(this._searchSystem);
this._searchPage = this._addPage(this._searchResults.actor, this._entry,
_("Search"), 'edit-find-symbolic');
// Default search providers
// Wanda comes obviously first
this.addSearchProvider(new Wanda.WandaSearchProvider());
this.addSearchProvider(new AppDisplay.AppSearchProvider());
this.addSearchProvider(new AppDisplay.SettingsSearchProvider());
this.addSearchProvider(new PlaceDisplay.PlaceSearchProvider());
// Load remote search providers provided by applications
RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, this.addSearchProvider));
// Since the entry isn't inside the results container we install this
// dummy widget as the last results container child so that we can
// include the entry in the keynav tab path
this._focusTrap = new FocusTrap({ can_focus: true });
// include the entry in the keynav tab path...
this._focusTrap = new St.Bin({ can_focus: true });
this._focusTrap.connect('key-focus-in', Lang.bind(this, function() {
this._entry.grab_key_focus();
}));
// ... but make it unfocusable using arrow keys keynav by making its
// bounding box always contain the possible focus source's bounding
// box since StWidget's keynav logic won't ever select it as a target
// in that case.
this._focusTrap.add_constraint(new Clutter.BindConstraint({ source: this._searchResults.actor,
coordinate: Clutter.BindCoordinate.ALL }));
this._searchResults.actor.add_actor(this._focusTrap);
global.focus_manager.add_group(this._searchResults.actor);
Main.overview.connect('item-drag-begin',
Lang.bind(this, this._resetShowAppsButton));
this._stageKeyPressId = 0;
Main.overview.connect('showing', Lang.bind(this,
function () {
this._resetShowAppsButton();
this._stageKeyPressId = global.stage.connect('key-press-event',
Lang.bind(this, this._onStageKeyPress));
}));
Main.overview.connect('hiding', Lang.bind(this,
function () {
this._resetShowAppsButton();
if (this._stageKeyPressId != 0) {
global.stage.disconnect(this._stageKeyPressId);
this._stageKeyPressId = 0;
}
}));
// Public constraints which may be used to tie actors' height or
// vertical position to the current tab's content; as the content's
// height and position depend on the view selector's style properties
// (e.g. font size, padding, spacing, ...) it would be extremely hard
// and ugly to get these from the outside. While it would be possible
// to use position and height properties directly, outside code would
// need to ensure that the content is properly allocated before
// accessing the properties.
this.constrainHeight = new Clutter.BindConstraint({ source: this._pageArea,
coordinate: Clutter.BindCoordinate.HEIGHT });
},
show: function() {
this._activePage = this._workspacesPage;
this._appsPage.hide();
this._searchPage.hide();
this._workspacesDisplay.show();
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
Main.overview.fadeOutDesktop();
this._showPage(this._workspacesPage);
},
zoomFromOverview: function() {
this._workspacesDisplay.zoomFromOverview();
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
Main.overview.fadeInDesktop();
},
hide: function() {
this._workspacesDisplay.hide();
},
_addPage: function(actor, a11yFocus, name, a11yIcon) {
let page = new St.Bin({ child: actor,
x_align: St.Align.START,
y_align: St.Align.START,
x_fill: true,
y_fill: true });
if (a11yFocus)
Main.ctrlAltTabManager.addGroup(a11yFocus, name, a11yIcon);
else
Main.ctrlAltTabManager.addGroup(actor, name, a11yIcon,
{ proxy: this.actor,
focusCallback: Lang.bind(this,
function() {
this._a11yFocusPage(page);
})
});;
this._pageArea.add_actor(page);
return page
},
_showPage: function(page) {
if(page == this._activePage)
return;
if(this._activePage) {
Tweener.addTween(this._activePage,
{ opacity: 0,
time: 0.1,
transition: 'easeOutQuad',
onComplete: Lang.bind(this,
function() {
this._activePage.hide();
this._activePage = page;
})
});
}
page.show();
Tweener.addTween(page,
{ opacity: 255,
time: 0.1,
transition: 'easeOutQuad'
});
},
_a11yFocusPage: function(page) {
this._showAppsButton.checked = page == this._appsPage;
page.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
},
_onShowAppsButtonToggled: function() {
if (this.active)
this.reset();
else
this._showPage(this._showAppsButton.checked ? this._appsPage
: this._workspacesPage);
},
_resetShowAppsButton: function() {
this._showAppsButton.checked = false;
},
_onStageKeyPress: function(actor, event) {
let modifiers = event.get_state();
let symbol = event.get_key_symbol();
if (symbol == Clutter.Escape) {
if (this.active)
this.reset();
else if (this._showAppsButton.checked)
this._resetShowAppsButton();
else
Main.overview.hide();
return true;
} else if (Clutter.keysym_to_unicode(symbol) ||
(symbol == Clutter.BackSpace && this.active)) {
this.startSearch(event);
} else if (!this.active) {
if (symbol == Clutter.Tab || symbol == Clutter.Down) {
this._activePage.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
return true;
} else if (symbol == Clutter.ISO_Left_Tab) {
this._activePage.navigate_focus(null, Gtk.DirectionType.TAB_BACKWARD, false);
return true;
}
}
return false;
},
_searchCancelled: function() {
this._showPage(this._showAppsButton.checked ? this._appsPage
: this._workspacesPage);
this.parent();
// Leave the entry focused when it doesn't have any text;
// when replacing a selected search term, Clutter emits
@@ -309,6 +227,16 @@ const ViewSelector = new Lang.Class({
}
},
addSearchProvider: function(provider) {
this._searchSystem.registerProvider(provider);
this._searchResults.createProviderMeta(provider);
},
removeSearchProvider: function(provider) {
this._searchSystem.unregisterProvider(provider);
this._searchResults.destroyProviderMeta(provider);
},
startSearch: function(event) {
global.stage.set_key_focus(this._text);
this._text.event(event, false);
@@ -335,13 +263,14 @@ const ViewSelector = new Lang.Class({
this.reset();
}));
}
this._activate();
} else {
if (this._iconClickedId > 0)
this._entry.disconnect(this._iconClickedId);
this._iconClickedId = 0;
this._entry.set_secondary_icon(this._inactiveIcon);
this._searchCancelled();
this.emit('search-cancelled');
}
if (!this.active) {
if (this._searchTimeoutId > 0) {
@@ -362,15 +291,6 @@ const ViewSelector = new Lang.Class({
this.reset();
return true;
}
} else if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
// We can't connect to 'activate' here because search providers
// might want to do something with the modifiers in activateDefault.
if (this._searchTimeoutId > 0) {
Mainloop.source_remove(this._searchTimeoutId);
this._doSearch();
}
this._searchResults.activateDefault();
return true;
} else if (this.active) {
let arrowNext, nextDirection;
if (entry.get_text_direction() == Clutter.TextDirection.RTL) {
@@ -420,17 +340,259 @@ const ViewSelector = new Lang.Class({
let text = this._text.get_text().replace(/^\s+/g, '').replace(/\s+$/g, '');
this._searchResults.doSearch(text);
this._showPage(this._searchPage);
return false;
}
});
const ViewSelector = new Lang.Class({
Name: 'ViewSelector',
_init : function() {
this.actor = new St.BoxLayout({ name: 'viewSelector',
vertical: true });
// The tab bar is located at the top of the view selector and
// holds both "normal" tab labels and the search entry. The former
// is left aligned, the latter right aligned - unless the text
// direction is RTL, in which case the order is reversed.
this._tabBar = new Shell.GenericContainer();
this._tabBar.connect('get-preferred-width',
Lang.bind(this, this._getPreferredTabBarWidth));
this._tabBar.connect('get-preferred-height',
Lang.bind(this, this._getPreferredTabBarHeight));
this._tabBar.connect('allocate',
Lang.bind(this, this._allocateTabBar));
this.actor.add(this._tabBar);
// Box to hold "normal" tab labels
this._tabBox = new St.BoxLayout({ name: 'viewSelectorTabBar' });
this._tabBar.add_actor(this._tabBox);
// The searchArea just holds the entry
this._searchArea = new St.Bin({ name: 'searchArea' });
this._tabBar.add_actor(this._searchArea);
// The page area holds the tab pages. Every page is given the
// area's full allocation, so that the pages would appear on top
// of each other if the inactive ones weren't hidden.
this._pageArea = new Shell.Stack();
this.actor.add(this._pageArea, { x_fill: true,
y_fill: true,
expand: true });
this._tabs = [];
this._activeTab = null;
this._searchTab = new SearchTab();
this._searchArea.set_child(this._searchTab.title);
this._addTab(this._searchTab);
this._searchTab.connect('search-cancelled', Lang.bind(this,
function() {
this._switchTab(this._activeTab);
}));
Main.overview.connect('item-drag-begin',
Lang.bind(this, this._switchDefaultTab));
this._stageKeyPressId = 0;
Main.overview.connect('showing', Lang.bind(this,
function () {
this._switchDefaultTab();
this._stageKeyPressId = global.stage.connect('key-press-event',
Lang.bind(this, this._onStageKeyPress));
}));
Main.overview.connect('hiding', Lang.bind(this,
function () {
this._switchDefaultTab();
if (this._stageKeyPressId != 0) {
global.stage.disconnect(this._stageKeyPressId);
this._stageKeyPressId = 0;
}
}));
// Public constraints which may be used to tie actors' height or
// vertical position to the current tab's content; as the content's
// height and position depend on the view selector's style properties
// (e.g. font size, padding, spacing, ...) it would be extremely hard
// and ugly to get these from the outside. While it would be possible
// to use position and height properties directly, outside code would
// need to ensure that the content is properly allocated before
// accessing the properties.
this.constrainY = new Clutter.BindConstraint({ source: this._pageArea,
coordinate: Clutter.BindCoordinate.Y });
this.constrainHeight = new Clutter.BindConstraint({ source: this._pageArea,
coordinate: Clutter.BindCoordinate.HEIGHT });
},
_addTab: function(tab) {
tab.page.hide();
this._pageArea.add_actor(tab.page);
tab.connect('activated', Lang.bind(this, function(tab) {
this._switchTab(tab);
}));
},
addViewTab: function(id, title, pageActor, a11yIcon) {
let viewTab = new ViewTab(id, title, pageActor, a11yIcon);
this._tabs.push(viewTab);
this._tabBox.add(viewTab.title);
this._addTab(viewTab);
},
_switchTab: function(tab) {
let firstSwitch = this._activeTab == null;
if (this._activeTab && this._activeTab.visible) {
if (this._activeTab == tab)
return;
this._activeTab.title.remove_style_pseudo_class('selected');
this._activeTab.hide();
}
if (tab != this._searchTab) {
tab.title.add_style_pseudo_class('selected');
this._activeTab = tab;
if (this._searchTab.visible) {
this._searchTab.hide();
}
}
// Only fade when switching between tabs,
// not when setting the initially selected one.
if (!tab.visible)
tab.show(!firstSwitch);
},
switchTab: function(id) {
for (let i = 0; i < this._tabs.length; i++)
if (this._tabs[i].id == id) {
this._switchTab(this._tabs[i]);
break;
}
},
_switchDefaultTab: function() {
if (this._tabs.length > 0)
this._switchTab(this._tabs[0]);
},
_nextTab: function() {
if (this._tabs.length == 0 ||
this._tabs[this._tabs.length - 1] == this._activeTab)
return;
for (let i = 0; i < this._tabs.length; i++)
if (this._tabs[i] == this._activeTab) {
this._switchTab(this._tabs[i + 1]);
return;
}
},
_prevTab: function() {
if (this._tabs.length == 0 || this._tabs[0] == this._activeTab)
return;
for (let i = 0; i < this._tabs.length; i++)
if (this._tabs[i] == this._activeTab) {
this._switchTab(this._tabs[i - 1]);
return;
}
},
_getPreferredTabBarWidth: function(box, forHeight, alloc) {
let children = box.get_children();
for (let i = 0; i < children.length; i++) {
let [childMin, childNat] = children[i].get_preferred_width(forHeight);
alloc.min_size += childMin;
alloc.natural_size += childNat;
}
},
_getPreferredTabBarHeight: function(box, forWidth, alloc) {
let children = box.get_children();
for (let i = 0; i < children.length; i++) {
let [childMin, childNatural] = children[i].get_preferred_height(forWidth);
if (childMin > alloc.min_size)
alloc.min_size = childMin;
if (childNatural > alloc.natural_size)
alloc.natural_size = childNatural;
}
},
_allocateTabBar: function(container, box, flags) {
let allocWidth = box.x2 - box.x1;
let allocHeight = box.y2 - box.y1;
let [searchMinWidth, searchNatWidth] = this._searchArea.get_preferred_width(-1);
let [barMinWidth, barNatWidth] = this._tabBox.get_preferred_width(-1);
let childBox = new Clutter.ActorBox();
childBox.y1 = 0;
childBox.y2 = allocHeight;
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL) {
childBox.x1 = allocWidth - barNatWidth;
childBox.x2 = allocWidth;
} else {
childBox.x1 = 0;
childBox.x2 = barNatWidth;
}
this._tabBox.allocate(childBox, flags);
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL) {
childBox.x1 = 0;
childBox.x2 = searchNatWidth;
} else {
childBox.x1 = allocWidth - searchNatWidth;
childBox.x2 = allocWidth;
}
this._searchArea.allocate(childBox, flags);
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
function() {
this.constrainY.offset = this.actor.y;
}));
},
_onStageKeyPress: function(actor, event) {
let modifiers = event.get_state();
let symbol = event.get_key_symbol();
if (symbol == Clutter.Escape) {
if (this._searchTab.active)
this._searchTab.reset();
else
Main.overview.hide();
return true;
} else if (Clutter.keysym_to_unicode(symbol) ||
(symbol == Clutter.BackSpace && this._searchTab.active)) {
this._searchTab.startSearch(event);
} else if (!this._searchTab.active) {
if (modifiers & Clutter.ModifierType.CONTROL_MASK) {
if (symbol == Clutter.Page_Up) {
this._prevTab();
return true;
} else if (symbol == Clutter.Page_Down) {
this._nextTab();
return true;
}
} else if (symbol == Clutter.Tab) {
this._activeTab.page.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
return true;
} else if (symbol == Clutter.ISO_Left_Tab) {
this._activeTab.page.navigate_focus(null, Gtk.DirectionType.TAB_BACKWARD, false);
return true;
}
}
return false;
},
addSearchProvider: function(provider) {
this._searchSystem.registerProvider(provider);
this._searchResults.createProviderMeta(provider);
this._searchTab.addSearchProvider(provider);
},
removeSearchProvider: function(provider) {
this._searchSystem.unregisterProvider(provider);
this._searchResults.destroyProviderMeta(provider);
this._searchTab.removeSearchProvider(provider);
}
});
Signals.addSignalMethods(ViewSelector.prototype);

View File

@@ -9,7 +9,6 @@ const Signals = imports.signals;
const St = imports.gi.St;
const IconGrid = imports.ui.iconGrid;
const Layout = imports.ui.layout;
const Main = imports.ui.main;
const Search = imports.ui.search;
@@ -55,7 +54,9 @@ const WandaIcon = new Lang.Class({
if (!this._imageFile) {
return new St.Icon({ icon_name: 'face-smile',
icon_size: iconSize });
icon_type: St.IconType.FULLCOLOR,
icon_size: iconSize
});
}
this._animations = St.TextureCache.get_default().load_sliced_image(this._imageFile, this._imgWidth, this._imgHeight);
@@ -141,18 +142,17 @@ const FortuneDialog = new Lang.Class({
this._button.connect('clicked', Lang.bind(this, this.destroy));
this._button.child = this._box;
this._bin = new St.Bin({ x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE });
this._bin.add_constraint(new Layout.MonitorConstraint({ primary: true }));
this._bin.add_actor(this._button);
let monitor = Main.layoutManager.primaryMonitor;
Main.layoutManager.addChrome(this._bin);
Main.layoutManager.addChrome(this._button);
this._button.set_position(Math.floor(monitor.width / 2 - this._button.width / 2),
Math.floor(monitor.height / 2 - this._button.height / 2));
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 10, Lang.bind(this, this.destroy));
},
destroy: function() {
this._bin.destroy();
this._button.destroy();
}
});
@@ -181,6 +181,7 @@ const WandaSearchProvider = new Lang.Class({
// triggers an assertion failure)
return St.TextureCache.get_default().load_icon_name(null,
'face-smile',
St.IconType.FULLCOLOR,
iconSize);
}
}]);

View File

@@ -15,7 +15,8 @@ const Tweener = imports.ui.tweener;
const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
const WINDOW_ANIMATION_TIME = 0.25;
const DIM_BRIGHTNESS = -0.3;
const DIM_DESATURATION = 0.6;
const DIM_BRIGHTNESS = -0.1;
const DIM_TIME = 0.500;
const UNDIM_TIME = 0.250;
@@ -24,27 +25,23 @@ const WindowDimmer = new Lang.Class({
Name: 'WindowDimmer',
_init: function(actor) {
this._desaturateEffect = new Clutter.DesaturateEffect();
this._brightnessEffect = new Clutter.BrightnessContrastEffect();
actor.add_effect(this._desaturateEffect);
actor.add_effect(this._brightnessEffect);
this.actor = actor;
this._enabled = true;
this._dimFactor = 0.0;
this._syncEnabled();
},
_syncEnabled: function() {
this._brightnessEffect.enabled = (this._enabled && this._dimFactor > 0);
},
setEnabled: function(enabled) {
this._enabled = enabled;
this._syncEnabled();
this._desaturateEffect.enabled = enabled;
this._brightnessEffect.enabled = enabled;
},
set dimFactor(factor) {
this._dimFactor = factor;
this._desaturateEffect.set_factor(factor * DIM_DESATURATION);
this._brightnessEffect.set_brightness(factor * DIM_BRIGHTNESS);
this._syncEnabled();
},
get dimFactor() {
@@ -53,17 +50,10 @@ const WindowDimmer = new Lang.Class({
});
function getWindowDimmer(actor) {
let enabled = Meta.prefs_get_attach_modal_dialogs();
if (actor._windowDimmer)
actor._windowDimmer.setEnabled(enabled);
if (!actor._windowDimmer)
actor._windowDimmer = new WindowDimmer(actor);
if (enabled) {
if (!actor._windowDimmer)
actor._windowDimmer = new WindowDimmer(actor);
return actor._windowDimmer;
} else {
return null;
}
return actor._windowDimmer;
}
const WindowManager = new Lang.Class({
@@ -270,7 +260,9 @@ const WindowManager = new Lang.Class({
if (!actor)
return;
let dimmer = getWindowDimmer(actor);
if (!dimmer)
let enabled = Meta.prefs_get_attach_modal_dialogs();
dimmer.setEnabled(enabled);
if (!enabled)
return;
Tweener.addTween(dimmer,
{ dimFactor: 1.0,
@@ -284,12 +276,15 @@ const WindowManager = new Lang.Class({
if (!actor)
return;
let dimmer = getWindowDimmer(actor);
if (!dimmer)
let enabled = Meta.prefs_get_attach_modal_dialogs();
dimmer.setEnabled(enabled);
if (!enabled)
return;
Tweener.addTween(dimmer,
{ dimFactor: 0.0,
time: UNDIM_TIME,
transition: 'linear' });
transition: 'linear'
});
},
_mapWindow : function(shellwm, actor) {
@@ -309,29 +304,12 @@ const WindowManager = new Lang.Class({
}));
if (actor.meta_window.is_attached_dialog()) {
this._checkDimming(actor.get_meta_window().get_transient_for());
if (this._shouldAnimate()) {
actor.set_scale(1.0, 0.0);
actor.scale_gravity = Clutter.Gravity.CENTER;
actor.show();
this._mapping.push(actor);
Tweener.addTween(actor,
{ scale_y: 1,
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._mapWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._mapWindowOverwrite,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
if (!this._shouldAnimate()) {
shellwm.completed_map(actor);
return;
}
shellwm.completed_map(actor);
return;
}
if (!this._shouldAnimateActor(actor)) {
} else if (!this._shouldAnimateActor(actor)) {
shellwm.completed_map(actor);
return;
}
@@ -387,8 +365,7 @@ const WindowManager = new Lang.Class({
return;
}
actor.set_scale(1.0, 1.0);
actor.scale_gravity = Clutter.Gravity.CENTER;
actor.opacity = 255;
actor.show();
this._destroying.push(actor);
@@ -398,7 +375,7 @@ const WindowManager = new Lang.Class({
}));
Tweener.addTween(actor,
{ scale_y: 0,
{ opacity: 0,
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._destroyWindowDone,

View File

@@ -499,9 +499,9 @@ const WindowOverlay = new Lang.Class({
this.title.opacity = 0;
this._parentActor.raise_top();
Tweener.addTween(this.title,
{ opacity: 255,
time: CLOSE_BUTTON_FADE_TIME,
transition: 'easeOutQuad' });
{ opacity: 255,
time: CLOSE_BUTTON_FADE_TIME,
transition: 'easeOutQuad' });
},
chromeWidth: function () {
@@ -510,7 +510,7 @@ const WindowOverlay = new Lang.Class({
chromeHeights: function () {
return [this.closeButton.height - this.closeButton._overlap,
this.title.height + this.title._spacing];
this.title.height + this.title._spacing];
},
/**
@@ -720,15 +720,12 @@ const Workspace = new Lang.Class({
Lang.bind(this, this._windowRemoved));
}
this._windowEnteredMonitorId = global.screen.connect('window-entered-monitor',
Lang.bind(this, this._windowEnteredMonitor));
Lang.bind(this, this._windowEnteredMonitor));
this._windowLeftMonitorId = global.screen.connect('window-left-monitor',
Lang.bind(this, this._windowLeftMonitor));
Lang.bind(this, this._windowLeftMonitor));
this._repositionWindowsId = 0;
this.leavingOverview = false;
this._positionWindowsFlags = 0;
this._positionWindowsId = 0;
},
setGeometry: function(x, y, width, height) {
@@ -737,13 +734,15 @@ const Workspace = new Lang.Class({
this._width = width;
this._height = height;
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
this._dropRect.set_position(x, y);
this._dropRect.set_size(width, height);
return false;
}));
// This is sometimes called during allocation, so we do this later
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
function () {
this._dropRect.set_position(x, y);
this._dropRect.set_size(width, height);
this.positionWindows(WindowPositionFlags.ANIMATE);
return false;
}));
this.positionWindows(WindowPositionFlags.ANIMATE);
},
_lookupIndex: function (metaWindow) {
@@ -986,10 +985,15 @@ const Workspace = new Lang.Class({
if (this._reservedSlot == clone)
return;
if (clone && this.containsMetaWindow(clone.metaWindow))
clone = null;
this._reservedSlot = clone;
if (clone && this.containsMetaWindow(clone.metaWindow)) {
this._reservedSlot = null;
this.positionWindows(WindowPositionFlags.ANIMATE);
return;
}
if (clone)
this._reservedSlot = clone;
else
this._reservedSlot = null;
this.positionWindows(WindowPositionFlags.ANIMATE);
},
@@ -999,21 +1003,7 @@ const Workspace = new Lang.Class({
* INITIAL - this is the initial positioning of the windows.
* ANIMATE - Indicates that we need animate changing position.
*/
positionWindows: function(flags) {
this._positionWindowsFlags |= flags;
if (this._positionWindowsId > 0)
return;
this._positionWindowsId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
this._realPositionWindows(this._positionWindowsFlags);
this._positionWindowsFlags = 0;
this._positionWindowsId = 0;
return false;
}));
},
_realPositionWindows : function(flags) {
positionWindows : function(flags) {
if (this._repositionWindowsId > 0) {
Mainloop.source_remove(this._repositionWindowsId);
this._repositionWindowsId = 0;
@@ -1054,20 +1044,20 @@ const Workspace = new Lang.Class({
/* Hidden windows should fade in and grow
* therefore we need to resize them now so they
* can be scaled up later */
if (initialPositioning) {
clone.actor.opacity = 0;
clone.actor.scale_x = 0;
clone.actor.scale_y = 0;
clone.actor.x = x;
clone.actor.y = y;
}
if (initialPositioning) {
clone.actor.opacity = 0;
clone.actor.scale_x = 0;
clone.actor.scale_y = 0;
clone.actor.x = x;
clone.actor.y = y;
}
// Make the window slightly transparent to indicate it's hidden
Tweener.addTween(clone.actor,
{ opacity: 255,
time: Overview.ANIMATION_TIME,
transition: 'easeInQuad'
});
// Make the window slightly transparent to indicate it's hidden
Tweener.addTween(clone.actor,
{ opacity: 255,
time: Overview.ANIMATION_TIME,
transition: 'easeInQuad'
});
}
this._animateClone(clone, overlay, x, y, scale, initialPositioning);
@@ -1098,16 +1088,16 @@ const Workspace = new Lang.Class({
_animateClone: function(clone, overlay, x, y, scale, initialPositioning) {
Tweener.addTween(clone.actor,
{ x: x,
y: y,
scale_x: scale,
scale_y: scale,
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this, function() {
this._showWindowOverlay(clone, overlay, true);
})
});
{ x: x,
y: y,
scale_x: scale,
scale_y: scale,
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this, function() {
this._showWindowOverlay(clone, overlay, true);
})
});
this._updateWindowOverlayPositions(clone, overlay, x, y, scale, true);
},
@@ -1382,9 +1372,6 @@ const Workspace = new Lang.Class({
if (this._repositionWindowsId > 0)
Mainloop.source_remove(this._repositionWindowsId);
if (this._positionWindowsId > 0)
Meta.later_remove(this._positionWindowsId);
// Usually, the windows will be destroyed automatically with
// their parent (this.actor), but we might have a zoomed window
// which has been reparented to the stage - _windows[0] holds

View File

@@ -1045,16 +1045,9 @@ const ThumbnailsBox = new Lang.Class({
childBox.y2 = box.y2;
this._background.allocate(childBox, flags);
let indicatorY1 = this._indicatorY;
let indicatorY2;
let indicatorY = this._indicatorY;
// when not animating, the workspace position overrides this._indicatorY
let indicatorWorkspace = !this._animatingIndicator ? global.screen.get_active_workspace() : null;
let indicatorThemeNode = this._indicator.get_theme_node();
let indicatorTopFullBorder = indicatorThemeNode.get_padding(St.Side.TOP) + indicatorThemeNode.get_border_width(St.Side.TOP);
let indicatorBottomFullBorder = indicatorThemeNode.get_padding(St.Side.BOTTOM) + indicatorThemeNode.get_border_width(St.Side.BOTTOM);
let indicatorLeftFullBorder = indicatorThemeNode.get_padding(St.Side.LEFT) + indicatorThemeNode.get_border_width(St.Side.LEFT);
let indicatorRightFullBorder = indicatorThemeNode.get_padding(St.Side.RIGHT) + indicatorThemeNode.get_border_width(St.Side.RIGHT);
let y = contentBox.y1;
@@ -1100,10 +1093,8 @@ const ThumbnailsBox = new Lang.Class({
let y2 = Math.round(y + thumbnailHeight);
let roundedVScale = (y2 - y1) / portholeHeight;
if (thumbnail.metaWorkspace == indicatorWorkspace) {
indicatorY1 = y1;
indicatorY2 = y2;
}
if (thumbnail.metaWorkspace == indicatorWorkspace)
indicatorY = y1;
// Allocating a scaled actor is funny - x1/y1 correspond to the origin
// of the actor, but x2/y2 are increased by the *unscaled* size.
@@ -1128,10 +1119,8 @@ const ThumbnailsBox = new Lang.Class({
childBox.x1 = contentBox.x2 - thumbnailWidth;
childBox.x2 = contentBox.x2;
}
childBox.x1 -= indicatorLeftFullBorder;
childBox.x2 += indicatorRightFullBorder;
childBox.y1 = indicatorY1 - indicatorTopFullBorder;
childBox.y2 = (indicatorY2 ? indicatorY2 : (indicatorY1 + thumbnailHeight)) + indicatorBottomFullBorder;
childBox.y1 = indicatorY;
childBox.y2 = childBox.y1 + thumbnailHeight;
this._indicator.allocate(childBox, flags);
},
@@ -1146,9 +1135,7 @@ const ThumbnailsBox = new Lang.Class({
}
this._animatingIndicator = true;
let indicatorThemeNode = this._indicator.get_theme_node();
let indicatorTopFullBorder = indicatorThemeNode.get_padding(St.Side.TOP) + indicatorThemeNode.get_border_width(St.Side.TOP);
this.indicatorY = this._indicator.allocation.y1 + indicatorTopFullBorder;
this.indicatorY = this._indicator.allocation.y1;
Tweener.addTween(this,
{ indicatorY: thumbnail.actor.allocation.y1,
time: WorkspacesView.WORKSPACE_SWITCH_TIME,

View File

@@ -317,6 +317,8 @@ const WorkspacesView = new Lang.Class({
this._updateWorkspaceActors(false);
}
this._scrollToActive(true);
},
_activeWorkspaceChanged: function(wm, from, to, direction) {
@@ -868,10 +870,15 @@ const WorkspacesDisplay = new Lang.Class({
let clipX = rtl ? x + controlsVisible : x;
let clipY = y + (fullHeight - clipHeight) / 2;
let widthAdjust = this._zoomOut ? controlsNatural : controlsVisible;
width -= widthAdjust;
if (rtl)
x += widthAdjust;
if (this._zoomOut) {
width -= controlsNatural;
if (rtl)
x += controlsNatural;
} else {
width -= controlsVisible;
if (rtl)
x += controlsVisible;
}
height = (fullHeight / fullWidth) * width;
let difference = fullHeight - height;

View File

@@ -4,7 +4,6 @@ data/org.gnome.shell.gschema.xml.in.in
js/extensionPrefs/main.js
js/gdm/loginDialog.js
js/gdm/powerMenu.js
js/gdm/util.js
js/misc/util.js
js/ui/appDisplay.js
js/ui/appFavorites.js
@@ -28,14 +27,12 @@ js/ui/placeDisplay.js
js/ui/polkitAuthenticationAgent.js
js/ui/popupMenu.js
js/ui/runDialog.js
js/ui/screenShield.js
js/ui/searchDisplay.js
js/ui/shellEntry.js
js/ui/shellMountOperation.js
js/ui/status/accessibility.js
js/ui/status/bluetooth.js
js/ui/status/keyboard.js
js/ui/status/lockScreenMenu.js
js/ui/status/network.js
js/ui/status/power.js
js/ui/status/volume.js

592
po/ar.po

File diff suppressed because it is too large Load Diff

557
po/as.po

File diff suppressed because it is too large Load Diff

919
po/de.po

File diff suppressed because it is too large Load Diff

860
po/el.po

File diff suppressed because it is too large Load Diff

609
po/es.po

File diff suppressed because it is too large Load Diff

699
po/gl.po

File diff suppressed because it is too large Load Diff

250
po/gu.po
View File

@@ -9,8 +9,8 @@ msgstr ""
"Project-Id-Version: gu\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug."
"cgi?product=gnome-shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-08-06 17:11+0000\n"
"PO-Revision-Date: 2012-08-07 15:02+0530\n"
"POT-Creation-Date: 2012-07-21 17:14+0000\n"
"PO-Revision-Date: 2012-07-30 12:48+0530\n"
"Last-Translator: \n"
"Language-Team: gu_IN <kde-i18n-doc@kde.org>\n"
"Language: \n"
@@ -187,49 +187,48 @@ msgid "There was an error loading the preferences dialog for %s:"
msgstr "ત્યાં %s માટે પસંદગી સંવાદને લાવવામાં ભૂલ હતી:"
#: ../js/extensionPrefs/main.js:164
#| msgid "<b>Extension</b>"
msgid "Extension"
msgstr "ઍક્સટેન્શન"
msgid "<b>Extension</b>"
msgstr "<b>ઍક્સટેન્શન</b>"
#: ../js/extensionPrefs/main.js:188
msgid "Select an extension to configure using the combobox above."
msgstr "ઉપર કોમ્બોબોક્સની મદદથી રૂપરેખાંકિત કરવા માટે ઍક્સટેન્શનને પસંદ કરો."
#: ../js/gdm/loginDialog.js:572
#: ../js/gdm/loginDialog.js:550
msgid "Session..."
msgstr "સત્ર..."
#: ../js/gdm/loginDialog.js:721
#: ../js/gdm/loginDialog.js:699
msgctxt "title"
msgid "Sign In"
msgstr "પ્રવેશો"
#. Translators: this message is shown below the password entry field
#. to indicate the user can swipe their finger instead
#: ../js/gdm/loginDialog.js:766 ../js/ui/unlockDialog.js:124
#: ../js/gdm/loginDialog.js:744 ../js/ui/unlockDialog.js:124
msgid "(or swipe finger)"
msgstr "(અથવા સ્વાઇપ આંગળી)"
#. translators: this message is shown below the user list on the
#. login screen. It can be activated to reveal an entry for
#. manually entering the username.
#: ../js/gdm/loginDialog.js:787
#: ../js/gdm/loginDialog.js:765
msgid "Not listed?"
msgstr "શું યાદી થયેલ નથી?"
#: ../js/gdm/loginDialog.js:930 ../js/ui/endSessionDialog.js:406
#: ../js/gdm/loginDialog.js:908 ../js/ui/endSessionDialog.js:406
#: ../js/ui/extensionDownloader.js:195 ../js/ui/networkAgent.js:153
#: ../js/ui/polkitAuthenticationAgent.js:176
#: ../js/ui/shellMountOperation.js:396 ../js/ui/status/bluetooth.js:432
#: ../js/ui/shellMountOperation.js:396 ../js/ui/status/bluetooth.js:436
msgid "Cancel"
msgstr "રદ કરો"
#: ../js/gdm/loginDialog.js:935
#: ../js/gdm/loginDialog.js:913
msgctxt "button"
msgid "Sign In"
msgstr "પ્રવેશો"
#: ../js/gdm/loginDialog.js:1280
#: ../js/gdm/loginDialog.js:1256
msgid "Login Window"
msgstr "પ્રવેશ વિન્ડો"
@@ -301,12 +300,12 @@ msgstr "%s ને તમારી પસંદીદામાંથી દૂર
msgid "Removable Devices"
msgstr "દૂર કરી શકાય તેવા ઉપકરણો"
#: ../js/ui/autorunManager.js:548
#: ../js/ui/autorunManager.js:549
#, c-format
msgid "Open with %s"
msgstr "%s સાથે ખોલો"
#: ../js/ui/autorunManager.js:574
#: ../js/ui/autorunManager.js:575
msgid "Eject"
msgstr "રદ કરો"
@@ -456,7 +455,7 @@ msgstr "આ અઠવાડિયે"
msgid "Next week"
msgstr "આગળનું અઠવાડિયું"
#: ../js/ui/dash.js:238 ../js/ui/messageTray.js:1317
#: ../js/ui/dash.js:238 ../js/ui/messageTray.js:1321
msgid "Remove"
msgstr "દૂર કરો"
@@ -579,8 +578,8 @@ msgstr "extensions.gnome.org માંથી '%s' ને સ્થાપિત
msgid "tray"
msgstr "ટ્રે"
#: ../js/ui/keyboard.js:545 ../js/ui/status/keyboard.js:146
#: ../js/ui/status/power.js:205
#: ../js/ui/keyboard.js:545 ../js/ui/status/keyboard.js:149
#: ../js/ui/status/power.js:209
msgid "Keyboard"
msgstr "કિબોર્ડ"
@@ -641,24 +640,24 @@ msgid "Web Page"
msgstr "વેબ પાનું"
#. Translators: this is a filename used for screencast recording
#: ../js/ui/main.js:138
#: ../js/ui/main.js:140
#, no-c-format
msgid "Screencast from %d %t"
msgstr "%d %t માંથી સ્ક્રીનકાસ્ટ"
#: ../js/ui/messageTray.js:1310
#: ../js/ui/messageTray.js:1314
msgid "Open"
msgstr "ખોલો"
#: ../js/ui/messageTray.js:1327
#: ../js/ui/messageTray.js:1331
msgid "Unmute"
msgstr "અવાજ ચાલુ રાખો"
#: ../js/ui/messageTray.js:1327
#: ../js/ui/messageTray.js:1331
msgid "Mute"
msgstr "મૂંગુ"
#: ../js/ui/messageTray.js:2638
#: ../js/ui/messageTray.js:2642
msgid "System Information"
msgstr "સિસ્ટમ જાણકારી"
@@ -741,7 +740,8 @@ msgstr "મોબાઇલ બ્રોડબેન્ડ નેટવર્ક
msgid "A password is required to connect to '%s'."
msgstr "પાસવર્ડ '%s' સાથે જોડાવા માટે જરૂરી છે."
#: ../js/ui/notificationDaemon.js:506 ../src/shell-app.c:374
#: ../js/ui/notificationDaemon.js:484 ../src/shell-app.c:374
#| msgid "Unknown"
msgctxt "program"
msgid "Unknown"
msgstr "અજ્ઞાત"
@@ -778,7 +778,7 @@ msgstr "બહાર નીકળો"
msgid "Activities"
msgstr "પ્રવૃત્તિઓ"
#: ../js/ui/panel.js:971
#: ../js/ui/panel.js:975
msgid "Top Bar"
msgstr "ટોચની પટ્ટી"
@@ -825,7 +825,7 @@ msgstr "દિલગીર છું, કામ કરતુ નથી. મહ
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle
#. switches containing "◯" and "|"). Other values will
#. simply result in invisible toggle switches.
#: ../js/ui/popupMenu.js:723
#: ../js/ui/popupMenu.js:727
msgid "toggle-switch-us"
msgstr "toggle-switch-us"
@@ -867,325 +867,326 @@ msgstr "પાસફ્રેજને યાદ રાખો"
#: ../js/ui/shellMountOperation.js:400 ../js/ui/unlockDialog.js:142
msgid "Unlock"
msgstr "તાળું ખોલો"
msgstr ""
#: ../js/ui/status/accessibility.js:39
#: ../js/ui/status/accessibility.js:47
msgid "Accessibility"
msgstr "ઉપલબ્ધતા"
#: ../js/ui/status/accessibility.js:44
#: ../js/ui/status/accessibility.js:52
msgid "Zoom"
msgstr "નાનુ મોટુ કરો"
#: ../js/ui/status/accessibility.js:51
#: ../js/ui/status/accessibility.js:59
#| msgid "Screen Keyboard"
msgid "Screen Reader"
msgstr "સ્ક્રીન રીડર"
#: ../js/ui/status/accessibility.js:55
#: ../js/ui/status/accessibility.js:63
msgid "Screen Keyboard"
msgstr "સ્ક્રીન કિબોર્ડ"
#: ../js/ui/status/accessibility.js:59
#: ../js/ui/status/accessibility.js:67
msgid "Visual Alerts"
msgstr "દેખાતી ચેતવણીઓ"
#: ../js/ui/status/accessibility.js:62
#: ../js/ui/status/accessibility.js:70
msgid "Sticky Keys"
msgstr "સ્ટીકી કી"
#: ../js/ui/status/accessibility.js:65
#: ../js/ui/status/accessibility.js:73
msgid "Slow Keys"
msgstr "ધીમી કી"
#: ../js/ui/status/accessibility.js:68
#: ../js/ui/status/accessibility.js:76
msgid "Bounce Keys"
msgstr "બાઉન્સ કી"
#: ../js/ui/status/accessibility.js:71
#: ../js/ui/status/accessibility.js:79
msgid "Mouse Keys"
msgstr "માઉસ કીઓ"
#: ../js/ui/status/accessibility.js:75
#: ../js/ui/status/accessibility.js:83
msgid "Universal Access Settings"
msgstr "યુનિવર્સલ વપરાશ સુયોજનો"
#: ../js/ui/status/accessibility.js:113
#: ../js/ui/status/accessibility.js:121
msgid "High Contrast"
msgstr "ઉચ્ચ વિરોધાભાસ"
#: ../js/ui/status/accessibility.js:150
#: ../js/ui/status/accessibility.js:158
msgid "Large Text"
msgstr "લાંબુ લખાણ"
#: ../js/ui/status/bluetooth.js:27 ../js/ui/status/bluetooth.js:31
#: ../js/ui/status/bluetooth.js:256 ../js/ui/status/bluetooth.js:309
#: ../js/ui/status/bluetooth.js:340 ../js/ui/status/bluetooth.js:376
#: ../js/ui/status/bluetooth.js:405 ../js/ui/status/network.js:841
#: ../js/ui/status/bluetooth.js:31 ../js/ui/status/bluetooth.js:35
#: ../js/ui/status/bluetooth.js:260 ../js/ui/status/bluetooth.js:313
#: ../js/ui/status/bluetooth.js:344 ../js/ui/status/bluetooth.js:380
#: ../js/ui/status/bluetooth.js:409 ../js/ui/status/network.js:844
msgid "Bluetooth"
msgstr "બ્લુટુથ"
#: ../js/ui/status/bluetooth.js:44
#: ../js/ui/status/bluetooth.js:48
msgid "Visibility"
msgstr "દૃશ્યતા"
#: ../js/ui/status/bluetooth.js:58
#: ../js/ui/status/bluetooth.js:62
msgid "Send Files to Device..."
msgstr "ઉપકરણમાં ફાઇલોને મોકલો..."
#: ../js/ui/status/bluetooth.js:59
#: ../js/ui/status/bluetooth.js:63
msgid "Set up a New Device..."
msgstr "નવા ઉપકરણને સુયોજિત કરો..."
#: ../js/ui/status/bluetooth.js:83
#: ../js/ui/status/bluetooth.js:87
msgid "Bluetooth Settings"
msgstr "બ્લુટુથ સુયોજનો"
#. TRANSLATORS: this means that bluetooth was disabled by hardware rfkill
#: ../js/ui/status/bluetooth.js:108 ../js/ui/status/network.js:208
#: ../js/ui/status/bluetooth.js:112 ../js/ui/status/network.js:211
msgid "hardware disabled"
msgstr "હાર્ડવેર નિષ્ક્રિય"
#: ../js/ui/status/bluetooth.js:201
#: ../js/ui/status/bluetooth.js:205
msgid "Connection"
msgstr "જોડાણ"
#: ../js/ui/status/bluetooth.js:212 ../js/ui/status/network.js:442
#: ../js/ui/status/bluetooth.js:216 ../js/ui/status/network.js:445
msgid "disconnecting..."
msgstr "જોડાઇ તૂટી રહ્યુ છે..."
#: ../js/ui/status/bluetooth.js:225 ../js/ui/status/network.js:448
#: ../js/ui/status/network.js:908
#: ../js/ui/status/bluetooth.js:229 ../js/ui/status/network.js:451
#: ../js/ui/status/network.js:911
msgid "connecting..."
msgstr "જોડાઇ રહ્યા છે..."
#: ../js/ui/status/bluetooth.js:243
#: ../js/ui/status/bluetooth.js:247
msgid "Send Files..."
msgstr "ફાઇલોને મોકલો..."
#: ../js/ui/status/bluetooth.js:248
#: ../js/ui/status/bluetooth.js:252
msgid "Browse Files..."
msgstr "ફાઇલોને બ્રાઉઝ કરો..."
#: ../js/ui/status/bluetooth.js:257
#: ../js/ui/status/bluetooth.js:261
msgid "Error browsing device"
msgstr "ઉપકરણને બ્રાઉઝ કરતી વખતે ભૂલ"
#: ../js/ui/status/bluetooth.js:258
#: ../js/ui/status/bluetooth.js:262
#, c-format
msgid "The requested device cannot be browsed, error is '%s'"
msgstr "સુચિત ઉપકરણને બ્રાઉઝ કરી શકાતુ નથી, ભૂલ '%s' છે"
#: ../js/ui/status/bluetooth.js:266
#: ../js/ui/status/bluetooth.js:270
msgid "Keyboard Settings"
msgstr "કીબોર્ડ સુયોજનો"
#: ../js/ui/status/bluetooth.js:269
#: ../js/ui/status/bluetooth.js:273
msgid "Mouse Settings"
msgstr "માઉસ સુયોજનો"
#: ../js/ui/status/bluetooth.js:274 ../js/ui/status/volume.js:54
#: ../js/ui/status/bluetooth.js:278 ../js/ui/status/volume.js:59
msgid "Sound Settings"
msgstr "સાઇન્ડ સુયોજનો"
#: ../js/ui/status/bluetooth.js:341
#: ../js/ui/status/bluetooth.js:345
#, c-format
msgid "Authorization request from %s"
msgstr "%s માંથી સત્તાધિકરણ માંગણી"
#: ../js/ui/status/bluetooth.js:347
#: ../js/ui/status/bluetooth.js:351
#, c-format
msgid "Device %s wants access to the service '%s'"
msgstr "ઉપકરણ %s એ સેવા %s' માટે પ્રવેશ ઇચ્છે છે"
#: ../js/ui/status/bluetooth.js:349
#: ../js/ui/status/bluetooth.js:353
msgid "Always grant access"
msgstr "હંમેશા વપરાશ મંજૂર કરો"
#: ../js/ui/status/bluetooth.js:350
#: ../js/ui/status/bluetooth.js:354
msgid "Grant this time only"
msgstr "ફક્ત આ સમયે સંમતિ આપો"
#: ../js/ui/status/bluetooth.js:351 ../js/ui/telepathyClient.js:1097
#: ../js/ui/status/bluetooth.js:355 ../js/ui/telepathyClient.js:1097
msgid "Reject"
msgstr "રદ કરો"
#: ../js/ui/status/bluetooth.js:377
#: ../js/ui/status/bluetooth.js:381
#, c-format
msgid "Pairing confirmation for %s"
msgstr "%s માટો જોડીની ખાતરી"
#: ../js/ui/status/bluetooth.js:383 ../js/ui/status/bluetooth.js:413
#: ../js/ui/status/bluetooth.js:387 ../js/ui/status/bluetooth.js:417
#, c-format
msgid "Device %s wants to pair with this computer"
msgstr "ઉપકરણ %s આ કમ્પ્યૂટર સાથે જોડી કરવા માંગે છે"
#: ../js/ui/status/bluetooth.js:384
#: ../js/ui/status/bluetooth.js:388
#, fuzzy, c-format
#| msgid "Please confirm whether the PIN '%s' matches the one on the device."
msgid "Please confirm whether the PIN '%06d' matches the one on the device."
msgstr "મહેરબાની કરીને ખાતરી કરો કે શું PIN '%s' એ ઉપકરણ પર એક સાથે બંધબેસે છે."
#: ../js/ui/status/bluetooth.js:386
#: ../js/ui/status/bluetooth.js:390
msgid "Matches"
msgstr "બંધબેસે છે"
#: ../js/ui/status/bluetooth.js:387
#: ../js/ui/status/bluetooth.js:391
msgid "Does not match"
msgstr "બંધબેસતુ નથી"
#: ../js/ui/status/bluetooth.js:406
#: ../js/ui/status/bluetooth.js:410
#, c-format
msgid "Pairing request for %s"
msgstr "%s માટે જોડી માંગણી"
#: ../js/ui/status/bluetooth.js:414
#: ../js/ui/status/bluetooth.js:418
msgid "Please enter the PIN mentioned on the device."
msgstr "મહેરબાની કરીને ઉપકરણ પર દર્શાવેલ PIN દાખલ કરો."
#: ../js/ui/status/bluetooth.js:431
#: ../js/ui/status/bluetooth.js:435
msgid "OK"
msgstr "બરાબર"
#: ../js/ui/status/keyboard.js:175
#: ../js/ui/status/keyboard.js:178
msgid "Show Keyboard Layout"
msgstr "કીબોર્ડ લેઆઉટને બતાવો"
#: ../js/ui/status/keyboard.js:177
#: ../js/ui/status/keyboard.js:180
msgid "Region and Language Settings"
msgstr "વિસ્તાર અને ભાષા સુયોજનો"
#: ../js/ui/status/network.js:93
#: ../js/ui/status/network.js:96
msgid "<unknown>"
msgstr "<અજ્ઞાત>"
#. Translators: this indicates that wireless or wwan is disabled by hardware killswitch
#: ../js/ui/status/network.js:230
#: ../js/ui/status/network.js:233
msgid "disabled"
msgstr "નિષ્ક્રિય"
#. Translators: this is for network devices that are physically present but are not
#. under NetworkManager's control (and thus cannot be used in the menu)
#: ../js/ui/status/network.js:440
#: ../js/ui/status/network.js:443
msgid "unmanaged"
msgstr "સંચાલિત થયેલ નથી"
#. Translators: this is for network connections that require some kind of key or password
#: ../js/ui/status/network.js:451 ../js/ui/status/network.js:911
#: ../js/ui/status/network.js:454 ../js/ui/status/network.js:914
msgid "authentication required"
msgstr "સત્તાધિકરણ જરૂરી"
#. Translators: this is for devices that require some kind of firmware or kernel
#. module, which is missing
#: ../js/ui/status/network.js:461
#: ../js/ui/status/network.js:464
msgid "firmware missing"
msgstr "ફર્મવેર ગેરહાજર"
#. Translators: this is for wired network devices that are physically disconnected
#: ../js/ui/status/network.js:468
#: ../js/ui/status/network.js:471
msgid "cable unplugged"
msgstr "કેબલ પ્લગ થયેલ નથી"
#. Translators: this is for a network device that cannot be activated (for example it
#. is disabled by rfkill, or it has no coverage
#: ../js/ui/status/network.js:473
#: ../js/ui/status/network.js:476
msgid "unavailable"
msgstr "બિનઉપલબ્ધ"
#: ../js/ui/status/network.js:475 ../js/ui/status/network.js:913
#: ../js/ui/status/network.js:478 ../js/ui/status/network.js:916
msgid "connection failed"
msgstr "જોડાણ નિષ્ફળ"
#: ../js/ui/status/network.js:536 ../js/ui/status/network.js:1534
#: ../js/ui/status/network.js:539 ../js/ui/status/network.js:1537
msgid "More..."
msgstr "વધારે..."
#. TRANSLATORS: this is the indication that a connection for another logged in user is active,
#. and we cannot access its settings (including the name)
#: ../js/ui/status/network.js:572 ../js/ui/status/network.js:1464
#: ../js/ui/status/network.js:575 ../js/ui/status/network.js:1467
msgid "Connected (private)"
msgstr "જોડાયેલ (ખાનગી)"
#: ../js/ui/status/network.js:647
#: ../js/ui/status/network.js:650
msgid "Auto Ethernet"
msgstr "આપમેળે ઇથરનેટ"
#: ../js/ui/status/network.js:705
#: ../js/ui/status/network.js:708
msgid "Auto broadband"
msgstr "આપમેળે બ્રોડબેન્ડ"
#: ../js/ui/status/network.js:708
#: ../js/ui/status/network.js:711
msgid "Auto dial-up"
msgstr ""
#. TRANSLATORS: this the automatic wireless connection name (including the network name)
#: ../js/ui/status/network.js:827 ../js/ui/status/network.js:1481
#: ../js/ui/status/network.js:830 ../js/ui/status/network.js:1484
#, c-format
msgid "Auto %s"
msgstr "આપમેળે %s"
#: ../js/ui/status/network.js:829
#: ../js/ui/status/network.js:832
msgid "Auto bluetooth"
msgstr "આપમેળે બ્લુટુથ"
#: ../js/ui/status/network.js:1483
#: ../js/ui/status/network.js:1486
msgid "Auto wireless"
msgstr ""
#: ../js/ui/status/network.js:1592
#: ../js/ui/status/network.js:1595
msgid "Enable networking"
msgstr "નેટવર્કીંગ સક્રિય કરો"
#: ../js/ui/status/network.js:1614
#: ../js/ui/status/network.js:1617
msgid "Wired"
msgstr "વાયરવાળું"
#: ../js/ui/status/network.js:1625
#: ../js/ui/status/network.js:1628
msgid "Wireless"
msgstr "વાયરલેસ"
#: ../js/ui/status/network.js:1635
#: ../js/ui/status/network.js:1638
msgid "Mobile broadband"
msgstr "મોબાઇલ બ્રોડબેન્ડ"
#: ../js/ui/status/network.js:1645
#: ../js/ui/status/network.js:1648
msgid "VPN Connections"
msgstr "VPN જોડાણો"
#: ../js/ui/status/network.js:1652
#: ../js/ui/status/network.js:1655
msgid "Network Settings"
msgstr "નેટવર્ક સુયોજનો"
#: ../js/ui/status/network.js:1709
#: ../js/ui/status/network.js:1712
msgid "Network Manager"
msgstr "નેટવર્ક સંચાલક"
#: ../js/ui/status/network.js:1802
#: ../js/ui/status/network.js:1805
msgid "Connection failed"
msgstr "જોડાણ નિષ્ફળ"
#: ../js/ui/status/network.js:1803
#: ../js/ui/status/network.js:1806
msgid "Activation of network connection failed"
msgstr "નેટવર્ક જોડાણનું સક્રિયકરણ નિષ્ફળ થયેલ છે"
#: ../js/ui/status/network.js:2066
#: ../js/ui/status/network.js:2069
msgid "Networking is disabled"
msgstr "નેટવર્કીંગ નિષ્ક્રિય થયેલ છે"
#: ../js/ui/status/power.js:55
#: ../js/ui/status/power.js:59
msgid "Battery"
msgstr "બેટરી"
#: ../js/ui/status/power.js:72
#: ../js/ui/status/power.js:76
msgid "Power Settings"
msgstr "પાવર સુયોજનો"
#. 0 is reported when UPower does not have enough data
#. to estimate battery life
#: ../js/ui/status/power.js:100
#: ../js/ui/status/power.js:104
msgid "Estimating..."
msgstr "અંદાજ કરી રહ્યા છે..."
#: ../js/ui/status/power.js:107
#: ../js/ui/status/power.js:111
#, c-format
msgid "%d hour remaining"
msgid_plural "%d hours remaining"
@@ -1193,87 +1194,88 @@ msgstr[0] "%d કલાક બાકી રહેલ છે"
msgstr[1] "%d કલાક બાકી રહેલ છે"
#. TRANSLATORS: this is a time string, as in "%d hours %d minutes remaining"
#: ../js/ui/status/power.js:110
#: ../js/ui/status/power.js:114
#, c-format
msgid "%d %s %d %s remaining"
msgstr "%d %s %d %s બાકી રહેલ છે"
#: ../js/ui/status/power.js:112
#: ../js/ui/status/power.js:116
msgid "hour"
msgid_plural "hours"
msgstr[0] "કલાક"
msgstr[1] "કલાકો"
#: ../js/ui/status/power.js:112
#: ../js/ui/status/power.js:116
msgid "minute"
msgid_plural "minutes"
msgstr[0] "મિનિટ"
msgstr[1] "મિનિટો"
#: ../js/ui/status/power.js:115
#: ../js/ui/status/power.js:119
#, c-format
msgid "%d minute remaining"
msgid_plural "%d minutes remaining"
msgstr[0] "%d મિનિટ બાકી રહી છે"
msgstr[1] "%d મિનિટ બાકી રહી છે"
#: ../js/ui/status/power.js:118 ../js/ui/status/power.js:188
#: ../js/ui/status/power.js:122 ../js/ui/status/power.js:192
#, c-format
msgctxt "percent of battery remaining"
msgid "%d%%"
msgstr "%d%%"
#: ../js/ui/status/power.js:195
#: ../js/ui/status/power.js:199
msgid "AC adapter"
msgstr "AC ઍડપ્ટર"
#: ../js/ui/status/power.js:197
#: ../js/ui/status/power.js:201
msgid "Laptop battery"
msgstr "લેપટોપ બેટરી"
#: ../js/ui/status/power.js:199
#: ../js/ui/status/power.js:203
msgid "UPS"
msgstr "UPS"
#: ../js/ui/status/power.js:201
#: ../js/ui/status/power.js:205
msgid "Monitor"
msgstr "મોનિટર"
#: ../js/ui/status/power.js:203
#: ../js/ui/status/power.js:207
msgid "Mouse"
msgstr "માઉસ"
#: ../js/ui/status/power.js:207
#: ../js/ui/status/power.js:211
msgid "PDA"
msgstr "PDA"
#: ../js/ui/status/power.js:209
#: ../js/ui/status/power.js:213
msgid "Cell phone"
msgstr "સેલ ફોન"
#: ../js/ui/status/power.js:211
#: ../js/ui/status/power.js:215
msgid "Media player"
msgstr "મીડિયા પ્લેયર"
#: ../js/ui/status/power.js:213
#: ../js/ui/status/power.js:217
msgid "Tablet"
msgstr "ટૅબલેટ"
#: ../js/ui/status/power.js:215
#: ../js/ui/status/power.js:219
msgid "Computer"
msgstr "કમ્પ્યૂટર"
#: ../js/ui/status/power.js:217
#: ../js/ui/status/power.js:221
#| msgid "Unknown"
msgctxt "device"
msgid "Unknown"
msgstr "અજ્ઞાત"
#. Translators: This is the label for audio volume
#: ../js/ui/status/volume.js:20 ../js/ui/status/volume.js:34
#: ../js/ui/status/volume.js:25 ../js/ui/status/volume.js:39
msgid "Volume"
msgstr "વોલ્યુમ"
#: ../js/ui/status/volume.js:46
#: ../js/ui/status/volume.js:51
msgid "Microphone"
msgstr "માઇક્રોફોન"
@@ -1538,6 +1540,7 @@ msgid "Switch User"
msgstr "વપરાશકર્તાને બદલો"
#: ../js/ui/userMenu.js:568
#| msgid "Switch User"
msgid "Switch Session"
msgstr "સત્ર બદલો"
@@ -1550,6 +1553,8 @@ msgid "System Settings"
msgstr "સિસ્ટમ સુયોજનો"
#: ../js/ui/userMenu.js:711
#| msgctxt "title"
#| msgid "Log Out"
msgid "Log Out"
msgstr "બહાર નીકળો"
@@ -1605,6 +1610,7 @@ msgid "'%s' is ready"
msgstr "'%s' તૈયાર છે"
#: ../src/calendar-server/evolution-calendar.desktop.in.in.h:1
#| msgid "Open Calendar"
msgid "Evolution Calendar"
msgstr "Evolution કૅલેન્ડર"

622
po/he.po

File diff suppressed because it is too large Load Diff

906
po/it.po

File diff suppressed because it is too large Load Diff

942
po/ja.po

File diff suppressed because it is too large Load Diff

1115
po/lt.po

File diff suppressed because it is too large Load Diff

920
po/mr.po

File diff suppressed because it is too large Load Diff

648
po/nb.po

File diff suppressed because it is too large Load Diff

779
po/pa.po

File diff suppressed because it is too large Load Diff

901
po/pl.po

File diff suppressed because it is too large Load Diff

612
po/ru.po

File diff suppressed because it is too large Load Diff

258
po/sl.po
View File

@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-08-06 22:25+0000\n"
"PO-Revision-Date: 2012-08-07 08:42+0100\n"
"POT-Creation-Date: 2012-07-29 08:27+0000\n"
"PO-Revision-Date: 2012-07-29 14:11+0100\n"
"Last-Translator: Matej Urbančič <mateju@svn.gnome.org>\n"
"Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups.com>\n"
"Language: Slovenian\n"
@@ -153,25 +153,25 @@ msgid "There was an error loading the preferences dialog for %s:"
msgstr "Prišlo je do napake med nalaganjem pogovornega okna z možnosti za %s:"
#: ../js/extensionPrefs/main.js:164
msgid "Extension"
msgstr "Pripona"
msgid "<b>Extension</b>"
msgstr "<b>Pripona</b>"
#: ../js/extensionPrefs/main.js:188
msgid "Select an extension to configure using the combobox above."
msgstr "Razširitev za nastavljanje je mogoče izbrati iz spustnega seznama zgoraj."
#: ../js/gdm/loginDialog.js:572
#: ../js/gdm/loginDialog.js:550
msgid "Session..."
msgstr "Seja ..."
#: ../js/gdm/loginDialog.js:721
#: ../js/gdm/loginDialog.js:699
msgctxt "title"
msgid "Sign In"
msgstr "Prijava"
#. Translators: this message is shown below the password entry field
#. to indicate the user can swipe their finger instead
#: ../js/gdm/loginDialog.js:766
#: ../js/gdm/loginDialog.js:744
#: ../js/ui/unlockDialog.js:124
msgid "(or swipe finger)"
msgstr "(ali pa povlecite prst)"
@@ -179,26 +179,26 @@ msgstr "(ali pa povlecite prst)"
#. translators: this message is shown below the user list on the
#. login screen. It can be activated to reveal an entry for
#. manually entering the username.
#: ../js/gdm/loginDialog.js:787
#: ../js/gdm/loginDialog.js:765
msgid "Not listed?"
msgstr "Ali je ni na seznamu?"
#: ../js/gdm/loginDialog.js:930
#: ../js/gdm/loginDialog.js:908
#: ../js/ui/endSessionDialog.js:406
#: ../js/ui/extensionDownloader.js:195
#: ../js/ui/networkAgent.js:153
#: ../js/ui/polkitAuthenticationAgent.js:176
#: ../js/ui/shellMountOperation.js:396
#: ../js/ui/status/bluetooth.js:432
#: ../js/ui/status/bluetooth.js:436
msgid "Cancel"
msgstr "Prekliči"
#: ../js/gdm/loginDialog.js:935
#: ../js/gdm/loginDialog.js:913
msgctxt "button"
msgid "Sign In"
msgstr "Prijava"
#: ../js/gdm/loginDialog.js:1280
#: ../js/gdm/loginDialog.js:1256
msgid "Login Window"
msgstr "Prijavno okno"
@@ -274,12 +274,12 @@ msgstr "Program \"%s\" je odstranjen iz priljubljenih."
msgid "Removable Devices"
msgstr "Odstranljive naprave"
#: ../js/ui/autorunManager.js:548
#: ../js/ui/autorunManager.js:549
#, c-format
msgid "Open with %s"
msgstr "Odpri s programom %s"
#: ../js/ui/autorunManager.js:574
#: ../js/ui/autorunManager.js:575
msgid "Eject"
msgstr "Izvrzi"
@@ -560,8 +560,8 @@ msgid "tray"
msgstr "sistemska vrstica"
#: ../js/ui/keyboard.js:545
#: ../js/ui/status/keyboard.js:146
#: ../js/ui/status/power.js:205
#: ../js/ui/status/keyboard.js:149
#: ../js/ui/status/power.js:209
msgid "Keyboard"
msgstr "Tipkovnica"
@@ -625,7 +625,7 @@ msgid "Web Page"
msgstr "Spletna stran"
#. Translators: this is a filename used for screencast recording
#: ../js/ui/main.js:138
#: ../js/ui/main.js:140
#, no-c-format
msgid "Screencast from %d %t"
msgstr "Screencast z %d %t"
@@ -726,7 +726,7 @@ msgstr "Geslo mobilnega širokopasovnega dostopa"
msgid "A password is required to connect to '%s'."
msgstr "Za povezavo z omrežjem '%s' je zahtevano geslo."
#: ../js/ui/notificationDaemon.js:506
#: ../js/ui/notificationDaemon.js:484
#: ../src/shell-app.c:374
msgctxt "program"
msgid "Unknown"
@@ -764,7 +764,7 @@ msgstr "Končaj"
msgid "Activities"
msgstr "Dejavnosti"
#: ../js/ui/panel.js:971
#: ../js/ui/panel.js:975
msgid "Top Bar"
msgstr "Vrhnja vrstica"
@@ -856,337 +856,337 @@ msgstr "Zapomni si šifrirno geslo"
msgid "Unlock"
msgstr "Odkleni"
#: ../js/ui/status/accessibility.js:39
#: ../js/ui/status/accessibility.js:47
msgid "Accessibility"
msgstr "Dostopnost"
#: ../js/ui/status/accessibility.js:44
#: ../js/ui/status/accessibility.js:52
msgid "Zoom"
msgstr "Približanje"
#: ../js/ui/status/accessibility.js:51
#: ../js/ui/status/accessibility.js:59
msgid "Screen Reader"
msgstr "Zaslonski bralnik"
#: ../js/ui/status/accessibility.js:55
#: ../js/ui/status/accessibility.js:63
msgid "Screen Keyboard"
msgstr "Zaslonska tipkovnica"
#: ../js/ui/status/accessibility.js:59
#: ../js/ui/status/accessibility.js:67
msgid "Visual Alerts"
msgstr "Vidna opozorila"
#: ../js/ui/status/accessibility.js:62
#: ../js/ui/status/accessibility.js:70
msgid "Sticky Keys"
msgstr "Lepljive tipke"
#: ../js/ui/status/accessibility.js:65
#: ../js/ui/status/accessibility.js:73
msgid "Slow Keys"
msgstr "Počasne tipke"
#: ../js/ui/status/accessibility.js:68
#: ../js/ui/status/accessibility.js:76
msgid "Bounce Keys"
msgstr "Odskočne tipke"
#: ../js/ui/status/accessibility.js:71
#: ../js/ui/status/accessibility.js:79
msgid "Mouse Keys"
msgstr "Miškine tipke"
#: ../js/ui/status/accessibility.js:75
#: ../js/ui/status/accessibility.js:83
msgid "Universal Access Settings"
msgstr "Splošne nastavitve dostopa"
#: ../js/ui/status/accessibility.js:113
#: ../js/ui/status/accessibility.js:121
msgid "High Contrast"
msgstr "Visok kontrast"
#: ../js/ui/status/accessibility.js:150
#: ../js/ui/status/accessibility.js:158
msgid "Large Text"
msgstr "Veliko besedilo"
#: ../js/ui/status/bluetooth.js:27
#: ../js/ui/status/bluetooth.js:31
#: ../js/ui/status/bluetooth.js:256
#: ../js/ui/status/bluetooth.js:309
#: ../js/ui/status/bluetooth.js:340
#: ../js/ui/status/bluetooth.js:376
#: ../js/ui/status/bluetooth.js:405
#: ../js/ui/status/network.js:841
#: ../js/ui/status/bluetooth.js:35
#: ../js/ui/status/bluetooth.js:260
#: ../js/ui/status/bluetooth.js:313
#: ../js/ui/status/bluetooth.js:344
#: ../js/ui/status/bluetooth.js:380
#: ../js/ui/status/bluetooth.js:409
#: ../js/ui/status/network.js:844
msgid "Bluetooth"
msgstr "Bluetooth"
#: ../js/ui/status/bluetooth.js:44
#: ../js/ui/status/bluetooth.js:48
msgid "Visibility"
msgstr "Vidnost"
#: ../js/ui/status/bluetooth.js:58
#: ../js/ui/status/bluetooth.js:62
msgid "Send Files to Device..."
msgstr "Pošilji datoteke na napravo ..."
#: ../js/ui/status/bluetooth.js:59
#: ../js/ui/status/bluetooth.js:63
msgid "Set up a New Device..."
msgstr "Nastavitev nove naprave ..."
#: ../js/ui/status/bluetooth.js:83
#: ../js/ui/status/bluetooth.js:87
msgid "Bluetooth Settings"
msgstr "Nastavitve za Bluetooth"
#. TRANSLATORS: this means that bluetooth was disabled by hardware rfkill
#: ../js/ui/status/bluetooth.js:108
#: ../js/ui/status/network.js:208
#: ../js/ui/status/bluetooth.js:112
#: ../js/ui/status/network.js:211
msgid "hardware disabled"
msgstr "strojno onemogočen"
#: ../js/ui/status/bluetooth.js:201
#: ../js/ui/status/bluetooth.js:205
msgid "Connection"
msgstr "Povezava"
#: ../js/ui/status/bluetooth.js:212
#: ../js/ui/status/network.js:442
#: ../js/ui/status/bluetooth.js:216
#: ../js/ui/status/network.js:445
msgid "disconnecting..."
msgstr "prekinjanje povezave ..."
#: ../js/ui/status/bluetooth.js:225
#: ../js/ui/status/network.js:448
#: ../js/ui/status/network.js:908
#: ../js/ui/status/bluetooth.js:229
#: ../js/ui/status/network.js:451
#: ../js/ui/status/network.js:911
msgid "connecting..."
msgstr "povezovanje ..."
#: ../js/ui/status/bluetooth.js:243
#: ../js/ui/status/bluetooth.js:247
msgid "Send Files..."
msgstr "Pošlji datoteke ..."
#: ../js/ui/status/bluetooth.js:248
#: ../js/ui/status/bluetooth.js:252
msgid "Browse Files..."
msgstr "Brskanje datotek ..."
#: ../js/ui/status/bluetooth.js:257
#: ../js/ui/status/bluetooth.js:261
msgid "Error browsing device"
msgstr "Napaka med brskanjem po napravi"
#: ../js/ui/status/bluetooth.js:258
#: ../js/ui/status/bluetooth.js:262
#, c-format
msgid "The requested device cannot be browsed, error is '%s'"
msgstr "Po zahtevani naprave ni mogoče brskati, napaka je '%s'"
#: ../js/ui/status/bluetooth.js:266
#: ../js/ui/status/bluetooth.js:270
msgid "Keyboard Settings"
msgstr "Nastavitve tipkovnice"
#: ../js/ui/status/bluetooth.js:269
#: ../js/ui/status/bluetooth.js:273
msgid "Mouse Settings"
msgstr "Nastavitve miške"
#: ../js/ui/status/bluetooth.js:274
#: ../js/ui/status/volume.js:54
#: ../js/ui/status/bluetooth.js:278
#: ../js/ui/status/volume.js:59
msgid "Sound Settings"
msgstr "Nastavitve zvoka"
#: ../js/ui/status/bluetooth.js:341
#: ../js/ui/status/bluetooth.js:345
#, c-format
msgid "Authorization request from %s"
msgstr "Zahteva za pooblastitev od %s"
#: ../js/ui/status/bluetooth.js:347
#: ../js/ui/status/bluetooth.js:351
#, c-format
msgid "Device %s wants access to the service '%s'"
msgstr "Naprava %s želi dostop do storitve '%s'."
#: ../js/ui/status/bluetooth.js:349
#: ../js/ui/status/bluetooth.js:353
msgid "Always grant access"
msgstr "Vedno odobri dostop"
#: ../js/ui/status/bluetooth.js:350
#: ../js/ui/status/bluetooth.js:354
msgid "Grant this time only"
msgstr "Odobri le tokrat"
#: ../js/ui/status/bluetooth.js:351
#: ../js/ui/status/bluetooth.js:355
#: ../js/ui/telepathyClient.js:1097
msgid "Reject"
msgstr "Zavrni"
#: ../js/ui/status/bluetooth.js:377
#: ../js/ui/status/bluetooth.js:381
#, c-format
msgid "Pairing confirmation for %s"
msgstr "Potrditev razčlenjevanja za %s"
#: ../js/ui/status/bluetooth.js:383
#: ../js/ui/status/bluetooth.js:413
#: ../js/ui/status/bluetooth.js:387
#: ../js/ui/status/bluetooth.js:417
#, c-format
msgid "Device %s wants to pair with this computer"
msgstr "Naprava %s se poskuša seznaniti s tem računalnikom"
#: ../js/ui/status/bluetooth.js:384
#: ../js/ui/status/bluetooth.js:388
#, c-format
msgid "Please confirm whether the PIN '%06d' matches the one on the device."
msgstr "Potrdite, ali se PIN '%06d' ujema s tistim na napravi."
#: ../js/ui/status/bluetooth.js:386
#: ../js/ui/status/bluetooth.js:390
msgid "Matches"
msgstr "Ujemanja"
#: ../js/ui/status/bluetooth.js:387
#: ../js/ui/status/bluetooth.js:391
msgid "Does not match"
msgstr "Se ne ujema"
#: ../js/ui/status/bluetooth.js:406
#: ../js/ui/status/bluetooth.js:410
#, c-format
msgid "Pairing request for %s"
msgstr "Zahteva razčlenjevanja za %s"
#: ../js/ui/status/bluetooth.js:414
#: ../js/ui/status/bluetooth.js:418
msgid "Please enter the PIN mentioned on the device."
msgstr "Vnesite PIN, ki je naveden na napravi."
#: ../js/ui/status/bluetooth.js:431
#: ../js/ui/status/bluetooth.js:435
msgid "OK"
msgstr "V redu"
#: ../js/ui/status/keyboard.js:175
#: ../js/ui/status/keyboard.js:178
msgid "Show Keyboard Layout"
msgstr "Pokaži razporeditev tipkovnice"
#: ../js/ui/status/keyboard.js:177
#: ../js/ui/status/keyboard.js:180
msgid "Region and Language Settings"
msgstr "Nastavitve območja in jezika"
#: ../js/ui/status/network.js:93
#: ../js/ui/status/network.js:96
msgid "<unknown>"
msgstr "<neznano>"
#. Translators: this indicates that wireless or wwan is disabled by hardware killswitch
#: ../js/ui/status/network.js:230
#: ../js/ui/status/network.js:233
msgid "disabled"
msgstr "onemogočeno"
#. Translators: this is for network devices that are physically present but are not
#. under NetworkManager's control (and thus cannot be used in the menu)
#: ../js/ui/status/network.js:440
#: ../js/ui/status/network.js:443
msgid "unmanaged"
msgstr "neupravljano"
#. Translators: this is for network connections that require some kind of key or password
#: ../js/ui/status/network.js:451
#: ../js/ui/status/network.js:911
#: ../js/ui/status/network.js:454
#: ../js/ui/status/network.js:914
msgid "authentication required"
msgstr "zahtevana je overitev"
#. Translators: this is for devices that require some kind of firmware or kernel
#. module, which is missing
#: ../js/ui/status/network.js:461
#: ../js/ui/status/network.js:464
msgid "firmware missing"
msgstr "manjka strojna programska oprema"
#. Translators: this is for wired network devices that are physically disconnected
#: ../js/ui/status/network.js:468
#: ../js/ui/status/network.js:471
msgid "cable unplugged"
msgstr "kabel ni priklopljen"
#. Translators: this is for a network device that cannot be activated (for example it
#. is disabled by rfkill, or it has no coverage
#: ../js/ui/status/network.js:473
#: ../js/ui/status/network.js:476
msgid "unavailable"
msgstr "ni na voljo"
#: ../js/ui/status/network.js:475
#: ../js/ui/status/network.js:913
#: ../js/ui/status/network.js:478
#: ../js/ui/status/network.js:916
msgid "connection failed"
msgstr "povezovanje je spodletelo"
#: ../js/ui/status/network.js:536
#: ../js/ui/status/network.js:1534
#: ../js/ui/status/network.js:539
#: ../js/ui/status/network.js:1537
msgid "More..."
msgstr "Več ..."
#. TRANSLATORS: this is the indication that a connection for another logged in user is active,
#. and we cannot access its settings (including the name)
#: ../js/ui/status/network.js:572
#: ../js/ui/status/network.js:1464
#: ../js/ui/status/network.js:575
#: ../js/ui/status/network.js:1467
msgid "Connected (private)"
msgstr "Povezano (zasebna povezava)"
#: ../js/ui/status/network.js:647
#: ../js/ui/status/network.js:650
msgid "Auto Ethernet"
msgstr "Samodejni eternet"
#: ../js/ui/status/network.js:705
#: ../js/ui/status/network.js:708
msgid "Auto broadband"
msgstr "Samodejni širokopasovni dostop"
#: ../js/ui/status/network.js:708
#: ../js/ui/status/network.js:711
msgid "Auto dial-up"
msgstr "Samodejni klicni dostop"
#. TRANSLATORS: this the automatic wireless connection name (including the network name)
#: ../js/ui/status/network.js:827
#: ../js/ui/status/network.js:1481
#: ../js/ui/status/network.js:830
#: ../js/ui/status/network.js:1484
#, c-format
msgid "Auto %s"
msgstr "Samodejna povezava z %s"
#: ../js/ui/status/network.js:829
#: ../js/ui/status/network.js:832
msgid "Auto bluetooth"
msgstr "Samodejna povezava z Bluetooth"
#: ../js/ui/status/network.js:1483
#: ../js/ui/status/network.js:1486
msgid "Auto wireless"
msgstr "Samodejni brezžični dostop"
#: ../js/ui/status/network.js:1592
#: ../js/ui/status/network.js:1595
msgid "Enable networking"
msgstr "Omogoči omrežje"
#: ../js/ui/status/network.js:1614
#: ../js/ui/status/network.js:1617
msgid "Wired"
msgstr "Žično"
#: ../js/ui/status/network.js:1625
#: ../js/ui/status/network.js:1628
msgid "Wireless"
msgstr "Brezžično"
#: ../js/ui/status/network.js:1635
#: ../js/ui/status/network.js:1638
msgid "Mobile broadband"
msgstr "Mobilni širokopasovni dostop"
#: ../js/ui/status/network.js:1645
#: ../js/ui/status/network.js:1648
msgid "VPN Connections"
msgstr "Povezave VPN"
#: ../js/ui/status/network.js:1652
#: ../js/ui/status/network.js:1655
msgid "Network Settings"
msgstr "Omrežne nastavitve"
#: ../js/ui/status/network.js:1709
#: ../js/ui/status/network.js:1712
msgid "Network Manager"
msgstr "Upravljalnik omrežij"
#: ../js/ui/status/network.js:1802
#: ../js/ui/status/network.js:1805
msgid "Connection failed"
msgstr "Povezava je spodletela"
#: ../js/ui/status/network.js:1803
#: ../js/ui/status/network.js:1806
msgid "Activation of network connection failed"
msgstr "Omogočanje omrežne povezave je spodletelo."
#: ../js/ui/status/network.js:2066
#: ../js/ui/status/network.js:2069
msgid "Networking is disabled"
msgstr "Omrežje je onemogočeno"
#: ../js/ui/status/power.js:55
#: ../js/ui/status/power.js:59
msgid "Battery"
msgstr "Baterija"
#: ../js/ui/status/power.js:72
#: ../js/ui/status/power.js:76
msgid "Power Settings"
msgstr "Upravljanje napajanja"
#. 0 is reported when UPower does not have enough data
#. to estimate battery life
#: ../js/ui/status/power.js:100
#: ../js/ui/status/power.js:104
msgid "Estimating..."
msgstr "Ocenjevanje ...."
#: ../js/ui/status/power.js:107
#: ../js/ui/status/power.js:111
#, c-format
msgid "%d hour remaining"
msgid_plural "%d hours remaining"
@@ -1196,12 +1196,12 @@ msgstr[2] "preostajata še %d uri"
msgstr[3] "preostajajo še %d ure"
#. TRANSLATORS: this is a time string, as in "%d hours %d minutes remaining"
#: ../js/ui/status/power.js:110
#: ../js/ui/status/power.js:114
#, c-format
msgid "%d %s %d %s remaining"
msgstr "Preostaja še %d %s %d %s"
#: ../js/ui/status/power.js:112
#: ../js/ui/status/power.js:116
msgid "hour"
msgid_plural "hours"
msgstr[0] "ur"
@@ -1209,7 +1209,7 @@ msgstr[1] "ura"
msgstr[2] "uri"
msgstr[3] "ure"
#: ../js/ui/status/power.js:112
#: ../js/ui/status/power.js:116
msgid "minute"
msgid_plural "minutes"
msgstr[0] "minut"
@@ -1217,7 +1217,7 @@ msgstr[1] "minuta"
msgstr[2] "minuti"
msgstr[3] "minute"
#: ../js/ui/status/power.js:115
#: ../js/ui/status/power.js:119
#, c-format
msgid "%d minute remaining"
msgid_plural "%d minutes remaining"
@@ -1226,65 +1226,65 @@ msgstr[1] "preostaja še %d minuta"
msgstr[2] "preostajata še %d minuti"
msgstr[3] "preostajajo še %d minute"
#: ../js/ui/status/power.js:118
#: ../js/ui/status/power.js:188
#: ../js/ui/status/power.js:122
#: ../js/ui/status/power.js:192
#, c-format
msgctxt "percent of battery remaining"
msgid "%d%%"
msgstr "%d%%"
#: ../js/ui/status/power.js:195
#: ../js/ui/status/power.js:199
msgid "AC adapter"
msgstr "Električni prilagodilnik"
#: ../js/ui/status/power.js:197
#: ../js/ui/status/power.js:201
msgid "Laptop battery"
msgstr "Baterija prenosnika"
#: ../js/ui/status/power.js:199
#: ../js/ui/status/power.js:203
msgid "UPS"
msgstr "UPS"
#: ../js/ui/status/power.js:201
#: ../js/ui/status/power.js:205
msgid "Monitor"
msgstr "Zaslon"
#: ../js/ui/status/power.js:203
#: ../js/ui/status/power.js:207
msgid "Mouse"
msgstr "Miška"
#: ../js/ui/status/power.js:207
#: ../js/ui/status/power.js:211
msgid "PDA"
msgstr "Dlančnik"
#: ../js/ui/status/power.js:209
#: ../js/ui/status/power.js:213
msgid "Cell phone"
msgstr "Mobilni telefon"
#: ../js/ui/status/power.js:211
#: ../js/ui/status/power.js:215
msgid "Media player"
msgstr "Predstavni predvajalnik"
#: ../js/ui/status/power.js:213
#: ../js/ui/status/power.js:217
msgid "Tablet"
msgstr "Tablični računalnik"
#: ../js/ui/status/power.js:215
#: ../js/ui/status/power.js:219
msgid "Computer"
msgstr "Računalnik"
#: ../js/ui/status/power.js:217
#: ../js/ui/status/power.js:221
msgctxt "device"
msgid "Unknown"
msgstr "Neznano"
#. Translators: This is the label for audio volume
#: ../js/ui/status/volume.js:20
#: ../js/ui/status/volume.js:34
#: ../js/ui/status/volume.js:25
#: ../js/ui/status/volume.js:39
msgid "Volume"
msgstr "Glasnost"
#: ../js/ui/status/volume.js:46
#: ../js/ui/status/volume.js:51
msgid "Microphone"
msgstr "Mikrofon"

1025
po/sr.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1006
po/ta.po

File diff suppressed because it is too large Load Diff

708
po/vi.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -59,7 +59,8 @@ function init() {
x_fill: true,
y_fill: false,
track_hover: true });
let icon = new St.Icon({ icon_name: 'system-run-symbolic',
let icon = new St.Icon({ icon_name: 'system-run',
icon_type: St.IconType.SYMBOLIC,
style_class: 'system-status-icon' });
button.set_child(icon);

View File

@@ -74,6 +74,7 @@ struct _ShellApp
char *casefolded_name;
char *name_collation_key;
char *casefolded_description;
char *casefolded_exec;
char **casefolded_keywords;
};
@@ -1281,8 +1282,6 @@ unref_running_state (ShellAppRunningState *state)
g_clear_object (&state->remote_menu);
g_clear_object (&state->muxer);
g_clear_pointer (&state->unique_bus_name, g_free);
g_clear_pointer (&state->remote_menu, g_free);
g_slice_free (ShellAppRunningState, state);
}
@@ -1311,6 +1310,7 @@ shell_app_init_search_data (ShellApp *app)
{
const char *name;
const char *exec;
const char *comment;
const char * const *keywords;
char *normalized_exec;
GDesktopAppInfo *appinfo;
@@ -1319,6 +1319,9 @@ shell_app_init_search_data (ShellApp *app)
name = g_app_info_get_name (G_APP_INFO (appinfo));
app->casefolded_name = shell_util_normalize_and_casefold (name);
comment = g_app_info_get_description (G_APP_INFO (appinfo));
app->casefolded_description = shell_util_normalize_and_casefold (comment);
exec = g_app_info_get_executable (G_APP_INFO (appinfo));
normalized_exec = shell_util_normalize_and_casefold (exec);
app->casefolded_exec = trim_exec_line (normalized_exec);
@@ -1400,6 +1403,16 @@ _shell_app_match_search_terms (ShellApp *app,
}
}
if (app->casefolded_description && current_match < MATCH_PREFIX)
{
/* Only do substring matches, as prefix matches are not meaningful
* enough for descriptions
*/
p = strstr (app->casefolded_description, term);
if (p != NULL)
current_match = MATCH_SUBSTRING;
}
if (app->casefolded_keywords)
{
int i = 0;
@@ -1498,6 +1511,7 @@ shell_app_finalize (GObject *object)
g_free (app->casefolded_name);
g_free (app->name_collation_key);
g_free (app->casefolded_description);
g_free (app->casefolded_exec);
g_strfreev (app->casefolded_keywords);

View File

@@ -1686,6 +1686,60 @@ gboolean _shell_global_check_xdnd_event (ShellGlobal *global,
return FALSE;
}
/**
* shell_global_launch_calendar_server:
* @global: The #ShellGlobal.
*
* Launch the gnome-shell-calendar-server helper.
*/
void
shell_global_launch_calendar_server (ShellGlobal *global)
{
const gchar *bin_dir;
gchar *calendar_server_exe;
GError *error;
gchar *argv[2];
gint child_standard_input;
/* launch calendar-server */
bin_dir = g_getenv ("GNOME_SHELL_BINDIR");
if (bin_dir != NULL)
calendar_server_exe = g_strdup_printf ("%s/gnome-shell-calendar-server", bin_dir);
else
calendar_server_exe = g_strdup_printf (GNOME_SHELL_LIBEXECDIR "/gnome-shell-calendar-server");
argv[0] = calendar_server_exe;
argv[1] = NULL;
error = NULL;
if (!g_spawn_async_with_pipes (NULL, /* working_directory */
argv,
NULL, /* envp */
0, /* GSpawnFlags */
NULL, /* child_setup */
NULL, /* user_data */
NULL, /* GPid *child_pid */
&child_standard_input,
NULL, /* gint *stdout */
NULL, /* gint *stderr */
&error))
{
g_warning ("Error launching `%s': %s (%s %d)",
calendar_server_exe,
error->message,
g_quark_to_string (error->domain),
error->code);
g_error_free (error);
}
/* Note that gnome-shell-calendar-server exits whenever its stdin
* file descriptor is HUP'ed. This means that whenever the the shell
* process exits or is being replaced, the calendar server is also
* exits...and if the shell is being replaced, a new copy of the
* calendar server is launched...
*/
g_free (calendar_server_exe);
}
const char *
shell_global_get_session_mode (ShellGlobal *global)
{

View File

@@ -134,6 +134,8 @@ void shell_global_init_xdnd (ShellGlobal *global);
void shell_global_reexec_self (ShellGlobal *global);
void shell_global_launch_calendar_server (ShellGlobal *global);
const char * shell_global_get_session_mode (ShellGlobal *global);
G_END_DECLS

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