Compare commits
	
		
			7 Commits
		
	
	
		
			wip/wobbly
			...
			wip/overvi
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 1afb04d1e4 | ||
|   | 51e63233ce | ||
|   | a7d7f94892 | ||
|   | 427f516d45 | ||
|   | cbb88ffdbb | ||
|   | 71670bad3b | ||
|   | a2e4153fa0 | 
							
								
								
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -24,13 +24,10 @@ data/gnome-shell-wayland.desktop.in | ||||
| data/gnome-shell-extension-prefs.desktop | ||||
| data/gnome-shell-extension-prefs.desktop.in | ||||
| data/gschemas.compiled | ||||
| data/perf-background.xml | ||||
| data/org.gnome.shell.gschema.xml | ||||
| data/org.gnome.shell.gschema.valid | ||||
| data/org.gnome.shell.evolution.calendar.gschema.xml | ||||
| data/org.gnome.shell.evolution.calendar.gschema.valid | ||||
| data/org.gnome.Shell.PortalHelper.desktop | ||||
| data/org.gnome.Shell.PortalHelper.service | ||||
| docs/reference/*/*.args | ||||
| docs/reference/*/*.bak | ||||
| docs/reference/*/*.hierarchy | ||||
| @@ -81,9 +78,11 @@ src/gnome-shell-calendar-server | ||||
| src/gnome-shell-extension-prefs | ||||
| src/gnome-shell-extension-tool | ||||
| src/gnome-shell-hotplug-sniffer | ||||
| src/gnome-shell-jhbuild | ||||
| src/gnome-shell-perf-helper | ||||
| src/gnome-shell-perf-tool | ||||
| src/gnome-shell-portal-helper | ||||
| src/gnome-shell-real | ||||
| src/gnome-shell-wayland | ||||
| src/hotplug-sniffer/org.gnome.Shell.HotplugSniffer.service | ||||
| src/run-js-test | ||||
| src/test-recorder | ||||
|   | ||||
							
								
								
									
										299
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										299
									
								
								NEWS
									
									
									
									
									
								
							| @@ -1,302 +1,3 @@ | ||||
| 3.13.91 | ||||
| ======= | ||||
| * Fix keynav into session menu on login screen [Florian; #735614] | ||||
| * Add gesture to summon message tray [Carlos G.; #735625] | ||||
| * Accept scrolls/swipes either way on the screen shield [Jasper; #734874] | ||||
| * Animate opening the app picker and improve app folder animations | ||||
|   [Carlos S.; #734726] | ||||
| * Animate app icons on launching a new window [Carlos S., Florian; #734726] | ||||
| * Show the on-screen keyboard when touch input is being used [David; #702015] | ||||
| * Misc. bug fixes [Bastien, Owen, Florian, Carlos G.; #735190, #735385, | ||||
|   #735608, #735681] | ||||
|  | ||||
| Contributors: | ||||
|   Carlos Garnacho, David King, Kalev Lember, Florian Müllner, Bastien Nocera, | ||||
|   Carlos Soriano, Jasper St. Pierre, Owen W. Taylor | ||||
|  | ||||
| Translations: | ||||
|   Fran Diéguez [gl], Sweta Kothari [gu], Manoj Kumar Giri [or], | ||||
|   Alain Lojewski [fr], Praveen Illa [te], Arash Mousavi [fa], | ||||
|   Andika Triwidada [id] | ||||
|  | ||||
| 3.13.90 | ||||
| ======= | ||||
| * Make use of GLSL optional [Adel; #733623] | ||||
| * Update on-screen-keyboard position on monitor changes [Cosimo; #733790] | ||||
| * Improve window manager animations [Giovanni; #732857] | ||||
| * Handle touch events [Carlos G.; #733633] | ||||
| * Try to not show "New Window" action for single-window apps | ||||
|   [Giovanni; #722554] | ||||
| * Fix overview exceeding screen size with many apps installed | ||||
|   [Carlos S.; #723496] | ||||
| * Add Software to default favorites [Mathieu; #734406] | ||||
| * Improve app picker <-> desktop transition [Carlos S.; #732901] | ||||
| * Remove <shift>-magic for switcher popups [Christophe; #732296] | ||||
| * Add a special background to use for performance testing [Owen; #734610] | ||||
| * Add support for default disabled search providers [Giovanni; #734110] | ||||
| * Fix portals that don't redirect properly [Giovanni; #733848] | ||||
| * Fix history trimming in chat notifications [Giovanni; #733899] | ||||
| * Try to use default calendar application [Florian; #722333] | ||||
| * Only show location menu when geolocation is in use [Zeeshan; #731122] | ||||
| * Misc. bug fixes and cleanups [Giovanni, Carlos G., Zeeshan, Carlos S., | ||||
|   Cosimo; #711682, #733840, #734483, #734680, #733813, #735062] | ||||
|  | ||||
| Contributors: | ||||
|   Zeeshan Ali (Khattak), Mathieu Bridon, Giovanni Campagna, Cosimo Cecchi, | ||||
|   Piotr Drąg, Christophe Fergeau, Adel Gadllah, Carlos Garnacho, | ||||
|   Florian Müllner, Carlos Soriano, Jasper St. Pierre, Olav Vitters, | ||||
|   Owen W. Taylor | ||||
|  | ||||
| Translations: | ||||
|   Aurimas Černius [lt], MarMav [el], Inaki Larranaga Murgoitio [eu], | ||||
|   Reinout van Schouwen [nl], ngoswami [as], Fabio Tomat [fur], | ||||
|   Chao-Hsiung Liao [zh_HK, zh_TW] | ||||
|  | ||||
| 3.13.4 | ||||
| ====== | ||||
| * Handle portal login requests [Giovanni; #704416] | ||||
| * Scale fonts on wayland on hiDPI devices [Adel; #732537] | ||||
| * Fix default ibus candidate index labels [Rui; #702944] | ||||
| * Add gestures for various system actions [Carlos G.] | ||||
| * Add performance test script for the perf.gnome.org [Owen; #732350] | ||||
| * Use new restart framework to improve restart visuals [Owen; #733026] | ||||
| * Improve keynav in app folder popups [Carlos S.; #731477] | ||||
| * Fix truncation of app search results [Carlos S.; #732416] | ||||
| * Automatically update renamed desktop files in favorites [Kalev; #729429] | ||||
| * Misc. bug fixes and cleanups [Giovanni, Yosef, Owen, Bastien, Javier; | ||||
|   #729823, #726401, #732301, #732348, #732349, #733498, #733540] | ||||
|  | ||||
| Contributors: | ||||
|   Giovanni Campagna, Adel Gadllah, Carlos Garnacho, Javier Hernández, | ||||
|   Kalev Lember, Rui Matos, Florian Müllner, Bastien Nocera, Yosef Or Boczko, | ||||
|   Carlos Soriano, Jasper St. Pierre, Owen W. Taylor | ||||
|  | ||||
| Translations: | ||||
|   Yuri Myasoedov [ru], Daniel Mustieles [es], Fran Diéguez [gl], | ||||
|   Cheng-Chia Tseng [zh_TW], A S Alam [pa], Benjamin Steinwender [de], | ||||
|   Enrico Nicoletto [pt_BR], MarMav [el], Yosef Or Boczko [he], | ||||
|   Kjartan Maraas [nb] | ||||
|  | ||||
| 3.13.3 | ||||
| ====== | ||||
| * Don't allow closing windows with attached modals [Florian; #729886] | ||||
| * Fix self-restarting on OpenBSD [Antoine; #727763] | ||||
| * Improve behavior of window buttons with compositor menus [Florian; #731058] | ||||
| * Work around atspi-related performance regression [Alejandro; #730118] | ||||
| * Misc bug fixes and cleanups [Florian, Lan, Jasper, Christophe, Debarshi, | ||||
|   Zeeshan; #728271, #726460, #703833, #731118, #731220, #695487, #730527, | ||||
|   #728170, #731619, #731738, #731882, #731923] | ||||
|  | ||||
| Contributors: | ||||
|   Zeeshan Ali (Khattak), Christophe Fergeau, Adel Gadllah, Antoine Jacoutot, | ||||
|   Ting-Wei Lan, Florian Müllner, Alejandro Piñeiro, Debarshi Ray, | ||||
|   Carlos Soriano, Jasper St. Pierre, Wim Taymans, Rico Tzschichholz | ||||
|  | ||||
| Translations: | ||||
|   Philip Withnall [en_GB], Milo Casagrande [it], Aurimas Černius [lt], | ||||
|   Enrico Nicoletto [pt_BR], Kjartan Maraas [nb], Balázs Meskó [hu], | ||||
|   Muhammet Kara [tr], Daniel Mustieles [es], Yosef Or Boczko [he], | ||||
|   Matej Urbančič [sl], Mattias Eriksson [sv] | ||||
|  | ||||
| 3.13.2 | ||||
| ====== | ||||
| * Make airplane mode menu insensitive in lock screen [Giovanni; #729224] | ||||
| * Don't always extend struts to the screen edge [Florian; #683819] | ||||
| * Fix keynav for alternatives in AltSwitcher [Florian; #727259] | ||||
| * Implement window menus in the shell [Jasper; #726352] | ||||
| * Support resource:/// URLs in GNOME_SHELL_JS envvar [Owen; #730409] | ||||
| * Fix switcher popups with keybindings containing Escape [Rui; #730739] | ||||
| * Update extension-prefs UI to follow GNOME 3 patterns [Florian; #730829] | ||||
| * Add support for fallback app menu in window decorations [Florian; #730752] | ||||
| * Fix keynav escaping open app folders [Florian; #726760] | ||||
| * Misc. bug fixes [Kalev, Florian, Owen; #729429, #728449, #730408, #730753, | ||||
|   #730653] | ||||
|  | ||||
| Contributors: | ||||
|   Giovanni Campagna, Piotr Drąg, Kalev Lember, Rui Matos, Florian Müllner, | ||||
|   Vadim Rutkovsky, Carlos Soriano, Jasper St. Pierre, Owen W. Taylor | ||||
|  | ||||
| Translations: | ||||
|   Ihar Hrachyshka [be], Giovanni Campagna [it], Carles Ferrando [ca@valencia], | ||||
|   Daniel Mustieles [es], Aurimas Černius [lt], Enrico Nicoletto [pt_BR], | ||||
|   Yosef Or Boczko [he], Marek Černocký [cs], Muhammet Kara [tr], | ||||
|   Georges Neto [pt_BR], Andika Triwidada [id] | ||||
|  | ||||
| 3.13.1 | ||||
| ====== | ||||
| * Ensure the currently focused app icon is viewable [Rui; #726759] | ||||
| * Improve language in location menu [Zeeshan; #726498] | ||||
| * Improve HiDpi support [Cosimo; #726907] | ||||
| * Set accessible role for window previews [Alejandro; #726670] | ||||
| * Fix bad antialiasing on panel menu buttons [Carlos; #727336] | ||||
| * Don't hide location menu [Zeeshan; #727398] | ||||
| * Fix IM candidate window obscuring current text [Rui; #727579] | ||||
| * Don't always extend struts to the screen edge [Florian; #663690] | ||||
| * Add shortcuts for switching to the last workspace [Elad; #659288] | ||||
| * Show OSD window on all monitors [Adel; #722684] | ||||
| * Improve consistency of labels in network menu [Paul; #727163] | ||||
| * Fix zombie search providers showing up [Jasper; #728597] | ||||
| * Remove ConsoleKit support [Florian; #686626] | ||||
| * Fix region screenshots with open shell menus [Florian; #709126] | ||||
| * Support <shift>insert in text entries [Florian; #648318] | ||||
| * Improve app picker scrolling on touch [Jasper; #729064] | ||||
| * Don't make date button clickable when on current date [Carlos; #726724] | ||||
| * Tweak heuristic for hiding workspace switcher [Florian; #662457] | ||||
| * Add option to show in Software to app context menu [Matthias; #643043] | ||||
| * Misc. bug fixes and cleanups [Bastien, Florian, Giovanni, Adel, Vadim, | ||||
|   Carlos; #727983, #727948, #728512, #728681, #728897, #727384, #728820, | ||||
|   #715042, #728449, #728343] | ||||
|  | ||||
| Contributors: | ||||
|   Elad Alfassa, Zeeshan Ali (Khattak), Giovanni Campagna, Cosimo Cecchi, | ||||
|   Matthias Clasen, Piotr Drąg, Adel Gadllah, Paul Lange, Rui Matos, | ||||
|   Simon McVittie, Florian Müllner, Bastien Nocera, Alejandro Piñeiro, | ||||
|   Vadim Rutkovsky, Carlos Soriano, Jasper St. Pierre | ||||
|  | ||||
| Translations: | ||||
|   Khaled Hosny [ar], Piotr Drąg [pl], Yosef Or Boczko [he], | ||||
|   Antonio Fernandes C. Neto [pt_BR], Marek Černocký [cs], maria thukididu [el], | ||||
|   Andika Triwidada [id], Daniel Mustieles [es], Changwoo Ryu [ko], | ||||
|   Benjamin Steinwender [de], Sphinx Jiang [zh_CN], | ||||
|   Inaki Larranaga Murgoitio [eu], Marcus Lundblad [sv], Aurimas Černius [lt], | ||||
|   Stas Solovey [ru], Alexandre Franke [fr], Matej Urbančič [sl], | ||||
|   Fran Diéguez [gl], Pau Iranzo [ca], Luca Ferretti [it], Milo Casagrande [it], | ||||
|   Tiago S [pt], Victor Ibragimov [tg], Dirgita [id], Khoem Sokhem [km], | ||||
|   Rūdolfs Mazurs [lv], Balázs Úr [hu], Ask H. Larsen [da], Ikuya Awashiro [ja], | ||||
|   Wouter Bolsterlee [nl], Daniel Korostil [uk], Daniel Șerbănescu [ro], | ||||
|   Enrico Nicoletto [pt_BR] | ||||
|  | ||||
| 3.12.0 | ||||
| ====== | ||||
| * gdm: Reset greeter when coming back to login screen [Jasper; #726989] | ||||
|  | ||||
| Contributors: | ||||
|   Jasper St. Pierre | ||||
|  | ||||
| Translations: | ||||
|   Daniel Martinez [an], Yuri Myasoedov [ru], Inaki Larranaga Murgoitio [eu], | ||||
|   Abderrahim Kitouni [ar], Praveen Illa [te], Matej Urbančič [sl], | ||||
|   Chao-Hsiung Liao [zh_HK, zh_TW], Frédéric Péters [fr], | ||||
|   Мирослав Николић [sr, sr@latin], Ask H. Larsen [da], Kenneth Nielsen [da], | ||||
|   Jiro Matsuzawa [ja], Dušan Kazik [sk] | ||||
|  | ||||
| 3.11.92 | ||||
| ======= | ||||
| * calendar: Grab key focus after changing day [Volker; #725606] | ||||
| * gdm: Don't load user list if disabled [Florian; #725905] | ||||
| * Don't show network-offline in the top bar [Jasper; #725340] | ||||
| * Improve radial shade effect of modal dialogs [Giovanni; #725830] | ||||
| * Fix broken suspend-on-idle functionality [Giovanni; #712706] | ||||
| * Close wifi selection dialog when device disappears [Giovanni; #723935] | ||||
| * Don't close chats when pressing Escape [Giovanni; #724178] | ||||
| * Improve smartcard support in login/lock screen [Ray; #726262, #726263] | ||||
| * Wake up screen when resuming from suspend [Giovanni; #726378] | ||||
| * Make bluetooth and location items insensitive when locked [Florian; #726319] | ||||
| * Don't show bluetooth icon when there is no adapter [Giovanni; #725057] | ||||
| * Make sure to keep the OSK on top of modal dialogs [Rui; #719451] | ||||
| * Misc. bug fixes and cleanups [Giovanni, Ray, Adel, Daniel, Jasper, Florian; | ||||
|   #725832, #725958, #722149, #724977, #724798, #725020, #723976, #726119, | ||||
|   #726238, #585500, #704844, #726323, #726322, #726120, #726414] | ||||
|  | ||||
| Contributors: | ||||
|   Giovanni Campagna, Daniel Drake, Adel Gadllah, Rui Matos, Florian Müllner, | ||||
|   Volker Sobek, Jasper St. Pierre, Ray Strode | ||||
|  | ||||
| Translations: | ||||
|   Fabio Tomat [fur], Rafael Ferreira [pt_BR], Fran Diéguez [gl], | ||||
|   Marek Černocký [cs], Baurzhan Muftakhidinov [kk], Andika Triwidada [id], | ||||
|   A S Alam [pa], Rūdolfs Mazurs [lv], Wylmer Wang [zh_CN], | ||||
|   Aurimas Černius [lt], Cheng-Chia Tseng [zh_TW], Stas Solovey [ru], | ||||
|   Tiagosdot [pt], Benjamin Steinwender [de], Frédéric Peters [fr], | ||||
|   Daniel Korostil [uk], Yaron Shahrabani [he], Ville-Pekka Vainio [fi], | ||||
|   maria thukididu [el], Victor Ibragimov [tg], Kjartan Maraas [nb], | ||||
|   Gábor Kelemen [hu], Ask H. Larsen [da] | ||||
|  | ||||
| 3.11.91 | ||||
| ======= | ||||
| * Don't use network profile name in menu [Giovanni; #725586] | ||||
| * calendar: Make date label clickable to return to current date [Vit; #641366] | ||||
| * Misc. bug fixes [Florian, Zeeshan, Adel, Jasper, Dan, Volker; #724813, | ||||
|   #724686, #725082, #724870, #724779, #725533] | ||||
|  | ||||
| Contributors: | ||||
|   Zeeshan Ali (Khattak), Giovanni Campagna, Piotr Drąg, Adel Gadllah, | ||||
|   Florian Müllner, Volker Sobek, Vit Stanislav, Jasper St. Pierre, Dan Williams | ||||
|  | ||||
| Translations: | ||||
|   Victor Ibragimov [tg], Aurimas Černius [lt], Dimitris Spingos [el], | ||||
|   Andika Triwidada [id], Rafael Ferreira [pt_BR], Daniel Mustieles [es], | ||||
|   Baurzhan Muftakhidinov [kk], Marek Černocký [cs], Ihar Hrachyshka [be], | ||||
|   eternalhui [zh_CN], Yosef Or Boczko [he], Fran Diéguez [gl], | ||||
|   Khaled Hosny [ar], Ville-Pekka Vainio [fi], Piotr Drąg [pl], | ||||
|   Kjartan Maraas [nb], Changwoo Ryu [ko] | ||||
|  | ||||
| 3.11.90 | ||||
| ======= | ||||
| * Stop showing two bluetooth entries [Giovanni; #709353] | ||||
| * Improve styling of login/lock screen [Reda; #723833] | ||||
| * Fix magnifier crosshairs [Magdalen; #723709] | ||||
| * Make NetworkManager support optional [Michael; #669495] | ||||
| * Make middle-click open a new instance [Florian; #695010] | ||||
| * Scale the UI on high resolution displays [Cosimo, Adel; #705410, #724607] | ||||
| * Remove notification counter on screen shield [Carlos; #709275] | ||||
| * Improve app picker transition [Carlos; #722331] | ||||
| * Add geolocation indicator to status menu [Zeeshan; #723684] | ||||
| * Improve timestamps in chat notifications [Carlos; #708031, #715158] | ||||
| * Improve network menus [Giovanni; #723570] | ||||
| * Add "VPN Setting" item to VPN submenu [Giovanni; #709167] | ||||
| * Improve appearance of disclosure arrows [Carlos; #720206] | ||||
| * Add GSetting key to disable version validation of extensions [Adel; #724683] | ||||
| * Delay auto-removing empty workspaces [Florian; #709064] | ||||
| * Offer offline updates in the shutdown dialog [Kalev; #722898] | ||||
| * Animate tile previews [Florian; #665758] | ||||
| * Misc. bug fixes and cleanups [Giovanni, Ryan, Debarshi, Florian; #709128, | ||||
|   #722342, #723661, #724184, #724256, #724293, #724305, #722554, #724282, | ||||
|   #724690, #722928] | ||||
|  | ||||
| Contributors: | ||||
|   Zeeshan Ali (Khattak), Magdalen Berns, Michael Biebl, Giovanni Campagna, | ||||
|   Cosimo Cecchi, Adel Gadllah, Reda Lazri, Kalev Lember, Ryan Lortie, | ||||
|   Florian Müllner, Debarshi Ray, Carlos Soriano, Jasper St. Pierre, | ||||
|   Colin Walters | ||||
|  | ||||
| Translations: | ||||
|   Victor Ibragimov [tg], Daniel Mustieles [es], Khaled Hosny [ar], | ||||
|   Enrico Nicoletto [pt_BR], Yosef Or Boczko [he], Fran Diéguez [gl], | ||||
|   Marek Černocký [cs], Baurzhan Muftakhidinov [kk], Jorge Pérez Pérez [an], | ||||
|   Kjartan Maraas [nb], David Lüder [de], Daniel Korostil [uk], ngoswami [as], | ||||
|   Rafael Ferreira [pt_BR] | ||||
|  | ||||
| 3.11.5 | ||||
| ====== | ||||
| * Fix extension preference tool [Florian; #722334] | ||||
| * Fix keyboard activation of legacy tray icons [Giovanni; #721267] | ||||
| * Add radial background shade for modal dialogs [Giovanni; #669798] | ||||
| * Show attached modal windows in the overview [Giovanni; #650843] | ||||
| * Add support for desktop actions [Giovanni; #669603] | ||||
| * Indicate in system status when location service is used [Zeeshan; #709372] | ||||
| * Add support for extended app folder schema [Jasper; #723179] | ||||
| * Show status icon for wired network connections [Jasper; #708966] | ||||
| * Indicate airplane mode in network selection dialog [Giovanni; #709128] | ||||
| * Misc bug fixes and cleanups [Florian, Sebastian, Giovanni, Tim, Matt, Jasper; | ||||
|   #722417, #722494, #722547, #722593, #722434, #722787, #722690, #722840, | ||||
|   #722660, #722812, #723197, #722927, #723306, #723308, #723523, #709685, | ||||
|   #723570] | ||||
|  | ||||
| Contributors: | ||||
|   Zeeshan Ali (Khattak), Magdalen Berns, Giovanni Campagna, William Jon McCann, | ||||
|   Sebastian Keller, Tim Lunn, Florian Müllner, Carlos Soriano, | ||||
|   Jasper St. Pierre, Rico Tzschichholz, Matt Watson | ||||
|  | ||||
| Translations: | ||||
|   Marek Černocký [cs], Mattias Põldaru [et], Tong Hui [zh_CN], | ||||
|   Victor Ibragimov [tg], Enrico Nicoletto [pt_BR], Daniel Mustieles [es], | ||||
|   Fran Diéguez [gl], Kjartan Maraas [nb], Nilamdyuti Goswami [as], | ||||
|   Aurimas Černius [lt], Stas Solovey [ru], Yosef Or Boczko [he], | ||||
|   Jorge Pérez Pérez [an], Dimitris Spingos [el], Baurzhan Muftakhidinov [kk], | ||||
|   Chao-Hsiung Liao [zh_HK, zh_TW], Shankar Prasad [kn], Yaron Shahrabani [he], | ||||
|   Andika Triwidada [id] | ||||
|  | ||||
| 3.11.4 | ||||
| ====== | ||||
| * Fix removal of workspacaes that are not at the end [Giovanni; #721417] | ||||
|   | ||||
							
								
								
									
										2
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								README
									
									
									
									
									
								
							| @@ -8,7 +8,7 @@ For more information about GNOME Shell, including instructions on how | ||||
| to build GNOME Shell from source and how to get involved with the project, | ||||
| see: | ||||
|  | ||||
|  https://wiki.gnome.org/Projects/GnomeShell | ||||
|  http://live.gnome.org/GnomeShell | ||||
|  | ||||
| Bugs should be reported at http://bugzilla.gnome.org against the 'gnome-shell' | ||||
| product. | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| #!/bin/sh | ||||
| #!/bin/bash | ||||
| # Run this to generate all the initial makefiles, etc. | ||||
|  | ||||
| srcdir=`dirname $0` | ||||
|   | ||||
| @@ -41,8 +41,6 @@ | ||||
|  | ||||
| #define PLUGIN_API_VERSION 5 | ||||
|  | ||||
| #define EXTENSION_DISABLE_VERSION_CHECK_KEY "disable-extension-version-validation" | ||||
|  | ||||
| typedef struct { | ||||
|   GDBusProxy *proxy; | ||||
| } PluginData; | ||||
| @@ -833,16 +831,6 @@ plugin_get_shell_version (PluginObject  *obj, | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| plugin_get_version_validation_enabled (PluginObject  *obj, | ||||
|                                        NPVariant     *result) | ||||
| { | ||||
|   gboolean is_enabled = !g_settings_get_boolean (obj->settings, EXTENSION_DISABLE_VERSION_CHECK_KEY); | ||||
|   BOOLEAN_TO_NPVARIANT(is_enabled, *result); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| #define METHODS                                 \ | ||||
|   METHOD (list_extensions)                      \ | ||||
|   METHOD (get_info)                             \ | ||||
| @@ -862,8 +850,6 @@ static NPIdentifier api_version_id; | ||||
| static NPIdentifier shell_version_id; | ||||
| static NPIdentifier onextension_changed_id; | ||||
| static NPIdentifier onrestart_id; | ||||
| static NPIdentifier version_validation_enabled_id; | ||||
|  | ||||
|  | ||||
| static bool | ||||
| plugin_object_has_method (NPObject     *npobj, | ||||
| @@ -906,8 +892,7 @@ plugin_object_has_property (NPObject     *npobj, | ||||
|   return (name == onextension_changed_id || | ||||
|           name == onrestart_id || | ||||
|           name == api_version_id || | ||||
|           name == shell_version_id || | ||||
|           name == version_validation_enabled_id); | ||||
|           name == shell_version_id); | ||||
| } | ||||
|  | ||||
| static bool | ||||
| @@ -925,8 +910,6 @@ plugin_object_get_property (NPObject     *npobj, | ||||
|     return plugin_get_api_version (obj, result); | ||||
|   else if (name == shell_version_id) | ||||
|     return plugin_get_shell_version (obj, result); | ||||
|   else if (name == version_validation_enabled_id) | ||||
|     return plugin_get_version_validation_enabled (obj, result); | ||||
|   else if (name == onextension_changed_id) | ||||
|     { | ||||
|       if (obj->listener) | ||||
| @@ -1005,7 +988,6 @@ init_methods_and_properties (void) | ||||
|   /* this is the JS public API; it is manipulated through NPIdentifiers for speed */ | ||||
|   api_version_id = funcs.getstringidentifier ("apiVersion"); | ||||
|   shell_version_id = funcs.getstringidentifier ("shellVersion"); | ||||
|   version_validation_enabled_id = funcs.getstringidentifier ("versionValidationEnabled"); | ||||
|  | ||||
|   get_info_id = funcs.getstringidentifier ("getExtensionInfo"); | ||||
|   list_extensions_id = funcs.getstringidentifier ("listExtensions"); | ||||
|   | ||||
							
								
								
									
										67
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								configure.ac
									
									
									
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| AC_PREREQ(2.63) | ||||
| AC_INIT([gnome-shell],[3.13.91],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell]) | ||||
| AC_INIT([gnome-shell],[3.11.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]) | ||||
| @@ -76,7 +76,7 @@ AC_MSG_RESULT($enable_systemd) | ||||
| CLUTTER_MIN_VERSION=1.15.90 | ||||
| GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1 | ||||
| GJS_MIN_VERSION=1.39.0 | ||||
| MUTTER_MIN_VERSION=3.13.91 | ||||
| MUTTER_MIN_VERSION=3.11.1 | ||||
| GTK_MIN_VERSION=3.7.9 | ||||
| GIO_MIN_VERSION=2.37.0 | ||||
| LIBECAL_MIN_VERSION=3.5.3 | ||||
| @@ -105,13 +105,22 @@ SHARED_PCS="gio-unix-2.0 >= $GIO_MIN_VERSION | ||||
|             libcanberra libcanberra-gtk3 | ||||
|             telepathy-glib >= $TELEPATHY_GLIB_MIN_VERSION | ||||
|             polkit-agent-1 >= $POLKIT_MIN_VERSION | ||||
|             gcr-base-3 >= $GCR_MIN_VERSION" | ||||
|             libnm-glib libnm-util >= $NETWORKMANAGER_MIN_VERSION | ||||
|             libnm-gtk >= $NETWORKMANAGER_MIN_VERSION | ||||
|             libsecret-unstable gcr-base-3 >= $GCR_MIN_VERSION" | ||||
| if test x$have_systemd = xyes; then | ||||
|   SHARED_PCS="${SHARED_PCS} libsystemd-journal" | ||||
| fi | ||||
|  | ||||
| PKG_CHECK_MODULES(GNOME_SHELL, $SHARED_PCS) | ||||
| PKG_CHECK_MODULES(MUTTER, libmutter >= $MUTTER_MIN_VERSION) | ||||
| PKG_CHECK_MODULES(MUTTER_WAYLAND, [libmutter-wayland >= $MUTTER_MIN_VERSION], | ||||
|                  [MUTTER_WAYLAND_TYPELIB_DIR=`$PKG_CONFIG --variable=typelibdir libmutter-wayland` | ||||
|                   AC_SUBST(MUTTER_WAYLAND_TYPELIB_DIR) | ||||
|                   have_mutter_wayland=yes], | ||||
|                  [have_mutter_wayland=no]) | ||||
|  | ||||
| AM_CONDITIONAL(HAVE_MUTTER_WAYLAND, test $have_mutter_wayland != no) | ||||
|  | ||||
| PKG_CHECK_MODULES(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION) | ||||
| PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11) | ||||
| @@ -173,38 +182,6 @@ if test "$langinfo_ok" = "yes"; then | ||||
|             [Define if _NL_TIME_FIRST_WEEKDAY is available]) | ||||
| fi | ||||
|  | ||||
| AC_ARG_ENABLE(networkmanager, | ||||
|              AS_HELP_STRING([--disable-networkmanager], | ||||
|                             [disable NetworkManager support  @<:@default=auto@:>@]),, | ||||
|               [enable_networkmanager=auto]) | ||||
|  | ||||
| if test "x$enable_networkmanager" != "xno"; then | ||||
|    PKG_CHECK_MODULES(NETWORKMANAGER, | ||||
|                      [libnm-glib | ||||
|                      libnm-util >= $NETWORKMANAGER_MIN_VERSION | ||||
|                      libnm-gtk >= $NETWORKMANAGER_MIN_VERSION | ||||
|                      libsecret-unstable], | ||||
|                      [have_networkmanager=yes], | ||||
|                      [have_networkmanager=no]) | ||||
|  | ||||
|    GNOME_SHELL_CFLAGS="$GNOME_SHELL_CFLAGS $NETWORKMANAGER_CFLAGS" | ||||
|    GNOME_SHELL_LIBS="$GNOME_SHELL_LIBS $NETWORKMANAGER_LIBS" | ||||
| else | ||||
|    have_networkmanager="no  (disabled)" | ||||
| fi | ||||
|  | ||||
| if test "x$have_networkmanager" = "xyes"; then | ||||
|    AC_DEFINE(HAVE_NETWORKMANAGER, [1], [Define if we have NetworkManager]) | ||||
|    AC_SUBST([HAVE_NETWORKMANAGER], [1]) | ||||
| else | ||||
|    if test "x$enable_networkmanager" = "xyes"; then | ||||
|       AC_MSG_ERROR([Couldn't find NetworkManager.]) | ||||
|    fi | ||||
|    AC_SUBST([HAVE_NETWORKMANAGER], [0]) | ||||
| fi | ||||
|  | ||||
| AM_CONDITIONAL(HAVE_NETWORKMANAGER, test "$have_networkmanager" = "yes") | ||||
|  | ||||
| # Sets GLIB_GENMARSHAL and GLIB_MKENUMS | ||||
| AM_PATH_GLIB_2_0() | ||||
|  | ||||
| @@ -223,14 +200,6 @@ fi | ||||
| AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no) | ||||
|  | ||||
| GNOME_COMPILE_WARNINGS([error]) | ||||
| case "$WARN_CFLAGS" in | ||||
|     *-Werror*) | ||||
|         WARN_CFLAGS="$WARN_CFLAGS -Wno-error=deprecated-declarations" | ||||
|         ;; | ||||
| esac | ||||
|  | ||||
| AM_CFLAGS="$AM_CFLAGS $WARN_CFLAGS" | ||||
| AC_SUBST(AM_CFLAGS) | ||||
|  | ||||
| BROWSER_PLUGIN_DIR="${BROWSER_PLUGIN_DIR:-"\${libdir}/mozilla/plugins"}" | ||||
| AC_ARG_VAR([BROWSER_PLUGIN_DIR],[Where to install the plugin to]) | ||||
| @@ -254,15 +223,3 @@ AC_CONFIG_FILES([ | ||||
|   man/Makefile | ||||
| ]) | ||||
| AC_OUTPUT | ||||
|  | ||||
| echo " | ||||
| Build configuration: | ||||
|  | ||||
|        Prefix:                                 ${prefix} | ||||
|        Source code location:                   ${srcdir} | ||||
|        Compiler:                               ${CC} | ||||
|        Compiler Warnings:                      $enable_compile_warnings | ||||
|  | ||||
|        Support for NetworkManager:             $have_networkmanager | ||||
|        Support for GStreamer recording:        $build_recorder | ||||
| " | ||||
|   | ||||
| @@ -1,23 +1,9 @@ | ||||
| CLEANFILES = | ||||
|  | ||||
| desktopdir=$(datadir)/applications | ||||
| desktop_DATA = gnome-shell.desktop gnome-shell-wayland.desktop  gnome-shell-extension-prefs.desktop | ||||
| desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop | ||||
| if HAVE_MUTTER_WAYLAND | ||||
| desktop_DATA += gnome-shell-wayland.desktop | ||||
| endif HAVE_MUTTER_WAYLAND | ||||
|  | ||||
| if HAVE_NETWORKMANAGER | ||||
| desktop_DATA += org.gnome.Shell.PortalHelper.desktop | ||||
|  | ||||
| servicedir = $(datadir)/dbus-1/services | ||||
| service_DATA = org.gnome.Shell.PortalHelper.service | ||||
|  | ||||
| CLEANFILES += \ | ||||
| 	org.gnome.Shell.PortalHelper.service \ | ||||
| 	org.gnome.Shell.PortalHelper.desktop | ||||
|  | ||||
| endif | ||||
|  | ||||
| %.service: %.service.in | ||||
| 	$(AM_V_GEN) sed -e "s|@libexecdir[@]|$(libexecdir)|" \ | ||||
| 	    $< > $@ || rm $@ | ||||
|  | ||||
| # We substitute in bindir so it works as an autostart | ||||
| # file when built in a non-system prefix | ||||
| @@ -74,13 +60,6 @@ dist_theme_DATA =				\ | ||||
| 	theme/ws-switch-arrow-up.png		\ | ||||
| 	theme/ws-switch-arrow-down.png | ||||
|  | ||||
| backgrounddir = $(pkgdatadir) | ||||
| background_DATA = perf-background.xml | ||||
|  | ||||
| perf-background.xml: perf-background.xml.in | ||||
| 	$(AM_V_GEN) sed -e "s|@datadir[@]|$(datadir)|" \ | ||||
| 	    $< > $@ || rm $@ | ||||
|  | ||||
| keysdir = @GNOME_KEYBINDINGS_KEYSDIR@ | ||||
| keys_in_files = 50-gnome-shell-system.xml.in | ||||
| keys_DATA = $(keys_in_files:.xml.in=.xml) | ||||
| @@ -113,19 +92,15 @@ EXTRA_DIST =						\ | ||||
| 	$(menu_DATA)					\ | ||||
| 	$(convert_DATA)					\ | ||||
| 	$(keys_in_files)				\ | ||||
| 	perf-background.xml.in				\ | ||||
| 	org.gnome.Shell.PortalHelper.desktop.in		\ | ||||
| 	org.gnome.Shell.PortalHelper.service.in		\ | ||||
| 	org.gnome.shell.gschema.xml.in.in | ||||
|  | ||||
| CLEANFILES +=						\ | ||||
| CLEANFILES =						\ | ||||
| 	gnome-shell.desktop.in				\ | ||||
| 	gnome-shell-wayland.desktop.in			\ | ||||
| 	gnome-shell-extension-prefs.in			\ | ||||
| 	$(desktop_DATA)					\ | ||||
| 	$(keys_DATA)					\ | ||||
| 	$(gsettings_SCHEMAS)				\ | ||||
| 	perf-background.xml				\ | ||||
| 	gschemas.compiled				\ | ||||
| 	org.gnome.shell.gschema.valid			\ | ||||
| 	org.gnome.shell.gschema.xml.in | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| [org.gnome.shell.overrides] | ||||
| attach-modal-dialogs = /desktop/gnome/shell/windows/attach_modal_dialogs | ||||
| button-layout = /desktop/gnome/shell/windows/button_layout | ||||
| edge-tiling = /desktop/gnome/shell/windows/edge_tiling | ||||
| workspaces-only-on-primary = /desktop/gnome/shell/windows/workspaces_only_on_primary | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
| Type=Application | ||||
| _Name=GNOME Shell (wayland compositor) | ||||
| _Comment=Window management and application launching | ||||
| Exec=@bindir@/gnome-shell --wayland --display-server | ||||
| Exec=@bindir@/mutter-launch -- gnome-shell-wayland --wayland | ||||
| X-GNOME-Bugzilla-Bugzilla=GNOME | ||||
| X-GNOME-Bugzilla-Product=gnome-shell | ||||
| X-GNOME-Bugzilla-Component=general | ||||
|   | ||||
| @@ -1,9 +0,0 @@ | ||||
| [Desktop Entry] | ||||
| _Name=Captive Portal | ||||
| Type=Application | ||||
| Exec=gapplication launch org.gnome.Shell.PortalHelper | ||||
| DBusActivatable=true | ||||
| NoDisplay=true | ||||
| Icon=network-workgroup | ||||
| StartupNotify=true | ||||
| OnlyShowIn=GNOME; | ||||
| @@ -1,3 +0,0 @@ | ||||
| [D-BUS Service] | ||||
| Name=org.gnome.Shell.PortalHelper | ||||
| Exec=@libexecdir@/gnome-shell-portal-helper | ||||
| @@ -38,6 +38,7 @@ | ||||
|     <method name="Screencast"> | ||||
|       <arg type="s" direction="in" name="file_template"/> | ||||
|       <arg type="a{sv}" direction="in" name="options"/> | ||||
|       <arg type="b" direction="in" name="flash"/> | ||||
|       <arg type="b" direction="out" name="success"/> | ||||
|       <arg type="s" direction="out" name="filename_used"/> | ||||
|     </method> | ||||
|   | ||||
| @@ -21,17 +21,8 @@ | ||||
|         EnableExtension and DisableExtension D-Bus methods on org.gnome.Shell. | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key name="disable-extension-version-validation" type="b"> | ||||
|       <default>false</default> | ||||
|       <_summary>Disables the validation of extension version compatibility</_summary> | ||||
|       <_description> | ||||
|         GNOME Shell will only load extensions that claim to support the current | ||||
|         running version. Enabling this option will disable this check and try to | ||||
|         load all extensions regardless of the versions they claim to support. | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key name="favorite-apps" type="as"> | ||||
|       <default>[ 'epiphany.desktop', 'evolution.desktop', 'empathy.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'libreoffice-writer.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Documents.desktop', 'org.gnome.Software.desktop' ]</default> | ||||
|       <default>[ 'epiphany.desktop', 'evolution.desktop', 'empathy.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'libreoffice-writer.desktop', 'nautilus.desktop', 'gnome-documents.desktop' ]</default> | ||||
|       <_summary>List of desktop file IDs for favorite applications</_summary> | ||||
|       <_description> | ||||
|         The applications corresponding to these identifiers | ||||
| @@ -40,10 +31,10 @@ | ||||
|     </key> | ||||
|     <key name="app-picker-view" type="u"> | ||||
|       <default>0</default> | ||||
|       <_summary>App Picker View</_summary> | ||||
|       <_description> | ||||
|       <summary>App Picker View</summary> | ||||
|       <description> | ||||
|         Index of the currently selected view in the application picker. | ||||
|       </_description> | ||||
|       </description> | ||||
|     </key> | ||||
|     <key name="command-history" type="as"> | ||||
|       <default>[]</default> | ||||
| @@ -127,8 +118,8 @@ | ||||
|     </key> | ||||
|     <key name="pause-resume-tweens" type="as"> | ||||
|       <default>[]</default> | ||||
|       <_summary>Keybinding that pauses and resumes all running tweens, for debugging purposes</_summary> | ||||
|       <_description></_description> | ||||
|       <summary>Keybinding that pauses and resumes all running tweens, for debugging purposes</summary> | ||||
|       <description></description> | ||||
|     </key> | ||||
|   </schema> | ||||
|  | ||||
| @@ -148,11 +139,11 @@ | ||||
|           gettext-domain="@GETTEXT_PACKAGE@"> | ||||
|     <key type="b" name="current-workspace-only"> | ||||
|       <default>false</default> | ||||
|       <_summary>Limit switcher to current workspace.</_summary> | ||||
|       <_description> | ||||
|       <summary>Limit switcher to current workspace.</summary> | ||||
|       <description> | ||||
| 	If true, only applications that have windows on the current workspace are shown in the switcher. | ||||
| 	Otherwise, all applications are included. | ||||
|       </_description> | ||||
|       </description> | ||||
|     </key> | ||||
|   </schema> | ||||
|  | ||||
| @@ -175,11 +166,11 @@ | ||||
|     </key> | ||||
|     <key type="b" name="current-workspace-only"> | ||||
|       <default>true</default> | ||||
|       <_summary>Limit switcher to current workspace.</_summary> | ||||
|       <_description> | ||||
|       <summary>Limit switcher to current workspace.</summary> | ||||
|       <description> | ||||
| 	If true, only windows from the current workspace are shown in the switcher. | ||||
| 	Otherwise, all windows are included. | ||||
|       </_description> | ||||
|       </description> | ||||
|     </key> | ||||
|   </schema> | ||||
|  | ||||
| @@ -194,6 +185,15 @@ | ||||
|       </_description> | ||||
|     </key> | ||||
|  | ||||
|     <key name="button-layout" type="s"> | ||||
|       <default>":close"</default> | ||||
|       <_summary>Arrangement of buttons on the titlebar</_summary> | ||||
|       <_description> | ||||
|         This key overrides the key in org.gnome.desktop.wm.preferences when | ||||
|         running GNOME Shell. | ||||
|       </_description> | ||||
|     </key> | ||||
|  | ||||
|     <key name="edge-tiling" type="b"> | ||||
|       <default>true</default> | ||||
|       <_summary>Enable edge tiling when dropping windows on screen edges</_summary> | ||||
|   | ||||
| @@ -1,31 +0,0 @@ | ||||
| <!-- With an animated background, performance will differ depending on whether | ||||
|      one layer or two layers are being blended together. This messes up our | ||||
|      benchmarks. We could just benchmark a single image, but since blended | ||||
|      images are present for much of the day with the GNOME default background, | ||||
|      we want to make sure that also performs well; for that reason we ship | ||||
|      an "animated" background that animates super-slowly to use during | ||||
|      performance tests; it will be in the blended state until 2030. --> | ||||
| <background> | ||||
|   <starttime> | ||||
|     <year>1990</year> | ||||
|     <month>1</month> | ||||
|     <day>1</day> | ||||
|     <hour>0</hour> | ||||
|     <minute>00</minute> | ||||
|     <second>00</second> | ||||
|   </starttime> | ||||
|  | ||||
| <!-- One transition that takes 40 years --> | ||||
| <transition type="overlay"> | ||||
| <duration>1261440000.0</duration> | ||||
| <from>@datadir@/backgrounds/gnome/adwaita-morning.jpg</from> | ||||
| <to>@datadir@/backgrounds/gnome/adwaita-day.jpg</to> | ||||
| </transition> | ||||
|  | ||||
| <!-- A single slide doesn't work, so another slide for 1 minute after 40 years --> | ||||
| <static> | ||||
| <duration>60</duration> | ||||
| <file>/usr/share/backgrounds/gnome/Sandstone.jpg</file> | ||||
| </static> | ||||
|  | ||||
| </background> | ||||
| @@ -45,7 +45,7 @@ stage { | ||||
| /* small bold */ | ||||
| .dash-label, | ||||
| .window-caption, | ||||
| .switcher-list, | ||||
| .switcher-list,  | ||||
| .app-well-app > .overview-icon, | ||||
| .show-apps > .overview-icon, | ||||
| .grid-search-result .overview-icon { | ||||
| @@ -153,43 +153,18 @@ StScrollBar StButton#vhandle:active { | ||||
|     -arrow-rise: 11px; | ||||
| } | ||||
|  | ||||
| .popup-menu-boxpointer.fallback-app-menu { | ||||
|     -arrow-border-radius: 4px; | ||||
|     -arrow-background-color: #ededed; | ||||
|     -arrow-border-width: 1px; | ||||
|     -arrow-border-color: #a6a6a6; | ||||
|     -arrow-base: 24px; | ||||
|     -arrow-rise: 11px; | ||||
| } | ||||
|  | ||||
| .popup-menu-boxpointer.fallback-app-menu.dark { | ||||
|     -arrow-background-color: #3f4747; | ||||
|     -arrow-border-color: #282b2b; | ||||
| } | ||||
|  | ||||
|  | ||||
| .popup-menu { | ||||
|     min-width: 200px; | ||||
| } | ||||
|  | ||||
| .popup-menu-arrow { | ||||
|     width: 16px; | ||||
|     height: 16px; | ||||
| .unicode-arrow { | ||||
|     font-size: 120%; | ||||
| } | ||||
|  | ||||
| .popup-submenu-menu-item:open { | ||||
|     background-color: #333333; | ||||
| } | ||||
|  | ||||
| .fallback-app-menu .popup-submenu-menu-item:open { | ||||
|     background-color: #888888; | ||||
|     color: white; | ||||
| } | ||||
|  | ||||
| .fallback-app-menu.dark .popup-submenu-menu-item:open { | ||||
|     background-color: #333333; | ||||
| } | ||||
|  | ||||
| .popup-sub-menu { | ||||
|     background-gradient-start: rgba(80,80,80,0.3); | ||||
|     background-gradient-end: rgba(80,80,80,0.4); | ||||
| @@ -197,20 +172,6 @@ StScrollBar StButton#vhandle:active { | ||||
|     box-shadow: inset 0px 2px 4px rgba(0,0,0,0.9); | ||||
| } | ||||
|  | ||||
| .fallback-app-menu .popup-sub-menu { | ||||
|     background-gradient-start: #dddddd; | ||||
|     background-gradient-end: #dfdfdf; | ||||
|     background-gradient-direction: vertical; | ||||
|     box-shadow: inset 0px 2px 4px rgba(0,0,0,0.4); | ||||
| } | ||||
|  | ||||
| .fallback-app-menu.dark .popup-sub-menu { | ||||
|     background-gradient-start: #474747; | ||||
|     background-gradient-end: #4b4b4b; | ||||
|     background-gradient-direction: vertical; | ||||
|     box-shadow: inset 0px 2px 4px rgba(0,0,0,0.9); | ||||
| } | ||||
|  | ||||
| .popup-sub-menu:scrolled .popup-menu-item:ltr { | ||||
|     padding-right: 0em; | ||||
| } | ||||
| @@ -259,29 +220,7 @@ StScrollBar StButton#vhandle:active { | ||||
|     color: #9f9f9f; | ||||
| } | ||||
|  | ||||
| .fallback-app-menu .popup-menu-item { | ||||
|     color: #43484a; | ||||
| } | ||||
|  | ||||
| .fallback-app-menu .popup-menu-item:active { | ||||
|     color: white; | ||||
|     background-color: #4689cd; | ||||
| } | ||||
|  | ||||
| .fallback-app-menu .popup-menu-item:insensitive { | ||||
|     color: gray; | ||||
| } | ||||
|  | ||||
| .fallback-app-menu.dark .popup-menu-item { | ||||
|     color: white; | ||||
| } | ||||
|  | ||||
| .fallback-app-menu.dark .popup-menu-item:active { | ||||
|     background-color: #445f7d; | ||||
| } | ||||
|  | ||||
| .fallback-app-menu.dark .popup-menu-item:insensitive { | ||||
|     color: #9f9f9f; | ||||
| .popup-image-menu-item { | ||||
| } | ||||
|  | ||||
| .popup-separator-menu-item { | ||||
| @@ -293,15 +232,8 @@ StScrollBar StButton#vhandle:active { | ||||
|     padding: 8px 0px; | ||||
| } | ||||
|  | ||||
| .fallback-app-menu .popup-separator-menu-item { | ||||
|     -gradient-start: #a0a2a3; | ||||
|     -gradient-end: #a0a2a3; | ||||
|     -margin-horizontal: 0; | ||||
| } | ||||
|  | ||||
| .fallback-app-menu.dark .popup-separator-menu-item { | ||||
|     -gradient-start: #818584; | ||||
|     -gradient-end: #818584; | ||||
| .popup-alternating-menu-item:alternate { | ||||
|     font-weight: bold; | ||||
| } | ||||
|  | ||||
| .popup-status-menu-item { | ||||
| @@ -357,20 +289,6 @@ StScrollBar StButton#vhandle:active { | ||||
|     spacing: 10px; | ||||
| } | ||||
|  | ||||
| .nm-dialog-airplane-box { | ||||
|     spacing: 12px; | ||||
| } | ||||
|  | ||||
| .nm-dialog-airplane-headline { | ||||
|     font-size: 1.1em; | ||||
|     font-weight: bold; | ||||
|     text-align: center; | ||||
| } | ||||
|  | ||||
| .nm-dialog-airplane-text { | ||||
|     color: #999999; | ||||
| } | ||||
|  | ||||
| .nm-dialog-header-icon { | ||||
|     icon-size: 32px; | ||||
| } | ||||
| @@ -403,14 +321,6 @@ StScrollBar StButton#vhandle:active { | ||||
|     icon-size: 16px; | ||||
| } | ||||
|  | ||||
| .no-networks-label { | ||||
|     color: #999999; | ||||
| } | ||||
|  | ||||
| .no-networks-box { | ||||
|     spacing: 12px; | ||||
| } | ||||
|  | ||||
| /* Buttons */ | ||||
|  | ||||
| .candidate-page-button, | ||||
| @@ -478,7 +388,7 @@ StScrollBar StButton#vhandle:active { | ||||
|  | ||||
| /* Common radii */ | ||||
|  | ||||
| .search-entry, | ||||
| #searchEntry, | ||||
| .modal-dialog-button, | ||||
| .notification-button, | ||||
| .hotplug-notification-item, | ||||
| @@ -500,7 +410,7 @@ StScrollBar StButton#vhandle:active { | ||||
|  | ||||
| /* Entries */ | ||||
|  | ||||
| .search-entry, | ||||
| #searchEntry, | ||||
| .login-dialog StEntry, | ||||
| .notification StEntry, | ||||
| .modal-dialog StEntry { | ||||
| @@ -512,7 +422,7 @@ StScrollBar StButton#vhandle:active { | ||||
|     padding: 4px 12px; | ||||
| } | ||||
|  | ||||
| .search-entry, | ||||
| #searchEntry, | ||||
| .login-dialog StEntry, | ||||
| .run-dialog-entry, | ||||
| .notification StEntry { | ||||
| @@ -524,8 +434,8 @@ StScrollBar StButton#vhandle:active { | ||||
|     box-shadow: inset 0px 2px 4px rgba(0,0,0,0.6); | ||||
| } | ||||
|  | ||||
| .search-entry:focus, | ||||
| .search-entry:hover, | ||||
| #searchEntry:focus, | ||||
| #searchEntry:hover, | ||||
| .login-dialog StEntry:focus, | ||||
| .notification StEntry:focus, | ||||
| .modal-dialog StEntry { | ||||
| @@ -542,18 +452,18 @@ StScrollBar StButton#vhandle:active { | ||||
|     border: 2px solid #3465a4; | ||||
| } | ||||
|  | ||||
| .search-entry { | ||||
| #searchEntry { | ||||
|     border-color: rgba(245,245,245,0.3); | ||||
|     color: rgb(192, 192, 192); | ||||
|     caret-color: rgb(192, 192, 192); | ||||
| } | ||||
|  | ||||
| .search-entry:hover { | ||||
| #searchEntry:hover { | ||||
|     color: rgb(128, 128, 128); | ||||
|     caret-color: rgb(128, 128, 128); | ||||
| } | ||||
|  | ||||
| .search-entry:focus { | ||||
| #searchEntry:focus { | ||||
|     color: rgb(64, 64, 64); | ||||
|     caret-color: rgb(64, 64, 64); | ||||
|     font-weight: bold; | ||||
| @@ -657,6 +567,11 @@ StScrollBar StButton#vhandle:active { | ||||
|     app-icon-bottom-clip: 2px; | ||||
| } | ||||
|  | ||||
| .app-menu-icon { | ||||
|     width: 24px; | ||||
|     height: 24px; | ||||
| } | ||||
|  | ||||
| .panel-button { | ||||
|     -natural-hpadding: 12px; | ||||
|     -minimum-hpadding: 6px; | ||||
| @@ -740,7 +655,7 @@ StScrollBar StButton#vhandle:active { | ||||
|     color: #e6e6e6; | ||||
|     border-radius: 32px; /* wish we could do 50% */ | ||||
|     padding: 13px; | ||||
|     border: 2px solid #5f5f5f; /* using rgba() is flaky unfortunately */ | ||||
|     border: 1px solid #5f5f5f; /* using rgba() is flaky unfortunately */ | ||||
| } | ||||
|  | ||||
| .system-menu-action:hover, | ||||
| @@ -748,7 +663,7 @@ StScrollBar StButton#vhandle:active { | ||||
|     color: white; | ||||
|     background-color: #4c4c4c; | ||||
|     border: none; | ||||
|     padding: 15px; | ||||
|     padding: 14px; | ||||
| } | ||||
|  | ||||
| .system-menu-action:active { | ||||
| @@ -917,7 +832,7 @@ StScrollBar StButton#vhandle:active { | ||||
|  | ||||
| /* Search Box */ | ||||
|  | ||||
| .search-entry { | ||||
| #searchEntry { | ||||
|     width: 320px; | ||||
| } | ||||
|  | ||||
| @@ -926,8 +841,8 @@ StScrollBar StButton#vhandle:active { | ||||
|     color: #c0c0c0; | ||||
| } | ||||
|  | ||||
| .search-entry:hover .search-entry-icon, | ||||
| .search-entry:focus .search-entry-icon { | ||||
| #searchEntry:hover .search-entry-icon, | ||||
| #searchEntry:focus .search-entry-icon { | ||||
|     color: #8d8f8a; | ||||
| } | ||||
|  | ||||
| @@ -1049,8 +964,6 @@ StScrollBar StButton#vhandle:active { | ||||
|  | ||||
| .app-folder-icon { | ||||
|     padding: 5px; | ||||
|     spacing-rows: 5px; | ||||
|     spacing-columns: 5px; | ||||
| } | ||||
|  | ||||
| .dash-item-container > StButton { | ||||
| @@ -1159,7 +1072,6 @@ StScrollBar StButton#vhandle:active { | ||||
| .show-apps:checked > .overview-icon, | ||||
| .show-apps:active > .overview-icon, | ||||
| .search-provider-icon:active, | ||||
| .grid-search-result:active .overview-icon, | ||||
| .list-search-result:active { | ||||
|     background-gradient-start: rgba(255, 255, 255, .05); | ||||
|     background-gradient-end: rgba(255, 255, 255, .15); | ||||
| @@ -1228,6 +1140,11 @@ StScrollBar StButton#vhandle:active { | ||||
|     text-shadow: black 0px 2px 2px; | ||||
| } | ||||
|  | ||||
| #LookingGlassDialog .lg-inspector-title { | ||||
|     font-weight: bold; | ||||
|     padding-bottom: 8px; | ||||
| } | ||||
|  | ||||
| .lg-dialog StEntry { | ||||
|     selection-background-color: #bbbbbb; | ||||
|     selected-color: #333333; | ||||
| @@ -1307,8 +1224,14 @@ StScrollBar StButton#vhandle:active { | ||||
|     width: 0.3em; | ||||
| } | ||||
|  | ||||
| #calendarPopup .calendar { | ||||
|     padding: 10px; | ||||
| } | ||||
|  | ||||
| .calendar { | ||||
|     padding: .4em 1.75em .8em 1.75em; | ||||
|     spacing-rows: 0px; | ||||
|     spacing-columns: 0px; | ||||
| } | ||||
|  | ||||
| .calendar-month-label { | ||||
| @@ -1366,18 +1289,12 @@ StScrollBar StButton#vhandle:active { | ||||
|     font-weight: bold; | ||||
|     text-align: center; | ||||
|     color: #eeeeec; | ||||
|     border-radius: 4px; | ||||
| } | ||||
|  | ||||
| .datemenu-date-label:hover, | ||||
| .datemenu-date-label:focus { | ||||
|     background-color: #999999; | ||||
| } | ||||
|  | ||||
| .datemenu-date-label:active { | ||||
|     background-color: #aaaaaa; | ||||
| } | ||||
|  | ||||
| .calendar-day-base { | ||||
|     font-size: 9pt; | ||||
|     text-align: center; | ||||
| @@ -1504,8 +1421,11 @@ StScrollBar StButton#vhandle:active { | ||||
|     padding-right: 8pt; | ||||
| } | ||||
|  | ||||
| /* Message Tray */ | ||||
| .url-highlighter { | ||||
|     link-color: #ccccff; | ||||
| } | ||||
|  | ||||
| /* Message Tray */ | ||||
| #message-tray { | ||||
|     background: #2e3436 url(message-tray-background.png); | ||||
|     background-repeat: repeat; | ||||
| @@ -1528,11 +1448,8 @@ StScrollBar StButton#vhandle:active { | ||||
|     color: #eeeeee; | ||||
| } | ||||
|  | ||||
| .url-highlighter { | ||||
|     link-color: #ccccff; | ||||
| } | ||||
|  | ||||
| .no-messages-label { | ||||
| .no-messages-label, | ||||
| .no-networks-label { | ||||
|     color: #999999; | ||||
| } | ||||
|  | ||||
| @@ -1713,8 +1630,8 @@ StScrollBar StButton#vhandle:active { | ||||
|     color: #888888; | ||||
| } | ||||
|  | ||||
| .chat-empty-line { | ||||
|     font-size: 4px; | ||||
| .chat-group-sent, .chat-group-meta { | ||||
|     padding: 8px 0; | ||||
| } | ||||
|  | ||||
| .chat-received { | ||||
| @@ -1739,7 +1656,6 @@ StScrollBar StButton#vhandle:active { | ||||
| .chat-meta-message { | ||||
|     padding-left: 4px; | ||||
|     font-size: 9pt; | ||||
|     font-weight: bold; | ||||
|     color: #bbbbbb; | ||||
| } | ||||
|  | ||||
| @@ -1829,6 +1745,26 @@ StScrollBar StButton#vhandle:active { | ||||
|     spacing: 8px; | ||||
| } | ||||
|  | ||||
| .thumbnail-scroll-gradient-left { | ||||
|     background-gradient-direction: horizontal; | ||||
|     background-gradient-start: rgba(51, 51, 51, 1.0); | ||||
|     background-gradient-end: rgba(51, 51, 51, 0); | ||||
|     border-radius: 24px; | ||||
|     border-radius-topright: 0px; | ||||
|     border-radius-bottomright: 0px; | ||||
|     width: 60px; | ||||
| } | ||||
|  | ||||
| .thumbnail-scroll-gradient-right { | ||||
|     background-gradient-direction: horizontal; | ||||
|     background-gradient-start: rgba(51, 51, 51, 0); | ||||
|     background-gradient-end: rgba(51, 51, 51, 1.0); | ||||
|     border-radius: 24px; | ||||
|     border-radius-topleft: 0px; | ||||
|     border-radius-bottomleft: 0px; | ||||
|     width: 60px; | ||||
| } | ||||
|  | ||||
| .switcher-list .item-box { | ||||
|     padding: 8px; | ||||
|     border-radius: 8px; | ||||
| @@ -1921,27 +1857,6 @@ StScrollBar StButton#vhandle:active { | ||||
|     border-radius: 8px; | ||||
| } | ||||
|  | ||||
| /* Tile previews */ | ||||
| .tile-preview { | ||||
|     background-color: rgba(74, 144, 217, 0.35); | ||||
|     border: 1px solid #4a90d9; /* Adwaita selected bg color */ | ||||
| } | ||||
|  | ||||
| .tile-preview-left.on-primary { | ||||
|     /* keep in sync with -panel-corner-radius */ | ||||
|     border-radius: 6px 0 0 0; | ||||
| } | ||||
|  | ||||
| .tile-preview-right.on-primary { | ||||
|     /* keep in sync with -panel-corner-radius */ | ||||
|     border-radius: 0 6px 0 0; | ||||
| } | ||||
|  | ||||
| .tile-preview-left.tile-preview-right.on-primary { | ||||
|     /* keep in sync with -panel-corner-radius */ | ||||
|     border-radius: 6px 6px 0 0; | ||||
| } | ||||
|  | ||||
| /* Modal Dialogs */ | ||||
|  | ||||
| /* Dialog Subject Text Style */ | ||||
| @@ -2012,57 +1927,45 @@ StScrollBar StButton#vhandle:active { | ||||
|     padding-top: 20px; | ||||
| } | ||||
|  | ||||
| .end-session-dialog-layout { | ||||
| .end-session-dialog-subject { | ||||
|     padding-left: 17px; | ||||
|     padding-bottom: 20px; | ||||
| } | ||||
|  | ||||
| .end-session-dialog-layout:rtl { | ||||
| .end-session-dialog-subject:rtl { | ||||
|     padding-left: 0px; | ||||
|     padding-right: 17px; | ||||
| } | ||||
|  | ||||
| .end-session-dialog-description { | ||||
|     padding-left: 17px; | ||||
|     width: 28em; | ||||
|     padding-bottom: 10px; | ||||
| } | ||||
|  | ||||
| .end-session-dialog-description:rtl { | ||||
|     width: 28em; | ||||
|     padding-bottom: 10px; | ||||
|     text-align: right; | ||||
| } | ||||
|  | ||||
| .end-session-dialog-warning { | ||||
|     width: 28em; | ||||
|     color: #f57900; | ||||
|     padding-top: 6px; | ||||
| } | ||||
|  | ||||
| .end-session-dialog-warning:rtl { | ||||
|     width: 28em; | ||||
|     color: #f57900; | ||||
|     padding-top: 6px; | ||||
|     padding-right: 17px; | ||||
|     text-align: right; | ||||
| } | ||||
|  | ||||
| .end-session-dialog-logout-icon { | ||||
|     border: 2px solid #8b8b8b; | ||||
|     border-radius: 5px; | ||||
|     width: 48px; | ||||
|     height: 48px; | ||||
|     width: 32px; | ||||
|     height: 32px; | ||||
|     background-size: contain; | ||||
| } | ||||
|  | ||||
| .end-session-dialog-shutdown-icon { | ||||
|     color: #bebebe; | ||||
|     width: 48px; | ||||
|     height: 48px; | ||||
|     width: 32px; | ||||
|     height: 32px; | ||||
| } | ||||
|  | ||||
| .end-session-dialog-inhibitor-layout { | ||||
|     spacing: 16px; | ||||
|     max-height: 200px; | ||||
|     padding-right: 65px; | ||||
|     padding-left: 65px; | ||||
|     padding-right: 50px; | ||||
|     padding-left: 50px; | ||||
| } | ||||
|  | ||||
| .end-session-dialog-session-list, | ||||
| @@ -2093,16 +1996,15 @@ StScrollBar StButton#vhandle:active { | ||||
|     font-size: 10pt; | ||||
| } | ||||
|  | ||||
| /* Restart message */ | ||||
| .restart-message { | ||||
|     font-size: 14pt; | ||||
| } | ||||
|  | ||||
| /* ShellMountOperation Dialogs */ | ||||
| .shell-mount-operation-icon { | ||||
|     icon-size: 48px; | ||||
| } | ||||
|  | ||||
| .mount-password-reask { | ||||
|     color: red; | ||||
| } | ||||
|  | ||||
| .show-processes-dialog, | ||||
| .mount-question-dialog { | ||||
|     spacing: 24px; | ||||
| @@ -2398,6 +2300,13 @@ StScrollBar StButton#vhandle:active { | ||||
|     padding-bottom: 1em; | ||||
| } | ||||
|  | ||||
| .login-dialog-title { | ||||
|     font-size: 14pt; | ||||
|     font-weight: bold; | ||||
|     color: #666666; | ||||
|     padding-bottom: 2em; | ||||
| } | ||||
|  | ||||
| .login-dialog { | ||||
|     /* Reset border and background */ | ||||
|     border: none; | ||||
| @@ -2446,6 +2355,10 @@ StScrollBar StButton#vhandle:active { | ||||
|     background-size: contain; | ||||
| } | ||||
|  | ||||
| .login-dialog-user-list-item-text-box { | ||||
|     padding: 0 0.5em; | ||||
| } | ||||
|  | ||||
| .login-dialog-user-list-item .login-dialog-timed-login-indicator { | ||||
|     background-color: rgba(0,0,0,0.0); | ||||
|     height: 2px; | ||||
| @@ -2475,13 +2388,12 @@ StScrollBar StButton#vhandle:active { | ||||
|     color: #E8E8E8; | ||||
| } | ||||
|  | ||||
| .login-dialog-username, | ||||
| .user-widget-label { | ||||
| .login-dialog-username { | ||||
|     font-size: 16pt; | ||||
|     font-weight: bold; | ||||
|     text-align: left; | ||||
|     padding-left: 15px; | ||||
|     text-shadow: rgba(0, 0, 0, 0.5) 0px 2px 1px 0px; | ||||
|     text-shadow: black 0px 4px 3px 0px; | ||||
| } | ||||
|  | ||||
| .login-dialog-prompt-layout { | ||||
| @@ -2573,6 +2485,11 @@ StScrollBar StButton#vhandle:active { | ||||
| } | ||||
|  | ||||
| .user-widget-label { | ||||
|     font-size: 20px; | ||||
|     font-weight: bold; | ||||
|     text-align: left; | ||||
|     color:white; | ||||
|     text-shadow: black 0px 4px 3px 0px; | ||||
| } | ||||
|  | ||||
| .user-widget-label:ltr { | ||||
| @@ -2595,7 +2512,7 @@ StScrollBar StButton#vhandle:active { | ||||
|     box-shadow: 0px 4px 8px rgba(0,0,0,0.9); | ||||
| } | ||||
|  | ||||
| #lockDialogGroup { | ||||
| #systemGroup { | ||||
|     background: #2e3436 url(noise-texture.png); | ||||
|     background-repeat: repeat; | ||||
| } | ||||
|   | ||||
| @@ -66,7 +66,6 @@ IGNORE_HFILES=					\ | ||||
| 	gactionmuxer.h				\ | ||||
| 	gactionobservable.h			\ | ||||
| 	gactionobserver.h			\ | ||||
| 	shell-network-agent.h			\ | ||||
| 	shell-recorder-src.h | ||||
|  | ||||
| if !BUILD_RECORDER | ||||
|   | ||||
| @@ -50,6 +50,7 @@ | ||||
|     <xi:include href="xml/shell-wm.xml"/> | ||||
|     <xi:include href="xml/shell-util.xml"/> | ||||
|     <xi:include href="xml/shell-mount-operation.xml"/> | ||||
|     <xi:include href="xml/shell-network-agent.xml"/> | ||||
|     <xi:include href="xml/shell-polkit-authentication-agent.xml"/> | ||||
|     <xi:include href="xml/shell-tp-client.xml"/> | ||||
|   </chapter> | ||||
|   | ||||
| @@ -17,19 +17,19 @@ packages. If you are interested in building GNOME Shell from source, | ||||
| we would recommend building from version control using the build | ||||
| script described at: | ||||
|  | ||||
|  https://wiki.gnome.org/Projects/GnomeShell | ||||
|  http://live.gnome.org/GnomeShell | ||||
|  | ||||
| Not only will that give you the very latest version of this rapidly | ||||
| changing project, it will be much easier than get GNOME Shell and | ||||
| its dependencies to build from tarballs.</description> | ||||
|   <homepage rdf:resource="https://wiki.gnome.org/Projects/GnomeShell" /> | ||||
|   <!-- | ||||
|   <homepage rdf:resource="http://live.gnome.org/GnomeShell" /> | ||||
|   --> | ||||
|   <mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gnome-shell-list" /> | ||||
|   <download-page rdf:resource="http://download.gnome.org/sources/gnome-shell/" /> | ||||
|   <bug-database rdf:resource="https://bugzilla.gnome.org/browse.cgi?product=gnome-shell" /> | ||||
|   <bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=gnome-shell" /> | ||||
|  | ||||
|   <category rdf:resource="http://api.gnome.org/doap-extensions#core" /> | ||||
|   <programming-language>JavaScript</programming-language> | ||||
|   <programming-language>C</programming-language> | ||||
|   <category rdf:resource="http://api.gnome.org/doap-extensions#desktop" /> | ||||
|  | ||||
|   <maintainer> | ||||
|     <foaf:Person> | ||||
|   | ||||
| @@ -6,14 +6,13 @@ misc/config.js: misc/config.js.in Makefile | ||||
| 	sed -e "s|[@]PACKAGE_NAME@|$(PACKAGE_NAME)|g" \ | ||||
| 	    -e "s|[@]PACKAGE_VERSION@|$(PACKAGE_VERSION)|g" \ | ||||
| 	    -e "s|[@]HAVE_BLUETOOTH@|$(HAVE_BLUETOOTH)|g" \ | ||||
| 	    -e "s|[@]HAVE_NETWORKMANAGER@|$(HAVE_NETWORKMANAGER)|g" \ | ||||
| 	    -e "s|[@]GETTEXT_PACKAGE@|$(GETTEXT_PACKAGE)|g" \ | ||||
| 	    -e "s|[@]datadir@|$(datadir)|g" \ | ||||
| 	    -e "s|[@]libexecdir@|$(libexecdir)|g" \ | ||||
| 	    -e "s|[@]sysconfdir@|$(sysconfdir)|g" \ | ||||
|                $< > $@ | ||||
|  | ||||
| js_resource_files = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --sourcedir=$(builddir) --generate-dependencies $(srcdir)/js-resources.gresource.xml) | ||||
| js_resource_files = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/js-resources.gresource.xml) | ||||
| js-resources.h: js-resources.gresource.xml $(js_resource_files) misc/config.js | ||||
| 	$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --sourcedir=$(builddir) --generate --c-name shell_js_resources $< | ||||
| js-resources.c: js-resources.gresource.xml $(js_resource_files) misc/config.js | ||||
|   | ||||
| @@ -23,11 +23,6 @@ const GnomeShellIface = '<node> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| const customCss = '.prefs-button { \ | ||||
|                        padding: 8px; \ | ||||
|                        border-radius: 20px; \ | ||||
|                    }'; | ||||
|  | ||||
| const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface); | ||||
|  | ||||
| function stripPrefix(string, prefix) { | ||||
| @@ -51,20 +46,22 @@ const Application = new Lang.Class({ | ||||
|  | ||||
|         this._extensionPrefsModules = {}; | ||||
|  | ||||
|         this._extensionIters = {}; | ||||
|         this._startupUuid = null; | ||||
|         this._loaded = false; | ||||
|         this._skipMainWindow = false; | ||||
|         this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' }); | ||||
|     }, | ||||
|  | ||||
|     _buildModel: function() { | ||||
|         this._model = new Gtk.ListStore(); | ||||
|         this._model.set_column_types([GObject.TYPE_STRING, GObject.TYPE_STRING]); | ||||
|     }, | ||||
|  | ||||
|     _extensionAvailable: function(uuid) { | ||||
|         let extension = ExtensionUtils.extensions[uuid]; | ||||
|         let checkVersion = !this._settings.get_boolean('disable-extension-version-validation'); | ||||
|  | ||||
|         if (!extension) | ||||
|             return false; | ||||
|  | ||||
|         if (checkVersion && ExtensionUtils.isOutOfDate(extension)) | ||||
|         if (ExtensionUtils.isOutOfDate(extension)) | ||||
|             return false; | ||||
|  | ||||
|         if (!extension.dir.get_child('prefs.js').query_exists(null)) | ||||
| @@ -73,6 +70,11 @@ const Application = new Lang.Class({ | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     _setExtensionInsensitive: function(layout, cell, model, iter, data) { | ||||
|         let uuid = model.get_value(iter, 0); | ||||
|         cell.set_sensitive(this._extensionAvailable(uuid)); | ||||
|     }, | ||||
|  | ||||
|     _getExtensionPrefsModule: function(extension) { | ||||
|         let uuid = extension.metadata.uuid; | ||||
|  | ||||
| @@ -102,23 +104,21 @@ const Application = new Lang.Class({ | ||||
|             widget = this._buildErrorUI(extension, e); | ||||
|         } | ||||
|  | ||||
|         let dialog = new Gtk.Dialog({ use_header_bar: true, | ||||
|                                       modal: true, | ||||
|                                       title: extension.metadata.name }); | ||||
|         // Destroy the current prefs widget, if it exists | ||||
|         if (this._extensionPrefsBin.get_child()) | ||||
|             this._extensionPrefsBin.get_child().destroy(); | ||||
|  | ||||
|         if (this._skipMainWindow) { | ||||
|             this.application.add_window(dialog); | ||||
|             if (this._window) | ||||
|                 this._window.destroy(); | ||||
|             this._window = dialog; | ||||
|             this._window.window_position = Gtk.WindowPosition.CENTER; | ||||
|         } else { | ||||
|             dialog.transient_for = this._window; | ||||
|         } | ||||
|         this._extensionPrefsBin.add(widget); | ||||
|         this._extensionSelector.set_active_iter(this._extensionIters[uuid]); | ||||
|     }, | ||||
|  | ||||
|         dialog.set_default_size(600, 400); | ||||
|         dialog.get_content_area().add(widget); | ||||
|         dialog.show(); | ||||
|     _extensionSelected: function() { | ||||
|         let [success, iter] = this._extensionSelector.get_active_iter(); | ||||
|         if (!success) | ||||
|             return; | ||||
|  | ||||
|         let uuid = this._model.get_value(iter, 0); | ||||
|         this._selectExtension(uuid); | ||||
|     }, | ||||
|  | ||||
|     _buildErrorUI: function(extension, exc) { | ||||
| @@ -151,26 +151,48 @@ const Application = new Lang.Class({ | ||||
|  | ||||
|     _buildUI: function(app) { | ||||
|         this._window = new Gtk.ApplicationWindow({ application: app, | ||||
|                                                    window_position: Gtk.WindowPosition.CENTER }); | ||||
|                                                    window_position: Gtk.WindowPosition.CENTER, | ||||
|                                                    title: _("GNOME Shell Extension Preferences") }); | ||||
|  | ||||
|         this._window.set_size_request(800, 500); | ||||
|         this._window.set_size_request(600, 400); | ||||
|  | ||||
|         this._titlebar = new Gtk.HeaderBar({ show_close_button: true, | ||||
|                                              title: _("GNOME Shell Extensions") }); | ||||
|         this._window.set_titlebar(this._titlebar); | ||||
|         let vbox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL }); | ||||
|         this._window.add(vbox); | ||||
|  | ||||
|         let scroll = new Gtk.ScrolledWindow({ hscrollbar_policy: Gtk.PolicyType.NEVER, | ||||
|                                               shadow_type: Gtk.ShadowType.IN, | ||||
|                                               halign: Gtk.Align.CENTER, | ||||
|                                               margin: 18 }); | ||||
|         this._window.add(scroll); | ||||
|         let toolbar = new Gtk.Toolbar(); | ||||
|         toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR); | ||||
|         vbox.add(toolbar); | ||||
|         let toolitem; | ||||
|  | ||||
|         this._extensionSelector = new Gtk.ListBox({ selection_mode: Gtk.SelectionMode.NONE }); | ||||
|         this._extensionSelector.set_sort_func(Lang.bind(this, this._sortList)); | ||||
|         this._extensionSelector.set_header_func(Lang.bind(this, this._updateHeader)); | ||||
|         let label = new Gtk.Label({ label: '<b>' + _("Extension") + '</b>', | ||||
|                                     use_markup: true }); | ||||
|         toolitem = new Gtk.ToolItem({ child: label }); | ||||
|         toolbar.add(toolitem); | ||||
|  | ||||
|         scroll.add(this._extensionSelector); | ||||
|         this._extensionSelector = new Gtk.ComboBox({ model: this._model, | ||||
|                                                      margin_left: 8, | ||||
|                                                      hexpand: true }); | ||||
|         this._extensionSelector.get_style_context().add_class(Gtk.STYLE_CLASS_RAISED); | ||||
|  | ||||
|         let renderer = new Gtk.CellRendererText(); | ||||
|         this._extensionSelector.pack_start(renderer, true); | ||||
|         this._extensionSelector.add_attribute(renderer, 'text', 1); | ||||
|         this._extensionSelector.set_cell_data_func(renderer, Lang.bind(this, this._setExtensionInsensitive)); | ||||
|         this._extensionSelector.connect('changed', Lang.bind(this, this._extensionSelected)); | ||||
|  | ||||
|         toolitem = new Gtk.ToolItem({ child: this._extensionSelector }); | ||||
|         toolitem.set_expand(true); | ||||
|         toolbar.add(toolitem); | ||||
|  | ||||
|         this._extensionPrefsBin = new Gtk.Frame(); | ||||
|         vbox.add(this._extensionPrefsBin); | ||||
|  | ||||
|         let label = new Gtk.Label({ | ||||
|             label: _("Select an extension to configure using the combobox above."), | ||||
|             vexpand: true | ||||
|         }); | ||||
|  | ||||
|         this._extensionPrefsBin.add(label); | ||||
|  | ||||
|         this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell'); | ||||
|         this._shellProxy.connectSignal('ExtensionStatusChanged', Lang.bind(this, function(proxy, senderName, [uuid, state, error]) { | ||||
| @@ -181,35 +203,6 @@ const Application = new Lang.Class({ | ||||
|         this._window.show_all(); | ||||
|     }, | ||||
|  | ||||
|     _addCustomStyle: function() { | ||||
|         let provider = new Gtk.CssProvider(); | ||||
|  | ||||
|         try { | ||||
|             provider.load_from_data(customCss, -1); | ||||
|         } catch(e) { | ||||
|             log('Failed to add application style'); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let screen = this._window.window.get_screen(); | ||||
|         let priority = Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION; | ||||
|         Gtk.StyleContext.add_provider_for_screen(screen, provider, priority); | ||||
|     }, | ||||
|  | ||||
|     _sortList: function(row1, row2) { | ||||
|         let name1 = ExtensionUtils.extensions[row1.uuid].metadata.name; | ||||
|         let name2 = ExtensionUtils.extensions[row2.uuid].metadata.name; | ||||
|         return name1.localeCompare(name2); | ||||
|     }, | ||||
|  | ||||
|     _updateHeader: function(row, before) { | ||||
|         if (!before || row.get_header()) | ||||
|             return; | ||||
|  | ||||
|         let sep = new Gtk.Separator({ orientation: Gtk.Orientation.HORIZONTAL }); | ||||
|         row.set_header(sep); | ||||
|     }, | ||||
|  | ||||
|     _scanExtensions: function() { | ||||
|         let finder = new ExtensionUtils.ExtensionFinder(); | ||||
|         finder.connect('extension-found', Lang.bind(this, this._extensionFound)); | ||||
| @@ -218,24 +211,15 @@ const Application = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _extensionFound: function(finder, extension) { | ||||
|         let row = new ExtensionRow(extension.uuid); | ||||
|  | ||||
|         row.prefsButton.visible = this._extensionAvailable(row.uuid); | ||||
|         row.prefsButton.connect('clicked', Lang.bind(this, | ||||
|             function() { | ||||
|                 this._selectExtension(row.uuid); | ||||
|             })); | ||||
|  | ||||
|         row.show_all(); | ||||
|         this._extensionSelector.add(row); | ||||
|         let iter = this._model.append(); | ||||
|         this._model.set(iter, [0, 1], [extension.uuid, extension.metadata.name]); | ||||
|         this._extensionIters[extension.uuid] = iter; | ||||
|     }, | ||||
|  | ||||
|     _extensionsLoaded: function() { | ||||
|         if (this._startupUuid && this._extensionAvailable(this._startupUuid)) | ||||
|             this._selectExtension(this._startupUuid); | ||||
|         this._startupUuid = null; | ||||
|         this._skipMainWindow = false; | ||||
|         this._loaded = true; | ||||
|     }, | ||||
|  | ||||
|     _onActivate: function() { | ||||
| @@ -243,125 +227,29 @@ const Application = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _onStartup: function(app) { | ||||
|         this._buildModel(); | ||||
|         this._buildUI(app); | ||||
|         this._addCustomStyle(); | ||||
|         this._scanExtensions(); | ||||
|     }, | ||||
|  | ||||
|     _onCommandLine: function(app, commandLine) { | ||||
|         app.activate(); | ||||
|         let args = commandLine.get_arguments(); | ||||
|  | ||||
|         if (args.length) { | ||||
|             let uuid = args[0]; | ||||
|  | ||||
|             this._skipMainWindow = true; | ||||
|  | ||||
|             // Strip off "extension:///" prefix which fakes a URI, if it exists | ||||
|             uuid = stripPrefix(uuid, "extension:///"); | ||||
|  | ||||
|             if (this._extensionAvailable(uuid)) | ||||
|                 this._selectExtension(uuid); | ||||
|             else if (!this._loaded) | ||||
|                 this._startupUuid = uuid; | ||||
|             else | ||||
|                 this._skipMainWindow = false; | ||||
|                 this._startupUuid = uuid; | ||||
|         } | ||||
|         return 0; | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const ExtensionRow = new Lang.Class({ | ||||
|     Name: 'ExtensionRow', | ||||
|     Extends: Gtk.ListBoxRow, | ||||
|  | ||||
|     _init: function(uuid) { | ||||
|         this.parent(); | ||||
|  | ||||
|         this.uuid = uuid; | ||||
|  | ||||
|         this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' }); | ||||
|         this._settings.connect('changed::enabled-extensions', Lang.bind(this, | ||||
|             function() { | ||||
|                 this._switch.state = this._isEnabled(); | ||||
|             })); | ||||
|  | ||||
|         this._buildUI(); | ||||
|     }, | ||||
|  | ||||
|     _buildUI: function() { | ||||
|         let extension = ExtensionUtils.extensions[this.uuid]; | ||||
|  | ||||
|         let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, | ||||
|                                  hexpand: true, margin: 12, spacing: 6 }); | ||||
|         this.add(hbox); | ||||
|  | ||||
|         let vbox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, | ||||
|                                  spacing: 6, hexpand: true }); | ||||
|         hbox.add(vbox); | ||||
|  | ||||
|         let name = GLib.markup_escape_text(extension.metadata.name, -1); | ||||
|         let label = new Gtk.Label({ label: '<b>' + name + '</b>', | ||||
|                                     use_markup: true, | ||||
|                                     halign: Gtk.Align.START }); | ||||
|         vbox.add(label); | ||||
|  | ||||
|         let desc = extension.metadata.description.split('\n')[0]; | ||||
|         label = new Gtk.Label({ label: desc, | ||||
|                                 ellipsize: Pango.EllipsizeMode.END, | ||||
|                                 halign: Gtk.Align.START }); | ||||
|         vbox.add(label); | ||||
|  | ||||
|         let button = new Gtk.Button({ valign: Gtk.Align.CENTER, | ||||
|                                       no_show_all: true }); | ||||
|         button.add(new Gtk.Image({ icon_name: 'emblem-system-symbolic', | ||||
|                                    icon_size: Gtk.IconSize.BUTTON, | ||||
|                                    visible: true })); | ||||
|         button.get_style_context().add_class('prefs-button'); | ||||
|         hbox.add(button); | ||||
|  | ||||
|         this.prefsButton = button; | ||||
|  | ||||
|         this._switch = new Gtk.Switch({ valign: Gtk.Align.CENTER, | ||||
|                                         state: this._isEnabled() }); | ||||
|         this._switch.connect('notify::active', Lang.bind(this, | ||||
|             function() { | ||||
|                 if (this._switch.active) | ||||
|                     this._enable(); | ||||
|                 else | ||||
|                     this._disable(); | ||||
|             })); | ||||
|         this._switch.connect('state-set', function() { return true; }); | ||||
|         hbox.add(this._switch); | ||||
|     }, | ||||
|  | ||||
|     _isEnabled: function() { | ||||
|         let extensions = this._settings.get_strv('enabled-extensions'); | ||||
|         return extensions.indexOf(this.uuid) != -1; | ||||
|     }, | ||||
|  | ||||
|     _enable: function() { | ||||
|         let extensions = this._settings.get_strv('enabled-extensions'); | ||||
|         if (extensions.indexOf(this.uuid) != -1) | ||||
|             return; | ||||
|  | ||||
|         extensions.push(this.uuid); | ||||
|         this._settings.set_strv('enabled-extensions', extensions); | ||||
|     }, | ||||
|  | ||||
|     _disable: function() { | ||||
|         let extensions = this._settings.get_strv('enabled-extensions'); | ||||
|         let pos = extensions.indexOf(this.uuid); | ||||
|         if (pos == -1) | ||||
|             return; | ||||
|         do { | ||||
|             extensions.splice(pos, 1); | ||||
|             pos = extensions.indexOf(this.uuid); | ||||
|         } while (pos != -1); | ||||
|         this._settings.set_strv('enabled-extensions', extensions); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| function initEnvironment() { | ||||
|     // Monkey-patch in a "global" object that fakes some Shell utilities | ||||
|     // that ExtensionUtils depends on. | ||||
|   | ||||
| @@ -450,7 +450,8 @@ const AuthPrompt = new Lang.Class({ | ||||
|             // respond to the request with the username | ||||
|             beginRequestType = BeginRequestType.PROVIDE_USERNAME; | ||||
|         } else if (this._userVerifier.serviceIsForeground(GdmUtil.OVIRT_SERVICE_NAME) || | ||||
|                    this._userVerifier.serviceIsForeground(GdmUtil.SMARTCARD_SERVICE_NAME)) { | ||||
|                    (this.smartcardDetected && | ||||
|                     this._userVerifier.serviceIsForeground(GdmUtil.SMARTCARD_SERVICE_NAME))) { | ||||
|             // We don't need to know the username if the user preempted the login screen | ||||
|             // with a smartcard or with preauthenticated oVirt credentials | ||||
|             beginRequestType = BeginRequestType.DONT_PROVIDE_USERNAME; | ||||
|   | ||||
| @@ -36,7 +36,6 @@ const BoxPointer = imports.ui.boxpointer; | ||||
| const CtrlAltTab = imports.ui.ctrlAltTab; | ||||
| const GdmUtil = imports.gdm.util; | ||||
| const Layout = imports.ui.layout; | ||||
| const LoginManager = imports.misc.loginManager; | ||||
| const Main = imports.ui.main; | ||||
| const PopupMenu = imports.ui.popupMenu; | ||||
| const Realmd = imports.gdm.realmd; | ||||
| @@ -48,6 +47,8 @@ const _SCROLL_ANIMATION_TIME = 0.5; | ||||
| const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0; | ||||
| const _LOGO_ICON_HEIGHT = 48; | ||||
|  | ||||
| let _loginDialog = null; | ||||
|  | ||||
| const UserListItem = new Lang.Class({ | ||||
|     Name: 'UserListItem', | ||||
|  | ||||
| @@ -273,7 +274,7 @@ const SessionMenuButton = new Lang.Class({ | ||||
|         this.actor = new St.Bin({ child: this._button }); | ||||
|  | ||||
|         this._menu = new PopupMenu.PopupMenu(this._button, 0, St.Side.TOP); | ||||
|         Main.uiGroup.add_actor(this._menu.actor); | ||||
|         Main.layoutManager.menuGroup.add_actor(this._menu.actor); | ||||
|         this._menu.actor.hide(); | ||||
|  | ||||
|         this._menu.connect('open-state-changed', | ||||
| @@ -382,7 +383,7 @@ const LoginDialog = new Lang.Class({ | ||||
|                                   Lang.bind(this, this._onTimedLoginRequested)); | ||||
|         } | ||||
|  | ||||
|         this._settings = new Gio.Settings({ schema_id: GdmUtil.LOGIN_SCREEN_SCHEMA }); | ||||
|         this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA }); | ||||
|  | ||||
|         this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_KEY, | ||||
|                                Lang.bind(this, this._updateBanner)); | ||||
| @@ -468,20 +469,7 @@ const LoginDialog = new Lang.Class({ | ||||
|         this._sessionMenuButton.actor.show(); | ||||
|         this._authPrompt.addActorToDefaultButtonWell(this._sessionMenuButton.actor); | ||||
|  | ||||
|         this._disableUserList = undefined; | ||||
|         this._userListLoaded = false; | ||||
|  | ||||
|         LoginManager.getLoginManager().getCurrentSessionProxy(Lang.bind(this, this._gotGreeterSessionProxy)); | ||||
|  | ||||
|         // If the user list is enabled, it should take key focus; make sure the | ||||
|         // screen shield is initialized first to prevent it from stealing the | ||||
|         // focus later | ||||
|         Main.layoutManager.connect('startup-complete', | ||||
|                                    Lang.bind(this, this._updateDisableUserList)); | ||||
|     }, | ||||
|  | ||||
|     _ensureUserListLoaded: function() { | ||||
|         if (!this._userManager.is_loaded) { | ||||
|         if (!this._userManager.is_loaded) | ||||
|             this._userManagerLoadedId = this._userManager.connect('notify::is-loaded', | ||||
|                                                                   Lang.bind(this, function() { | ||||
|                                                                       if (this._userManager.is_loaded) { | ||||
| @@ -490,11 +478,10 @@ const LoginDialog = new Lang.Class({ | ||||
|                                                                           this._userManagerLoadedId = 0; | ||||
|                                                                       } | ||||
|                                                                   })); | ||||
|         } else { | ||||
|             let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, this._loadUserList)); | ||||
|             GLib.Source.set_name_by_id(id, '[gnome-shell] _loadUserList'); | ||||
|         } | ||||
|     }, | ||||
|         else | ||||
|             GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, this._loadUserList)); | ||||
|  | ||||
|    }, | ||||
|  | ||||
|     _updateDisableUserList: function() { | ||||
|         let disableUserList = this._settings.get_boolean(GdmUtil.DISABLE_USER_LIST_KEY); | ||||
| @@ -537,12 +524,9 @@ const LoginDialog = new Lang.Class({ | ||||
|             return; | ||||
|  | ||||
|         this._logoBin.destroy_all_children(); | ||||
|         if (this._logoFileUri) { | ||||
|             let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; | ||||
|         if (this._logoFileUri) | ||||
|             this._logoBin.add_child(this._textureCache.load_uri_async(this._logoFileUri, | ||||
|                                                                       -1, _LOGO_ICON_HEIGHT, | ||||
|                                                                       scaleFactor)); | ||||
|         } | ||||
|                                                                       -1, _LOGO_ICON_HEIGHT)); | ||||
|     }, | ||||
|  | ||||
|     _updateLogo: function() { | ||||
| @@ -641,36 +625,6 @@ const LoginDialog = new Lang.Class({ | ||||
|         this._showPrompt(); | ||||
|     }, | ||||
|  | ||||
|     _loginScreenSessionActivated: function() { | ||||
|         if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFICATION_SUCCEEDED) | ||||
|             return; | ||||
|  | ||||
|         Tweener.addTween(this.actor, | ||||
|                          { opacity: 255, | ||||
|                            time: _FADE_ANIMATION_TIME, | ||||
|                            transition: 'easeOutQuad', | ||||
|                            onUpdate: function() { | ||||
|                                let children = Main.layoutManager.uiGroup.get_children(); | ||||
|  | ||||
|                                for (let i = 0; i < children.length; i++) { | ||||
|                                    if (children[i] != Main.layoutManager.screenShieldGroup) | ||||
|                                        children[i].opacity = this.actor.opacity; | ||||
|                                } | ||||
|                            }, | ||||
|                            onUpdateScope: this, | ||||
|                            onComplete: function() { | ||||
|                                this._authPrompt.reset(); | ||||
|                            }, | ||||
|                            onCompleteScope: this }); | ||||
|     }, | ||||
|  | ||||
|     _gotGreeterSessionProxy: function(proxy) { | ||||
|         proxy.connect('g-properties-changed', Lang.bind(this, function() { | ||||
|             if (proxy.Active) | ||||
|                 this._loginScreenSessionActivated(); | ||||
|         })); | ||||
|     }, | ||||
|  | ||||
|     _startSession: function(serviceName) { | ||||
|         Tweener.addTween(this.actor, | ||||
|                          { opacity: 0, | ||||
| @@ -686,11 +640,10 @@ const LoginDialog = new Lang.Class({ | ||||
|                            }, | ||||
|                            onUpdateScope: this, | ||||
|                            onComplete: function() { | ||||
|                                let id = Mainloop.idle_add(Lang.bind(this, function() { | ||||
|                                Mainloop.idle_add(Lang.bind(this, function() { | ||||
|                                    this._greeter.call_start_session_when_ready_sync(serviceName, true, null); | ||||
|                                    return GLib.SOURCE_REMOVE; | ||||
|                                })); | ||||
|                                GLib.Source.set_name_by_id(id, '[gnome-shell] this._greeter.call_start_session_when_ready_sync'); | ||||
|                            }, | ||||
|                            onCompleteScope: this }); | ||||
|     }, | ||||
| @@ -746,7 +699,6 @@ const LoginDialog = new Lang.Class({ | ||||
|                                                                          hold.release(); | ||||
|                                                                          return GLib.SOURCE_REMOVE; | ||||
|                                                                      }); | ||||
|         GLib.Source.set_name_by_id(this._timedLoginIdleTimeOutId, '[gnome-shell] this._timedLoginAnimationTime'); | ||||
|         return hold; | ||||
|     }, | ||||
|  | ||||
| @@ -849,7 +801,6 @@ const LoginDialog = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _showUserList: function() { | ||||
|         this._ensureUserListLoaded(); | ||||
|         this._authPrompt.hide(); | ||||
|         this._sessionMenuButton.close(); | ||||
|         this._setUserListExpanded(true); | ||||
| @@ -893,17 +844,14 @@ const LoginDialog = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _loadUserList: function() { | ||||
|         if (this._userListLoaded) | ||||
|             return GLib.SOURCE_REMOVE; | ||||
|  | ||||
|         this._userListLoaded = true; | ||||
|  | ||||
|         let users = this._userManager.list_users(); | ||||
|  | ||||
|         for (let i = 0; i < users.length; i++) { | ||||
|             this._userList.addUser(users[i]); | ||||
|         } | ||||
|  | ||||
|         this._updateDisableUserList(); | ||||
|  | ||||
|         this._userManager.connect('user-added', | ||||
|                                   Lang.bind(this, function(userManager, user) { | ||||
|                                       this._userList.addUser(user); | ||||
| @@ -913,8 +861,6 @@ const LoginDialog = new Lang.Class({ | ||||
|                                   Lang.bind(this, function(userManager, user) { | ||||
|                                       this._userList.removeUser(user); | ||||
|                                   })); | ||||
|  | ||||
|         return GLib.SOURCE_REMOVE; | ||||
|     }, | ||||
|  | ||||
|     open: function() { | ||||
| @@ -926,8 +872,6 @@ const LoginDialog = new Lang.Class({ | ||||
|         this.actor.show(); | ||||
|         this.actor.opacity = 0; | ||||
|  | ||||
|         Main.pushModal(this.actor, { keybindingMode: Shell.KeyBindingMode.LOGIN_SCREEN }); | ||||
|  | ||||
|         Tweener.addTween(this.actor, | ||||
|                          { opacity: 255, | ||||
|                            time: 1, | ||||
| @@ -937,8 +881,7 @@ const LoginDialog = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     close: function() { | ||||
|         Main.popModal(this.actor); | ||||
|         Main.ctrlAltTabManager.removeGroup(this.actor); | ||||
|         Main.ctrlAltTabManager.removeGroup(this.dialogLayout); | ||||
|     }, | ||||
|  | ||||
|     cancel: function() { | ||||
|   | ||||
| @@ -128,7 +128,7 @@ const ShellUserVerifier = new Lang.Class({ | ||||
|  | ||||
|         this._client = client; | ||||
|  | ||||
|         this._settings = new Gio.Settings({ schema_id: LOGIN_SCREEN_SCHEMA }); | ||||
|         this._settings = new Gio.Settings({ schema: LOGIN_SCREEN_SCHEMA }); | ||||
|         this._settings.connect('changed', | ||||
|                                Lang.bind(this, this._updateDefaultService)); | ||||
|         this._updateDefaultService(); | ||||
| @@ -252,7 +252,6 @@ const ShellUserVerifier = new Lang.Class({ | ||||
|                                                            this._queueMessageTimeout(); | ||||
|                                                            return GLib.SOURCE_REMOVE; | ||||
|                                                        })); | ||||
|         GLib.Source.set_name_by_id(this._messageQueueTimeoutId, '[gnome-shell] this._queueMessageTimeout'); | ||||
|     }, | ||||
|  | ||||
|     _queueMessage: function(message, messageType) { | ||||
| @@ -299,7 +298,7 @@ const ShellUserVerifier = new Lang.Class({ | ||||
|  | ||||
|         if (!this._settings.get_boolean(SMARTCARD_AUTHENTICATION_KEY)) | ||||
|             smartcardDetected = false; | ||||
|         else if (this._reauthOnly) | ||||
|         else if (this.reauthenticating) | ||||
|             smartcardDetected = this._smartcardManager.hasInsertedLoginToken(); | ||||
|         else | ||||
|             smartcardDetected = this._smartcardManager.hasInsertedTokens(); | ||||
|   | ||||
| @@ -25,9 +25,6 @@ | ||||
|     <file>misc/util.js</file> | ||||
|  | ||||
|     <file>perf/core.js</file> | ||||
|     <file>perf/hwtest.js</file> | ||||
|  | ||||
|     <file>portalHelper/main.js</file> | ||||
|  | ||||
|     <file>ui/altTab.js</file> | ||||
|     <file>ui/animation.js</file> | ||||
| @@ -42,7 +39,6 @@ | ||||
|     <file>ui/dash.js</file> | ||||
|     <file>ui/dateMenu.js</file> | ||||
|     <file>ui/dnd.js</file> | ||||
|     <file>ui/edgeDragAction.js</file> | ||||
|     <file>ui/endSessionDialog.js</file> | ||||
|     <file>ui/environment.js</file> | ||||
|     <file>ui/extensionDownloader.js</file> | ||||
| @@ -88,9 +84,7 @@ | ||||
|     <file>ui/userWidget.js</file> | ||||
|     <file>ui/viewSelector.js</file> | ||||
|     <file>ui/windowAttentionHandler.js</file> | ||||
|     <file>ui/windowMenu.js</file> | ||||
|     <file>ui/windowManager.js</file> | ||||
|     <file>ui/wobbly.js</file> | ||||
|     <file>ui/workspace.js</file> | ||||
|     <file>ui/workspaceSwitcherPopup.js</file> | ||||
|     <file>ui/workspaceThumbnail.js</file> | ||||
|   | ||||
| @@ -6,8 +6,6 @@ const PACKAGE_NAME = '@PACKAGE_NAME@'; | ||||
| const PACKAGE_VERSION = '@PACKAGE_VERSION@'; | ||||
| /* 1 if gnome-bluetooth is available, 0 otherwise */ | ||||
| const HAVE_BLUETOOTH = @HAVE_BLUETOOTH@; | ||||
| /* 1 if networkmanager is available, 0 otherwise */ | ||||
| const HAVE_NETWORKMANAGER = @HAVE_NETWORKMANAGER@; | ||||
| /* gettext package */ | ||||
| const GETTEXT_PACKAGE = '@GETTEXT_PACKAGE@'; | ||||
| /* locale dir */ | ||||
|   | ||||
| @@ -39,13 +39,38 @@ const SystemdLoginSessionIface = '<node> \ | ||||
| <interface name="org.freedesktop.login1.Session"> \ | ||||
| <signal name="Lock" /> \ | ||||
| <signal name="Unlock" /> \ | ||||
| <property name="Active" type="b" access="read" /> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| const SystemdLoginManager = Gio.DBusProxy.makeProxyWrapper(SystemdLoginManagerIface); | ||||
| const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIface); | ||||
|  | ||||
| const ConsoleKitManagerIface = '<node> \ | ||||
| <interface name="org.freedesktop.ConsoleKit.Manager"> \ | ||||
| <method name="CanRestart"> \ | ||||
|     <arg type="b" direction="out"/> \ | ||||
| </method> \ | ||||
| <method name="CanStop"> \ | ||||
|     <arg type="b" direction="out"/> \ | ||||
| </method> \ | ||||
| <method name="Restart" /> \ | ||||
| <method name="Stop" /> \ | ||||
| <method name="GetCurrentSession"> \ | ||||
|     <arg type="o" direction="out" /> \ | ||||
| </method> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| const ConsoleKitSessionIface = '<node> \ | ||||
| <interface name="org.freedesktop.ConsoleKit.Session"> \ | ||||
| <signal name="Lock" /> \ | ||||
| <signal name="Unlock" /> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| const ConsoleKitSession = Gio.DBusProxy.makeProxyWrapper(ConsoleKitSessionIface); | ||||
| const ConsoleKitManager = Gio.DBusProxy.makeProxyWrapper(ConsoleKitManagerIface); | ||||
|  | ||||
| function haveSystemd() { | ||||
|     return GLib.access("/run/systemd/seats", 0) >= 0; | ||||
| } | ||||
| @@ -75,7 +100,7 @@ function canLock() { | ||||
|                                                -1, null); | ||||
|  | ||||
|         let version = result.deep_unpack()[0].deep_unpack(); | ||||
|         return haveSystemd() && versionCompare('3.5.91', version); | ||||
|         return versionCompare('3.5.91', version); | ||||
|     } catch(e) { | ||||
|         return false; | ||||
|     } | ||||
| @@ -93,7 +118,7 @@ function getLoginManager() { | ||||
|         if (haveSystemd()) | ||||
|             _loginManager = new LoginManagerSystemd(); | ||||
|         else | ||||
|             _loginManager = new LoginManagerDummy(); | ||||
|             _loginManager = new LoginManagerConsoleKit(); | ||||
|     } | ||||
|  | ||||
|     return _loginManager; | ||||
| @@ -110,6 +135,9 @@ const LoginManagerSystemd = new Lang.Class({ | ||||
|                                   Lang.bind(this, this._prepareForSleep)); | ||||
|     }, | ||||
|  | ||||
|     // Having this function is a bit of a hack since the Systemd and ConsoleKit | ||||
|     // session objects have different interfaces - but in both cases there are | ||||
|     // Lock/Unlock signals, and that's all we count upon at the moment. | ||||
|     getCurrentSessionProxy: function(callback) { | ||||
|         if (this._currentSession) { | ||||
|             callback (this._currentSession); | ||||
| @@ -162,7 +190,7 @@ const LoginManagerSystemd = new Lang.Class({ | ||||
|                 let fd = -1; | ||||
|                 try { | ||||
|                     let [outVariant, fdList] = proxy.call_with_unix_fd_list_finish(result); | ||||
|                     fd = fdList.steal_fds()[0]; | ||||
|                     fd = fdList.steal_fds(outVariant.deep_unpack())[0]; | ||||
|                     callback(new Gio.UnixInputStream({ fd: fd })); | ||||
|                 } catch(e) { | ||||
|                     logError(e, "Error getting systemd inhibitor"); | ||||
| @@ -177,13 +205,35 @@ const LoginManagerSystemd = new Lang.Class({ | ||||
| }); | ||||
| Signals.addSignalMethods(LoginManagerSystemd.prototype); | ||||
|  | ||||
| const LoginManagerDummy = new Lang.Class({ | ||||
|     Name: 'LoginManagerDummy', | ||||
| 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(callback) { | ||||
|         // we could return a DummySession object that fakes whatever callers | ||||
|         // expect (at the time of writing: connect() and connectSignal() | ||||
|         // methods), but just never calling the callback should be safer | ||||
|         if (this._currentSession) { | ||||
|             callback (this._currentSession); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         this._proxy.GetCurrentSessionRemote(Lang.bind(this, | ||||
|             function(result, error) { | ||||
|                 if (error) { | ||||
|                     logError(error, 'Could not get a proxy for the current session'); | ||||
|                 } else { | ||||
|                     this._currentSession = new ConsoleKitSession(Gio.DBus.system, | ||||
|                                                                  'org.freedesktop.ConsoleKit', | ||||
|                                                                  result[0]); | ||||
|                     callback(this._currentSession); | ||||
|                 } | ||||
|             })); | ||||
|     }, | ||||
|  | ||||
|     canSuspend: function(asyncCallback) { | ||||
| @@ -203,4 +253,4 @@ const LoginManagerDummy = new Lang.Class({ | ||||
|         callback(null); | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(LoginManagerDummy.prototype); | ||||
| Signals.addSignalMethods(LoginManagerConsoleKit.prototype); | ||||
|   | ||||
| @@ -129,7 +129,7 @@ function trySpawn(argv) | ||||
|     // Dummy child watch; we don't want to double-fork internally | ||||
|     // because then we lose the parent-child relationship, which | ||||
|     // can break polkit.  See https://bugzilla.redhat.com//show_bug.cgi?id=819275 | ||||
|     GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, function () {}); | ||||
|     GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, function () {}, null); | ||||
| } | ||||
|  | ||||
| // trySpawnCommandLine: | ||||
|   | ||||
| @@ -72,9 +72,6 @@ function run() { | ||||
|     Scripting.defineScriptEvent("applicationsShowStart", "Starting to switch to applications view"); | ||||
|     Scripting.defineScriptEvent("applicationsShowDone", "Done switching to applications view"); | ||||
|  | ||||
|     // Enable recording of timestamps for different points in the frame cycle | ||||
|     global.frame_timestamps = true; | ||||
|  | ||||
|     Main.overview.connect('shown', function() { | ||||
|                               Scripting.scriptEvent('overviewShowDone'); | ||||
|                           }); | ||||
| @@ -90,10 +87,7 @@ function run() { | ||||
|             yield Scripting.destroyTestWindows(); | ||||
|  | ||||
|             for (let k = 0; k < config.count; k++) | ||||
|                 yield Scripting.createTestWindow({ width: config.width, | ||||
|                                                    height: config.height, | ||||
|                                                    alpha: config.alpha, | ||||
|                                                    maximized: config.maximized }); | ||||
|                 yield Scripting.createTestWindow(config.width, config.height, config.alpha, config.maximized); | ||||
|  | ||||
|             yield Scripting.waitTestWindows(); | ||||
|             yield Scripting.sleep(1000); | ||||
|   | ||||
| @@ -1,308 +0,0 @@ | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const Gio = imports.gi.Gio; | ||||
| const Gtk = imports.gi.Gtk; | ||||
| const Meta = imports.gi.Meta; | ||||
| const Main = imports.ui.main; | ||||
| const Scripting = imports.ui.scripting; | ||||
| const Shell = imports.gi.Shell; | ||||
|  | ||||
| let METRICS = { | ||||
|     timeToDesktop: | ||||
|     { description: "Time from starting graphical.target to desktop showing", | ||||
|       units: "us" }, | ||||
|  | ||||
|     overviewShowTime: | ||||
|     { description: "Time to switch to overview view, first time", | ||||
|       units: "us" }, | ||||
|  | ||||
|     applicationsShowTime: | ||||
|     { description: "Time to switch to applications view, first time", | ||||
|       units: "us" }, | ||||
|  | ||||
|     mainViewRedrawTime: | ||||
|     { description: "Time to redraw the main view, full screen", | ||||
|       units: "us" }, | ||||
|  | ||||
|     overviewRedrawTime: | ||||
|     { description: "Time to redraw the overview, full screen, 5 windows", | ||||
|       units: "us" }, | ||||
|  | ||||
|     applicationRedrawTime: | ||||
|     { description: "Time to redraw frame with a maximized application update", | ||||
|       units: "us" }, | ||||
|  | ||||
|     geditStartTime: | ||||
|     { description: "Time from gedit launch to window drawn", | ||||
|       units: "us" }, | ||||
| } | ||||
|  | ||||
| function waitAndDraw(milliseconds) { | ||||
|     let cb; | ||||
|  | ||||
|     let timeline = new Clutter.Timeline({ duration: milliseconds }); | ||||
|     timeline.start(); | ||||
|  | ||||
|     timeline.connect('new-frame', | ||||
|         function(timeline, frame) { | ||||
|             global.stage.queue_redraw(); | ||||
|         }); | ||||
|  | ||||
|     timeline.connect('completed', | ||||
|         function() { | ||||
|             timeline.stop(); | ||||
|             if (cb) | ||||
|                 cb(); | ||||
|         }); | ||||
|  | ||||
|     return function(callback) { | ||||
|         cb = callback; | ||||
|     }; | ||||
| } | ||||
|  | ||||
| function waitSignal(object, signal) { | ||||
|     let cb; | ||||
|  | ||||
|     let id = object.connect(signal, function() { | ||||
|         object.disconnect(id); | ||||
|         if (cb) | ||||
|             cb(); | ||||
|     }); | ||||
|  | ||||
|     return function(callback) { | ||||
|         cb = callback; | ||||
|     }; | ||||
| } | ||||
|  | ||||
| function extractBootTimestamp() { | ||||
|     let sp = Gio.Subprocess.new(['journalctl', '-b', | ||||
|                                  'MESSAGE_ID=7d4958e842da4a758f6c1cdc7b36dcc5', | ||||
|                                  'UNIT=graphical.target', | ||||
|                                  '-o', | ||||
|                                  'json'], | ||||
|                                 Gio.SubprocessFlags.STDOUT_PIPE); | ||||
|     let result = null; | ||||
|  | ||||
|     let datastream = Gio.DataInputStream.new(sp.get_stdout_pipe()); | ||||
|     while (true) { | ||||
|         let [line, length] = datastream.read_line_utf8(null); | ||||
|         if (line === null) | ||||
|             break; | ||||
|  | ||||
|         let fields = JSON.parse(line); | ||||
|         result = Number(fields['__MONOTONIC_TIMESTAMP']); | ||||
|     } | ||||
|     datastream.close(null); | ||||
|     return result; | ||||
| } | ||||
|  | ||||
| function run() { | ||||
|     Scripting.defineScriptEvent("desktopShown", "Finished initial animation"); | ||||
|     Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview"); | ||||
|     Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing"); | ||||
|     Scripting.defineScriptEvent("applicationsShowStart", "Starting to switch to applications view"); | ||||
|     Scripting.defineScriptEvent("applicationsShowDone", "Done switching to applications view"); | ||||
|     Scripting.defineScriptEvent("mainViewDrawStart", "Drawing main view"); | ||||
|     Scripting.defineScriptEvent("mainViewDrawDone", "Ending timing main view drawing"); | ||||
|     Scripting.defineScriptEvent("overviewDrawStart", "Drawing overview"); | ||||
|     Scripting.defineScriptEvent("overviewDrawDone", "Ending timing overview drawing"); | ||||
|     Scripting.defineScriptEvent("redrawTestStart", "Drawing application window"); | ||||
|     Scripting.defineScriptEvent("redrawTestDone", "Ending timing application window drawing"); | ||||
|     Scripting.defineScriptEvent("collectTimings", "Accumulate frame timings from redraw tests"); | ||||
|     Scripting.defineScriptEvent("geditLaunch", "gedit application launch"); | ||||
|     Scripting.defineScriptEvent("geditFirstFrame", "first frame of gedit window drawn"); | ||||
|  | ||||
|     yield Scripting.waitLeisure(); | ||||
|     Scripting.scriptEvent('desktopShown'); | ||||
|  | ||||
|     Gtk.Settings.get_default().gtk_enable_animations = false; | ||||
|  | ||||
|     Scripting.scriptEvent('overviewShowStart'); | ||||
|     Main.overview.show(); | ||||
|     yield Scripting.waitLeisure(); | ||||
|     Scripting.scriptEvent('overviewShowDone'); | ||||
|  | ||||
|     yield Scripting.sleep(1000); | ||||
|  | ||||
|     Scripting.scriptEvent('applicationsShowStart'); | ||||
|     Main.overview._dash.showAppsButton.checked = true; | ||||
|  | ||||
|     yield Scripting.waitLeisure(); | ||||
|     Scripting.scriptEvent('applicationsShowDone'); | ||||
|  | ||||
|     yield Scripting.sleep(1000); | ||||
|  | ||||
|     Main.overview.hide(); | ||||
|     yield Scripting.waitLeisure(); | ||||
|  | ||||
|     //////////////////////////////////////// | ||||
|     // Tests of redraw speed | ||||
|     //////////////////////////////////////// | ||||
|  | ||||
|     global.frame_timestamps = true; | ||||
|     global.frame_finish_timestamp = true; | ||||
|  | ||||
|     for (let k = 0; k < 5; k++) | ||||
|         yield Scripting.createTestWindow(640, 480, | ||||
|                                          { maximized: true }); | ||||
|     yield Scripting.waitTestWindows(); | ||||
|  | ||||
|     yield Scripting.sleep(1000); | ||||
|  | ||||
|     Scripting.scriptEvent('mainViewDrawStart'); | ||||
|     yield waitAndDraw(1000); | ||||
|     Scripting.scriptEvent('mainViewDrawDone'); | ||||
|  | ||||
|     Main.overview.show(); | ||||
|     Scripting.waitLeisure(); | ||||
|  | ||||
|     yield Scripting.sleep(1500); | ||||
|  | ||||
|     Scripting.scriptEvent('overviewDrawStart'); | ||||
|     yield waitAndDraw(1000); | ||||
|     Scripting.scriptEvent('overviewDrawDone'); | ||||
|  | ||||
|     yield Scripting.destroyTestWindows(); | ||||
|     Main.overview.hide(); | ||||
|  | ||||
|     yield Scripting.createTestWindow(640, 480, | ||||
|                                      { maximized: true, | ||||
|                                        redraws: true}); | ||||
|     yield Scripting.waitTestWindows(); | ||||
|  | ||||
|     yield Scripting.sleep(1000); | ||||
|  | ||||
|     Scripting.scriptEvent('redrawTestStart'); | ||||
|     yield Scripting.sleep(1000); | ||||
|     Scripting.scriptEvent('redrawTestDone'); | ||||
|  | ||||
|     yield Scripting.sleep(1000); | ||||
|     Scripting.scriptEvent('collectTimings'); | ||||
|  | ||||
|     yield Scripting.destroyTestWindows(); | ||||
|  | ||||
|     global.frame_timestamps = false; | ||||
|     global.frame_finish_timestamp = false; | ||||
|  | ||||
|     yield Scripting.sleep(1000); | ||||
|  | ||||
|     //////////////////////////////////////// | ||||
|  | ||||
|     let appSys = Shell.AppSystem.get_default(); | ||||
|     let app = appSys.lookup_app('org.gnome.gedit.desktop'); | ||||
|  | ||||
|     Scripting.scriptEvent('geditLaunch'); | ||||
|     app.activate(); | ||||
|  | ||||
|     let windows = app.get_windows(); | ||||
|     if (windows.length > 0) | ||||
|         throw new Error('gedit was already running'); | ||||
|  | ||||
|     while (windows.length == 0) { | ||||
|         yield waitSignal(global.display, 'window-created'); | ||||
|         windows = app.get_windows(); | ||||
|     } | ||||
|  | ||||
|     let actor = windows[0].get_compositor_private(); | ||||
|     yield waitSignal(actor, 'first-frame'); | ||||
|     Scripting.scriptEvent('geditFirstFrame'); | ||||
|  | ||||
|     yield Scripting.sleep(1000); | ||||
|  | ||||
|     windows[0].delete(global.get_current_time()); | ||||
|  | ||||
|     yield Scripting.sleep(1000); | ||||
|  | ||||
|     Gtk.Settings.get_default().gtk_enable_animations = true; | ||||
| } | ||||
|  | ||||
| let overviewShowStart; | ||||
| let applicationsShowStart; | ||||
| let stagePaintStart; | ||||
| let redrawTiming; | ||||
| let redrawTimes = {}; | ||||
| let geditLaunchTime; | ||||
|  | ||||
| function script_desktopShown(time) { | ||||
|     let bootTimestamp = extractBootTimestamp(); | ||||
|     METRICS.timeToDesktop.value = time - bootTimestamp; | ||||
| } | ||||
|  | ||||
| function script_overviewShowStart(time) { | ||||
|     overviewShowStart = time; | ||||
| } | ||||
|  | ||||
| function script_overviewShowDone(time) { | ||||
|     METRICS.overviewShowTime.value = time - overviewShowStart; | ||||
| } | ||||
|  | ||||
| function script_applicationsShowStart(time) { | ||||
|     applicationsShowStart = time; | ||||
| } | ||||
|  | ||||
| function script_applicationsShowDone(time) { | ||||
|     METRICS.applicationsShowTime.value = time - applicationsShowStart; | ||||
| } | ||||
|  | ||||
| function script_mainViewDrawStart(time) { | ||||
|     redrawTiming = 'mainView'; | ||||
| } | ||||
|  | ||||
| function script_mainViewDrawDone(time) { | ||||
|     redrawTiming = null; | ||||
| } | ||||
|  | ||||
| function script_overviewDrawStart(time) { | ||||
|     redrawTiming = 'overview'; | ||||
| } | ||||
|  | ||||
| function script_overviewDrawDone(time) { | ||||
|     redrawTiming = null; | ||||
| } | ||||
|  | ||||
| function script_redrawTestStart(time) { | ||||
|     redrawTiming = 'application'; | ||||
| } | ||||
|  | ||||
| function script_redrawTestDone(time) { | ||||
|     redrawTiming = null; | ||||
| } | ||||
|  | ||||
| function script_collectTimings(time) { | ||||
|     for (let timing in redrawTimes) { | ||||
|         let times = redrawTimes[timing]; | ||||
|         times.sort(function(a, b) { return a - b }); | ||||
|  | ||||
|         let len = times.length; | ||||
|         let median; | ||||
|  | ||||
|         if (len == 0) | ||||
|             median = -1; | ||||
|         else if (len % 2 == 1) | ||||
|             median = times[(len - 1)/ 2]; | ||||
|         else | ||||
|             median = Math.round((times[len / 2 - 1] + times[len / 2]) / 2); | ||||
|  | ||||
|         METRICS[timing + 'RedrawTime'].value = median; | ||||
|     } | ||||
| } | ||||
|  | ||||
| function script_geditLaunch(time) { | ||||
|     geditLaunchTime = time; | ||||
| } | ||||
|  | ||||
| function script_geditFirstFrame(time) { | ||||
|     METRICS.geditStartTime.value = time - geditLaunchTime; | ||||
| } | ||||
|  | ||||
| function clutter_stagePaintStart(time) { | ||||
|     stagePaintStart = time; | ||||
| } | ||||
|  | ||||
| function clutter_paintCompletedTimestamp(time) { | ||||
|     if (redrawTiming != null && stagePaintStart != null) { | ||||
|         if (!(redrawTiming in redrawTimes)) | ||||
|             redrawTimes[redrawTiming] = []; | ||||
|         redrawTimes[redrawTiming].push(time - stagePaintStart); | ||||
|     } | ||||
|     stagePaintStart = null; | ||||
| } | ||||
| @@ -1,247 +0,0 @@ | ||||
| const Format = imports.format; | ||||
| const Gettext = imports.gettext; | ||||
| const GLib = imports.gi.GLib; | ||||
| const GObject = imports.gi.GObject; | ||||
| const Gio = imports.gi.Gio; | ||||
| const Gtk = imports.gi.Gtk; | ||||
| const Lang = imports.lang; | ||||
| const Pango = imports.gi.Pango; | ||||
| const Soup = imports.gi.Soup; | ||||
| const WebKit = imports.gi.WebKit2; | ||||
|  | ||||
| const _ = Gettext.gettext; | ||||
|  | ||||
| const Config = imports.misc.config; | ||||
|  | ||||
| const PortalHelperResult = { | ||||
|     CANCELLED: 0, | ||||
|     COMPLETED: 1, | ||||
|     RECHECK: 2 | ||||
| }; | ||||
|  | ||||
| const INACTIVITY_TIMEOUT = 30000; //ms | ||||
| const CONNECTIVITY_RECHECK_RATELIMIT_TIMEOUT = 30 * GLib.USEC_PER_SEC; | ||||
|  | ||||
| const HelperDBusInterface = '<node> \ | ||||
| <interface name="org.gnome.Shell.PortalHelper"> \ | ||||
| <method name="Authenticate"> \ | ||||
|     <arg type="o" direction="in" name="connection" /> \ | ||||
|     <arg type="s" direction="in" name="url" /> \ | ||||
|     <arg type="u" direction="in" name="timestamp" /> \ | ||||
| </method> \ | ||||
| <method name="Close"> \ | ||||
|     <arg type="o" direction="in" name="connection" /> \ | ||||
| </method> \ | ||||
| <method name="Refresh"> \ | ||||
|     <arg type="o" direction="in" name="connection" /> \ | ||||
| </method> \ | ||||
| <signal name="Done"> \ | ||||
|     <arg type="o" name="connection" /> \ | ||||
|     <arg type="u" name="result" /> \ | ||||
| </signal> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| const PortalWindow = new Lang.Class({ | ||||
|     Name: 'PortalWindow', | ||||
|     Extends: Gtk.ApplicationWindow, | ||||
|  | ||||
|     _init: function(application, url, timestamp, doneCallback) { | ||||
|         this.parent({ application: application }); | ||||
|  | ||||
|         if (!url) { | ||||
|             url = 'http://www.gnome.org'; | ||||
|             this._originalUrlWasGnome = true; | ||||
|         } else { | ||||
|             this._originalUrlWasGnome = false; | ||||
|         } | ||||
|         this._uri = new Soup.URI(url); | ||||
|         this._everSeenRedirect = false; | ||||
|         this._originalUrl = url; | ||||
|         this._doneCallback = doneCallback; | ||||
|         this._lastRecheck = 0; | ||||
|         this._recheckAtExit = false; | ||||
|  | ||||
|         this._webView = new WebKit.WebView(); | ||||
|         this._webView.connect('decide-policy', Lang.bind(this, this._onDecidePolicy)); | ||||
|         this._webView.load_uri(url); | ||||
|         this._webView.connect('notify::title', Lang.bind(this, this._syncTitle)); | ||||
|         this._syncTitle(); | ||||
|  | ||||
|         this.add(this._webView); | ||||
|         this._webView.show(); | ||||
|         this.maximize(); | ||||
|         this.present_with_time(timestamp); | ||||
|     }, | ||||
|  | ||||
|     _syncTitle: function() { | ||||
|         let title = this._webView.title; | ||||
|  | ||||
|         if (title) { | ||||
|             this.title = title; | ||||
|         } else { | ||||
|             // TRANSLATORS: this is the title of the wifi captive portal login | ||||
|             // window, until we know the title of the actual login page | ||||
|             this.title = _("Web Authentication Redirect"); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     refresh: function() { | ||||
|         this._everSeenRedirect = false; | ||||
|         this._webView.load_uri(this._originalUrl); | ||||
|     }, | ||||
|  | ||||
|     vfunc_delete_event: function(event) { | ||||
|         if (this._recheckAtExit) | ||||
|             this._doneCallback(PortalHelperResult.RECHECK); | ||||
|         else | ||||
|             this._doneCallback(PortalHelperResult.CANCELLED); | ||||
|         return false; | ||||
|     }, | ||||
|  | ||||
|     _onDecidePolicy: function(view, decision, type) { | ||||
|         if (type == WebKit.PolicyDecisionType.NEW_WINDOW_ACTION) { | ||||
|             decision.ignore(); | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         if (type != WebKit.PolicyDecisionType.NAVIGATION_ACTION) | ||||
|             return false; | ||||
|  | ||||
|         let request = decision.get_request(); | ||||
|         let uri = new Soup.URI(request.get_uri()); | ||||
|  | ||||
|         if (!uri.host_equal(this._uri) && this._originalUrlWasGnome) { | ||||
|             if (uri.get_host() == 'www.gnome.org' && this._everSeenRedirect) { | ||||
|                 // Yay, we got to gnome! | ||||
|                 decision.ignore(); | ||||
|                 this._doneCallback(PortalHelperResult.COMPLETED); | ||||
|                 return true; | ||||
|             } else if (uri.get_host() != 'www.gnome.org') { | ||||
|                 this._everSeenRedirect = true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // We *may* have finished here, but we don't know for | ||||
|         // sure. Tell gnome-shell to run another connectivity check | ||||
|         // (but ratelimit the checks, we don't want to spam | ||||
|         // nmcheck.gnome.org for portals that have 10 or more internal | ||||
|         // redirects - and unfortunately they exist) | ||||
|         // If we hit the rate limit, we also queue a recheck | ||||
|         // when the window is closed, just in case we miss the | ||||
|         // final check and don't realize we're connected | ||||
|         // This should not be a problem in the cancelled logic, | ||||
|         // because if the user doesn't want to start the login, | ||||
|         // we should not see any redirect at all, outside this._uri | ||||
|  | ||||
|         let now = GLib.get_monotonic_time(); | ||||
|         let shouldRecheck = (now - this._lastRecheck) > | ||||
|             CONNECTIVITY_RECHECK_RATELIMIT_TIMEOUT; | ||||
|  | ||||
|         if (shouldRecheck) { | ||||
|             this._lastRecheck = now; | ||||
|             this._recheckAtExit = false; | ||||
|             this._doneCallback(PortalHelperResult.RECHECK); | ||||
|         } else { | ||||
|             this._recheckAtExit = true; | ||||
|         } | ||||
|  | ||||
|         // Update the URI, in case of chained redirects, so we still | ||||
|         // think we're doing the login until gnome-shell kills us | ||||
|         this._uri = uri; | ||||
|  | ||||
|         decision.use(); | ||||
|         return true; | ||||
|     }, | ||||
| }); | ||||
|  | ||||
| const WebPortalHelper = new Lang.Class({ | ||||
|     Name: 'WebPortalHelper', | ||||
|     Extends: Gtk.Application, | ||||
|  | ||||
|     _init: function() { | ||||
|         this.parent({ application_id: 'org.gnome.Shell.PortalHelper', | ||||
|                       flags: Gio.ApplicationFlags.IS_SERVICE, | ||||
|                       inactivity_timeout: 30000 }); | ||||
|  | ||||
|         this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(HelperDBusInterface, this); | ||||
|         this._queue = []; | ||||
|     }, | ||||
|  | ||||
|     vfunc_dbus_register: function(connection, path) { | ||||
|         this._dbusImpl.export(connection, path); | ||||
|         this.parent(connection, path); | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     vfunc_dbus_unregister: function(connection, path) { | ||||
|         this._dbusImpl.unexport_from_connection(connection); | ||||
|         this.parent(connection, path); | ||||
|     }, | ||||
|  | ||||
|     vfunc_activate: function() { | ||||
|         // If launched manually (for example for testing), force a dummy authentication | ||||
|         // session with the default url | ||||
|         this.Authenticate('/org/gnome/dummy', '', 0); | ||||
|     }, | ||||
|  | ||||
|     Authenticate: function(connection, url, timestamp) { | ||||
|         this._queue.push({ connection: connection, url: url, timestamp: timestamp }); | ||||
|  | ||||
|         this._processQueue(); | ||||
|     }, | ||||
|  | ||||
|     Close: function(connection) { | ||||
|         for (let i = 0; i < this._queue.length; i++) { | ||||
|             let obj = this._queue[i]; | ||||
|  | ||||
|             if (obj.connection == connection) { | ||||
|                 if (obj.window) | ||||
|                     obj.window.destroy(); | ||||
|                 this._queue.splice(i, 1); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         this._processQueue(); | ||||
|     }, | ||||
|  | ||||
|     Refresh: function(connection) { | ||||
|         for (let i = 0; i < this._queue.length; i++) { | ||||
|             let obj = this._queue[i]; | ||||
|  | ||||
|             if (obj.connection == connection) { | ||||
|                 if (obj.window) | ||||
|                     obj.window.refresh(); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _processQueue: function() { | ||||
|         if (this._queue.length == 0) | ||||
|             return; | ||||
|  | ||||
|         let top = this._queue[0]; | ||||
|         if (top.window != null) | ||||
|             return; | ||||
|  | ||||
|         top.window = new PortalWindow(this, top.uri, top.timestamp, Lang.bind(this, function(result) { | ||||
|             this._dbusImpl.emit_signal('Done', new GLib.Variant('(ou)', [top.connection, result])); | ||||
|         })); | ||||
|     }, | ||||
| }); | ||||
|  | ||||
| function initEnvironment() { | ||||
|     String.prototype.format = Format.format; | ||||
| } | ||||
|  | ||||
| function main(argv) { | ||||
|     initEnvironment(); | ||||
|  | ||||
|     Gettext.bindtextdomain(Config.GETTEXT_PACKAGE, Config.LOCALEDIR); | ||||
|     Gettext.textdomain(Config.GETTEXT_PACKAGE); | ||||
|  | ||||
|     let app = new WebPortalHelper(); | ||||
|     return app.run(argv); | ||||
| } | ||||
| @@ -24,7 +24,7 @@ const WINDOW_PREVIEW_SIZE = 128; | ||||
| const APP_ICON_SIZE = 96; | ||||
| const APP_ICON_SIZE_SMALL = 48; | ||||
|  | ||||
| const baseIconSizes = [96, 64, 48, 32, 22]; | ||||
| const iconSizes = [96, 64, 48, 32, 22]; | ||||
|  | ||||
| const AppIconMode = { | ||||
|     THUMBNAIL_ONLY: 1, | ||||
| @@ -151,13 +151,13 @@ const AppSwitcherPopup = new Lang.Class({ | ||||
|                                  this._items[this._selectedIndex].cachedWindows.length); | ||||
|     }, | ||||
|  | ||||
|     _keyPressHandler: function(keysym, action) { | ||||
|     _keyPressHandler: function(keysym, backwards, action) { | ||||
|         if (action == Meta.KeyBindingAction.SWITCH_GROUP) { | ||||
|             this._select(this._selectedIndex, this._nextWindow()); | ||||
|             this._select(this._selectedIndex, backwards ? this._previousWindow() : this._nextWindow()); | ||||
|         } else if (action == Meta.KeyBindingAction.SWITCH_GROUP_BACKWARD) { | ||||
|             this._select(this._selectedIndex, this._previousWindow()); | ||||
|         } else if (action == Meta.KeyBindingAction.SWITCH_APPLICATIONS) { | ||||
|             this._select(this._next()); | ||||
|             this._select(backwards ? this._previous() : this._next()); | ||||
|         } else if (action == Meta.KeyBindingAction.SWITCH_APPLICATIONS_BACKWARD) { | ||||
|             this._select(this._previous()); | ||||
|         } else if (this._thumbnailsFocused) { | ||||
| @@ -167,8 +167,6 @@ const AppSwitcherPopup = new Lang.Class({ | ||||
|                 this._select(this._selectedIndex, this._nextWindow()); | ||||
|             else if (keysym == Clutter.Up) | ||||
|                 this._select(this._selectedIndex, null, true); | ||||
|             else | ||||
|                 return Clutter.EVENT_PROPAGATE; | ||||
|         } else { | ||||
|             if (keysym == Clutter.Left) | ||||
|                 this._select(this._previous()); | ||||
| @@ -176,11 +174,7 @@ const AppSwitcherPopup = new Lang.Class({ | ||||
|                 this._select(this._next()); | ||||
|             else if (keysym == Clutter.Down) | ||||
|                 this._select(this._selectedIndex, 0); | ||||
|             else | ||||
|                 return Clutter.EVENT_PROPAGATE; | ||||
|         } | ||||
|  | ||||
|         return Clutter.EVENT_STOP; | ||||
|     }, | ||||
|  | ||||
|     _scrollHandler: function(direction) { | ||||
| @@ -311,7 +305,6 @@ const AppSwitcherPopup = new Lang.Class({ | ||||
|             this._thumbnailTimeoutId = Mainloop.timeout_add ( | ||||
|                 THUMBNAIL_POPUP_TIME, | ||||
|                 Lang.bind(this, this._timeoutPopupThumbnails)); | ||||
|             GLib.Source.set_name_by_id(this._thumbnailTimeoutId, '[gnome-shell] this._timeoutPopupThumbnails'); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
| @@ -367,12 +360,12 @@ const WindowSwitcherPopup = new Lang.Class({ | ||||
|  | ||||
|     _init: function(items) { | ||||
|         this.parent(items); | ||||
|         this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' }); | ||||
|         this._settings = new Gio.Settings({ schema: 'org.gnome.shell.window-switcher' }); | ||||
|     }, | ||||
|  | ||||
|     _getWindowList: function() { | ||||
|         let workspace = this._settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace() : null; | ||||
|         return global.display.get_tab_list(Meta.TabList.NORMAL, workspace); | ||||
|         return global.display.get_tab_list(Meta.TabList.NORMAL, global.screen, workspace); | ||||
|     }, | ||||
|  | ||||
|     _createSwitcher: function() { | ||||
| @@ -400,9 +393,9 @@ const WindowSwitcherPopup = new Lang.Class({ | ||||
|             this._select(1); | ||||
|     }, | ||||
|  | ||||
|     _keyPressHandler: function(keysym, action) { | ||||
|     _keyPressHandler: function(keysym, backwards, action) { | ||||
|         if (action == Meta.KeyBindingAction.SWITCH_WINDOWS) { | ||||
|             this._select(this._next()); | ||||
|             this._select(backwards ? this._previous() : this._next()); | ||||
|         } else if (action == Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD) { | ||||
|             this._select(this._previous()); | ||||
|         } else { | ||||
| @@ -410,11 +403,7 @@ const WindowSwitcherPopup = new Lang.Class({ | ||||
|                 this._select(this._previous()); | ||||
|             else if (keysym == Clutter.Right) | ||||
|                 this._select(this._next()); | ||||
|             else | ||||
|                 return Clutter.EVENT_PROPAGATE; | ||||
|         } | ||||
|  | ||||
|         return Clutter.EVENT_STOP; | ||||
|     }, | ||||
|  | ||||
|     _finish: function() { | ||||
| @@ -441,6 +430,7 @@ const AppIcon = new Lang.Class({ | ||||
|  | ||||
|     set_size: function(size) { | ||||
|         this.icon = this.app.create_icon_texture(size); | ||||
|         this._iconBin.set_size(size, size); | ||||
|         this._iconBin.child = this.icon; | ||||
|     } | ||||
| }); | ||||
| @@ -456,10 +446,11 @@ const AppSwitcher = new Lang.Class({ | ||||
|         this._arrows = []; | ||||
|  | ||||
|         let windowTracker = Shell.WindowTracker.get_default(); | ||||
|         let settings = new Gio.Settings({ schema_id: 'org.gnome.shell.app-switcher' }); | ||||
|         let settings = new Gio.Settings({ schema: 'org.gnome.shell.app-switcher' }); | ||||
|         let workspace = settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace() | ||||
|                                                                        : null; | ||||
|         let allWindows = global.display.get_tab_list(Meta.TabList.NORMAL, workspace); | ||||
|         let allWindows = global.display.get_tab_list(Meta.TabList.NORMAL, | ||||
|                                                      global.screen, workspace); | ||||
|  | ||||
|         // Construct the AppIcons, add to the popup | ||||
|         for (let i = 0; i < apps.length; i++) { | ||||
| @@ -488,13 +479,12 @@ const AppSwitcher = new Lang.Class({ | ||||
|             Mainloop.source_remove(this._mouseTimeOutId); | ||||
|     }, | ||||
|  | ||||
|     _setIconSize: function() { | ||||
|     _getPreferredHeight: function (actor, forWidth, alloc) { | ||||
|         let j = 0; | ||||
|         while(this._items.length > 1 && this._items[j].style_class != 'item-box') { | ||||
|                 j++; | ||||
|         } | ||||
|         let themeNode = this._items[j].get_theme_node(); | ||||
|  | ||||
|         let iconPadding = themeNode.get_horizontal_padding(); | ||||
|         let iconBorder = themeNode.get_border_width(St.Side.LEFT) + themeNode.get_border_width(St.Side.RIGHT); | ||||
|         let [iconMinHeight, iconNaturalHeight] = this.icons[j].label.get_preferred_height(-1); | ||||
| @@ -505,22 +495,19 @@ const AppSwitcher = new Lang.Class({ | ||||
|         let primary = Main.layoutManager.primaryMonitor; | ||||
|         let parentPadding = this.actor.get_parent().get_theme_node().get_horizontal_padding(); | ||||
|         let availWidth = primary.width - parentPadding - this.actor.get_theme_node().get_horizontal_padding(); | ||||
|         let height = 0; | ||||
|  | ||||
|         let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; | ||||
|         let iconSizes = baseIconSizes.map(function(s) { | ||||
|             return s * scaleFactor; | ||||
|         }); | ||||
|  | ||||
|         if (this._items.length == 1) { | ||||
|             this._iconSize = baseIconSizes[0]; | ||||
|         } else { | ||||
|             for(let i =  0; i < baseIconSizes.length; i++) { | ||||
|                 this._iconSize = baseIconSizes[i]; | ||||
|                 let height = iconSizes[i] + iconSpacing; | ||||
|         for(let i =  0; i < iconSizes.length; i++) { | ||||
|                 this._iconSize = iconSizes[i]; | ||||
|                 height = iconSizes[i] + iconSpacing; | ||||
|                 let w = height * this._items.length + totalSpacing; | ||||
|                 if (w <= availWidth) | ||||
|                     break; | ||||
|             } | ||||
|                         break; | ||||
|         } | ||||
|  | ||||
|         if (this._items.length == 1) { | ||||
|             this._iconSize = iconSizes[0]; | ||||
|             height = iconSizes[0] + iconSpacing; | ||||
|         } | ||||
|  | ||||
|         for(let i = 0; i < this.icons.length; i++) { | ||||
| @@ -528,11 +515,9 @@ const AppSwitcher = new Lang.Class({ | ||||
|                 break; | ||||
|             this.icons[i].set_size(this._iconSize); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _getPreferredHeight: function (actor, forWidth, alloc) { | ||||
|         this._setIconSize(); | ||||
|         this.parent(actor, forWidth, alloc); | ||||
|         alloc.min_size = height; | ||||
|         alloc.natural_size = height; | ||||
|     }, | ||||
|  | ||||
|     _allocate: function (actor, box, flags) { | ||||
| @@ -566,7 +551,6 @@ const AppSwitcher = new Lang.Class({ | ||||
|                                                                             this._mouseTimeOutId = 0; | ||||
|                                                                             return GLib.SOURCE_REMOVE; | ||||
|                                                         })); | ||||
|             GLib.Source.set_name_by_id(this._mouseTimeOutId, '[gnome-shell] this._enterItem'); | ||||
|         } else | ||||
|            this._itemEntered(index); | ||||
|     }, | ||||
| @@ -666,19 +650,17 @@ const ThumbnailList = new Lang.Class({ | ||||
|         totalPadding += this.actor.get_theme_node().get_horizontal_padding() + this.actor.get_theme_node().get_vertical_padding(); | ||||
|         let [labelMinHeight, labelNaturalHeight] = this._labels[0].get_preferred_height(-1); | ||||
|         let spacing = this._items[0].child.get_theme_node().get_length('spacing'); | ||||
|         let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; | ||||
|         let thumbnailSize = THUMBNAIL_DEFAULT_SIZE * scaleFactor; | ||||
|  | ||||
|         availHeight = Math.min(availHeight - labelNaturalHeight - totalPadding - spacing, thumbnailSize); | ||||
|         availHeight = Math.min(availHeight - labelNaturalHeight - totalPadding - spacing, THUMBNAIL_DEFAULT_SIZE); | ||||
|         let binHeight = availHeight + this._items[0].get_theme_node().get_vertical_padding() + this.actor.get_theme_node().get_vertical_padding() - spacing; | ||||
|         binHeight = Math.min(thumbnailSize, binHeight); | ||||
|         binHeight = Math.min(THUMBNAIL_DEFAULT_SIZE, binHeight); | ||||
|  | ||||
|         for (let i = 0; i < this._thumbnailBins.length; i++) { | ||||
|             let mutterWindow = this._windows[i].get_compositor_private(); | ||||
|             if (!mutterWindow) | ||||
|                 continue; | ||||
|  | ||||
|             let clone = _createWindowClone(mutterWindow, thumbnailSize); | ||||
|             let clone = _createWindowClone(mutterWindow, THUMBNAIL_DEFAULT_SIZE); | ||||
|             this._thumbnailBins[i].set_height(binHeight); | ||||
|             this._thumbnailBins[i].add_actor(clone); | ||||
|             this._clones.push(clone); | ||||
|   | ||||
| @@ -21,9 +21,7 @@ const Animation = new Lang.Class({ | ||||
|         this._isPlaying = false; | ||||
|         this._timeoutId = 0; | ||||
|         this._frame = 0; | ||||
|  | ||||
|         let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; | ||||
|         this._animations = St.TextureCache.get_default().load_sliced_image (filename, width, height, scaleFactor, | ||||
|         this._animations = St.TextureCache.get_default().load_sliced_image (filename, width, height, | ||||
|                                                                             Lang.bind(this, this._animationsLoaded)); | ||||
|         this.actor.set_child(this._animations); | ||||
|     }, | ||||
| @@ -34,7 +32,6 @@ const Animation = new Lang.Class({ | ||||
|                 this._showFrame(0); | ||||
|  | ||||
|             this._timeoutId = Mainloop.timeout_add(this._speed, Lang.bind(this, this._update)); | ||||
|             GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] this._update'); | ||||
|         } | ||||
|  | ||||
|         this._isPlaying = true; | ||||
|   | ||||
| @@ -16,7 +16,6 @@ const Atk = imports.gi.Atk; | ||||
| const AppFavorites = imports.ui.appFavorites; | ||||
| const BoxPointer = imports.ui.boxpointer; | ||||
| const DND = imports.ui.dnd; | ||||
| const GrabHelper = imports.ui.grabHelper; | ||||
| const IconGrid = imports.ui.iconGrid; | ||||
| const Main = imports.ui.main; | ||||
| const Overview = imports.ui.overview; | ||||
| @@ -34,9 +33,7 @@ const MIN_COLUMNS = 4; | ||||
| const MIN_ROWS = 4; | ||||
|  | ||||
| const INACTIVE_GRID_OPACITY = 77; | ||||
| // This time needs to be less than IconGrid.EXTRA_SPACE_ANIMATION_TIME | ||||
| // to not clash with other animations | ||||
| const INACTIVE_GRID_OPACITY_ANIMATION_TIME = 0.24; | ||||
| const INACTIVE_GRID_OPACITY_ANIMATION_TIME = 0.40; | ||||
| const FOLDER_SUBICON_FRACTION = .4; | ||||
|  | ||||
| const MIN_FREQUENT_APPS_COUNT = 3; | ||||
| @@ -44,22 +41,11 @@ const MIN_FREQUENT_APPS_COUNT = 3; | ||||
| const INDICATORS_BASE_TIME = 0.25; | ||||
| const INDICATORS_ANIMATION_DELAY = 0.125; | ||||
| const INDICATORS_ANIMATION_MAX_TIME = 0.75; | ||||
|  | ||||
| // Follow iconGrid animations approach and divide by 2 to animate out to | ||||
| // not annoy the user when the user wants to quit appDisplay. | ||||
| // Also, make sure we don't exceed iconGrid animation total time or | ||||
| // views switch time. | ||||
| const INDICATORS_BASE_TIME_OUT = 0.125; | ||||
| const INDICATORS_ANIMATION_DELAY_OUT = 0.0625; | ||||
| const INDICATORS_ANIMATION_MAX_TIME_OUT = | ||||
|     Math.min (VIEWS_SWITCH_TIME, | ||||
|               IconGrid.ANIMATION_TIME_OUT + IconGrid.ANIMATION_MAX_DELAY_OUT_FOR_ITEM); | ||||
|  | ||||
| // Fraction of page height the finger or mouse must reach | ||||
| // to change page | ||||
| const PAGE_SWITCH_TRESHOLD = 0.2; | ||||
| const PAGE_SWITCH_TIME = 0.3; | ||||
|  | ||||
| const VIEWS_SWITCH_TIME = 0.4; | ||||
| const VIEWS_SWITCH_ANIMATION_DELAY = 0.1; | ||||
|  | ||||
| function _getCategories(info) { | ||||
|     let categoriesStr = info.get_categories(); | ||||
|     if (!categoriesStr) | ||||
| @@ -67,6 +53,14 @@ function _getCategories(info) { | ||||
|     return categoriesStr.split(';'); | ||||
| } | ||||
|  | ||||
| function _isTerminal(app) { | ||||
|     let info = app.get_app_info(); | ||||
|     if (!info) | ||||
|         return false; | ||||
|     let categories = _getCategories(info); | ||||
|     return categories.indexOf('TerminalEmulator') > -1; | ||||
| } | ||||
|  | ||||
| function _listsIntersect(a, b) { | ||||
|     for (let itemA of a) | ||||
|         if (b.indexOf(itemA) >= 0) | ||||
| @@ -92,10 +86,6 @@ function _getFolderName(folder) { | ||||
|     return name; | ||||
| } | ||||
|  | ||||
| function clamp(value, min, max) { | ||||
|     return Math.max(min, Math.min(max, value)); | ||||
| } | ||||
|  | ||||
| const BaseAppView = new Lang.Class({ | ||||
|     Name: 'BaseAppView', | ||||
|     Abstract: true, | ||||
| @@ -114,9 +104,6 @@ const BaseAppView = new Lang.Class({ | ||||
|         else | ||||
|             this._grid = new IconGrid.IconGrid(gridParams); | ||||
|  | ||||
|         this._grid.connect('key-focus-in', Lang.bind(this, function(grid, actor) { | ||||
|             this._keyFocusIn(actor); | ||||
|         })); | ||||
|         // Standard hack for ClutterBinLayout | ||||
|         this._grid.actor.x_expand = true; | ||||
|  | ||||
| @@ -124,10 +111,6 @@ const BaseAppView = new Lang.Class({ | ||||
|         this._allItems = []; | ||||
|     }, | ||||
|  | ||||
|     _keyFocusIn: function(actor) { | ||||
|         // Nothing by default | ||||
|     }, | ||||
|  | ||||
|     removeAll: function() { | ||||
|         this._grid.destroyAll(); | ||||
|         this._items = {}; | ||||
| @@ -189,98 +172,26 @@ const BaseAppView = new Lang.Class({ | ||||
|                 this.selectApp(id); | ||||
|             })); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _doSpringAnimation: function(animationDirection) { | ||||
|         this._grid.actor.opacity = 255; | ||||
|         this._grid.animateSpring(animationDirection, | ||||
|                                  Main.overview.getShowAppsButton()); | ||||
|     }, | ||||
|  | ||||
|     animate: function(animationDirection, onComplete) { | ||||
|         if (animationDirection == IconGrid.AnimationDirection.IN) { | ||||
|             let toAnimate = this._grid.actor.connect('notify::allocation', Lang.bind(this, | ||||
|                 function() { | ||||
|                     this._grid.actor.disconnect(toAnimate); | ||||
|                     // We need to hide the grid temporary to not flash it | ||||
|                     // for a frame | ||||
|                     this._grid.actor.opacity = 0; | ||||
|                     Meta.later_add(Meta.LaterType.BEFORE_REDRAW, | ||||
|                                    Lang.bind(this, function() { | ||||
|                                        this._doSpringAnimation(animationDirection) | ||||
|                                   })); | ||||
|                 })); | ||||
|         } else { | ||||
|             this._doSpringAnimation(animationDirection); | ||||
|         } | ||||
|  | ||||
|         if (onComplete) { | ||||
|             let animationDoneId = this._grid.connect('animation-done', Lang.bind(this, | ||||
|                 function () { | ||||
|                     this._grid.disconnect(animationDoneId); | ||||
|                     onComplete(); | ||||
|             })); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     animateSwitch: function(animationDirection) { | ||||
|         Tweener.removeTweens(this.actor); | ||||
|         Tweener.removeTweens(this._grid.actor); | ||||
|  | ||||
|         let params = { time: VIEWS_SWITCH_TIME, | ||||
|                        transition: 'easeOutQuad' }; | ||||
|         if (animationDirection == IconGrid.AnimationDirection.IN) { | ||||
|             this.actor.show(); | ||||
|             params.opacity = 255; | ||||
|             params.delay = VIEWS_SWITCH_ANIMATION_DELAY; | ||||
|         } else { | ||||
|             params.opacity = 0; | ||||
|             params.delay = 0; | ||||
|             params.onComplete = Lang.bind(this, function() { this.actor.hide() }); | ||||
|         } | ||||
|  | ||||
|         Tweener.addTween(this._grid.actor, params); | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(BaseAppView.prototype); | ||||
|  | ||||
| const PageIndicatorsActor = new Lang.Class({ | ||||
|     Name:'PageIndicatorsActor', | ||||
|     Extends: St.BoxLayout, | ||||
|  | ||||
|     _init: function() { | ||||
|         this.parent({ style_class: 'page-indicators', | ||||
|                       vertical: true, | ||||
|                       x_expand: true, y_expand: true, | ||||
|                       x_align: Clutter.ActorAlign.END, | ||||
|                       y_align: Clutter.ActorAlign.CENTER, | ||||
|                       reactive: true, | ||||
|                       clip_to_allocation: true }); | ||||
|     }, | ||||
|  | ||||
|     vfunc_get_preferred_height: function(forWidth) { | ||||
|         // We want to request the natural height of all our children as our | ||||
|         // natural height, so we chain up to St.BoxLayout, but we only request 0 | ||||
|         // as minimum height, since it's not that important if some indicators | ||||
|         // are not shown | ||||
|         let [, natHeight] = this.parent(forWidth); | ||||
|         return [0, natHeight]; | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const PageIndicators = new Lang.Class({ | ||||
|     Name:'PageIndicators', | ||||
|  | ||||
|     _init: function() { | ||||
|         this.actor = new PageIndicatorsActor(); | ||||
|         this.actor = new St.BoxLayout({ style_class: 'page-indicators', | ||||
|                                         vertical: true, | ||||
|                                         x_expand: true, y_expand: true, | ||||
|                                         x_align: Clutter.ActorAlign.END, | ||||
|                                         y_align: Clutter.ActorAlign.CENTER, | ||||
|                                         reactive: true }); | ||||
|         this._nPages = 0; | ||||
|         this._currentPage = undefined; | ||||
|  | ||||
|         this.actor.connect('notify::mapped', | ||||
|                            Lang.bind(this, function() { | ||||
|                                this.animateIndicators(IconGrid.AnimationDirection.IN); | ||||
|                            }) | ||||
|                           ); | ||||
|                            Lang.bind(this, this._animateIndicators)); | ||||
|     }, | ||||
|  | ||||
|     setNPages: function(nPages) { | ||||
| @@ -321,7 +232,7 @@ const PageIndicators = new Lang.Class({ | ||||
|             children[i].set_checked(i == this._currentPage); | ||||
|     }, | ||||
|  | ||||
|     animateIndicators: function(animationDirection) { | ||||
|     _animateIndicators: function() { | ||||
|         if (!this.actor.mapped) | ||||
|             return; | ||||
|  | ||||
| @@ -329,32 +240,23 @@ const PageIndicators = new Lang.Class({ | ||||
|         if (children.length == 0) | ||||
|             return; | ||||
|  | ||||
|         for (let i = 0; i < this._nPages; i++) | ||||
|             Tweener.removeTweens(children[i]); | ||||
|  | ||||
|         let offset; | ||||
|         if (this.actor.get_text_direction() == Clutter.TextDirection.RTL) | ||||
|             offset = -children[0].width; | ||||
|         else | ||||
|             offset = children[0].width; | ||||
|  | ||||
|         let isAnimationIn = animationDirection == IconGrid.AnimationDirection.IN; | ||||
|         let delay = isAnimationIn ? INDICATORS_ANIMATION_DELAY : | ||||
|                                     INDICATORS_ANIMATION_DELAY_OUT; | ||||
|         let baseTime = isAnimationIn ? INDICATORS_BASE_TIME : INDICATORS_BASE_TIME_OUT; | ||||
|         let totalAnimationTime = baseTime + delay * this._nPages; | ||||
|         let maxTime = isAnimationIn ? INDICATORS_ANIMATION_MAX_TIME : | ||||
|                                       INDICATORS_ANIMATION_MAX_TIME_OUT; | ||||
|         if (totalAnimationTime > maxTime) | ||||
|             delay -= (totalAnimationTime - maxTime) / this._nPages; | ||||
|         let delay = INDICATORS_ANIMATION_DELAY; | ||||
|         let totalAnimationTime = INDICATORS_BASE_TIME + INDICATORS_ANIMATION_DELAY * this._nPages; | ||||
|         if (totalAnimationTime > INDICATORS_ANIMATION_MAX_TIME) | ||||
|             delay -= (totalAnimationTime - INDICATORS_ANIMATION_MAX_TIME) / this._nPages; | ||||
|  | ||||
|         for (let i = 0; i < this._nPages; i++) { | ||||
|             children[i].translation_x = isAnimationIn ? offset : 0; | ||||
|             children[i].translation_x = offset; | ||||
|             Tweener.addTween(children[i], | ||||
|                              { translation_x: isAnimationIn ? 0 : offset, | ||||
|                                time: baseTime + delay * i, | ||||
|                                transition: 'easeInOutQuad', | ||||
|                                delay: isAnimationIn ? VIEWS_SWITCH_ANIMATION_DELAY : 0 | ||||
|                              { translation_x: 0, | ||||
|                                time: INDICATORS_BASE_TIME + delay * i, | ||||
|                                transition: 'easeInOutQuad' | ||||
|                              }); | ||||
|         } | ||||
|     } | ||||
| @@ -397,7 +299,7 @@ const AllView = new Lang.Class({ | ||||
|         this._stack = new St.Widget({ layout_manager: new Clutter.BinLayout() }); | ||||
|         let box = new St.BoxLayout({ vertical: true }); | ||||
|  | ||||
|         this._grid.currentPage = 0; | ||||
|         this._currentPage = 0; | ||||
|         this._stack.add_actor(this._grid.actor); | ||||
|         this._eventBlocker = new St.Widget({ x_expand: true, y_expand: true }); | ||||
|         this._stack.add_actor(this._eventBlocker); | ||||
| @@ -463,7 +365,7 @@ const AllView = new Lang.Class({ | ||||
|         Shell.AppSystem.get_default().connect('installed-changed', Lang.bind(this, function() { | ||||
|             Main.queueDeferredWork(this._redisplayWorkId); | ||||
|         })); | ||||
|         this._folderSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.app-folders' }); | ||||
|         this._folderSettings = new Gio.Settings({ schema: 'org.gnome.desktop.app-folders' }); | ||||
|         this._folderSettings.connect('changed::folder-children', Lang.bind(this, function() { | ||||
|             Main.queueDeferredWork(this._redisplayWorkId); | ||||
|         })); | ||||
| @@ -529,52 +431,14 @@ const AllView = new Lang.Class({ | ||||
|         this._refilterApps(); | ||||
|     }, | ||||
|  | ||||
|     // Overriden from BaseAppView | ||||
|     animate: function (animationDirection, onComplete) { | ||||
|         if (animationDirection == IconGrid.AnimationDirection.OUT && | ||||
|             this._displayingPopup && this._currentPopup) { | ||||
|             this._currentPopup.popdown(); | ||||
|             let spaceClosedId = this._grid.connect('space-closed', Lang.bind(this, | ||||
|                 function() { | ||||
|                     this._grid.disconnect(spaceClosedId); | ||||
|                     // Given that we can't call this.parent() inside the | ||||
|                     // signal handler, call again animate which will | ||||
|                     // call the parent given that popup is already | ||||
|                     // closed. | ||||
|                     this.animate(animationDirection, onComplete); | ||||
|                 })); | ||||
|         } else { | ||||
|             this.parent(animationDirection, onComplete); | ||||
|             if (animationDirection == IconGrid.AnimationDirection.OUT) | ||||
|                 this._pageIndicators.animateIndicators(animationDirection); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     animateSwitch: function(animationDirection) { | ||||
|         this.parent(animationDirection); | ||||
|  | ||||
|         if (this._currentPopup && this._displayingPopup && | ||||
|             animationDirection == IconGrid.AnimationDirection.OUT) | ||||
|             Tweener.addTween(this._currentPopup.actor, | ||||
|                              { time: VIEWS_SWITCH_TIME, | ||||
|                                transition: 'easeOutQuad', | ||||
|                                opacity: 0, | ||||
|                                onComplete: function() { | ||||
|                                   this.opacity = 255; | ||||
|                                } }); | ||||
|  | ||||
|         if (animationDirection == IconGrid.AnimationDirection.OUT) | ||||
|             this._pageIndicators.animateIndicators(animationDirection); | ||||
|     }, | ||||
|  | ||||
|     getCurrentPageY: function() { | ||||
|         return this._grid.getPageY(this._grid.currentPage); | ||||
|         return this._grid.getPageY(this._currentPage); | ||||
|     }, | ||||
|  | ||||
|     goToPage: function(pageNumber) { | ||||
|         pageNumber = clamp(pageNumber, 0, this._grid.nPages() - 1); | ||||
|  | ||||
|         if (this._grid.currentPage == pageNumber && this._displayingPopup && this._currentPopup) | ||||
|         if(pageNumber < 0 || pageNumber > this._grid.nPages() - 1) | ||||
|             return; | ||||
|         if (this._currentPage == pageNumber && this._displayingPopup && this._currentPopup) | ||||
|             return; | ||||
|         if (this._displayingPopup && this._currentPopup) | ||||
|             this._currentPopup.popdown(); | ||||
| @@ -594,7 +458,7 @@ const AllView = new Lang.Class({ | ||||
|         let time; | ||||
|         // Only take the velocity into account on page changes, otherwise | ||||
|         // return smoothly to the current page using the default velocity | ||||
|         if (this._grid.currentPage != pageNumber) { | ||||
|         if (this._currentPage != pageNumber) { | ||||
|             let minVelocity = totalHeight / (PAGE_SWITCH_TIME * 1000); | ||||
|             velocity = Math.max(minVelocity, velocity); | ||||
|             time = (diffToPage / velocity) / 1000; | ||||
| @@ -605,12 +469,14 @@ const AllView = new Lang.Class({ | ||||
|         // longer than PAGE_SWITCH_TIME | ||||
|         time = Math.min(time, PAGE_SWITCH_TIME); | ||||
|  | ||||
|         this._grid.currentPage = pageNumber; | ||||
|         Tweener.addTween(this._adjustment, | ||||
|                          { value: this._grid.getPageY(this._grid.currentPage), | ||||
|                            time: time, | ||||
|                            transition: 'easeOutQuad' }); | ||||
|         this._pageIndicators.setCurrentPage(pageNumber); | ||||
|         if (pageNumber < this._grid.nPages() && pageNumber >= 0) { | ||||
|             this._currentPage = pageNumber; | ||||
|             Tweener.addTween(this._adjustment, | ||||
|                              { value: this._grid.getPageY(this._currentPage), | ||||
|                                time: time, | ||||
|                                transition: 'easeOutQuad' }); | ||||
|             this._pageIndicators.setCurrentPage(pageNumber); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _diffToPage: function (pageNumber) { | ||||
| @@ -636,9 +502,9 @@ const AllView = new Lang.Class({ | ||||
|  | ||||
|         let direction = event.get_scroll_direction(); | ||||
|         if (direction == Clutter.ScrollDirection.UP) | ||||
|             this.goToPage(this._grid.currentPage - 1); | ||||
|             this.goToPage(this._currentPage - 1); | ||||
|         else if (direction == Clutter.ScrollDirection.DOWN) | ||||
|             this.goToPage(this._grid.currentPage + 1); | ||||
|             this.goToPage(this._currentPage + 1); | ||||
|  | ||||
|         return Clutter.EVENT_STOP; | ||||
|     }, | ||||
| @@ -657,19 +523,15 @@ const AllView = new Lang.Class({ | ||||
|     _onPanEnd: function(action) { | ||||
|          if (this._displayingPopup) | ||||
|             return; | ||||
|  | ||||
|         let pageHeight = this._grid.getPageHeight(); | ||||
|  | ||||
|         // Calculate the scroll value we'd be at, which is our current | ||||
|         // scroll plus any velocity the user had when they released | ||||
|         // their finger. | ||||
|  | ||||
|         let velocity = -action.get_velocity(0)[2]; | ||||
|         let endPanValue = this._adjustment.value + velocity; | ||||
|  | ||||
|         let closestPage = Math.round(endPanValue / pageHeight); | ||||
|         this.goToPage(closestPage); | ||||
|  | ||||
|         let diffCurrentPage = this._diffToPage(this._currentPage); | ||||
|         if (diffCurrentPage > this._scrollView.height * PAGE_SWITCH_TRESHOLD) { | ||||
|             if (action.get_velocity(0)[2] > 0) | ||||
|                 this.goToPage(this._currentPage - 1); | ||||
|             else | ||||
|                 this.goToPage(this._currentPage + 1); | ||||
|         } else { | ||||
|             this.goToPage(this._currentPage); | ||||
|         } | ||||
|         this._panning = false; | ||||
|     }, | ||||
|  | ||||
| @@ -678,10 +540,10 @@ const AllView = new Lang.Class({ | ||||
|             return Clutter.EVENT_STOP; | ||||
|  | ||||
|         if (event.get_key_symbol() == Clutter.Page_Up) { | ||||
|             this.goToPage(this._grid.currentPage - 1); | ||||
|             this.goToPage(this._currentPage - 1); | ||||
|             return Clutter.EVENT_STOP; | ||||
|         } else if (event.get_key_symbol() == Clutter.Page_Down) { | ||||
|             this.goToPage(this._grid.currentPage + 1); | ||||
|             this.goToPage(this._currentPage + 1); | ||||
|             return Clutter.EVENT_STOP; | ||||
|         } | ||||
|  | ||||
| @@ -700,7 +562,7 @@ const AllView = new Lang.Class({ | ||||
|             })); | ||||
|     }, | ||||
|  | ||||
|     _keyFocusIn: function(icon) { | ||||
|     _ensureIconVisible: function(icon) { | ||||
|         let itemPage = this._grid.getItemPage(icon); | ||||
|         this.goToPage(itemPage); | ||||
|     }, | ||||
| @@ -742,7 +604,6 @@ const AllView = new Lang.Class({ | ||||
|  | ||||
|         if (this._availWidth != availWidth || this._availHeight != availHeight || oldNPages != this._grid.nPages()) { | ||||
|             this._adjustment.value = 0; | ||||
|             this._grid.currentPage = 0; | ||||
|             Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, | ||||
|                 function() { | ||||
|                     this._pageIndicators.setNPages(this._grid.nPages()); | ||||
| @@ -872,7 +733,7 @@ const AppDisplay = new Lang.Class({ | ||||
|     Name: 'AppDisplay', | ||||
|  | ||||
|     _init: function() { | ||||
|         this._privacySettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.privacy' }); | ||||
|         this._privacySettings = new Gio.Settings({ schema: 'org.gnome.desktop.privacy' }); | ||||
|         this._privacySettings.connect('changed::remember-app-usage', | ||||
|                                       Lang.bind(this, this._updateFrequentVisibility)); | ||||
|  | ||||
| @@ -900,23 +761,10 @@ const AppDisplay = new Lang.Class({ | ||||
|         this._viewStack = new St.Widget({ x_expand: true, y_expand: true, | ||||
|                                           layout_manager: this._viewStackLayout }); | ||||
|         this._viewStackLayout.connect('allocated-size-changed', Lang.bind(this, this._onAllocatedSizeChanged)); | ||||
|         this.actor.add_actor(this._viewStack); | ||||
|         this.actor.add_actor(this._viewStack, { expand: true }); | ||||
|         let layout = new ControlsBoxLayout({ homogeneous: true }); | ||||
|         this._controls = new St.Widget({ style_class: 'app-view-controls', | ||||
|                                          layout_manager: layout }); | ||||
|         this._controls.connect('notify::mapped', Lang.bind(this, | ||||
|             function() { | ||||
|                 // controls are faded either with their parent or | ||||
|                 // explicitly in animate(); we can't know how they'll be | ||||
|                 // shown next, so make sure to restore their opacity | ||||
|                 // when they are hidden | ||||
|                 if (this._controls.mapped) | ||||
|                   return; | ||||
|  | ||||
|                 Tweener.removeTweens(this._controls); | ||||
|                 this._controls.opacity = 255; | ||||
|             })); | ||||
|  | ||||
|         layout.hookup_style(this._controls); | ||||
|         this.actor.add_actor(new St.Bin({ child: this._controls })); | ||||
|  | ||||
| @@ -940,39 +788,21 @@ const AppDisplay = new Lang.Class({ | ||||
|         this._updateFrequentVisibility(); | ||||
|     }, | ||||
|  | ||||
|     animate: function(animationDirection, onComplete) { | ||||
|         let currentView = this._views[global.settings.get_uint('app-picker-view')].view; | ||||
|  | ||||
|         // Animate controls opacity using iconGrid animation time, since | ||||
|         // it will be the time the AllView or FrequentView takes to show | ||||
|         // it entirely. | ||||
|         let finalOpacity; | ||||
|         if (animationDirection == IconGrid.AnimationDirection.IN) { | ||||
|             this._controls.opacity = 0; | ||||
|             finalOpacity = 255; | ||||
|         } else { | ||||
|             finalOpacity = 0 | ||||
|         } | ||||
|  | ||||
|         Tweener.addTween(this._controls, | ||||
|                          { time: IconGrid.ANIMATION_TIME_IN, | ||||
|                            transition: 'easeInOutQuad', | ||||
|                            opacity: finalOpacity, | ||||
|                           }); | ||||
|  | ||||
|         currentView.animate(animationDirection, onComplete); | ||||
|     }, | ||||
|  | ||||
|     _showView: function(activeIndex) { | ||||
|         for (let i = 0; i < this._views.length; i++) { | ||||
|             let actor = this._views[i].view.actor; | ||||
|             let params = { time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME, | ||||
|                            opacity: (i == activeIndex) ? 255 : 0 }; | ||||
|             if (i == activeIndex) | ||||
|                 actor.visible = true; | ||||
|             else | ||||
|                 params.onComplete = function() { actor.hide(); }; | ||||
|             Tweener.addTween(actor, params); | ||||
|  | ||||
|             if (i == activeIndex) | ||||
|                 this._views[i].control.add_style_pseudo_class('checked'); | ||||
|             else | ||||
|                 this._views[i].control.remove_style_pseudo_class('checked'); | ||||
|  | ||||
|             let animationDirection = i == activeIndex ? IconGrid.AnimationDirection.IN : | ||||
|                                                         IconGrid.AnimationDirection.OUT; | ||||
|             this._views[i].view.animateSwitch(animationDirection); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
| @@ -1054,6 +884,26 @@ const AppSearchProvider = new Lang.Class({ | ||||
|         this.getInitialResultSet(terms, callback, cancellable); | ||||
|     }, | ||||
|  | ||||
|     activateResult: function(result) { | ||||
|         let app = this._appSys.lookup_app(result); | ||||
|         let event = Clutter.get_current_event(); | ||||
|         let modifiers = event ? event.get_state() : 0; | ||||
|         let openNewWindow = (modifiers & Clutter.ModifierType.CONTROL_MASK) || _isTerminal(app); | ||||
|  | ||||
|         if (openNewWindow) | ||||
|             app.open_new_window(-1); | ||||
|         else | ||||
|             app.activate(); | ||||
|     }, | ||||
|  | ||||
|     dragActivateResult: function(id, params) { | ||||
|         params = Params.parse(params, { workspace: -1, | ||||
|                                         timestamp: 0 }); | ||||
|  | ||||
|         let app = this._appSys.lookup_app(id); | ||||
|         app.open_new_window(workspace); | ||||
|     }, | ||||
|  | ||||
|     createResultObject: function (resultMeta) { | ||||
|         let app = this._appSys.lookup_app(resultMeta['id']); | ||||
|         return new AppIcon(app); | ||||
| @@ -1081,33 +931,20 @@ const FolderView = new Lang.Class({ | ||||
|         this.actor.add_action(action); | ||||
|     }, | ||||
|  | ||||
|     _keyFocusIn: function(actor) { | ||||
|         Util.ensureActorVisibleInScrollView(this.actor, actor); | ||||
|     }, | ||||
|  | ||||
|     // Overriden from BaseAppView | ||||
|     animate: function(animationDirection) { | ||||
|         this._grid.animatePulse(animationDirection); | ||||
|     }, | ||||
|  | ||||
|     createFolderIcon: function(size) { | ||||
|         let layout = new Clutter.GridLayout(); | ||||
|         let icon = new St.Widget({ layout_manager: layout, | ||||
|                                    style_class: 'app-folder-icon' }); | ||||
|         layout.hookup_style(icon); | ||||
|         let icon = new St.Widget({ layout_manager: new Clutter.BinLayout(), | ||||
|                                    style_class: 'app-folder-icon', | ||||
|                                    width: size, height: size }); | ||||
|         let subSize = Math.floor(FOLDER_SUBICON_FRACTION * size); | ||||
|  | ||||
|         let numItems = this._allItems.length; | ||||
|         let rtl = icon.get_text_direction() == Clutter.TextDirection.RTL; | ||||
|         for (let i = 0; i < 4; i++) { | ||||
|             let bin; | ||||
|             if (i < numItems) { | ||||
|                 let texture = this._allItems[i].app.create_icon_texture(subSize); | ||||
|                 bin = new St.Bin({ child: texture }); | ||||
|             } else { | ||||
|                 bin = new St.Bin({ width: subSize, height: subSize }); | ||||
|             } | ||||
|             layout.attach(bin, rtl ? (i + 1) % 2 : i % 2, Math.floor(i / 2), 1, 1); | ||||
|         let aligns = [ Clutter.ActorAlign.START, Clutter.ActorAlign.END ]; | ||||
|         for (let i = 0; i < Math.min(this._allItems.length, 4); i++) { | ||||
|             let texture = this._allItems[i].app.create_icon_texture(subSize); | ||||
|             let bin = new St.Bin({ child: texture, | ||||
|                                    x_expand: true, y_expand: true }); | ||||
|             bin.set_x_align(aligns[i % 2]); | ||||
|             bin.set_y_align(aligns[Math.floor(i / 2)]); | ||||
|             icon.add_actor(bin); | ||||
|         } | ||||
|  | ||||
|         return icon; | ||||
| @@ -1396,53 +1233,18 @@ const AppFolderPopup = new Lang.Class({ | ||||
|             function() { | ||||
|                 this.actor.destroy(); | ||||
|             })); | ||||
|         this._grabHelper = new GrabHelper.GrabHelper(this.actor); | ||||
|         this._grabHelper.addActor(Main.layoutManager.overviewGroup); | ||||
|         this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPress)); | ||||
|     }, | ||||
|  | ||||
|     _onKeyPress: function(actor, event) { | ||||
|         if (global.stage.get_key_focus() != actor) | ||||
|         if (!this._isOpen) | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|         // Since we need to only grab focus on one item child when the user | ||||
|         // actually press a key we don't use navigate_focus when opening | ||||
|         // the popup. | ||||
|         // Instead of that, grab the focus on the AppFolderPopup actor | ||||
|         // and actually moves the focus to a child only when the user | ||||
|         // actually press a key. | ||||
|         // It should work with just grab_key_focus on the AppFolderPopup | ||||
|         // actor, but since the arrow keys are not wrapping_around the focus | ||||
|         // is not grabbed by a child when the widget that has the current focus | ||||
|         // is the same that is requesting focus, so to make it works with arrow | ||||
|         // keys we need to connect to the key-press-event and navigate_focus | ||||
|         // when that happens using TAB_FORWARD or TAB_BACKWARD instead of arrow | ||||
|         // keys | ||||
|         if (event.get_key_symbol() != Clutter.KEY_Escape) | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|         // Use TAB_FORWARD for down key and right key | ||||
|         // and TAB_BACKWARD for up key and left key on ltr | ||||
|         // languages | ||||
|         let direction; | ||||
|         let isLtr = Clutter.get_default_text_direction() == Clutter.TextDirection.LTR; | ||||
|         switch (event.get_key_symbol()) { | ||||
|             case Clutter.Down: | ||||
|                 direction = Gtk.DirectionType.TAB_FORWARD; | ||||
|                 break; | ||||
|             case Clutter.Right: | ||||
|                 direction = isLtr ? Gtk.DirectionType.TAB_FORWARD : | ||||
|                                     Gtk.DirectionType.TAB_BACKWARD; | ||||
|                 break; | ||||
|             case Clutter.Up: | ||||
|                 direction = Gtk.DirectionType.TAB_BACKWARD; | ||||
|                 break; | ||||
|             case Clutter.Left: | ||||
|                 direction = isLtr ? Gtk.DirectionType.TAB_BACKWARD : | ||||
|                                     Gtk.DirectionType.TAB_FORWARD; | ||||
|                 break; | ||||
|             default: | ||||
|                 return Clutter.EVENT_PROPAGATE; | ||||
|         } | ||||
|         return actor.navigate_focus(null, direction, false); | ||||
|         this.popdown(); | ||||
|         return Clutter.EVENT_STOP; | ||||
|     }, | ||||
|  | ||||
|     toggle: function() { | ||||
| @@ -1456,27 +1258,15 @@ const AppFolderPopup = new Lang.Class({ | ||||
|         if (this._isOpen) | ||||
|             return; | ||||
|  | ||||
|         this._isOpen = this._grabHelper.grab({ actor: this.actor, | ||||
|                                                onUngrab: Lang.bind(this, this.popdown) }); | ||||
|  | ||||
|         if (!this._isOpen) | ||||
|             return; | ||||
|  | ||||
|         this.actor.show(); | ||||
|  | ||||
|         this._boxPointer.setArrowActor(this._source.actor); | ||||
|         // We need to hide the icons of the view until the boxpointer animation | ||||
|         // is completed so we can animate the icons after as we like without | ||||
|         // showing them while boxpointer is animating. | ||||
|         this._view.actor.opacity = 0; | ||||
|         this._boxPointer.show(BoxPointer.PopupAnimation.FADE | | ||||
|                               BoxPointer.PopupAnimation.SLIDE, | ||||
|                               Lang.bind(this, | ||||
|             function() { | ||||
|                 this._view.actor.opacity = 255; | ||||
|                 this._view.animate(IconGrid.AnimationDirection.IN); | ||||
|             })); | ||||
|                               BoxPointer.PopupAnimation.SLIDE); | ||||
|  | ||||
|         this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); | ||||
|  | ||||
|         this._isOpen = true; | ||||
|         this.emit('open-state-changed', true); | ||||
|     }, | ||||
|  | ||||
| @@ -1484,8 +1274,6 @@ const AppFolderPopup = new Lang.Class({ | ||||
|         if (!this._isOpen) | ||||
|             return; | ||||
|  | ||||
|         this._grabHelper.ungrab({ actor: this.actor }); | ||||
|  | ||||
|         this._boxPointer.hide(BoxPointer.PopupAnimation.FADE | | ||||
|                               BoxPointer.PopupAnimation.SLIDE); | ||||
|         this._isOpen = false; | ||||
| @@ -1536,9 +1324,7 @@ const AppIcon = new Lang.Class({ | ||||
|  | ||||
|         this.actor.label_actor = this.icon.label; | ||||
|  | ||||
|         this.actor.connect('leave-event', Lang.bind(this, this._onLeaveEvent)); | ||||
|         this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress)); | ||||
|         this.actor.connect('touch-event', Lang.bind(this, this._onTouchEvent)); | ||||
|         this.actor.connect('clicked', Lang.bind(this, this._onClicked)); | ||||
|         this.actor.connect('popup-menu', Lang.bind(this, this._onKeyboardPopupMenu)); | ||||
|  | ||||
| @@ -1594,26 +1380,16 @@ const AppIcon = new Lang.Class({ | ||||
|             this.actor.remove_style_class_name('running'); | ||||
|     }, | ||||
|  | ||||
|     _setPopupTimeout: function() { | ||||
|         this._removeMenuTimeout(); | ||||
|         this._menuTimeoutId = Mainloop.timeout_add(MENU_POPUP_TIMEOUT, | ||||
|             Lang.bind(this, function() { | ||||
|                 this._menuTimeoutId = 0; | ||||
|                 this.popupMenu(); | ||||
|                 return GLib.SOURCE_REMOVE; | ||||
|             })); | ||||
|         GLib.Source.set_name_by_id(this._menuTimeoutId, '[gnome-shell] this.popupMenu'); | ||||
|     }, | ||||
|  | ||||
|     _onLeaveEvent: function(actor, event) { | ||||
|         this.actor.fake_release(); | ||||
|         this._removeMenuTimeout(); | ||||
|     }, | ||||
|  | ||||
|     _onButtonPress: function(actor, event) { | ||||
|         let button = event.get_button(); | ||||
|         if (button == 1) { | ||||
|             this._setPopupTimeout(); | ||||
|             this._removeMenuTimeout(); | ||||
|             this._menuTimeoutId = Mainloop.timeout_add(MENU_POPUP_TIMEOUT, | ||||
|                 Lang.bind(this, function() { | ||||
|                     this._menuTimeoutId = 0; | ||||
|                     this.popupMenu(); | ||||
|                     return GLib.SOURCE_REMOVE; | ||||
|                 })); | ||||
|         } else if (button == 3) { | ||||
|             this.popupMenu(); | ||||
|             return Clutter.EVENT_STOP; | ||||
| @@ -1621,16 +1397,19 @@ const AppIcon = new Lang.Class({ | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     }, | ||||
|  | ||||
|     _onTouchEvent: function (actor, event) { | ||||
|         if (event.type() == Clutter.EventType.TOUCH_BEGIN) | ||||
|             this._setPopupTimeout(); | ||||
|  | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     }, | ||||
|  | ||||
|     _onClicked: function(actor, button) { | ||||
|         this._removeMenuTimeout(); | ||||
|         this.activate(button); | ||||
|  | ||||
|         if (button == 1) { | ||||
|             this._onActivate(Clutter.get_current_event()); | ||||
|         } else if (button == 2) { | ||||
|             // Last workspace is always empty | ||||
|             let launchWorkspace = global.screen.get_workspace_by_index(global.screen.n_workspaces - 1); | ||||
|             launchWorkspace.activate(global.get_current_time()); | ||||
|             this.app.open_new_window(-1); | ||||
|             Main.overview.hide(); | ||||
|         } | ||||
|         return false; | ||||
|     }, | ||||
|  | ||||
|     _onKeyboardPopupMenu: function() { | ||||
| @@ -1684,28 +1463,20 @@ const AppIcon = new Lang.Class({ | ||||
|         this.emit('menu-state-changed', false); | ||||
|     }, | ||||
|  | ||||
|     activate: function (button) { | ||||
|         let event = Clutter.get_current_event(); | ||||
|         let modifiers = event ? event.get_state() : 0; | ||||
|         let openNewWindow = modifiers & Clutter.ModifierType.CONTROL_MASK && | ||||
|                             this.app.state == Shell.AppState.RUNNING || | ||||
|                             button && button == 2; | ||||
|     _onActivate: function (event) { | ||||
|         let modifiers = event.get_state(); | ||||
|  | ||||
|         if (this.app.state == Shell.AppState.STOPPED || openNewWindow) | ||||
|             this.animateLaunch(); | ||||
|  | ||||
|         if (openNewWindow) | ||||
|         if ((modifiers & Clutter.ModifierType.CONTROL_MASK | ||||
|              && this.app.state == Shell.AppState.RUNNING) | ||||
|             || _isTerminal(this.app)) { | ||||
|             this.app.open_new_window(-1); | ||||
|         else | ||||
|         } else { | ||||
|             this.app.activate(); | ||||
|         } | ||||
|  | ||||
|         Main.overview.hide(); | ||||
|     }, | ||||
|  | ||||
|     animateLaunch: function() { | ||||
|         this.icon.animateZoomOut(); | ||||
|     }, | ||||
|  | ||||
|     shellWorkspaceLaunch : function(params) { | ||||
|         params = Params.parse(params, { workspace: -1, | ||||
|                                         timestamp: 0 }); | ||||
| @@ -1754,7 +1525,7 @@ const AppIconMenu = new Lang.Class({ | ||||
|         })); | ||||
|         source.actor.connect('destroy', Lang.bind(this, function () { this.actor.destroy(); })); | ||||
|  | ||||
|         Main.uiGroup.add_actor(this.actor); | ||||
|         Main.layoutManager.menuGroup.add_actor(this.actor); | ||||
|     }, | ||||
|  | ||||
|     _redisplay: function() { | ||||
| @@ -1784,17 +1555,12 @@ const AppIconMenu = new Lang.Class({ | ||||
|         if (!this._source.app.is_window_backed()) { | ||||
|             this._appendSeparator(); | ||||
|  | ||||
|             if (this._source.app.can_open_new_window()) { | ||||
|                 this._newWindowMenuItem = this._appendMenuItem(_("New Window")); | ||||
|                 this._newWindowMenuItem.connect('activate', Lang.bind(this, function() { | ||||
|                     if (this._source.app.state == Shell.AppState.STOPPED) | ||||
|                         this._source.animateLaunch(); | ||||
|  | ||||
|                     this._source.app.open_new_window(-1); | ||||
|                     this.emit('activate-window', null); | ||||
|                 })); | ||||
|                 this._appendSeparator(); | ||||
|             } | ||||
|             this._newWindowMenuItem = this._appendMenuItem(_("New Window")); | ||||
|             this._newWindowMenuItem.connect('activate', Lang.bind(this, function() { | ||||
|                 this._source.app.open_new_window(-1); | ||||
|                 this.emit('activate-window', null); | ||||
|             })); | ||||
|             this._appendSeparator(); | ||||
|  | ||||
|             let appInfo = this._source.app.get_app_info(); | ||||
|             let actions = appInfo.list_actions(); | ||||
| @@ -1823,26 +1589,6 @@ const AppIconMenu = new Lang.Class({ | ||||
|                     favs.addFavorite(this._source.app.get_id()); | ||||
|                 })); | ||||
|             } | ||||
|  | ||||
|             if (Shell.AppSystem.get_default().lookup_app('org.gnome.Software.desktop')) { | ||||
|                 this._appendSeparator(); | ||||
|                 let item = this._appendMenuItem(_("Show Details")); | ||||
|                 item.connect('activate', Lang.bind(this, function() { | ||||
|                     let id = this._source.app.get_id(); | ||||
|                     let args = GLib.Variant.new('(ss)', [id, '']); | ||||
|                     Gio.DBus.get(Gio.BusType.SESSION, null, | ||||
|                         function(o, res) { | ||||
|                             let bus = Gio.DBus.get_finish(res); | ||||
|                             bus.call('org.gnome.Software', | ||||
|                                      '/org/gnome/Software', | ||||
|                                      'org.gtk.Actions', 'Activate', | ||||
|                                      GLib.Variant.new('(sava{sv})', | ||||
|                                                       ['details', [args], null]), | ||||
|                                      null, 0, -1, null, null); | ||||
|                             Main.overview.hide(); | ||||
|                         }); | ||||
|                 })); | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|   | ||||
| @@ -6,28 +6,6 @@ const Signals = imports.signals; | ||||
|  | ||||
| const Main = imports.ui.main; | ||||
|  | ||||
| const RENAMED_DESKTOP_IDS = { | ||||
|     'baobab.desktop': 'org.gnome.baobab.desktop', | ||||
|     'cheese.desktop': 'org.gnome.Cheese.desktop', | ||||
|     'dconf-editor.desktop': 'ca.desrt.dconf-editor.desktop', | ||||
|     'file-roller.desktop': 'org.gnome.FileRoller.desktop', | ||||
|     'gcalctool.desktop': 'gnome-calculator.desktop', | ||||
|     'gedit.desktop': 'org.gnome.gedit.desktop', | ||||
|     'glchess.desktop': 'gnome-chess.desktop', | ||||
|     'gnome-clocks.desktop': 'org.gnome.clocks.desktop', | ||||
|     'gnome-contacts.desktop': 'org.gnome.Contacts.desktop', | ||||
|     'gnome-documents.desktop': 'org.gnome.Documents.desktop', | ||||
|     'gnome-font-viewer.desktop': 'org.gnome.font-viewer.desktop', | ||||
|     'gnome-photos.desktop': 'org.gnome.Photos.desktop', | ||||
|     'gnome-screenshot.desktop': 'org.gnome.Screenshot.desktop', | ||||
|     'gnome-software.desktop': 'org.gnome.Software.desktop', | ||||
|     'gnome-weather.desktop': 'org.gnome.Weather.Application.desktop', | ||||
|     'gnomine.desktop': 'gnome-mines.desktop', | ||||
|     'nautilus.desktop': 'org.gnome.Nautilus.desktop', | ||||
|     'polari.desktop': 'org.gnome.Polari.desktop', | ||||
|     'totem.desktop': 'org.gnome.Totem.desktop', | ||||
| }; | ||||
|  | ||||
| const AppFavorites = new Lang.Class({ | ||||
|     Name: 'AppFavorites', | ||||
|  | ||||
| @@ -46,21 +24,6 @@ const AppFavorites = new Lang.Class({ | ||||
|  | ||||
|     reload: function() { | ||||
|         let ids = global.settings.get_strv(this.FAVORITE_APPS_KEY); | ||||
|  | ||||
|         // Map old desktop file names to the current ones | ||||
|         let updated = false; | ||||
|         ids = ids.map(function (id) { | ||||
|             let newId = RENAMED_DESKTOP_IDS[id]; | ||||
|             if (newId !== undefined) { | ||||
|                 updated = true; | ||||
|                 return newId; | ||||
|             } | ||||
|             return id; | ||||
|         }); | ||||
|         // ... and write back the updated desktop file names | ||||
|         if (updated) | ||||
|             global.settings.set_strv(this.FAVORITE_APPS_KEY, ids); | ||||
|  | ||||
|         let appSys = Shell.AppSystem.get_default(); | ||||
|         let apps = ids.map(function (id) { | ||||
|                 return appSys.lookup_app(id); | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -22,7 +22,7 @@ const BackgroundMenu = new Lang.Class({ | ||||
|  | ||||
|         this.actor.add_style_class_name('background-menu'); | ||||
|  | ||||
|         layoutManager.uiGroup.add_actor(this.actor); | ||||
|         layoutManager.menuGroup.add_actor(this.actor); | ||||
|         this.actor.hide(); | ||||
|     } | ||||
| }); | ||||
| @@ -33,40 +33,31 @@ function addBackgroundMenu(actor, layoutManager) { | ||||
|     actor._backgroundManager = new PopupMenu.PopupMenuManager({ actor: actor }); | ||||
|     actor._backgroundManager.addMenu(actor._backgroundMenu); | ||||
|  | ||||
|     function openMenu(x, y) { | ||||
|         Main.layoutManager.setDummyCursorGeometry(x, y, 0, 0); | ||||
|     function openMenu() { | ||||
|         let [x, y] = global.get_pointer(); | ||||
|         Main.layoutManager.setDummyCursorPosition(x, y); | ||||
|         actor._backgroundMenu.open(BoxPointer.PopupAnimation.NONE); | ||||
|     } | ||||
|  | ||||
|     let clickAction = new Clutter.ClickAction(); | ||||
|     clickAction.connect('long-press', function(action, actor, state) { | ||||
|         if (state == Clutter.LongPressState.QUERY) | ||||
|             return ((action.get_button() == 0 || | ||||
|                      action.get_button() == 1) && | ||||
|                     !actor._backgroundMenu.isOpen); | ||||
|             return action.get_button() == 1 && !actor._backgroundMenu.isOpen; | ||||
|         if (state == Clutter.LongPressState.ACTIVATE) { | ||||
|             let [x, y] = action.get_coords(); | ||||
|             openMenu(x, y); | ||||
|             openMenu(); | ||||
|             actor._backgroundManager.ignoreRelease(); | ||||
|         } | ||||
|         return true; | ||||
|     }); | ||||
|     clickAction.connect('clicked', function(action) { | ||||
|         if (action.get_button() == 3) { | ||||
|             let [x, y] = action.get_coords(); | ||||
|             openMenu(x, y); | ||||
|         } | ||||
|         if (action.get_button() == 3) | ||||
|             openMenu(); | ||||
|     }); | ||||
|     actor.add_action(clickAction); | ||||
|  | ||||
|     let grabOpBeginId = global.display.connect('grab-op-begin', function () { | ||||
|         clickAction.release(); | ||||
|     }); | ||||
|  | ||||
|     actor.connect('destroy', function() { | ||||
|         actor._backgroundMenu.destroy(); | ||||
|         actor._backgroundMenu = null; | ||||
|         actor._backgroundManager = null; | ||||
|         global.display.disconnect(grabOpBeginId); | ||||
|     }); | ||||
| } | ||||
|   | ||||
| @@ -14,9 +14,6 @@ const Shell = imports.gi.Shell; | ||||
| const MSECS_IN_DAY = 24 * 60 * 60 * 1000; | ||||
| const SHOW_WEEKDATE_KEY = 'show-weekdate'; | ||||
|  | ||||
| // alias to prevent xgettext from picking up strings translated in GTK+ | ||||
| const gtk30_ = Gettext_gtk30.gettext; | ||||
|  | ||||
| // in org.gnome.desktop.interface | ||||
| const CLOCK_FORMAT_KEY        = 'clock-format'; | ||||
|  | ||||
| @@ -383,14 +380,14 @@ const Calendar = new Lang.Class({ | ||||
|  | ||||
|     _init: function() { | ||||
|         this._weekStart = Shell.util_get_week_start(); | ||||
|         this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.calendar' }); | ||||
|         this._settings = new Gio.Settings({ schema: 'org.gnome.shell.calendar' }); | ||||
|  | ||||
|         this._settings.connect('changed::' + SHOW_WEEKDATE_KEY, Lang.bind(this, this._onSettingsChange)); | ||||
|         this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY); | ||||
|  | ||||
|         // Find the ordering for month/year in the calendar heading | ||||
|         this._headerFormatWithoutYear = '%B'; | ||||
|         switch (gtk30_('calendar:MY')) { | ||||
|         switch (Gettext_gtk30.gettext('calendar:MY')) { | ||||
|         case 'calendar:MY': | ||||
|             this._headerFormat = '%B %Y'; | ||||
|             break; | ||||
| @@ -406,11 +403,9 @@ const Calendar = new Lang.Class({ | ||||
|         // Start off with the current date | ||||
|         this._selectedDate = new Date(); | ||||
|  | ||||
|         this._shouldDateGrabFocus = false; | ||||
|  | ||||
|         this.actor = new St.Widget({ style_class: 'calendar', | ||||
|                                      layout_manager: new Clutter.GridLayout(), | ||||
|                                      reactive: true }); | ||||
|         this.actor = new St.Table({ homogeneous: false, | ||||
|                                     style_class: 'calendar', | ||||
|                                     reactive: true }); | ||||
|  | ||||
|         this.actor.connect('scroll-event', | ||||
|                            Lang.bind(this, this._onScroll)); | ||||
| @@ -423,10 +418,8 @@ const Calendar = new Lang.Class({ | ||||
|     setEventSource: function(eventSource) { | ||||
|         this._eventSource = eventSource; | ||||
|         this._eventSource.connect('changed', Lang.bind(this, function() { | ||||
|             this._rebuildCalendar(); | ||||
|             this._update(); | ||||
|         })); | ||||
|         this._rebuildCalendar(); | ||||
|         this._update(); | ||||
|     }, | ||||
|  | ||||
| @@ -441,13 +434,13 @@ const Calendar = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _buildHeader: function() { | ||||
|         let layout = this.actor.layout_manager; | ||||
|         let offsetCols = this._useWeekdate ? 1 : 0; | ||||
|         this.actor.destroy_all_children(); | ||||
|  | ||||
|         // Top line of the calendar '<| September 2009 |>' | ||||
|         this._topBox = new St.BoxLayout(); | ||||
|         layout.attach(this._topBox, 0, 0, offsetCols + 7, 1); | ||||
|         this.actor.add(this._topBox, | ||||
|                        { row: 0, col: 0, col_span: offsetCols + 7 }); | ||||
|  | ||||
|         this._backButton = new St.Button({ style_class: 'calendar-change-month-back', | ||||
|                                            accessible_name: _("Previous month"), | ||||
| @@ -479,12 +472,10 @@ const Calendar = new Lang.Class({ | ||||
|             let customDayAbbrev = _getCalendarDayAbbreviation(iter.getDay()); | ||||
|             let label = new St.Label({ style_class: 'calendar-day-base calendar-day-heading', | ||||
|                                        text: customDayAbbrev }); | ||||
|             let col; | ||||
|             if (this.actor.get_text_direction() == Clutter.TextDirection.RTL) | ||||
|                 col = 6 - (7 + iter.getDay() - this._weekStart) % 7; | ||||
|             else | ||||
|                 col = offsetCols + (7 + iter.getDay() - this._weekStart) % 7; | ||||
|             layout.attach(label, col, 1, 1, 1); | ||||
|             this.actor.add(label, | ||||
|                            { row: 1, | ||||
|                              col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7, | ||||
|                              x_fill: false, x_align: St.Align.MIDDLE }); | ||||
|             iter.setTime(iter.getTime() + MSECS_IN_DAY); | ||||
|         } | ||||
|  | ||||
| @@ -557,7 +548,6 @@ const Calendar = new Lang.Class({ | ||||
|     _onSettingsChange: function() { | ||||
|         this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY); | ||||
|         this._buildHeader(); | ||||
|         this._rebuildCalendar(); | ||||
|         this._update(); | ||||
|     }, | ||||
|  | ||||
| @@ -603,7 +593,6 @@ const Calendar = new Lang.Class({ | ||||
|  | ||||
|         beginDate.setTime(beginDate.getTime() - (weekPadding + daysToWeekStart) * MSECS_IN_DAY); | ||||
|  | ||||
|         let layout = this.actor.layout_manager; | ||||
|         let iter = new Date(beginDate); | ||||
|         let row = 2; | ||||
|         // nRows here means 6 weeks + one header + one navbar | ||||
| @@ -618,9 +607,7 @@ const Calendar = new Lang.Class({ | ||||
|  | ||||
|             button._date = new Date(iter); | ||||
|             button.connect('clicked', Lang.bind(this, function() { | ||||
|                 this._shouldDateGrabFocus = true; | ||||
|                 this.setDate(button._date); | ||||
|                 this._shouldDateGrabFocus = false; | ||||
|             })); | ||||
|  | ||||
|             let hasEvents = this._eventSource.hasEvents(iter); | ||||
| @@ -651,19 +638,16 @@ const Calendar = new Lang.Class({ | ||||
|             button.style_class = styleClass; | ||||
|  | ||||
|             let offsetCols = this._useWeekdate ? 1 : 0; | ||||
|             let col; | ||||
|             if (rtl) | ||||
|                 col = 6 - (7 + iter.getDay() - this._weekStart) % 7; | ||||
|             else | ||||
|                 col = offsetCols + (7 + iter.getDay() - this._weekStart) % 7; | ||||
|             layout.attach(button, col, row, 1, 1); | ||||
|             this.actor.add(button, | ||||
|                            { row: row, col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7 }); | ||||
|  | ||||
|             this._buttons.push(button); | ||||
|  | ||||
|             if (this._useWeekdate && iter.getDay() == 4) { | ||||
|                 let label = new St.Label({ text: _getCalendarWeekForDate(iter).toString(), | ||||
|                                            style_class: 'calendar-day-base calendar-week-number'}); | ||||
|                 layout.attach(label, rtl ? 7 : 0, row, 1, 1); | ||||
|                 this.actor.add(label, | ||||
|                                { row: row, col: 0, y_align: St.Align.MIDDLE }); | ||||
|             } | ||||
|  | ||||
|             iter.setTime(iter.getTime() + MSECS_IN_DAY); | ||||
| @@ -689,11 +673,8 @@ const Calendar = new Lang.Class({ | ||||
|             this._rebuildCalendar(); | ||||
|  | ||||
|         this._buttons.forEach(Lang.bind(this, function(button) { | ||||
|             if (_sameDay(button._date, this._selectedDate)) { | ||||
|             if (_sameDay(button._date, this._selectedDate)) | ||||
|                 button.add_style_pseudo_class('active'); | ||||
|                 if (this._shouldDateGrabFocus) | ||||
|                     button.grab_key_focus(); | ||||
|             } | ||||
|             else | ||||
|                 button.remove_style_pseudo_class('active'); | ||||
|         })); | ||||
| @@ -706,12 +687,9 @@ const EventsList = new Lang.Class({ | ||||
|     Name: 'EventsList', | ||||
|  | ||||
|     _init: function() { | ||||
|         let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL }); | ||||
|         this.actor = new St.Widget({ style_class: 'events-table', | ||||
|                                      layout_manager: layout }); | ||||
|         layout.hookup_style(this.actor); | ||||
|         this.actor = new St.Table({ style_class: 'events-table' }); | ||||
|         this._date = new Date(); | ||||
|         this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' }); | ||||
|         this._desktopSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' }); | ||||
|         this._desktopSettings.connect('changed', Lang.bind(this, this._update)); | ||||
|         this._weekStart = Shell.util_get_week_start(); | ||||
|     }, | ||||
| @@ -729,34 +707,33 @@ const EventsList = new Lang.Class({ | ||||
|             dayString = ''; | ||||
|  | ||||
|         let dayLabel = new St.Label({ style_class: 'events-day-dayname', | ||||
|                                       text: dayString, | ||||
|                                       x_align: Clutter.ActorAlign.END, | ||||
|                                       y_align: Clutter.ActorAlign.START }); | ||||
|                                       text: dayString }); | ||||
|         dayLabel.clutter_text.line_wrap = false; | ||||
|         dayLabel.clutter_text.ellipsize = false; | ||||
|  | ||||
|         let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL; | ||||
|  | ||||
|         let layout = this.actor.layout_manager; | ||||
|         layout.attach(dayLabel, rtl ? 2 : 0, index, 1, 1); | ||||
|         this.actor.add(dayLabel, { row: index, col: 0, | ||||
|                                    x_expand: false, x_align: St.Align.END, | ||||
|                                    y_fill: false, y_align: St.Align.START }); | ||||
|  | ||||
|         let clockFormat = this._desktopSettings.get_string(CLOCK_FORMAT_KEY); | ||||
|         let timeString = _formatEventTime(event, clockFormat); | ||||
|         let timeLabel = new St.Label({ style_class: 'events-day-time', | ||||
|                                        text: timeString, | ||||
|                                        y_align: Clutter.ActorAlign.START }); | ||||
|                                        text: timeString }); | ||||
|         timeLabel.clutter_text.line_wrap = false; | ||||
|         timeLabel.clutter_text.ellipsize = false; | ||||
|  | ||||
|         layout.attach(timeLabel, 1, index, 1, 1); | ||||
|         this.actor.add(timeLabel, { row: index, col: 1, | ||||
|                                     x_expand: false, x_align: St.Align.MIDDLE, | ||||
|                                     y_fill: false, y_align: St.Align.START }); | ||||
|  | ||||
|         let titleLabel = new St.Label({ style_class: 'events-day-task', | ||||
|                                         text: event.summary, | ||||
|                                         x_expand: true }); | ||||
|                                         text: event.summary }); | ||||
|         titleLabel.clutter_text.line_wrap = true; | ||||
|         titleLabel.clutter_text.ellipsize = false; | ||||
|  | ||||
|         layout.attach(titleLabel, rtl ? 0 : 2, index, 1, 1); | ||||
|         this.actor.add(titleLabel, { row: index, col: 2, | ||||
|                                      x_expand: true, x_align: St.Align.START, | ||||
|                                      y_fill: false, y_align: St.Align.START }); | ||||
|     }, | ||||
|  | ||||
|     _addPeriod: function(header, index, begin, end, includeDayName, showNothingScheduled) { | ||||
| @@ -765,9 +742,13 @@ const EventsList = new Lang.Class({ | ||||
|         if (events.length == 0 && !showNothingScheduled) | ||||
|             return index; | ||||
|  | ||||
|         let label = new St.Label({ style_class: 'events-day-header', text: header }); | ||||
|         let layout = this.actor.layout_manager; | ||||
|         layout.attach(label, 0, index, 3, 1); | ||||
|         this.actor.add(new St.Label({ style_class: 'events-day-header', text: header }), | ||||
|                        { row: index, col: 0, col_span: 3, | ||||
|                          // In theory, x_expand should be true here, but x_expand | ||||
|                          // is a property of the column for StTable, ie all day cells | ||||
|                          // get it too | ||||
|                          x_expand: false, x_align: St.Align.START, | ||||
|                          y_fill: false, y_align: St.Align.START }); | ||||
|         index++; | ||||
|  | ||||
|         for (let n = 0; n < events.length; n++) { | ||||
|   | ||||
| @@ -23,7 +23,7 @@ const AutomountManager = new Lang.Class({ | ||||
|     Name: 'AutomountManager', | ||||
|  | ||||
|     _init: function() { | ||||
|         this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA }); | ||||
|         this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA }); | ||||
|         this._volumeQueue = []; | ||||
|         this._session = new GnomeSession.SessionManager(); | ||||
|         this._session.connectSignal('InhibitorAdded', | ||||
| @@ -43,7 +43,6 @@ const AutomountManager = new Lang.Class({ | ||||
|         this._driveEjectButtonId = this._volumeMonitor.connect('drive-eject-button', Lang.bind(this, this._onDriveEjectButton)); | ||||
|  | ||||
|         this._mountAllId = Mainloop.idle_add(Lang.bind(this, this._startupMountAll)); | ||||
|         GLib.Source.set_name_by_id(this._mountAllId, '[gnome-shell] this._startupMountAll'); | ||||
|     }, | ||||
|  | ||||
|     disable: function() { | ||||
| @@ -235,11 +234,10 @@ const AutomountManager = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _allowAutorunExpire: function(volume) { | ||||
|         let id = Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, function() { | ||||
|         Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, function() { | ||||
|             volume.allowAutorun = false; | ||||
|             return GLib.SOURCE_REMOVE; | ||||
|         }); | ||||
|         GLib.Source.set_name_by_id(id, '[gnome-shell] volume.allowAutorun'); | ||||
|     } | ||||
| }); | ||||
| const Component = AutomountManager; | ||||
|   | ||||
| @@ -96,7 +96,7 @@ const ContentTypeDiscoverer = new Lang.Class({ | ||||
|  | ||||
|     _init: function(callback) { | ||||
|         this._callback = callback; | ||||
|         this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA }); | ||||
|         this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA }); | ||||
|     }, | ||||
|  | ||||
|     guessContentTypes: function(mount) { | ||||
| @@ -441,7 +441,7 @@ const AutorunTransientDispatcher = new Lang.Class({ | ||||
|     _init: function(manager) { | ||||
|         this._manager = manager; | ||||
|         this._sources = []; | ||||
|         this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA }); | ||||
|         this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA }); | ||||
|     }, | ||||
|  | ||||
|     _getAutorunSettingForType: function(contentType) { | ||||
|   | ||||
| @@ -80,46 +80,44 @@ const KeyringDialog = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _buildControlTable: function() { | ||||
|         let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL }); | ||||
|         let layout = new Clutter.TableLayout(); | ||||
|         let table = new St.Widget({ style_class: 'keyring-dialog-control-table', | ||||
|                                     layout_manager: layout }); | ||||
|         layout.hookup_style(table); | ||||
|         let row = 0; | ||||
|  | ||||
|         if (this.prompt.password_visible) { | ||||
|             let label = new St.Label({ style_class: 'prompt-dialog-password-label', | ||||
|                                        x_align: Clutter.ActorAlign.START, | ||||
|                                        y_align: Clutter.ActorAlign.CENTER }); | ||||
|             let label = new St.Label({ style_class: 'prompt-dialog-password-label' }); | ||||
|             label.set_text(_("Password:")); | ||||
|             label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; | ||||
|             layout.attach(label, 0, row, 1, 1); | ||||
|             layout.pack(label, 0, row); | ||||
|             layout.child_set(label, { x_expand: false, y_fill: false, | ||||
|                                       x_align: Clutter.TableAlignment.START }); | ||||
|             this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry', | ||||
|                                                  text: '', | ||||
|                                                  can_focus: true, | ||||
|                                                  x_expand: true }); | ||||
|                                                  can_focus: true }); | ||||
|             this._passwordEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE | ||||
|             ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true }); | ||||
|             this._passwordEntry.clutter_text.connect('activate', Lang.bind(this, this._onPasswordActivate)); | ||||
|             layout.attach(this._passwordEntry, 1, row, 1, 1); | ||||
|             layout.pack(this._passwordEntry, 1, row); | ||||
|             row++; | ||||
|         } else { | ||||
|             this._passwordEntry = null; | ||||
|         } | ||||
|  | ||||
|         if (this.prompt.confirm_visible) { | ||||
|             var label = new St.Label(({ style_class: 'prompt-dialog-password-label', | ||||
|                                         x_align: Clutter.ActorAlign.START, | ||||
|                                         y_align: Clutter.ActorAlign.CENTER })); | ||||
|             var label = new St.Label(({ style_class: 'prompt-dialog-password-label' })); | ||||
|             label.set_text(_("Type again:")); | ||||
|             layout.attach(label, 0, row, 1, 1); | ||||
|             layout.pack(label, 0, row); | ||||
|             layout.child_set(label, { x_expand: false, y_fill: false, | ||||
|                                       x_align: Clutter.TableAlignment.START }); | ||||
|             this._confirmEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry', | ||||
|                                                 text: '', | ||||
|                                                 can_focus: true, | ||||
|                                                 x_expand: true }); | ||||
|                                                 can_focus: true }); | ||||
|             this._confirmEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE | ||||
|             ShellEntry.addContextMenu(this._confirmEntry, { isPassword: true }); | ||||
|             this._confirmEntry.clutter_text.connect('activate', Lang.bind(this, this._onConfirmActivate)); | ||||
|             layout.attach(this._confirmEntry, 1, row, 1, 1); | ||||
|             layout.pack(this._confirmEntry, 1, row); | ||||
|             row++; | ||||
|         } else { | ||||
|             this._confirmEntry = null; | ||||
| @@ -132,15 +130,15 @@ const KeyringDialog = new Lang.Class({ | ||||
|             let choice = new CheckBox.CheckBox(); | ||||
|             this.prompt.bind_property('choice-label', choice.getLabelActor(), 'text', GObject.BindingFlags.SYNC_CREATE); | ||||
|             this.prompt.bind_property('choice-chosen', choice.actor, 'checked', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL); | ||||
|             layout.attach(choice.actor, 1, row, 1, 1); | ||||
|             layout.pack(choice.actor, 1, row); | ||||
|             row++; | ||||
|         } | ||||
|  | ||||
|         let warning = new St.Label({ style_class: 'prompt-dialog-error-label', | ||||
|                                      x_align: Clutter.ActorAlign.START }); | ||||
|         let warning = new St.Label({ style_class: 'prompt-dialog-error-label' }); | ||||
|         warning.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; | ||||
|         warning.clutter_text.line_wrap = true; | ||||
|         layout.attach(warning, 1, row, 1, 1); | ||||
|         layout.pack(warning, 1, row); | ||||
|         layout.child_set(warning, { x_fill: false, x_align: Clutter.TableAlignment.START }); | ||||
|         this.prompt.bind_property('warning-visible', warning, 'visible', GObject.BindingFlags.SYNC_CREATE); | ||||
|         this.prompt.bind_property('warning', warning, 'text', GObject.BindingFlags.SYNC_CREATE); | ||||
|  | ||||
|   | ||||
| @@ -72,28 +72,24 @@ const NetworkSecretDialog = new Lang.Class({ | ||||
|                              expand: true }); | ||||
|         } | ||||
|  | ||||
|         let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL }); | ||||
|         let layout = new Clutter.TableLayout(); | ||||
|         let secretTable = new St.Widget({ style_class: 'network-dialog-secret-table', | ||||
|                                           layout_manager: layout }); | ||||
|         layout.hookup_style(secretTable); | ||||
|  | ||||
|         let rtl = secretTable.get_text_direction() == Clutter.TextDirection.RTL; | ||||
|         let initialFocusSet = false; | ||||
|         let pos = 0; | ||||
|         for (let i = 0; i < this._content.secrets.length; i++) { | ||||
|             let secret = this._content.secrets[i]; | ||||
|             let label = new St.Label({ style_class: 'prompt-dialog-password-label', | ||||
|                                        text: secret.label, | ||||
|                                        x_align: Clutter.ActorAlign.START, | ||||
|                                        y_align: Clutter.ActorAlign.CENTER }); | ||||
|                                        text: secret.label }); | ||||
|             label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; | ||||
|  | ||||
|             let reactive = secret.key != null; | ||||
|  | ||||
|             secret.entry = new St.Entry({ style_class: 'prompt-dialog-password-entry', | ||||
|                                           text: secret.value, can_focus: reactive, | ||||
|                                           reactive: reactive, | ||||
|                                           x_expand: true }); | ||||
|                                           reactive: reactive }); | ||||
|             ShellEntry.addContextMenu(secret.entry, | ||||
|                                       { isPassword: secret.password }); | ||||
|  | ||||
| @@ -120,13 +116,10 @@ const NetworkSecretDialog = new Lang.Class({ | ||||
|             } else | ||||
|                 secret.valid = true; | ||||
|  | ||||
|             if (rtl) { | ||||
|                 layout.attach(secret.entry, 0, pos, 1, 1); | ||||
|                 layout.attach(label, 1, pos, 1, 1); | ||||
|             } else { | ||||
|                 layout.attach(label, 0, pos, 1, 1); | ||||
|                 layout.attach(secret.entry, 1, pos, 1, 1); | ||||
|             } | ||||
|             layout.pack(label, 0, pos); | ||||
|             layout.child_set(label, { x_expand: false, y_fill: false, | ||||
|                                       x_align: Clutter.TableAlignment.START }); | ||||
|             layout.pack(secret.entry, 1, pos); | ||||
|             pos++; | ||||
|  | ||||
|             if (secret.password) | ||||
| @@ -517,12 +510,10 @@ const VPNRequestHandler = new Lang.Class({ | ||||
|  | ||||
|     _showNewStyleDialog: function() { | ||||
|         let keyfile = new GLib.KeyFile(); | ||||
|         let data; | ||||
|         let contentOverride; | ||||
|  | ||||
|         try { | ||||
|             data = this._dataStdout.peek_buffer(); | ||||
|  | ||||
|             let data = this._dataStdout.peek_buffer(); | ||||
|             keyfile.load_from_data(data.toString(), data.length, | ||||
|                                    GLib.KeyFileFlags.NONE); | ||||
|  | ||||
| @@ -555,16 +546,13 @@ const VPNRequestHandler = new Lang.Class({ | ||||
|                 } | ||||
|             } | ||||
|         } catch(e) { | ||||
|             // No output is a valid case it means "both secrets are stored" | ||||
|             if (data.length > 0) { | ||||
|                 logError(e, 'error while reading VPN plugin output keyfile'); | ||||
|             logError(e, 'error while reading VPN plugin output keyfile'); | ||||
|  | ||||
|                 this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR); | ||||
|                 return; | ||||
|             } | ||||
|             this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (contentOverride && contentOverride.secrets.length) { | ||||
|         if (contentOverride.secrets.length) { | ||||
|             // Only show the dialog if we actually have something to ask | ||||
|             this._shellDialog = new NetworkSecretDialog(this._agent, this._requestId, this._connection, 'vpn', [], contentOverride); | ||||
|             this._shellDialog.open(global.get_current_time()); | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
|  | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const Gio = imports.gi.Gio; | ||||
| const GLib = imports.gi.GLib; | ||||
| const Lang = imports.lang; | ||||
| @@ -29,8 +28,6 @@ const SCROLLBACK_HISTORY_LINES = 10; | ||||
| // See Notification._onEntryChanged | ||||
| const COMPOSING_STOP_TIMEOUT = 5; | ||||
|  | ||||
| const CLOCK_FORMAT_KEY = 'clock-format'; | ||||
|  | ||||
| const NotificationDirection = { | ||||
|     SENT: 'chat-sent', | ||||
|     RECEIVED: 'chat-received' | ||||
| @@ -681,7 +678,6 @@ const ChatSource = new Lang.Class({ | ||||
|             Mainloop.source_remove(this._notifyTimeoutId); | ||||
|         this._notifyTimeoutId = Mainloop.timeout_add(500, | ||||
|             Lang.bind(this, this._notifyTimeout)); | ||||
|         GLib.Source.set_name_by_id(this._notifyTimeoutId, '[gnome-shell] this._notifyTimeout'); | ||||
|     }, | ||||
|  | ||||
|     _notifyTimeout: function() { | ||||
| @@ -783,6 +779,7 @@ const ChatNotification = new Lang.Class({ | ||||
|  | ||||
|         this._createScrollArea(); | ||||
|         this._lastGroup = null; | ||||
|         this._lastGroupActor = null; | ||||
|  | ||||
|         // Keep track of the bottom position for the current adjustment and | ||||
|         // force a scroll to the bottom if things change while we were at the | ||||
| @@ -863,6 +860,13 @@ const ChatNotification = new Lang.Class({ | ||||
|             for (let i = 0; i < expired.length; i++) | ||||
|                 expired[i].actor.destroy(); | ||||
|         } | ||||
|  | ||||
|         let groups = this._contentArea.get_children(); | ||||
|         for (let i = 0; i < groups.length; i++) { | ||||
|             let group = groups[i]; | ||||
|             if (group.get_n_children() == 0) | ||||
|                 group.destroy(); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
| @@ -901,35 +905,30 @@ const ChatNotification = new Lang.Class({ | ||||
|  | ||||
|         let group = props.group; | ||||
|         if (group != this._lastGroup) { | ||||
|             let style = 'chat-group-' + group; | ||||
|             this._lastGroup = group; | ||||
|             let emptyLine = new St.Label({ style_class: 'chat-empty-line' }); | ||||
|             this.addActor(emptyLine); | ||||
|             this._history.unshift({ actor: emptyLine, time: timestamp, | ||||
|                                     realMessage: false }); | ||||
|             this._lastGroupActor = new St.BoxLayout({ style_class: style, | ||||
|                                                       vertical: true }); | ||||
|             this.addActor(this._lastGroupActor); | ||||
|         } | ||||
|  | ||||
|         let lineBox = new St.BoxLayout({ vertical: false }); | ||||
|         lineBox.add(body, props.childProps); | ||||
|         this.addActor(lineBox); | ||||
|         this._lastMessageBox = lineBox; | ||||
|         this._lastGroupActor.add(body, props.childProps); | ||||
|  | ||||
|         this.updated(); | ||||
|  | ||||
|         let timestamp = props.timestamp; | ||||
|         this._history.unshift({ actor: lineBox, time: timestamp, | ||||
|         this._history.unshift({ actor: body, time: timestamp, | ||||
|                                 realMessage: group != 'meta' }); | ||||
|  | ||||
|         if (!props.noTimestamp) { | ||||
|             if (timestamp < currentTime - SCROLLBACK_IMMEDIATE_TIME) { | ||||
|             if (timestamp < currentTime - SCROLLBACK_IMMEDIATE_TIME) | ||||
|                 this.appendTimestamp(); | ||||
|             } else { | ||||
|             else | ||||
|                 // Schedule a new timestamp in SCROLLBACK_IMMEDIATE_TIME | ||||
|                 // from the timestamp of the message. | ||||
|                 this._timestampTimeoutId = Mainloop.timeout_add_seconds( | ||||
|                     SCROLLBACK_IMMEDIATE_TIME - (currentTime - timestamp), | ||||
|                     Lang.bind(this, this.appendTimestamp)); | ||||
|                 GLib.Source.set_name_by_id(this._timestampTimeoutId, '[gnome-shell] this.appendTimestamp'); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         this._filterMessages(); | ||||
| @@ -942,77 +941,32 @@ const ChatNotification = new Lang.Class({ | ||||
|  | ||||
|         let format; | ||||
|  | ||||
|         let desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' }); | ||||
|         let clockFormat = desktopSettings.get_string(CLOCK_FORMAT_KEY); | ||||
|         let hasAmPm = date.toLocaleFormat('%p') != ''; | ||||
|  | ||||
|         if (clockFormat == '24h' || !hasAmPm) { | ||||
|             // Show only the time if date is on today | ||||
|             if(daysAgo < 1){ | ||||
|                 /* Translators: Time in 24h format */ | ||||
|                 format = _("%H\u2236%M"); | ||||
|             } | ||||
|             // Show the word "Yesterday" and time if date is on yesterday | ||||
|             else if(daysAgo <2){ | ||||
|                 /* Translators: this is the word "Yesterday" followed by a | ||||
|                  time string in 24h format. i.e. "Yesterday, 14:30" */ | ||||
|                 // xgettext:no-c-format | ||||
|                 format = _("Yesterday, %H\u2236%M"); | ||||
|             } | ||||
|             // Show a week day and time if date is in the last week | ||||
|             else if (daysAgo < 7) { | ||||
|                 /* Translators: this is the week day name followed by a time | ||||
|                  string in 24h format. i.e. "Monday, 14:30" */ | ||||
|                 // xgettext:no-c-format | ||||
|                 format = _("%A, %H\u2236%M"); | ||||
|  | ||||
|             } else if (date.getYear() == now.getYear()) { | ||||
|                 /* Translators: this is the month name and day number | ||||
|                  followed by a time string in 24h format. | ||||
|                  i.e. "May 25, 14:30" */ | ||||
|                 // xgettext:no-c-format | ||||
|                 format = _("%B %d, %H\u2236%M"); | ||||
|             } else { | ||||
|                 /* Translators: this is the month name, day number, year | ||||
|                  number followed by a time string in 24h format. | ||||
|                  i.e. "May 25 2012, 14:30" */ | ||||
|                 // xgettext:no-c-format | ||||
|                 format = _("%B %d %Y, %H\u2236%M"); | ||||
|             } | ||||
|         } else { | ||||
|             // Show only the time if date is on today | ||||
|             if(daysAgo < 1){ | ||||
|                 /* Translators: Time in 24h format */ | ||||
|                 format = _("%l\u2236%M %p"); | ||||
|             } | ||||
|             // Show the word "Yesterday" and time if date is on yesterday | ||||
|             else if(daysAgo <2){ | ||||
|                 /* Translators: this is the word "Yesterday" followed by a | ||||
|                  time string in 12h format. i.e. "Yesterday, 2:30 pm" */ | ||||
|                 // xgettext:no-c-format | ||||
|                 format = _("Yesterday, %l\u2236%M %p"); | ||||
|             } | ||||
|             // Show a week day and time if date is in the last week | ||||
|             else if (daysAgo < 7) { | ||||
|                 /* Translators: this is the week day name followed by a time | ||||
|                  string in 12h format. i.e. "Monday, 2:30 pm" */ | ||||
|                 // xgettext:no-c-format | ||||
|                 format = _("%A, %l\u2236%M %p"); | ||||
|  | ||||
|             } else if (date.getYear() == now.getYear()) { | ||||
|                 /* Translators: this is the month name and day number | ||||
|                  followed by a time string in 12h format. | ||||
|                  i.e. "May 25, 2:30 pm" */ | ||||
|                 // xgettext:no-c-format | ||||
|                 format = _("%B %d, %l\u2236%M %p"); | ||||
|             } else { | ||||
|                 /* Translators: this is the month name, day number, year | ||||
|                  number followed by a time string in 12h format. | ||||
|                  i.e. "May 25 2012, 2:30 pm"*/ | ||||
|                 // xgettext:no-c-format | ||||
|                 format = _("%B %d %Y, %l\u2236%M %p"); | ||||
|             } | ||||
|         // Show only the hour if date is on today | ||||
|         if(daysAgo < 1){ | ||||
|             format = "<b>%H:%M</b>"; | ||||
|         } | ||||
|         // Show the word "Yesterday" and time if date is on yesterday | ||||
|         else if(daysAgo <2){ | ||||
|             /* Translators: this is the word "Yesterday" followed by a time string. i.e. "Yesterday, 14:30"*/ | ||||
|             // xgettext:no-c-format | ||||
|             format = _("<b>Yesterday</b>, <b>%H:%M</b>"); | ||||
|         } | ||||
|         // Show a week day and time if date is in the last week | ||||
|         else if (daysAgo < 7) { | ||||
|             /* Translators: this is the week day name followed by a time string. i.e. "Monday, 14:30*/ | ||||
|             // xgettext:no-c-format | ||||
|             format = _("<b>%A</b>, <b>%H:%M</b>"); | ||||
|  | ||||
|         } else if (date.getYear() == now.getYear()) { | ||||
|             /* Translators: this is the month name and day number followed by a time string. i.e. "May 25, 14:30"*/ | ||||
|             // xgettext:no-c-format | ||||
|             format = _("<b>%B</b> <b>%d</b>, <b>%H:%M</b>"); | ||||
|         } else { | ||||
|             /* Translators: this is the month name, day number, year number followed by a time string. i.e. "May 25 2012, 14:30"*/ | ||||
|             // xgettext:no-c-format | ||||
|             format = _("<b>%B</b> <b>%d</b> <b>%Y</b>, <b>%H:%M</b> "); | ||||
|         } | ||||
|  | ||||
|         return date.toLocaleFormat(format); | ||||
|     }, | ||||
|  | ||||
| @@ -1022,14 +976,13 @@ const ChatNotification = new Lang.Class({ | ||||
|         let lastMessageTime = this._history[0].time; | ||||
|         let lastMessageDate = new Date(lastMessageTime * 1000); | ||||
|  | ||||
|         let timeLabel = new St.Label({ text: this._formatTimestamp(lastMessageDate), | ||||
|                                        style_class: 'chat-meta-message', | ||||
|                                        x_expand: true, | ||||
|                                        y_expand: true, | ||||
|                                        x_align: Clutter.ActorAlign.END, | ||||
|                                        y_align: Clutter.ActorAlign.END }); | ||||
|  | ||||
|         this._lastMessageBox.add_actor(timeLabel); | ||||
|         let timeLabel = this._append({ body: this._formatTimestamp(lastMessageDate), | ||||
|                                        group: 'meta', | ||||
|                                        styles: ['chat-meta-message'], | ||||
|                                        childProps: { expand: true, x_fill: false, | ||||
|                                                      x_align: St.Align.END }, | ||||
|                                        noTimestamp: true, | ||||
|                                        timestamp: lastMessageTime }); | ||||
|  | ||||
|         this._filterMessages(); | ||||
|  | ||||
| @@ -1094,7 +1047,6 @@ const ChatNotification = new Lang.Class({ | ||||
|             this._composingTimeoutId = Mainloop.timeout_add_seconds( | ||||
|                 COMPOSING_STOP_TIMEOUT, | ||||
|                 Lang.bind(this, this._composingStopTimeout)); | ||||
|             GLib.Source.set_name_by_id(this._composingTimeoutId, '[gnome-shell] this._composingStopTimeout'); | ||||
|         } else { | ||||
|             this.source.setChatState(Tp.ChannelChatState.ACTIVE); | ||||
|         } | ||||
| @@ -1265,8 +1217,7 @@ const SubscriptionRequestNotification = new Lang.Class({ | ||||
|  | ||||
|         if (file) { | ||||
|             let uri = file.get_uri(); | ||||
|             let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; | ||||
|             iconBox.child = textureCache.load_uri_async(uri, iconBox._size, iconBox._size, scaleFactor); | ||||
|             iconBox.child = textureCache.load_uri_async(uri, iconBox._size, iconBox._size); | ||||
|         } | ||||
|         else { | ||||
|             iconBox.child = new St.Icon({ icon_name: 'avatar-default', | ||||
| @@ -1417,12 +1368,7 @@ const AccountNotification = new Lang.Class({ | ||||
|                 if (status == Tp.ConnectionStatus.CONNECTED) { | ||||
|                     this.destroy(); | ||||
|                 } else if (status == Tp.ConnectionStatus.DISCONNECTED) { | ||||
|                     let connectionError = account.connection_error; | ||||
|  | ||||
|                     if (connectionError == Tp.error_get_dbus_name(Tp.Error.CANCELLED)) | ||||
|                         this.destroy(); | ||||
|                     else | ||||
|                         this.update(this.title, this._getMessage(connectionError)); | ||||
|                     this.update(this.title, this._getMessage(account.connection_error)); | ||||
|                 } | ||||
|             })); | ||||
|     }, | ||||
|   | ||||
| @@ -87,7 +87,7 @@ const CtrlAltTabManager = new Lang.Class({ | ||||
|         if (Main.sessionMode.hasWindows && !Main.overview.visible) { | ||||
|             let screen = global.screen; | ||||
|             let display = screen.get_display(); | ||||
|             let windows = display.get_tab_list(Meta.TabList.DOCKS, screen.get_active_workspace ()); | ||||
|             let windows = display.get_tab_list(Meta.TabList.DOCKS, screen, screen.get_active_workspace ()); | ||||
|             let windowTracker = Shell.WindowTracker.get_default(); | ||||
|             let textureCache = St.TextureCache.get_default(); | ||||
|             for (let i = 0; i < windows.length; i++) { | ||||
| @@ -156,19 +156,15 @@ const CtrlAltTabPopup = new Lang.Class({ | ||||
|         this._select(this._selectedIndex); | ||||
|     }, | ||||
|  | ||||
|     _keyPressHandler: function(keysym, action) { | ||||
|     _keyPressHandler: function(keysym, backwards, action) { | ||||
|         if (action == Meta.KeyBindingAction.SWITCH_PANELS) | ||||
|             this._select(this._next()); | ||||
|             this._select(backwards ? this._previous() : this._next()); | ||||
|         else if (action == Meta.KeyBindingAction.SWITCH_PANELS_BACKWARD) | ||||
|             this._select(this._previous()); | ||||
|             this._select(backwards ? this._next() : this._previous()); | ||||
|         else if (keysym == Clutter.Left) | ||||
|             this._select(this._previous()); | ||||
|         else if (keysym == Clutter.Right) | ||||
|             this._select(this._next()); | ||||
|         else | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|         return Clutter.EVENT_STOP; | ||||
|     }, | ||||
|  | ||||
|     _finish : function(time) { | ||||
|   | ||||
| @@ -381,8 +381,6 @@ const DashActor = new Lang.Class({ | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const baseIconSizes = [ 16, 22, 24, 32, 48, 64 ]; | ||||
|  | ||||
| const Dash = new Lang.Class({ | ||||
|     Name: 'Dash', | ||||
|  | ||||
| @@ -582,7 +580,6 @@ const Dash = new Lang.Class({ | ||||
|                         this._showLabelTimeoutId = 0; | ||||
|                         return GLib.SOURCE_REMOVE; | ||||
|                     })); | ||||
|                 GLib.Source.set_name_by_id(this._showLabelTimeoutId, '[gnome-shell] item.showLabel'); | ||||
|                 if (this._resetHoverTimeoutId > 0) { | ||||
|                     Mainloop.source_remove(this._resetHoverTimeoutId); | ||||
|                     this._resetHoverTimeoutId = 0; | ||||
| @@ -600,7 +597,6 @@ const Dash = new Lang.Class({ | ||||
|                         this._resetHoverTimeoutId = 0; | ||||
|                         return GLib.SOURCE_REMOVE; | ||||
|                     })); | ||||
|                 GLib.Source.set_name_by_id(this._resetHoverTimeoutId, '[gnome-shell] this._labelShowing'); | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
| @@ -636,24 +632,25 @@ const Dash = new Lang.Class({ | ||||
|         let minHeight, natHeight; | ||||
|  | ||||
|         // Enforce the current icon size during the size request | ||||
|         firstIcon.setIconSize(this.iconSize); | ||||
|         let [currentWidth, currentHeight] = firstIcon.icon.get_size(); | ||||
|  | ||||
|         firstIcon.icon.set_size(this.iconSize, this.iconSize); | ||||
|         [minHeight, natHeight] = firstButton.get_preferred_height(-1); | ||||
|  | ||||
|         let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; | ||||
|         let iconSizes = baseIconSizes.map(function(s) { | ||||
|             return s * scaleFactor; | ||||
|         }); | ||||
|         firstIcon.icon.set_size(currentWidth, currentHeight); | ||||
|  | ||||
|         // Subtract icon padding and box spacing from the available height | ||||
|         availHeight -= iconChildren.length * (natHeight - this.iconSize * scaleFactor) + | ||||
|         availHeight -= iconChildren.length * (natHeight - this.iconSize) + | ||||
|                        (iconChildren.length - 1) * spacing; | ||||
|  | ||||
|         let availSize = availHeight / iconChildren.length; | ||||
|  | ||||
|         let newIconSize = baseIconSizes[0]; | ||||
|         let iconSizes = [ 16, 22, 24, 32, 48, 64 ]; | ||||
|  | ||||
|         let newIconSize = 16; | ||||
|         for (let i = 0; i < iconSizes.length; i++) { | ||||
|             if (iconSizes[i] < availSize) | ||||
|                 newIconSize = baseIconSizes[i]; | ||||
|                 newIconSize = iconSizes[i]; | ||||
|         } | ||||
|  | ||||
|         if (newIconSize == this.iconSize) | ||||
|   | ||||
| @@ -18,7 +18,8 @@ const PanelMenu = imports.ui.panelMenu; | ||||
| const PopupMenu = imports.ui.popupMenu; | ||||
| const Calendar = imports.ui.calendar; | ||||
|  | ||||
| function _onVertSepRepaint(area) { | ||||
| function _onVertSepRepaint (area) | ||||
| { | ||||
|     let cr = area.get_context(); | ||||
|     let themeNode = area.get_theme_node(); | ||||
|     let [width, height] = area.get_surface_size(); | ||||
| @@ -32,7 +33,7 @@ function _onVertSepRepaint(area) { | ||||
|     cr.setLineWidth(stippleWidth); | ||||
|     cr.stroke(); | ||||
|     cr.$dispose(); | ||||
| } | ||||
| }; | ||||
|  | ||||
| const DateMenuButton = new Lang.Class({ | ||||
|     Name: 'DateMenuButton', | ||||
| @@ -62,17 +63,9 @@ const DateMenuButton = new Lang.Class({ | ||||
|         hbox.add(vbox); | ||||
|  | ||||
|         // Date | ||||
|         // Having the ability to go to the current date if the user is already | ||||
|         // on the current date can be confusing. So don't make the button reactive | ||||
|         // until the selected date changes. | ||||
|         this._date = new St.Button({ style_class: 'datemenu-date-label', | ||||
|                                      reactive: false | ||||
|                                    }); | ||||
|         this._date.connect('clicked', | ||||
|                            Lang.bind(this, function() { | ||||
|                                this._calendar.setDate(new Date(), false); | ||||
|                            })); | ||||
|         vbox.add(this._date, { x_fill: false  }); | ||||
|         this._date = new St.Label({ style_class: 'datemenu-date-label', | ||||
|                                     can_focus: true }); | ||||
|         vbox.add(this._date); | ||||
|  | ||||
|         this._eventList = new Calendar.EventsList(); | ||||
|         this._calendar = new Calendar.Calendar(); | ||||
| @@ -84,9 +77,6 @@ const DateMenuButton = new Lang.Class({ | ||||
|                                   // and the calender makes those dates unclickable when instantiated with | ||||
|                                   // a null event source | ||||
|                                    this._eventList.setDate(date); | ||||
|  | ||||
|                                    // Make the button reactive only if the selected date is not the current date. | ||||
|                                    this._date.can_focus = this._date.reactive = !this._isToday(date) | ||||
|                                })); | ||||
|         vbox.add(this._calendar.actor); | ||||
|  | ||||
| @@ -137,13 +127,6 @@ const DateMenuButton = new Lang.Class({ | ||||
|         this._sessionUpdated(); | ||||
|     }, | ||||
|  | ||||
|     _isToday: function(date) { | ||||
|         let now = new Date(); | ||||
|         return now.getYear() == date.getYear() && | ||||
|                now.getMonth() == date.getMonth() && | ||||
|                now.getDay() == date.getDay(); | ||||
|     }, | ||||
|  | ||||
|     _appInstalledChanged: function() { | ||||
|         this._calendarApp = undefined; | ||||
|         this._updateEventsVisibility(); | ||||
| @@ -203,7 +186,7 @@ const DateMenuButton = new Lang.Class({ | ||||
|          */ | ||||
|         let dateFormat = _("%A %B %e, %Y"); | ||||
|         let displayDate = new Date(); | ||||
|         this._date.set_label(displayDate.toLocaleFormat(dateFormat)); | ||||
|         this._date.set_text(displayDate.toLocaleFormat(dateFormat)); | ||||
|     }, | ||||
|  | ||||
|     _getCalendarApp: function() { | ||||
| @@ -211,18 +194,15 @@ const DateMenuButton = new Lang.Class({ | ||||
|             return this._calendarApp; | ||||
|  | ||||
|         let apps = Gio.AppInfo.get_recommended_for_type('text/calendar'); | ||||
|         if (apps && (apps.length > 0)) { | ||||
|             let app = Gio.AppInfo.get_default_for_type('text/calendar', false); | ||||
|             let defaultInRecommended = apps.some(function(a) { return a.equal(app); }); | ||||
|             this._calendarApp = defaultInRecommended ? app : apps[0]; | ||||
|         } else { | ||||
|         if (apps && (apps.length > 0)) | ||||
|             this._calendarApp = apps[0]; | ||||
|         else | ||||
|             this._calendarApp = null; | ||||
|         } | ||||
|         return this._calendarApp; | ||||
|     }, | ||||
|  | ||||
|     _getClockApp: function() { | ||||
|         return Shell.AppSystem.get_default().lookup_app('org.gnome.clocks.desktop'); | ||||
|         return Shell.AppSystem.get_default().lookup_app('gnome-clocks.desktop'); | ||||
|     }, | ||||
|  | ||||
|     _onOpenCalendarActivate: function() { | ||||
|   | ||||
							
								
								
									
										13
									
								
								js/ui/dnd.js
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								js/ui/dnd.js
									
									
									
									
									
								
							| @@ -46,7 +46,7 @@ let dragMonitors = []; | ||||
| function _getEventHandlerActor() { | ||||
|     if (!eventHandlerActor) { | ||||
|         eventHandlerActor = new Clutter.Actor({ width: 0, height: 0 }); | ||||
|         Main.uiGroup.add_actor(eventHandlerActor); | ||||
|         Main.layoutManager.sessionGroup.add_actor(eventHandlerActor); | ||||
|         // We connect to 'event' rather than 'captured-event' because the capturing phase doesn't happen | ||||
|         // when you've grabbed the pointer. | ||||
|         eventHandlerActor.connect('event', | ||||
| @@ -236,7 +236,7 @@ const _Draggable = new Lang.Class({ | ||||
|  | ||||
|         if (this.actor._delegate && this.actor._delegate.getDragActor) { | ||||
|             this._dragActor = this.actor._delegate.getDragActor(); | ||||
|             Main.uiGroup.add_child(this._dragActor); | ||||
|             Main.layoutManager.sessionGroup.add_child(this._dragActor); | ||||
|             this._dragActor.raise_top(); | ||||
|             Shell.util_set_hidden_from_pick(this._dragActor, true); | ||||
|  | ||||
| @@ -276,7 +276,7 @@ const _Draggable = new Lang.Class({ | ||||
|             this._dragOrigScale = this._dragActor.scale_x; | ||||
|  | ||||
|             // Set the actor's scale such that it will keep the same | ||||
|             // transformed size when it's reparented to the uiGroup | ||||
|             // transformed size when it's reparented to the sessionGroup | ||||
|             let [scaledWidth, scaledHeight] = this.actor.get_transformed_size(); | ||||
|             this._dragActor.set_scale(scaledWidth / this.actor.width, | ||||
|                                       scaledHeight / this.actor.height); | ||||
| @@ -286,7 +286,7 @@ const _Draggable = new Lang.Class({ | ||||
|             this._dragOffsetY = actorStageY - this._dragStartY; | ||||
|  | ||||
|             this._dragOrigParent.remove_actor(this._dragActor); | ||||
|             Main.uiGroup.add_child(this._dragActor); | ||||
|             Main.layoutManager.sessionGroup.add_child(this._dragActor); | ||||
|             this._dragActor.raise_top(); | ||||
|             Shell.util_set_hidden_from_pick(this._dragActor, true); | ||||
|         } | ||||
| @@ -395,7 +395,6 @@ const _Draggable = new Lang.Class({ | ||||
|  | ||||
|         this._updateHoverId = GLib.idle_add(GLib.PRIORITY_DEFAULT, | ||||
|                                             Lang.bind(this, this._updateDragHover)); | ||||
|         GLib.Source.set_name_by_id(this._updateHoverId, '[gnome-shell] this._updateDragHover'); | ||||
|     }, | ||||
|  | ||||
|     _updateDragPosition : function (event) { | ||||
| @@ -449,7 +448,7 @@ const _Draggable = new Lang.Class({ | ||||
|                                                 event.get_time())) { | ||||
|                     // If it accepted the drop without taking the actor, | ||||
|                     // handle it ourselves. | ||||
|                     if (this._dragActor.get_parent() == Main.uiGroup) { | ||||
|                     if (this._dragActor.get_parent() == Main.layoutManager.sessionGroup) { | ||||
|                         if (this._restoreOnSuccess) { | ||||
|                             this._restoreDragActor(event.get_time()); | ||||
|                             return true; | ||||
| @@ -558,7 +557,7 @@ const _Draggable = new Lang.Class({ | ||||
|  | ||||
|     _onAnimationComplete : function (dragActor, eventTime) { | ||||
|         if (this._dragOrigParent) { | ||||
|             Main.uiGroup.remove_child(this._dragActor); | ||||
|             Main.layoutManager.sessionGroup.remove_child(this._dragActor); | ||||
|             this._dragOrigParent.add_actor(this._dragActor); | ||||
|             dragActor.set_scale(this._dragOrigScale, this._dragOrigScale); | ||||
|             dragActor.set_position(this._dragOrigX, this._dragOrigY); | ||||
|   | ||||
| @@ -1,78 +0,0 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
|  | ||||
| const Lang = imports.lang; | ||||
| const Signals = imports.signals; | ||||
| const Meta = imports.gi.Meta; | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| const EDGE_THRESHOLD = 20; | ||||
| const DRAG_DISTANCE = 80; | ||||
|  | ||||
| const EdgeDragAction = new Lang.Class({ | ||||
|     Name: 'EdgeDragAction', | ||||
|     Extends: Clutter.GestureAction, | ||||
|  | ||||
|     _init : function(side) { | ||||
|         this.parent(); | ||||
|         this._side = side; | ||||
|         this.set_n_touch_points(1); | ||||
|  | ||||
|         global.display.connect('grab-op-begin', Lang.bind(this, function() { | ||||
|             this.cancel(); | ||||
|         })); | ||||
|     }, | ||||
|  | ||||
|     _getMonitorRect : function (x, y) { | ||||
|         let rect = new Meta.Rectangle({ x: x - 1, y: y - 1, width: 1, height: 1 }); | ||||
|         let monitorIndex = global.screen.get_monitor_index_for_rect(rect); | ||||
|  | ||||
|         return global.screen.get_monitor_geometry(monitorIndex); | ||||
|     }, | ||||
|  | ||||
|     vfunc_gesture_prepare : function(action, actor) { | ||||
|         if (this.get_n_current_points() == 0) | ||||
|             return false; | ||||
|  | ||||
|         let [x, y] = this.get_press_coords(0); | ||||
|         let monitorRect = this._getMonitorRect(x, y); | ||||
|  | ||||
|         return ((this._side == St.Side.LEFT && x < monitorRect.x + EDGE_THRESHOLD) || | ||||
|                 (this._side == St.Side.RIGHT && x > monitorRect.x + monitorRect.width - EDGE_THRESHOLD) || | ||||
|                 (this._side == St.Side.TOP && y < monitorRect.y + EDGE_THRESHOLD) || | ||||
|                 (this._side == St.Side.BOTTOM && y > monitorRect.y + monitorRect.height - EDGE_THRESHOLD)); | ||||
|     }, | ||||
|  | ||||
|     vfunc_gesture_progress : function (action, actor) { | ||||
|         let [startX, startY] = this.get_press_coords(0); | ||||
|         let [x, y] = this.get_motion_coords(0); | ||||
|         let offsetX = Math.abs (x - startX); | ||||
|         let offsetY = Math.abs (y - startY); | ||||
|  | ||||
|         if (offsetX < EDGE_THRESHOLD && offsetY < EDGE_THRESHOLD) | ||||
|             return true; | ||||
|  | ||||
|         if ((offsetX > offsetY && | ||||
|              (this._side == St.Side.TOP || this._side == St.Side.BOTTOM)) || | ||||
|             (offsetY > offsetX && | ||||
|              (this._side == St.Side.LEFT || this._side == St.Side.RIGHT))) { | ||||
|             this.cancel(); | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     vfunc_gesture_end : function (action, actor) { | ||||
|         let [startX, startY] = this.get_press_coords(0); | ||||
|         let [x, y] = this.get_motion_coords(0); | ||||
|         let monitorRect = this._getMonitorRect(startX, startY); | ||||
|  | ||||
|         if ((this._side == St.Side.TOP && y > monitorRect.y + DRAG_DISTANCE) || | ||||
|             (this._side == St.Side.BOTTOM && y < monitorRect.y + monitorRect.height - DRAG_DISTANCE) || | ||||
|             (this._side == St.Side.LEFT && x > monitorRect.x + DRAG_DISTANCE) || | ||||
|             (this._side == St.Side.RIGHT && x < monitorRect.x + monitorRect.width - DRAG_DISTANCE)) | ||||
|             this.emit('activated'); | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(EdgeDragAction.prototype); | ||||
| @@ -25,11 +25,9 @@ const Gio = imports.gi.Gio; | ||||
| const GLib = imports.gi.GLib; | ||||
| const Gtk = imports.gi.Gtk; | ||||
| const Pango = imports.gi.Pango; | ||||
| const Polkit = imports.gi.Polkit; | ||||
| const St = imports.gi.St; | ||||
| const Shell = imports.gi.Shell; | ||||
|  | ||||
| const CheckBox = imports.ui.checkBox; | ||||
| const GnomeSession = imports.misc.gnomeSession; | ||||
| const LoginManager = imports.misc.loginManager; | ||||
| const ModalDialog = imports.ui.modalDialog; | ||||
| @@ -38,10 +36,8 @@ const UserWidget = imports.ui.userWidget; | ||||
|  | ||||
| let _endSessionDialog = null; | ||||
|  | ||||
| const TRIGGER_OFFLINE_UPDATE = '/usr/libexec/pk-trigger-offline-update'; | ||||
|  | ||||
| const _ITEM_ICON_SIZE = 48; | ||||
| const _DIALOG_ICON_SIZE = 48; | ||||
| const _DIALOG_ICON_SIZE = 32; | ||||
|  | ||||
| const GSM_SESSION_MANAGER_LOGOUT_FORCE = 2; | ||||
|  | ||||
| @@ -75,7 +71,6 @@ const logoutDialogContent = { | ||||
|                         "You will be logged out automatically in %d seconds.", | ||||
|                         seconds).format(seconds); | ||||
|     }, | ||||
|     showBatteryWarning: false, | ||||
|     confirmButtons: [{ signal: 'ConfirmedLogout', | ||||
|                        label:  C_("button", "Log Out") }], | ||||
|     iconStyleClass: 'end-session-dialog-logout-icon', | ||||
| @@ -84,14 +79,11 @@ const logoutDialogContent = { | ||||
|  | ||||
| const shutdownDialogContent = { | ||||
|     subject: C_("title", "Power Off"), | ||||
|     subjectWithUpdates: C_("title", "Install Updates & Power Off"), | ||||
|     description: function(seconds) { | ||||
|         return ngettext("The system will power off automatically in %d second.", | ||||
|                         "The system will power off automatically in %d seconds.", | ||||
|                         seconds).format(seconds); | ||||
|     }, | ||||
|     checkBoxText: C_("checkbox", "Install pending software updates"), | ||||
|     showBatteryWarning: true, | ||||
|     confirmButtons: [{ signal: 'ConfirmedReboot', | ||||
|                        label:  C_("button", "Restart") }, | ||||
|                      { signal: 'ConfirmedShutdown', | ||||
| @@ -108,7 +100,6 @@ const restartDialogContent = { | ||||
|                         "The system will restart automatically in %d seconds.", | ||||
|                         seconds).format(seconds); | ||||
|     }, | ||||
|     showBatteryWarning: false, | ||||
|     confirmButtons: [{ signal: 'ConfirmedReboot', | ||||
|                        label:  C_("button", "Restart") }], | ||||
|     iconName: 'view-refresh-symbolic', | ||||
| @@ -124,11 +115,8 @@ const restartInstallDialogContent = { | ||||
|                         "The system will automatically restart and install updates in %d seconds.", | ||||
|                         seconds).format(seconds); | ||||
|     }, | ||||
|     showBatteryWarning: true, | ||||
|     confirmButtons: [{ signal: 'ConfirmedReboot', | ||||
|                        label:  C_("button", "Restart & Install") }], | ||||
|     unusedFutureButtonForTranslation: C_("button", "Install & Power Off"), | ||||
|     unusedFutureCheckBoxForTranslation: C_("checkbox", "Power off after updates are installed"), | ||||
|                        label:  C_("button", "Restart & Install") }], | ||||
|     iconName: 'view-refresh-symbolic', | ||||
|     iconStyleClass: 'end-session-dialog-shutdown-icon', | ||||
|     showOtherSessions: true, | ||||
| @@ -155,14 +143,6 @@ const LogindSessionIface = '<node> \ | ||||
|  | ||||
| const LogindSession = Gio.DBusProxy.makeProxyWrapper(LogindSessionIface); | ||||
|  | ||||
| const UPowerIface = '<node> \ | ||||
| <interface name="org.freedesktop.UPower"> \ | ||||
|     <property name="OnBattery" type="b" access="read"/> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| const UPowerProxy = Gio.DBusProxy.makeProxyWrapper(UPowerIface); | ||||
|  | ||||
| function findAppFromInhibitor(inhibitor) { | ||||
|     let desktopFile; | ||||
|     try { | ||||
| @@ -215,18 +195,6 @@ function _setLabelText(label, text) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| function _setCheckBoxLabel(checkBox, text) { | ||||
|     let label = checkBox.getLabelActor(); | ||||
|  | ||||
|     if (text) { | ||||
|         label.set_text(text); | ||||
|         checkBox.actor.show(); | ||||
|     } else { | ||||
|         label.set_text(''); | ||||
|         checkBox.actor.hide(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| function init() { | ||||
|     // This always returns the same singleton object | ||||
|     // By instantiating it initially, we register the | ||||
| @@ -246,20 +214,6 @@ const EndSessionDialog = new Lang.Class({ | ||||
|         this._userManager = AccountsService.UserManager.get_default(); | ||||
|         this._user = this._userManager.get_user(GLib.get_user_name()); | ||||
|         this._updatesFile = Gio.File.new_for_path('/system-update'); | ||||
|         this._preparedUpdateFile = Gio.File.new_for_path('/var/lib/PackageKit/prepared-update'); | ||||
|  | ||||
|         this._powerProxy = new UPowerProxy(Gio.DBus.system, | ||||
|                                            'org.freedesktop.UPower', | ||||
|                                            '/org/freedesktop/UPower', | ||||
|                                            Lang.bind(this, function(proxy, error) { | ||||
|                                                if (error) { | ||||
|                                                    log(error.message); | ||||
|                                                    return; | ||||
|                                                } | ||||
|                                                this._powerProxy.connect('g-properties-changed', | ||||
|                                                                         Lang.bind(this, this._sync)); | ||||
|                                                this._sync(); | ||||
|                                            })); | ||||
|  | ||||
|         this._secondsLeft = 0; | ||||
|         this._totalSecondsToStayOpen = 0; | ||||
| @@ -286,8 +240,7 @@ const EndSessionDialog = new Lang.Class({ | ||||
|                                 x_align: St.Align.END, | ||||
|                                 y_align: St.Align.START }); | ||||
|  | ||||
|         let messageLayout = new St.BoxLayout({ vertical: true, | ||||
|                                                style_class: 'end-session-dialog-layout' }); | ||||
|         let messageLayout = new St.BoxLayout({ vertical: true }); | ||||
|         mainContentLayout.add(messageLayout, | ||||
|                               { y_align: St.Align.START }); | ||||
|  | ||||
| @@ -307,16 +260,6 @@ const EndSessionDialog = new Lang.Class({ | ||||
|                           { y_fill:  true, | ||||
|                             y_align: St.Align.START }); | ||||
|  | ||||
|         this._checkBox = new CheckBox.CheckBox(); | ||||
|         this._checkBox.actor.connect('clicked', Lang.bind(this, this._sync)); | ||||
|         messageLayout.add(this._checkBox.actor); | ||||
|  | ||||
|         this._batteryWarning = new St.Label({ style_class: 'end-session-dialog-warning', | ||||
|                                               text: _("Running on battery power: please plug in before installing updates.") }); | ||||
|         this._batteryWarning.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; | ||||
|         this._batteryWarning.clutter_text.line_wrap = true; | ||||
|         messageLayout.add(this._batteryWarning); | ||||
|  | ||||
|         this._scrollView = new St.ScrollView({ style_class: 'end-session-dialog-list' }); | ||||
|         this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); | ||||
|         this.contentLayout.add(this._scrollView, | ||||
| @@ -342,12 +285,6 @@ const EndSessionDialog = new Lang.Class({ | ||||
|         this._inhibitorSection.add_actor(this._sessionHeader); | ||||
|         this._inhibitorSection.add_actor(this._sessionList); | ||||
|  | ||||
|         try { | ||||
|             this._updatesPermission = Polkit.Permission.new_sync("org.freedesktop.packagekit.trigger-offline-update", null, null); | ||||
|         } catch(e) { | ||||
|             log('No permission to trigger offline updates: %s'.format(e.toString())); | ||||
|         } | ||||
|  | ||||
|         this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(EndSessionDialogIface, this); | ||||
|         this._dbusImpl.export(Gio.DBus.session, '/org/gnome/SessionManager/EndSessionDialog'); | ||||
|     }, | ||||
| @@ -362,22 +299,13 @@ const EndSessionDialog = new Lang.Class({ | ||||
|         if (!open) | ||||
|             return; | ||||
|  | ||||
|         if (this._type == 2 && this._updatesFile.query_exists(null)) | ||||
|             this._type = 3; | ||||
|  | ||||
|         let dialogContent = DialogContent[this._type]; | ||||
|  | ||||
|         let subject = dialogContent.subject; | ||||
|  | ||||
|         // Use different title when we are installing updates | ||||
|         if (dialogContent.subjectWithUpdates && this._checkBox.actor.checked) | ||||
|             subject = dialogContent.subjectWithUpdates; | ||||
|  | ||||
|         if (dialogContent.showBatteryWarning) { | ||||
|             // Warn when running on battery power | ||||
|             if (this._powerProxy.OnBattery && this._checkBox.actor.checked) | ||||
|                 this._batteryWarning.opacity = 255; | ||||
|             else | ||||
|                 this._batteryWarning.opacity = 0; | ||||
|         } | ||||
|  | ||||
|         let description; | ||||
|         let displayTime = _roundSecondsToInterval(this._totalSecondsToStayOpen, | ||||
|                                                   this._secondsLeft, | ||||
| @@ -460,75 +388,15 @@ const EndSessionDialog = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _confirm: function(signal) { | ||||
|         let callback = Lang.bind(this, function() { | ||||
|             this._fadeOutDialog(); | ||||
|             this._stopTimer(); | ||||
|             this._dbusImpl.emit_signal(signal, null); | ||||
|         }); | ||||
|  | ||||
|         // Offline update not available; just emit the signal | ||||
|         if (!this._checkBox.actor.visible) { | ||||
|             callback(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // Trigger the offline update as requested | ||||
|         if (this._checkBox.actor.checked) { | ||||
|             switch (signal) { | ||||
|                 case "ConfirmedReboot": | ||||
|                     this._triggerOfflineUpdateReboot(callback); | ||||
|                     break; | ||||
|                 case "ConfirmedShutdown": | ||||
|                     // To actually trigger the offline update, we need to | ||||
|                     // reboot to do the upgrade. When the upgrade is complete, | ||||
|                     // the computer will shut down automatically. | ||||
|                     signal = "ConfirmedReboot"; | ||||
|                     this._triggerOfflineUpdateShutdown(callback); | ||||
|                     break; | ||||
|                 default: | ||||
|                     callback(); | ||||
|                     break; | ||||
|             } | ||||
|         } else { | ||||
|             this._triggerOfflineUpdateCancel(callback); | ||||
|         } | ||||
|         this._fadeOutDialog(); | ||||
|         this._stopTimer(); | ||||
|         this._dbusImpl.emit_signal(signal, null); | ||||
|     }, | ||||
|  | ||||
|     _onOpened: function() { | ||||
|         this._sync(); | ||||
|     }, | ||||
|  | ||||
|     _triggerOfflineUpdateReboot: function(callback) { | ||||
|         this._pkexecSpawn([TRIGGER_OFFLINE_UPDATE, 'reboot'], callback); | ||||
|     }, | ||||
|  | ||||
|     _triggerOfflineUpdateShutdown: function(callback) { | ||||
|         this._pkexecSpawn([TRIGGER_OFFLINE_UPDATE, 'power-off'], callback); | ||||
|     }, | ||||
|  | ||||
|     _triggerOfflineUpdateCancel: function(callback) { | ||||
|         this._pkexecSpawn([TRIGGER_OFFLINE_UPDATE, '--cancel'], callback); | ||||
|     }, | ||||
|  | ||||
|     _pkexecSpawn: function(argv, callback) { | ||||
|         let ret, pid; | ||||
|         try { | ||||
|             [ret, pid] = GLib.spawn_async(null, ['pkexec'].concat(argv), null, | ||||
|                                           GLib.SpawnFlags.DO_NOT_REAP_CHILD | GLib.SpawnFlags.SEARCH_PATH, | ||||
|                                           null); | ||||
|         } catch (e) { | ||||
|             log('Error spawning "pkexec %s": %s'.format(argv.join(' '), e.toString())); | ||||
|             callback(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, function(pid, status) { | ||||
|             GLib.spawn_close_pid(pid); | ||||
|  | ||||
|             callback(); | ||||
|         }); | ||||
|     }, | ||||
|  | ||||
|     _startTimer: function() { | ||||
|         let startTime = GLib.get_monotonic_time(); | ||||
|         this._secondsLeft = this._totalSecondsToStayOpen; | ||||
| @@ -551,7 +419,6 @@ const EndSessionDialog = new Lang.Class({ | ||||
|  | ||||
|                 return GLib.SOURCE_REMOVE; | ||||
|             })); | ||||
|         GLib.Source.set_name_by_id(this._timerId, '[gnome-shell] this._confirm'); | ||||
|     }, | ||||
|  | ||||
|     _stopTimer: function() { | ||||
| @@ -677,9 +544,6 @@ const EndSessionDialog = new Lang.Class({ | ||||
|         this._totalSecondsToStayOpen = totalSecondsToStayOpen; | ||||
|         this._type = type; | ||||
|  | ||||
|         if (this._type == 2 && this._updatesFile.query_exists(null)) | ||||
|             this._type = 3; | ||||
|  | ||||
|         this._applications = []; | ||||
|         this._applicationList.destroy_all_children(); | ||||
|  | ||||
| @@ -692,8 +556,6 @@ const EndSessionDialog = new Lang.Class({ | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let dialogContent = DialogContent[this._type]; | ||||
|  | ||||
|         for (let i = 0; i < inhibitorObjectPaths.length; i++) { | ||||
|             let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i], Lang.bind(this, function(proxy, error) { | ||||
|                 this._onInhibitorLoaded(proxy); | ||||
| @@ -702,23 +564,9 @@ const EndSessionDialog = new Lang.Class({ | ||||
|             this._applications.push(inhibitor); | ||||
|         } | ||||
|  | ||||
|         if (dialogContent.showOtherSessions) | ||||
|         if (DialogContent[type].showOtherSessions) | ||||
|             this._loadSessions(); | ||||
|  | ||||
|         let preparedUpdate = this._preparedUpdateFile.query_exists(null); | ||||
|         let updateAlreadyTriggered = this._updatesFile.query_exists(null); | ||||
|         let updatesAllowed = this._updatesPermission && this._updatesPermission.allowed; | ||||
|  | ||||
|         _setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText); | ||||
|         this._checkBox.actor.visible = (dialogContent.checkBoxText && preparedUpdate && updatesAllowed); | ||||
|         this._checkBox.actor.checked = (preparedUpdate && updateAlreadyTriggered); | ||||
|  | ||||
|         // We show the warning either together with the checkbox, or when | ||||
|         // updates have already been triggered, but the user doesn't have | ||||
|         // enough permissions to cancel them. | ||||
|         this._batteryWarning.visible = (dialogContent.showBatteryWarning && | ||||
|                                         (this._checkBox.actor.visible || preparedUpdate && updateAlreadyTriggered && !updatesAllowed)); | ||||
|  | ||||
|         this._updateButtons(); | ||||
|  | ||||
|         if (!this.open(timestamp)) { | ||||
|   | ||||
| @@ -5,8 +5,6 @@ imports.gi.versions.Gio = '2.0'; | ||||
| imports.gi.versions.Gdk = '3.0'; | ||||
| imports.gi.versions.GdkPixbuf = '2.0'; | ||||
| imports.gi.versions.Gtk = '3.0'; | ||||
| imports.gi.versions.TelepathyGLib = '0.12'; | ||||
| imports.gi.versions.TelepathyLogger = '0.2'; | ||||
|  | ||||
| const Clutter = imports.gi.Clutter;; | ||||
| const Gettext = imports.gettext; | ||||
| @@ -47,11 +45,8 @@ function _patchLayoutClass(layoutClass, styleProps) { | ||||
|         layoutClass.prototype.hookup_style = function(container) { | ||||
|             container.connect('style-changed', Lang.bind(this, function() { | ||||
|                 let node = container.get_theme_node(); | ||||
|                 for (let prop in styleProps) { | ||||
|                     let [found, length] = node.lookup_length(styleProps[prop], false); | ||||
|                     if (found) | ||||
|                         this[prop] = length; | ||||
|                 } | ||||
|                 for (let prop in styleProps) | ||||
|                     this[prop] = node.get_length(styleProps[prop]); | ||||
|             })); | ||||
|         }; | ||||
|     layoutClass.prototype.child_set = function(actor, props) { | ||||
|   | ||||
| @@ -38,7 +38,6 @@ const connect = Lang.bind(_signals, _signals.connect); | ||||
| const disconnect = Lang.bind(_signals, _signals.disconnect); | ||||
|  | ||||
| const ENABLED_EXTENSIONS_KEY = 'enabled-extensions'; | ||||
| const EXTENSION_DISABLE_VERSION_CHECK_KEY = 'disable-extension-version-validation'; | ||||
|  | ||||
| var initted = false; | ||||
| var enabled; | ||||
| @@ -157,9 +156,7 @@ function loadExtension(extension) { | ||||
|     // Default to error, we set success as the last step | ||||
|     extension.state = ExtensionState.ERROR; | ||||
|  | ||||
|     let checkVersion = !global.settings.get_boolean(EXTENSION_DISABLE_VERSION_CHECK_KEY); | ||||
|  | ||||
|     if (checkVersion && ExtensionUtils.isOutOfDate(extension)) { | ||||
|     if (ExtensionUtils.isOutOfDate(extension)) { | ||||
|         extension.state = ExtensionState.OUT_OF_DATE; | ||||
|     } else { | ||||
|         let enabled = enabledExtensions.indexOf(extension.uuid) != -1; | ||||
| @@ -270,19 +267,8 @@ function onEnabledExtensionsChanged() { | ||||
|     enabledExtensions = newEnabledExtensions; | ||||
| } | ||||
|  | ||||
| function _onVersionValidationChanged() { | ||||
|     if (Main.sessionMode.allowExtensions) { | ||||
|         enabledExtensions.forEach(function(uuid) { | ||||
|             if (ExtensionUtils.extensions[uuid]) | ||||
|                 reloadExtension(ExtensionUtils.extensions[uuid]); | ||||
|         }); | ||||
|     } | ||||
| } | ||||
|  | ||||
| function _loadExtensions() { | ||||
|     global.settings.connect('changed::' + ENABLED_EXTENSIONS_KEY, onEnabledExtensionsChanged); | ||||
|     global.settings.connect('changed::' + EXTENSION_DISABLE_VERSION_CHECK_KEY, _onVersionValidationChanged); | ||||
|  | ||||
|     enabledExtensions = getEnabledExtensions(); | ||||
|  | ||||
|     let finder = new ExtensionUtils.ExtensionFinder(); | ||||
|   | ||||
| @@ -32,11 +32,9 @@ const FocusCaretTracker = new Lang.Class({ | ||||
|     Name: 'FocusCaretTracker', | ||||
|  | ||||
|     _init: function() { | ||||
|         Atspi.init(); | ||||
|         Atspi.set_timeout(250, 250); | ||||
|         this._atspiListener = Atspi.EventListener.new(Lang.bind(this, this._onChanged)); | ||||
|  | ||||
|         this._atspiInited = false; | ||||
|         this._focusListenerRegistered = false; | ||||
|         this._caretListenerRegistered = false; | ||||
|     }, | ||||
|  | ||||
|     _onChanged: function(event) { | ||||
| @@ -46,50 +44,22 @@ const FocusCaretTracker = new Lang.Class({ | ||||
|             this.emit('caret-moved', event); | ||||
|     }, | ||||
|  | ||||
|     _initAtspi: function() { | ||||
|         if (!this._atspiInited) { | ||||
|             Atspi.init(); | ||||
|             Atspi.set_timeout(250, 250); | ||||
|             this._atspiInited = true; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     registerFocusListener: function() { | ||||
|         if (this._focusListenerRegistered) | ||||
|             return; | ||||
|  | ||||
|         this._initAtspi(); | ||||
|  | ||||
|         this._atspiListener.register(STATECHANGED + ':focused'); | ||||
|         this._atspiListener.register(STATECHANGED + ':selected'); | ||||
|         this._focusListenerRegistered = true; | ||||
|         return this._atspiListener.register(STATECHANGED + ':focused') && | ||||
|                this._atspiListener.register(STATECHANGED + ':selected'); | ||||
|     }, | ||||
|  | ||||
|     registerCaretListener: function() { | ||||
|         if (this._caretListenerRegistered) | ||||
|             return; | ||||
|  | ||||
|         this._initAtspi(); | ||||
|  | ||||
|         this._atspiListener.register(CARETMOVED); | ||||
|         this._caretListenerRegistered = true; | ||||
|         return this._atspiListener.register(CARETMOVED); | ||||
|     }, | ||||
|  | ||||
|     deregisterFocusListener: function() { | ||||
|         if (!this._focusListenerRegistered) | ||||
|             return; | ||||
|  | ||||
|         this._atspiListener.deregister(STATECHANGED + ':focused'); | ||||
|         this._atspiListener.deregister(STATECHANGED + ':selected'); | ||||
|         this._focusListenerRegistered = false; | ||||
|         return this._atspiListener.deregister(STATECHANGED + ':focused') && | ||||
|                this._atspiListener.deregister(STATECHANGED + ':selected'); | ||||
|     }, | ||||
|  | ||||
|     deregisterCaretListener: function() { | ||||
|         if (!this._caretListenerRegistered) | ||||
|             return; | ||||
|  | ||||
|         this._atspiListener.deregister(CARETMOVED); | ||||
|         this._caretListenerRegistered = false; | ||||
|         return this._atspiListener.deregister(CARETMOVED); | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(FocusCaretTracker.prototype); | ||||
|   | ||||
| @@ -56,7 +56,7 @@ const GrabHelper = new Lang.Class({ | ||||
|         this._grabStack = []; | ||||
|  | ||||
|         this._actors = []; | ||||
|         this._ignoreUntilRelease = false; | ||||
|         this._ignoreRelease = false; | ||||
|  | ||||
|         this._modalCount = 0; | ||||
|     }, | ||||
| @@ -215,7 +215,7 @@ const GrabHelper = new Lang.Class({ | ||||
|  | ||||
|         _popGrabHelper(this); | ||||
|  | ||||
|         this._ignoreUntilRelease = false; | ||||
|         this._ignoreRelease = false; | ||||
|  | ||||
|         Main.popModal(this._owner); | ||||
|         global.sync_pointer(); | ||||
| @@ -228,7 +228,7 @@ const GrabHelper = new Lang.Class({ | ||||
|     // like the ComboBoxMenu that go away on press, but need to eat | ||||
|     // the next release event. | ||||
|     ignoreRelease: function() { | ||||
|         this._ignoreUntilRelease = true; | ||||
|         this._ignoreRelease = true; | ||||
|     }, | ||||
|  | ||||
|     // ungrab: | ||||
| @@ -283,22 +283,12 @@ const GrabHelper = new Lang.Class({ | ||||
|             return Clutter.EVENT_STOP; | ||||
|         } | ||||
|  | ||||
|         let motion = type == Clutter.EventType.MOTION; | ||||
|         let press = type == Clutter.EventType.BUTTON_PRESS; | ||||
|         let release = type == Clutter.EventType.BUTTON_RELEASE; | ||||
|         let button = press || release; | ||||
|  | ||||
|         let touchUpdate = type == Clutter.EventType.TOUCH_UPDATE; | ||||
|         let touchBegin = type == Clutter.EventType.TOUCH_BEGIN; | ||||
|         let touchEnd = type == Clutter.EventType.TOUCH_END; | ||||
|         let touch = touchUpdate || touchBegin || touchEnd; | ||||
|  | ||||
|         if (touch && !global.display.is_pointer_emulating_sequence (event.get_event_sequence())) | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|         if (this._ignoreUntilRelease && (motion || release || touch)) { | ||||
|             if (release || touchEnd) | ||||
|                 this._ignoreUntilRelease = false; | ||||
|         if (release && this._ignoreRelease) { | ||||
|             this._ignoreRelease = false; | ||||
|             return Clutter.EVENT_STOP; | ||||
|         } | ||||
|  | ||||
| @@ -308,12 +298,11 @@ const GrabHelper = new Lang.Class({ | ||||
|         if (Main.keyboard.shouldTakeEvent(event)) | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|         if (button || touchBegin) { | ||||
|             // If we have a press event, ignore the next | ||||
|             // motion/release events. | ||||
|             if (press || touchBegin) | ||||
|                 this._ignoreUntilRelease = true; | ||||
|  | ||||
|         if (button) { | ||||
|             // If we have a press event, ignore the next event, | ||||
|             // which should be a release event. | ||||
|             if (press) | ||||
|                 this._ignoreRelease = true; | ||||
|             let i = this._actorInGrabStack(event.get_source()) + 1; | ||||
|             this.ungrab({ actor: this._grabStack[i].actor, isUser: true }); | ||||
|             return Clutter.EVENT_STOP; | ||||
|   | ||||
| @@ -11,9 +11,6 @@ const Main = imports.ui.main; | ||||
|  | ||||
| const MAX_CANDIDATES_PER_PAGE = 16; | ||||
|  | ||||
| const DEFAULT_INDEX_LABELS = [ '1', '2', '3', '4', '5', '6', '7', '8', | ||||
|                                '9', '0', 'a', 'b', 'c', 'd', 'e', 'f' ]; | ||||
|  | ||||
| const CandidateArea = new Lang.Class({ | ||||
|     Name: 'CandidateArea', | ||||
|  | ||||
| @@ -92,7 +89,7 @@ const CandidateArea = new Lang.Class({ | ||||
|             if (!visible) | ||||
|                 continue; | ||||
|  | ||||
|             box._indexLabel.text = ((indexes && indexes[i]) ? indexes[i] : DEFAULT_INDEX_LABELS[i]); | ||||
|             box._indexLabel.text = ((indexes && indexes[i]) ? indexes[i] : '%x'.format(i + 1)); | ||||
|             box._candidateLabel.text = candidates[i]; | ||||
|         } | ||||
|  | ||||
| @@ -158,7 +155,7 @@ const CandidatePopup = new Lang.Class({ | ||||
|  | ||||
|         panelService.connect('set-cursor-location', | ||||
|                              Lang.bind(this, function(ps, x, y, w, h) { | ||||
|                                  Main.layoutManager.setDummyCursorGeometry(x, y, w, h); | ||||
|                                  Main.layoutManager.setDummyCursorPosition(x, y); | ||||
|                                  if (this._boxPointer.actor.visible) | ||||
|                                      this._boxPointer.setPosition(Main.layoutManager.dummyCursor, 0); | ||||
|                              })); | ||||
|   | ||||
| @@ -10,29 +10,12 @@ const St = imports.gi.St; | ||||
| const Lang = imports.lang; | ||||
| const Params = imports.misc.params; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const Main = imports.ui.main; | ||||
|  | ||||
| const ICON_SIZE = 96; | ||||
| const MIN_ICON_SIZE = 16; | ||||
|  | ||||
| const EXTRA_SPACE_ANIMATION_TIME = 0.25; | ||||
|  | ||||
| const ANIMATION_TIME_IN = 0.350; | ||||
| const ANIMATION_TIME_OUT = 1/2 * ANIMATION_TIME_IN; | ||||
| const ANIMATION_MAX_DELAY_FOR_ITEM = 2/3 * ANIMATION_TIME_IN; | ||||
| const ANIMATION_MAX_DELAY_OUT_FOR_ITEM = 2/3 * ANIMATION_TIME_OUT; | ||||
| const ANIMATION_FADE_IN_TIME_FOR_ITEM = 1/4 * ANIMATION_TIME_IN; | ||||
|  | ||||
| const ANIMATION_BOUNCE_ICON_SCALE = 1.1; | ||||
|  | ||||
| const AnimationDirection = { | ||||
|     IN: 0, | ||||
|     OUT: 1 | ||||
| }; | ||||
|  | ||||
| const APPICON_ANIMATION_OUT_SCALE = 3; | ||||
| const APPICON_ANIMATION_OUT_TIME = 0.25; | ||||
|  | ||||
| const BaseIcon = new Lang.Class({ | ||||
|     Name: 'BaseIcon', | ||||
|  | ||||
| @@ -160,6 +143,11 @@ const BaseIcon = new Lang.Class({ | ||||
|         this.icon = this.createIcon(this.iconSize); | ||||
|  | ||||
|         this._iconBin.child = this.icon; | ||||
|  | ||||
|         // The icon returned by createIcon() might actually be smaller than | ||||
|         // the requested icon size (for instance StTextureCache does this | ||||
|         // for fallback icons), so set the size explicitly. | ||||
|         this._iconBin.set_size(this.iconSize, this.iconSize); | ||||
|     }, | ||||
|  | ||||
|     _onStyleChanged: function() { | ||||
| @@ -190,55 +178,9 @@ const BaseIcon = new Lang.Class({ | ||||
|  | ||||
|     _onIconThemeChanged: function() { | ||||
|         this._createIconTexture(this.iconSize); | ||||
|     }, | ||||
|  | ||||
|     animateZoomOut: function() { | ||||
|         // Animate only the child instead of the entire actor, so the | ||||
|         // styles like hover and running are not applied while | ||||
|         // animating. | ||||
|         zoomOutActor(this.actor.child); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| function clamp(value, min, max) { | ||||
|     return Math.max(Math.min(value, max), min); | ||||
| }; | ||||
|  | ||||
| function zoomOutActor(actor) { | ||||
|     let actorClone = new Clutter.Clone({ source: actor, | ||||
|                                          reactive: false }); | ||||
|     let [width, height] = actor.get_transformed_size(); | ||||
|     let [x, y] = actor.get_transformed_position(); | ||||
|     actorClone.set_size(width, height); | ||||
|     actorClone.set_position(x, y); | ||||
|     actorClone.opacity = 255; | ||||
|     actorClone.set_pivot_point(0.5, 0.5); | ||||
|  | ||||
|     Main.uiGroup.add_actor(actorClone); | ||||
|  | ||||
|     // Avoid monitor edges to not zoom outside the current monitor | ||||
|     let monitor = Main.layoutManager.findMonitorForActor(actor); | ||||
|     let scaledWidth = width * APPICON_ANIMATION_OUT_SCALE; | ||||
|     let scaledHeight = height * APPICON_ANIMATION_OUT_SCALE; | ||||
|     let scaledX = x - (scaledWidth - width) / 2; | ||||
|     let scaledY = y - (scaledHeight - height) / 2; | ||||
|     let containedX = clamp(scaledX, monitor.x, monitor.x + monitor.width - scaledWidth); | ||||
|     let containedY = clamp(scaledY, monitor.y, monitor.y + monitor.height - scaledHeight); | ||||
|  | ||||
|     Tweener.addTween(actorClone, | ||||
|                      { time: APPICON_ANIMATION_OUT_TIME, | ||||
|                        scale_x: APPICON_ANIMATION_OUT_SCALE, | ||||
|                        scale_y: APPICON_ANIMATION_OUT_SCALE, | ||||
|                        translation_x: containedX - scaledX, | ||||
|                        translation_y: containedY - scaledY, | ||||
|                        opacity: 0, | ||||
|                        transition: 'easeOutQuad', | ||||
|                        onComplete: function() { | ||||
|                            actorClone.destroy(); | ||||
|                        } | ||||
|                     }); | ||||
| } | ||||
|  | ||||
| const IconGrid = new Lang.Class({ | ||||
|     Name: 'IconGrid', | ||||
|  | ||||
| @@ -277,20 +219,6 @@ const IconGrid = new Lang.Class({ | ||||
|         this._grid.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth)); | ||||
|         this._grid.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight)); | ||||
|         this._grid.connect('allocate', Lang.bind(this, this._allocate)); | ||||
|         this._grid.connect('actor-added', Lang.bind(this, this._childAdded)); | ||||
|         this._grid.connect('actor-removed', Lang.bind(this, this._childRemoved)); | ||||
|     }, | ||||
|  | ||||
|     _keyFocusIn: function(actor) { | ||||
|         this.emit('key-focus-in', actor); | ||||
|     }, | ||||
|  | ||||
|     _childAdded: function(grid, child) { | ||||
|         child._iconGridKeyFocusInId = child.connect('key-focus-in', Lang.bind(this, this._keyFocusIn)); | ||||
|     }, | ||||
|  | ||||
|     _childRemoved: function(grid, child) { | ||||
|         child.disconnect(child._iconGridKeyFocusInId); | ||||
|     }, | ||||
|  | ||||
|     _getPreferredWidth: function (grid, forHeight, alloc) { | ||||
| @@ -401,207 +329,15 @@ const IconGrid = new Lang.Class({ | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Intended to be override by subclasses if they need a different | ||||
|      * set of items to be animated. | ||||
|      */ | ||||
|     _getChildrenToAnimate: function() { | ||||
|         return this._getVisibleChildren(); | ||||
|     }, | ||||
|  | ||||
|     _animationDone: function() { | ||||
|         this._animating = false; | ||||
|         this.emit('animation-done'); | ||||
|     }, | ||||
|  | ||||
|     animatePulse: function(animationDirection) { | ||||
|         if (animationDirection != AnimationDirection.IN) | ||||
|             throw new Error("Pulse animation only implements 'in' animation direction"); | ||||
|  | ||||
|         if (this._animating) | ||||
|             return; | ||||
|  | ||||
|         this._animating = true; | ||||
|  | ||||
|         let actors = this._getChildrenToAnimate(); | ||||
|         if (actors.length == 0) { | ||||
|             this._animationDone(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         for (let index = 0; index < actors.length; index++) { | ||||
|             let actor = actors[index]; | ||||
|             actor.opacity = 0; | ||||
|             actor.reactive = false; | ||||
|  | ||||
|             let delay = index / actors.length * ANIMATION_MAX_DELAY_FOR_ITEM; | ||||
|             let [originalX, originalY] = actor.get_transformed_position(); | ||||
|             let [originalWidth, originalHeight,,] = this._getAllocatedChildSizeAndSpacing(actor); | ||||
|  | ||||
|             let actorClone = new Clutter.Clone({ source: actor }); | ||||
|             Main.uiGroup.add_actor(actorClone); | ||||
|  | ||||
|             actorClone.set_position(originalX, originalY); | ||||
|             actorClone.set_scale(0, 0); | ||||
|             actorClone.set_pivot_point(0.5, 0.5); | ||||
|             actorClone.set_size(originalWidth, originalHeight); | ||||
|  | ||||
|             let bounceUpTime = ANIMATION_TIME_IN / 4; | ||||
|             // Defeat onComplete anonymous function closure | ||||
|             let isLastItem = index == actors.length - 1; | ||||
|             Tweener.addTween(actorClone, | ||||
|                             { time: bounceUpTime, | ||||
|                               transition: 'easeInOutQuad', | ||||
|                               delay: delay, | ||||
|                               scale_x: ANIMATION_BOUNCE_ICON_SCALE, | ||||
|                               scale_y: ANIMATION_BOUNCE_ICON_SCALE, | ||||
|                               onComplete: Lang.bind(this, function() { | ||||
|                                   Tweener.addTween(actorClone, | ||||
|                                                    { time: ANIMATION_TIME_IN - bounceUpTime, | ||||
|                                                      transition: 'easeInOutQuad', | ||||
|                                                      scale_x: 1, | ||||
|                                                      scale_y: 1, | ||||
|                                                      onComplete: Lang.bind(this, function() { | ||||
|                                                         if (isLastItem) | ||||
|                                                             this._animationDone(); | ||||
|  | ||||
|                                                         actor.opacity = 255; | ||||
|                                                         actor.reactive = true; | ||||
|                                                         actorClone.destroy(); | ||||
|                                                     }) | ||||
|                                                    }); | ||||
|                               }) | ||||
|                             }); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     animateSpring: function(animationDirection, sourceActor) { | ||||
|         if (this._animating) | ||||
|             return; | ||||
|  | ||||
|         this._animating = true; | ||||
|  | ||||
|         let actors = this._getChildrenToAnimate(); | ||||
|         if (actors.length == 0) { | ||||
|             this._animationDone(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let [sourceX, sourceY] = sourceActor.get_transformed_position(); | ||||
|         let [sourceWidth, sourceHeight] = sourceActor.get_size(); | ||||
|         // Get the center | ||||
|         let [sourceCenterX, sourceCenterY] = [sourceX + sourceWidth / 2, sourceY + sourceHeight / 2]; | ||||
|         // Design decision, 1/2 of the source actor size. | ||||
|         let [sourceScaledWidth, sourceScaledHeight] = [sourceWidth / 2, sourceHeight / 2]; | ||||
|  | ||||
|         actors.forEach(function(actor) { | ||||
|             let [actorX, actorY] = actor._transformedPosition = actor.get_transformed_position(); | ||||
|             let [x, y] = [actorX - sourceX, actorY - sourceY]; | ||||
|             actor._distance = Math.sqrt(x * x + y * y); | ||||
|         }); | ||||
|         let maxDist = actors.reduce(function(prev, cur) { | ||||
|             return Math.max(prev, cur._distance); | ||||
|         }, 0); | ||||
|         let minDist = actors.reduce(function(prev, cur) { | ||||
|             return Math.min(prev, cur._distance); | ||||
|         }, Infinity); | ||||
|         let normalization = maxDist - minDist; | ||||
|  | ||||
|         for (let index = 0; index < actors.length; index++) { | ||||
|             let actor = actors[index]; | ||||
|             actor.opacity = 0; | ||||
|             actor.reactive = false; | ||||
|  | ||||
|             let actorClone = new Clutter.Clone({ source: actor }); | ||||
|             Main.uiGroup.add_actor(actorClone); | ||||
|  | ||||
|             let [width, height,,] = this._getAllocatedChildSizeAndSpacing(actor); | ||||
|             actorClone.set_size(width, height); | ||||
|             let scaleX = sourceScaledWidth / width; | ||||
|             let scaleY = sourceScaledHeight / height; | ||||
|             let [adjustedSourcePositionX, adjustedSourcePositionY] = [sourceCenterX - sourceScaledWidth / 2, sourceCenterY - sourceScaledHeight / 2]; | ||||
|  | ||||
|             // Defeat onComplete anonymous function closure | ||||
|             let isLastItem = index == actors.length - 1; | ||||
|  | ||||
|             let movementParams, fadeParams; | ||||
|             if (animationDirection == AnimationDirection.IN) { | ||||
|                 actorClone.opacity = 0; | ||||
|                 actorClone.set_scale(scaleX, scaleY); | ||||
|  | ||||
|                 actorClone.set_position(adjustedSourcePositionX, adjustedSourcePositionY); | ||||
|  | ||||
|                 let delay = (1 - (actor._distance - minDist) / normalization) * ANIMATION_MAX_DELAY_FOR_ITEM; | ||||
|                 let [finalX, finalY]  = actor._transformedPosition; | ||||
|                 movementParams = { time: ANIMATION_TIME_IN, | ||||
|                                    transition: 'easeInOutQuad', | ||||
|                                    delay: delay, | ||||
|                                    x: finalX, | ||||
|                                    y: finalY, | ||||
|                                    scale_x: 1, | ||||
|                                    scale_y: 1, | ||||
|                                    onComplete: Lang.bind(this, function() { | ||||
|                                        if (isLastItem) | ||||
|                                            this._animationDone(); | ||||
|  | ||||
|                                        actor.opacity = 255; | ||||
|                                        actor.reactive = true; | ||||
|                                        actorClone.destroy(); | ||||
|                                    })}; | ||||
|                 fadeParams = { time: ANIMATION_FADE_IN_TIME_FOR_ITEM, | ||||
|                                transition: 'easeInOutQuad', | ||||
|                                delay: delay, | ||||
|                                opacity: 255 }; | ||||
|             } else { | ||||
|                 let [startX, startY]  = actor._transformedPosition; | ||||
|                 actorClone.set_position(startX, startY); | ||||
|  | ||||
|                 let delay = (actor._distance - minDist) / normalization * ANIMATION_MAX_DELAY_OUT_FOR_ITEM; | ||||
|                 movementParams = { time: ANIMATION_TIME_OUT, | ||||
|                                    transition: 'easeInOutQuad', | ||||
|                                    delay: delay, | ||||
|                                    x: adjustedSourcePositionX, | ||||
|                                    y: adjustedSourcePositionY, | ||||
|                                    scale_x: scaleX, | ||||
|                                    scale_y: scaleY, | ||||
|                                    onComplete: Lang.bind(this, function() { | ||||
|                                        if (isLastItem) { | ||||
|                                            this._animationDone(); | ||||
|                                            this._restoreItemsOpacity(); | ||||
|                                        } | ||||
|                                        actorClone.destroy(); | ||||
|                                    })}; | ||||
|                 fadeParams = { time: ANIMATION_FADE_IN_TIME_FOR_ITEM, | ||||
|                                transition: 'easeInOutQuad', | ||||
|                                delay: ANIMATION_TIME_OUT + delay - ANIMATION_FADE_IN_TIME_FOR_ITEM, | ||||
|                                opacity: 0 }; | ||||
|             } | ||||
|  | ||||
|  | ||||
|             Tweener.addTween(actorClone, movementParams); | ||||
|             Tweener.addTween(actorClone, fadeParams); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _restoreItemsOpacity: function() { | ||||
|         for (let index = 0; index < this._items.length; index++) { | ||||
|             this._items[index].actor.opacity = 255; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _getAllocatedChildSizeAndSpacing: function(child) { | ||||
|         let [,, natWidth, natHeight] = child.get_preferred_size(); | ||||
|         let width = Math.min(this._getHItemSize(), natWidth); | ||||
|         let xSpacing = Math.max(0, width - natWidth) / 2; | ||||
|         let height = Math.min(this._getVItemSize(), natHeight); | ||||
|         let ySpacing = Math.max(0, height - natHeight) / 2; | ||||
|         return [width, height, xSpacing, ySpacing]; | ||||
|     }, | ||||
|  | ||||
|     _calculateChildBox: function(child, x, y, box) { | ||||
|         let [childMinWidth, childMinHeight, childNaturalWidth, childNaturalHeight] = | ||||
|              child.get_preferred_size(); | ||||
|  | ||||
|         /* Center the item in its allocation horizontally */ | ||||
|         let [width, height, childXSpacing, childYSpacing] = | ||||
|             this._getAllocatedChildSizeAndSpacing(child); | ||||
|         let width = Math.min(this._getHItemSize(), childNaturalWidth); | ||||
|         let childXSpacing = Math.max(0, width - childNaturalWidth) / 2; | ||||
|         let height = Math.min(this._getVItemSize(), childNaturalHeight); | ||||
|         let childYSpacing = Math.max(0, height - childNaturalHeight) / 2; | ||||
|  | ||||
|         let childBox = new Clutter.ActorBox(); | ||||
|         if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) { | ||||
| @@ -777,22 +513,25 @@ const IconGrid = new Lang.Class({ | ||||
|             this._fixedHItemSize = Math.max(this._hItemSize - neededSpacePerItem, MIN_ICON_SIZE); | ||||
|             this._fixedVItemSize = Math.max(this._vItemSize - neededSpacePerItem, MIN_ICON_SIZE); | ||||
|  | ||||
|             if (this._fixedHItemSize < MIN_ICON_SIZE) | ||||
|                 this._fixedHItemSize = MIN_ICON_SIZE; | ||||
|             if (this._fixedVItemSize < MIN_ICON_SIZE) | ||||
|                 this._fixedVItemSize = MIN_ICON_SIZE; | ||||
|  | ||||
|             this._updateSpacingForSize(availWidth, availHeight); | ||||
|         } | ||||
|         Meta.later_add(Meta.LaterType.BEFORE_REDRAW, | ||||
|                        Lang.bind(this, this._updateIconSizes)); | ||||
|         let scale = Math.min(this._fixedHItemSize, this._fixedVItemSize) / Math.max(this._hItemSize, this._vItemSize); | ||||
|         Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { this._updateChildrenScale(scale); })); | ||||
|     }, | ||||
|  | ||||
|     // Note that this is ICON_SIZE as used by BaseIcon, not elsewhere in IconGrid; it's a bit messed up | ||||
|     _updateIconSizes: function() { | ||||
|         let scale = Math.min(this._fixedHItemSize, this._fixedVItemSize) / Math.max(this._hItemSize, this._vItemSize); | ||||
|         let newIconSize = Math.floor(ICON_SIZE * scale); | ||||
|     _updateChildrenScale: function(scale) { | ||||
|         for (let i in this._items) { | ||||
|             let newIconSize = Math.floor(ICON_SIZE * scale); | ||||
|             this._items[i].icon.setIconSize(newIconSize); | ||||
|         } | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(IconGrid.prototype); | ||||
|  | ||||
| const PaginatedIconGrid = new Lang.Class({ | ||||
|     Name: 'PaginatedIconGrid', | ||||
| @@ -801,7 +540,6 @@ const PaginatedIconGrid = new Lang.Class({ | ||||
|     _init: function(params) { | ||||
|         this.parent(params); | ||||
|         this._nPages = 0; | ||||
|         this.currentPage = 0; | ||||
|         this._rowsPerPage = 0; | ||||
|         this._spaceBetweenPages = 0; | ||||
|         this._childrenPerPage = 0; | ||||
| @@ -865,15 +603,6 @@ const PaginatedIconGrid = new Lang.Class({ | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     // Overriden from IconGrid | ||||
|     _getChildrenToAnimate: function() { | ||||
|         let children = this._getVisibleChildren(); | ||||
|         let firstIndex = this._childrenPerPage * this.currentPage; | ||||
|         let lastIndex = firstIndex + this._childrenPerPage; | ||||
|  | ||||
|         return children.slice(firstIndex, lastIndex); | ||||
|     }, | ||||
|  | ||||
|     _computePages: function (availWidthPerPage, availHeightPerPage) { | ||||
|         let [nColumns, usedWidth] = this._computeLayout(availWidthPerPage); | ||||
|         let nRows; | ||||
| @@ -906,10 +635,6 @@ const PaginatedIconGrid = new Lang.Class({ | ||||
|         return this._nPages; | ||||
|     }, | ||||
|  | ||||
|     getPageHeight: function() { | ||||
|         return this._availableHeightPerPageForItems(); | ||||
|     }, | ||||
|  | ||||
|     getPageY: function(pageNumber) { | ||||
|         if (!this._nPages) | ||||
|             return 0; | ||||
|   | ||||
| @@ -23,12 +23,6 @@ const KEYBOARD_TYPE = 'keyboard-type'; | ||||
| const A11Y_APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications'; | ||||
| const SHOW_KEYBOARD = 'screen-keyboard-enabled'; | ||||
|  | ||||
| const CURSOR_BUS_NAME = 'org.gnome.SettingsDaemon.Cursor'; | ||||
| const CURSOR_OBJECT_PATH = '/org/gnome/SettingsDaemon/Cursor'; | ||||
|  | ||||
| const CARIBOU_BUS_NAME = 'org.gnome.Caribou.Daemon'; | ||||
| const CARIBOU_OBJECT_PATH = '/org/gnome/Caribou/Daemon'; | ||||
|  | ||||
| const CaribouKeyboardIface = '<node> \ | ||||
| <interface name="org.gnome.Caribou.Keyboard"> \ | ||||
| <method name="Show"> \ | ||||
| @@ -53,28 +47,13 @@ const CaribouKeyboardIface = '<node> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| const CaribouDaemonIface = '<node> \ | ||||
| <interface name="org.gnome.Caribou.Daemon"> \ | ||||
| <method name="Run" /> \ | ||||
| <method name="Quit" /> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| const CursorManagerIface = '<node> \ | ||||
| <interface name="org.gnome.SettingsDaemon.Cursor"> \ | ||||
| <property name="ShowOSK" type="b" access="read" /> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| const CaribouDaemonProxy = Gio.DBusProxy.makeProxyWrapper(CaribouDaemonIface); | ||||
| const CursorManagerProxy = Gio.DBusProxy.makeProxyWrapper(CursorManagerIface); | ||||
|  | ||||
| const Key = new Lang.Class({ | ||||
|     Name: 'Key', | ||||
|  | ||||
|     _init : function(key) { | ||||
|         this._key = key; | ||||
|         this.actor = this._makeKey(key, GLib.markup_escape_text(key.label, -1)); | ||||
|  | ||||
|         this.actor = this._makeKey(); | ||||
|  | ||||
|         this._extended_keys = this._key.get_extended_keys(); | ||||
|         this._extended_keyboard = null; | ||||
| @@ -97,19 +76,20 @@ const Key = new Lang.Class({ | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _makeKey: function (key, label) { | ||||
|     _makeKey: function () { | ||||
|         let label = GLib.markup_escape_text(this._key.label, -1); | ||||
|         let button = new St.Button ({ label: label, | ||||
|                                       style_class: 'keyboard-key' }); | ||||
|  | ||||
|         button.key_width = this._key.width; | ||||
|         button.connect('button-press-event', Lang.bind(this, | ||||
|             function () { | ||||
|                 key.press(); | ||||
|                 this._key.press(); | ||||
|                 return Clutter.EVENT_PROPAGATE; | ||||
|             })); | ||||
|         button.connect('button-release-event', Lang.bind(this, | ||||
|             function () { | ||||
|                 key.release(); | ||||
|                 this._key.release(); | ||||
|                 return Clutter.EVENT_PROPAGATE; | ||||
|             })); | ||||
|  | ||||
| @@ -132,9 +112,18 @@ const Key = new Lang.Class({ | ||||
|         for (let i = 0; i < this._extended_keys.length; ++i) { | ||||
|             let extended_key = this._extended_keys[i]; | ||||
|             let label = this._getUnichar(extended_key); | ||||
|             let key = this._makeKey(extended_key, label); | ||||
|  | ||||
|             let key = new St.Button({ label: label, style_class: 'keyboard-key' }); | ||||
|             key.extended_key = extended_key; | ||||
|             key.connect('button-press-event', Lang.bind(this, | ||||
|                 function () { | ||||
|                     extended_key.press(); | ||||
|                     return Clutter.EVENT_PROPAGATE; | ||||
|                 })); | ||||
|             key.connect('button-release-event', Lang.bind(this, | ||||
|                 function () { | ||||
|                     extended_key.release(); | ||||
|                     return Clutter.EVENT_PROPAGATE; | ||||
|                 })); | ||||
|             this._extended_keyboard.add(key); | ||||
|         } | ||||
|         this._boxPointer.bin.add_actor(this._extended_keyboard); | ||||
| @@ -172,33 +161,11 @@ const Keyboard = new Lang.Class({ | ||||
|  | ||||
|         this._timestamp = global.display.get_current_time_roundtrip(); | ||||
|  | ||||
|         this._keyboardSettings = new Gio.Settings({ schema_id: KEYBOARD_SCHEMA }); | ||||
|         this._keyboardSettings.connect('changed', Lang.bind(this, this._sync)); | ||||
|         this._a11yApplicationsSettings = new Gio.Settings({ schema_id: A11Y_APPLICATIONS_SCHEMA }); | ||||
|         this._a11yApplicationsSettings.connect('changed', Lang.bind(this, this._sync)); | ||||
|         this._watchNameId = Gio.bus_watch_name(Gio.BusType.SESSION, CURSOR_BUS_NAME, 0, | ||||
|                                                Lang.bind(this, this._sync), | ||||
|                                                Lang.bind(this, this._sync)); | ||||
|         this._daemonProxy = new CaribouDaemonProxy(Gio.DBus.session, CARIBOU_BUS_NAME, | ||||
|                                                    CARIBOU_OBJECT_PATH, | ||||
|                                                    Lang.bind(this, function(proxy, error) { | ||||
|                                                        if (error) { | ||||
|                                                            log(error.message); | ||||
|                                                            return; | ||||
|                                                        } | ||||
|                                                    })); | ||||
|         this._cursorProxy = new CursorManagerProxy(Gio.DBus.session, CURSOR_BUS_NAME, | ||||
|                                                    CURSOR_OBJECT_PATH, | ||||
|                                                    Lang.bind(this, function(proxy, error) { | ||||
|                                                        if (error) { | ||||
|                                                            log(error.message); | ||||
|                                                            return; | ||||
|                                                        } | ||||
|                                                        this._cursorProxy.connect('g-properties-changed', | ||||
|                                                                                  Lang.bind(this, this._sync)); | ||||
|                                                        this._sync(); | ||||
|                                                    })); | ||||
|         this._sync(); | ||||
|         this._keyboardSettings = new Gio.Settings({ schema: KEYBOARD_SCHEMA }); | ||||
|         this._keyboardSettings.connect('changed', Lang.bind(this, this._settingsChanged)); | ||||
|         this._a11yApplicationsSettings = new Gio.Settings({ schema: A11Y_APPLICATIONS_SCHEMA }); | ||||
|         this._a11yApplicationsSettings.connect('changed', Lang.bind(this, this._settingsChanged)); | ||||
|         this._settingsChanged(); | ||||
|  | ||||
|         this._showIdleId = 0; | ||||
|         this._subkeysBoxPointer = null; | ||||
| @@ -216,9 +183,8 @@ const Keyboard = new Lang.Class({ | ||||
|         this._redraw(); | ||||
|     }, | ||||
|  | ||||
|     _sync: function () { | ||||
|         this._enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD) || | ||||
|                                this._cursorProxy.ShowOSK; | ||||
|     _settingsChanged: function (settings, key) { | ||||
|         this._enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD); | ||||
|         if (!this._enableKeyboard && !this._keyboard) | ||||
|             return; | ||||
|         if (this._enableKeyboard && this._keyboard && | ||||
| @@ -248,22 +214,9 @@ const Keyboard = new Lang.Class({ | ||||
|         this.actor = null; | ||||
|  | ||||
|         this._destroySource(); | ||||
|         this._daemonProxy.QuitRemote(function (result, error) { | ||||
|             if (error) { | ||||
|                 log(error.message); | ||||
|                 return; | ||||
|             } | ||||
|         }); | ||||
|     }, | ||||
|  | ||||
|     _setupKeyboard: function() { | ||||
|         this._daemonProxy.RunRemote(function (result, error) { | ||||
|             if (error) { | ||||
|                 log(error.message); | ||||
|                 return; | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         this.actor = new St.BoxLayout({ name: 'keyboard', vertical: true, reactive: true }); | ||||
|         Main.layoutManager.keyboardBox.add_actor(this.actor); | ||||
|         Main.layoutManager.trackChrome(this.actor); | ||||
| @@ -313,14 +266,12 @@ const Keyboard = new Lang.Class({ | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (!this._showIdleId) { | ||||
|           this._showIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, | ||||
|                                            Lang.bind(this, function() { | ||||
|                                                this.Show(time); | ||||
|                                                return GLib.SOURCE_REMOVE; | ||||
|                                            })); | ||||
|           GLib.Source.set_name_by_id(this._showIdleId, '[gnome-shell] this.Show'); | ||||
|         } | ||||
|         if (!this._showIdleId) | ||||
|             this._showIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, | ||||
|                                              Lang.bind(this, function() { | ||||
|                                                  this.Show(time); | ||||
|                                                  return GLib.SOURCE_REMOVE; | ||||
|                                              })); | ||||
|     }, | ||||
|  | ||||
|     _createLayersForGroup: function (gname) { | ||||
| @@ -549,7 +500,6 @@ const Keyboard = new Lang.Class({ | ||||
|                                                        this._show(monitor); | ||||
|                                                        return GLib.SOURCE_REMOVE; | ||||
|                                                    })); | ||||
|         GLib.Source.set_name_by_id(this._keyboardRestingId, '[gnome-shell] this._clearKeyboardRestTimer'); | ||||
|     }, | ||||
|  | ||||
|     _show: function(monitor) { | ||||
| @@ -576,7 +526,6 @@ const Keyboard = new Lang.Class({ | ||||
|                                                        this._hide(); | ||||
|                                                        return GLib.SOURCE_REMOVE; | ||||
|                                                    })); | ||||
|         GLib.Source.set_name_by_id(this._keyboardRestingId, '[gnome-shell] this._clearKeyboardRestTimer'); | ||||
|     }, | ||||
|  | ||||
|     _hide: function() { | ||||
|   | ||||
							
								
								
									
										228
									
								
								js/ui/layout.js
									
									
									
									
									
								
							
							
						
						
									
										228
									
								
								js/ui/layout.js
									
									
									
									
									
								
							| @@ -4,6 +4,7 @@ const Clutter = imports.gi.Clutter; | ||||
| const GLib = imports.gi.GLib; | ||||
| const GObject = imports.gi.GObject; | ||||
| const Lang = imports.lang; | ||||
| const Mainloop = imports.mainloop; | ||||
| const Meta = imports.gi.Meta; | ||||
| const Shell = imports.gi.Shell; | ||||
| const Signals = imports.signals; | ||||
| @@ -161,9 +162,9 @@ const LayoutManager = new Lang.Class({ | ||||
|         this._startingUp = true; | ||||
|  | ||||
|         // Normally, the stage is always covered so Clutter doesn't need to clear | ||||
|         // it; however it becomes visible during the startup animation | ||||
|         // See the comment below for a longer explanation | ||||
|         global.stage.background_color = DEFAULT_BACKGROUND_COLOR; | ||||
|         // it; however it becomes visible when using the magnifier. | ||||
|         global.stage.color = DEFAULT_BACKGROUND_COLOR; | ||||
|         global.stage.no_clear_hint = true; | ||||
|  | ||||
|         // Set up stage hierarchy to group all UI actors under one container. | ||||
|         this.uiGroup = new Shell.GenericContainer({ name: 'uiGroup' }); | ||||
| @@ -183,52 +184,72 @@ const LayoutManager = new Lang.Class({ | ||||
|                             let height = global.stage.height; | ||||
|                             [alloc.min_size, alloc.natural_size] = [height, height]; | ||||
|                         }); | ||||
|         global.stage.add_child(this.uiGroup); | ||||
|  | ||||
|         this.systemGroup = new St.Widget({ name: 'systemGroup', | ||||
|                                            layout_manager: new Clutter.BinLayout() }); | ||||
|         this.uiGroup.add_actor(this.systemGroup); | ||||
|  | ||||
|         this.sessionGroup = new St.Widget({ name: 'sessionGroup' }); | ||||
|         this.uiGroup.add_child(this.sessionGroup); | ||||
|  | ||||
|         global.stage.remove_actor(global.window_group); | ||||
|         this.uiGroup.add_actor(global.window_group); | ||||
|  | ||||
|         global.stage.add_child(this.uiGroup); | ||||
|         this.sessionGroup.add_actor(global.window_group); | ||||
|  | ||||
|         this.overviewGroup = new St.Widget({ name: 'overviewGroup', | ||||
|                                              visible: false }); | ||||
|         this.addChrome(this.overviewGroup); | ||||
|  | ||||
|         this.screenShieldGroup = new St.Widget({ name: 'screenShieldGroup', | ||||
|                                                  visible: false, | ||||
|                                                  clip_to_allocation: true, | ||||
|                                                  layout_manager: new Clutter.BinLayout(), | ||||
|                                                }); | ||||
|         this.addChrome(this.screenShieldGroup); | ||||
|  | ||||
|         this.panelBox = new St.BoxLayout({ name: 'panelBox', | ||||
|                                            vertical: true }); | ||||
|         this.addChrome(this.panelBox, { affectsStruts: true, | ||||
|                                         trackFullscreen: true }); | ||||
|         this.panelBox.connect('allocation-changed', | ||||
|                               Lang.bind(this, this._panelBoxChanged)); | ||||
|         this.uiGroup.add_child(this.screenShieldGroup); | ||||
|  | ||||
|         this.trayBox = new St.Widget({ name: 'trayBox', | ||||
|                                        layout_manager: new Clutter.BinLayout() });  | ||||
|         this.addChrome(this.trayBox); | ||||
|         this._setupTrayPressure(); | ||||
|  | ||||
|         this.modalDialogGroup = new St.Widget({ name: 'modalDialogGroup', | ||||
|                                                 layout_manager: new Clutter.BinLayout() }); | ||||
|         this.uiGroup.add_actor(this.modalDialogGroup); | ||||
|  | ||||
|         this.keyboardBox = new St.BoxLayout({ name: 'keyboardBox', | ||||
|                                               reactive: true, | ||||
|                                               track_hover: true }); | ||||
|         this.addChrome(this.keyboardBox); | ||||
|         this._keyboardHeightNotifyId = 0; | ||||
|  | ||||
|         // A dummy actor that tracks the mouse or text cursor, based on the | ||||
|         // position and size set in setDummyCursorGeometry. | ||||
|         this.dummyCursor = new St.Widget({ width: 0, height: 0, visible: false }); | ||||
|         this.uiGroup.add_actor(this.dummyCursor); | ||||
|         this.osdGroup = new St.Widget(); | ||||
|         this.sessionGroup.add_child(this.osdGroup); | ||||
|  | ||||
|         global.stage.remove_actor(global.top_window_group); | ||||
|         this.uiGroup.add_actor(global.top_window_group); | ||||
|         this.switcherPopupGroup = new St.Widget(); | ||||
|         this.sessionGroup.add_child(this.switcherPopupGroup); | ||||
|  | ||||
|         this.dialogGroup = new St.Widget(); | ||||
|         this.sessionGroup.add_child(this.dialogGroup); | ||||
|  | ||||
|         // A dummy actor that tracks the mouse or text cursor, based on the | ||||
|         // position set in setDummyCursorPosition. | ||||
|         this.dummyCursor = new St.Widget({ width: 0, height: 0 }); | ||||
|         this.uiGroup.add_child(this.dummyCursor); | ||||
|  | ||||
|         // The panel group isn't in the session, as it needs to go above the screen | ||||
|         // shield, and it isn't animated in the login animation. | ||||
|         this.panelGroup = new St.Widget({ name: 'panelGroup' }); | ||||
|         this.uiGroup.add_child(this.panelGroup); | ||||
|         this._trackActor(this.panelGroup, { affectsStruts: true, | ||||
|                                             trackFullscreen: true }); | ||||
|         this.panelGroup.connect('allocation-changed', | ||||
|                                 Lang.bind(this, this._panelGroupChanged)); | ||||
|  | ||||
|         this.overlayGroup = new St.Widget({ name: 'overlayGroup' }); | ||||
|         this.uiGroup.add_child(this.overlayGroup); | ||||
|  | ||||
|         this.menuGroup = new St.Widget(); | ||||
|         this.overlayGroup.add_child(this.menuGroup); | ||||
|  | ||||
|         this._topSessionGroup = new St.Widget(); | ||||
|         this.overlayGroup.add_child(this._topSessionGroup); | ||||
|         global.stage.remove_child(global.top_window_group); | ||||
|         this._topSessionGroup.add_child(global.top_window_group); | ||||
|  | ||||
|         this._backgroundGroup = new Meta.BackgroundGroup(); | ||||
|         global.window_group.add_child(this._backgroundGroup); | ||||
| @@ -250,8 +271,7 @@ const LayoutManager = new Lang.Class({ | ||||
|     // This is called by Main after everything else is constructed | ||||
|     init: function() { | ||||
|         Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated)); | ||||
|  | ||||
|         this._loadBackground(); | ||||
|         this._prepareStartupAnimation(); | ||||
|     }, | ||||
|  | ||||
|     showOverview: function() { | ||||
| @@ -260,6 +280,9 @@ const LayoutManager = new Lang.Class({ | ||||
|         this._inOverview = true; | ||||
|         this._updateVisibility(); | ||||
|         this._updateRegions(); | ||||
|  | ||||
|         global.window_group.hide(); | ||||
|         global.top_window_group.hide(); | ||||
|     }, | ||||
|  | ||||
|     hideOverview: function() { | ||||
| @@ -268,6 +291,9 @@ const LayoutManager = new Lang.Class({ | ||||
|         this._inOverview = false; | ||||
|         this._updateVisibility(); | ||||
|         this._queueUpdateRegions(); | ||||
|  | ||||
|         global.window_group.show(); | ||||
|         global.top_window_group.show(); | ||||
|     }, | ||||
|  | ||||
|     _sessionUpdated: function() { | ||||
| @@ -309,7 +335,7 @@ const LayoutManager = new Lang.Class({ | ||||
|         }); | ||||
|         this.hotCorners = []; | ||||
|  | ||||
|         let size = this.panelBox.height; | ||||
|         let size = this.panelGroup.height; | ||||
|  | ||||
|         // build new hot corners | ||||
|         for (let i = 0; i < this.monitors.length; i++) { | ||||
| @@ -361,7 +387,7 @@ const LayoutManager = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _addBackgroundMenu: function(bgManager) { | ||||
|         BackgroundMenu.addBackgroundMenu(bgManager.backgroundActor, this); | ||||
|         BackgroundMenu.addBackgroundMenu(bgManager.background.actor, this); | ||||
|     }, | ||||
|  | ||||
|     _createBackgroundManager: function(monitorIndex) { | ||||
| @@ -378,10 +404,10 @@ const LayoutManager = new Lang.Class({ | ||||
|     _showSecondaryBackgrounds: function() { | ||||
|         for (let i = 0; i < this.monitors.length; i++) { | ||||
|             if (i != this.primaryIndex) { | ||||
|                 let backgroundActor = this._bgManagers[i].backgroundActor; | ||||
|                 backgroundActor.show(); | ||||
|                 backgroundActor.opacity = 0; | ||||
|                 Tweener.addTween(backgroundActor, | ||||
|                 let background = this._bgManagers[i].background; | ||||
|                 background.actor.show(); | ||||
|                 background.actor.opacity = 0; | ||||
|                 Tweener.addTween(background.actor, | ||||
|                                  { opacity: 255, | ||||
|                                    time: BACKGROUND_FADE_ANIMATION_TIME, | ||||
|                                    transition: 'easeOutQuad' }); | ||||
| @@ -404,37 +430,29 @@ const LayoutManager = new Lang.Class({ | ||||
|             this._bgManagers.push(bgManager); | ||||
|  | ||||
|             if (i != this.primaryIndex && this._startingUp) | ||||
|                 bgManager.backgroundActor.hide(); | ||||
|                 bgManager.background.actor.hide(); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _updateKeyboardBox: function() { | ||||
|         this.keyboardBox.set_position(this.keyboardMonitor.x, | ||||
|                                       this.keyboardMonitor.y + this.keyboardMonitor.height); | ||||
|         this.keyboardBox.set_size(this.keyboardMonitor.width, -1); | ||||
|     }, | ||||
|  | ||||
|     _updateBoxes: function() { | ||||
|         this.screenShieldGroup.set_position(0, 0); | ||||
|         this.screenShieldGroup.set_size(global.screen_width, global.screen_height); | ||||
|         this.systemGroup.set_position(0, 0); | ||||
|         this.systemGroup.set_size(global.screen_width, global.screen_height); | ||||
|  | ||||
|         this.panelBox.set_position(this.primaryMonitor.x, this.primaryMonitor.y); | ||||
|         this.panelBox.set_size(this.primaryMonitor.width, -1); | ||||
|         this.panelGroup.set_position(this.primaryMonitor.x, this.primaryMonitor.y); | ||||
|         this.panelGroup.set_size(this.primaryMonitor.width, -1); | ||||
|  | ||||
|         if (this.keyboardIndex < 0) | ||||
|             this.keyboardIndex = this.primaryIndex; | ||||
|         else | ||||
|             this._updateKeyboardBox(); | ||||
|  | ||||
|         this.trayBox.set_position(this.bottomMonitor.x, | ||||
|                                   this.bottomMonitor.y + this.bottomMonitor.height); | ||||
|         this.trayBox.set_size(this.bottomMonitor.width, -1); | ||||
|     }, | ||||
|  | ||||
|     _panelBoxChanged: function() { | ||||
|     _panelGroupChanged: function() { | ||||
|         this._updatePanelBarrier(); | ||||
|  | ||||
|         let size = this.panelBox.height; | ||||
|         let size = this.panelGroup.height; | ||||
|         this.hotCorners.forEach(function(corner) { | ||||
|             if (corner) | ||||
|                 corner.setBarrierSize(size); | ||||
| @@ -447,12 +465,12 @@ const LayoutManager = new Lang.Class({ | ||||
|             this._rightPanelBarrier = null; | ||||
|         } | ||||
|  | ||||
|         if (this.panelBox.height) { | ||||
|         if (this.panelGroup.height) { | ||||
|             let primary = this.primaryMonitor; | ||||
|  | ||||
|             this._rightPanelBarrier = new Meta.Barrier({ display: global.display, | ||||
|                                                          x1: primary.x + primary.width, y1: primary.y, | ||||
|                                                          x2: primary.x + primary.width, y2: primary.y + this.panelBox.height, | ||||
|                                                          x2: primary.x + primary.width, y2: primary.y + this.panelGroup.height, | ||||
|                                                          directions: Meta.BarrierDirection.NEGATIVE_X }); | ||||
|         } | ||||
|     }, | ||||
| @@ -549,32 +567,15 @@ const LayoutManager = new Lang.Class({ | ||||
|  | ||||
|     set keyboardIndex(v) { | ||||
|         this._keyboardIndex = v; | ||||
|         this._updateKeyboardBox(); | ||||
|         this.keyboardBox.set_position(this.keyboardMonitor.x, | ||||
|                                       this.keyboardMonitor.y + this.keyboardMonitor.height); | ||||
|         this.keyboardBox.set_size(this.keyboardMonitor.width, -1); | ||||
|     }, | ||||
|  | ||||
|     get keyboardIndex() { | ||||
|         return this._keyboardIndex; | ||||
|     }, | ||||
|  | ||||
|     _loadBackground: function() { | ||||
|         this._systemBackground = new Background.SystemBackground(); | ||||
|         this._systemBackground.actor.hide(); | ||||
|  | ||||
|         global.stage.insert_child_below(this._systemBackground.actor, null); | ||||
|  | ||||
|         let constraint = new Clutter.BindConstraint({ source: global.stage, | ||||
|                                                       coordinate: Clutter.BindCoordinate.ALL }); | ||||
|         this._systemBackground.actor.add_constraint(constraint); | ||||
|  | ||||
|         let signalId = this._systemBackground.connect('loaded', Lang.bind(this, function() { | ||||
|             this._systemBackground.disconnect(signalId); | ||||
|             this._systemBackground.actor.show(); | ||||
|             global.stage.show(); | ||||
|  | ||||
|             this._prepareStartupAnimation(); | ||||
|         })); | ||||
|     }, | ||||
|  | ||||
|     // Startup Animations | ||||
|     // | ||||
|     // We have two different animations, depending on whether we're a greeter | ||||
| @@ -595,6 +596,8 @@ const LayoutManager = new Lang.Class({ | ||||
|     // screen. So, we set no_clear_hint at the end of the animation. | ||||
|  | ||||
|     _prepareStartupAnimation: function() { | ||||
|         global.stage.show(); | ||||
|  | ||||
|         // During the initial transition, add a simple actor to block all events, | ||||
|         // so they don't get delivered to X11 windows that have been transformed. | ||||
|         this._coverPane = new Clutter.Actor({ opacity: 0, | ||||
| @@ -603,15 +606,13 @@ const LayoutManager = new Lang.Class({ | ||||
|                                               reactive: true }); | ||||
|         this.addChrome(this._coverPane); | ||||
|  | ||||
|         if (Meta.is_restart()) { | ||||
|             // On restart, we don't do an animation | ||||
|         } else if (Main.sessionMode.isGreeter) { | ||||
|             this.panelBox.translation_y = -this.panelBox.height; | ||||
|         if (Main.sessionMode.isGreeter) { | ||||
|             this.panelGroup.translation_y = -this.panelGroup.height; | ||||
|         } else { | ||||
|             this._updateBackgrounds(); | ||||
|  | ||||
|             // We need to force an update of the regions now before we scale | ||||
|             // the UI group to get the correct allocation for the struts. | ||||
|             // the UI group to get the coorect allocation for the struts. | ||||
|             this._updateRegions(); | ||||
|  | ||||
|             this.trayBox.hide(); | ||||
| @@ -621,10 +622,10 @@ const LayoutManager = new Lang.Class({ | ||||
|             let x = monitor.x + monitor.width / 2.0; | ||||
|             let y = monitor.y + monitor.height / 2.0; | ||||
|  | ||||
|             this.uiGroup.set_pivot_point(x / global.screen_width, | ||||
|                                          y / global.screen_height); | ||||
|             this.uiGroup.scale_x = this.uiGroup.scale_y = 0.75; | ||||
|             this.uiGroup.opacity = 0; | ||||
|             this.sessionGroup.set_pivot_point(x / global.screen_width, | ||||
|                                               y / global.screen_height); | ||||
|             this.sessionGroup.scale_x = this.sessionGroup.scale_y = 0.75; | ||||
|             this.sessionGroup.opacity = 0; | ||||
|             global.window_group.set_clip(monitor.x, monitor.y, monitor.width, monitor.height); | ||||
|         } | ||||
|  | ||||
| @@ -636,24 +637,21 @@ const LayoutManager = new Lang.Class({ | ||||
|         // until the event loop is uncontended and idle. | ||||
|         // This helps to prevent us from running the animation | ||||
|         // when the system is bogged down | ||||
|         let id = GLib.idle_add(GLib.PRIORITY_LOW, Lang.bind(this, function() { | ||||
|         GLib.idle_add(GLib.PRIORITY_LOW, Lang.bind(this, function() { | ||||
|             this._startupAnimation(); | ||||
|             return GLib.SOURCE_REMOVE; | ||||
|         })); | ||||
|         GLib.Source.set_name_by_id(id, '[gnome-shell] this._startupAnimation'); | ||||
|     }, | ||||
|  | ||||
|     _startupAnimation: function() { | ||||
|         if (Meta.is_restart()) | ||||
|             this._startupAnimationComplete(); | ||||
|         else if (Main.sessionMode.isGreeter) | ||||
|         if (Main.sessionMode.isGreeter) | ||||
|             this._startupAnimationGreeter(); | ||||
|         else | ||||
|             this._startupAnimationSession(); | ||||
|     }, | ||||
|  | ||||
|     _startupAnimationGreeter: function() { | ||||
|         Tweener.addTween(this.panelBox, | ||||
|         Tweener.addTween(this.panelGroup, | ||||
|                          { translation_y: 0, | ||||
|                            time: STARTUP_ANIMATION_TIME, | ||||
|                            transition: 'easeOutQuad', | ||||
| @@ -662,7 +660,7 @@ const LayoutManager = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _startupAnimationSession: function() { | ||||
|         Tweener.addTween(this.uiGroup, | ||||
|         Tweener.addTween(this.sessionGroup, | ||||
|                          { scale_x: 1, | ||||
|                            scale_y: 1, | ||||
|                            opacity: 255, | ||||
| @@ -673,16 +671,9 @@ const LayoutManager = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _startupAnimationComplete: function() { | ||||
|         // At this point, the UI group is covering everything, so | ||||
|         // we no longer need to clear the stage | ||||
|         global.stage.no_clear_hint = true; | ||||
|  | ||||
|         this._coverPane.destroy(); | ||||
|         this._coverPane = null; | ||||
|  | ||||
|         this._systemBackground.actor.destroy(); | ||||
|         this._systemBackground = null; | ||||
|  | ||||
|         this._startingUp = false; | ||||
|  | ||||
|         this.trayBox.show(); | ||||
| @@ -739,7 +730,7 @@ const LayoutManager = new Lang.Class({ | ||||
|         this._updateRegions(); | ||||
|     }, | ||||
|  | ||||
|     // setDummyCursorGeometry: | ||||
|     // setDummyCursorPosition: | ||||
|     // | ||||
|     // The cursor dummy is a standard widget commonly used for popup | ||||
|     // menus and box pointers to track, as the box pointer API only | ||||
| @@ -748,10 +739,9 @@ const LayoutManager = new Lang.Class({ | ||||
|     // is what you should use. Given that the menu should not track | ||||
|     // the actual mouse pointer as it moves, you need to call this | ||||
|     // function before you show the menu to ensure it is at the right | ||||
|     // position and has the right size. | ||||
|     setDummyCursorGeometry: function(x, y, w, h) { | ||||
|     // position. | ||||
|     setDummyCursorPosition: function(x, y) { | ||||
|         this.dummyCursor.set_position(Math.round(x), Math.round(y)); | ||||
|         this.dummyCursor.set_size(Math.round(w), Math.round(h)); | ||||
|     }, | ||||
|  | ||||
|     // addChrome: | ||||
| @@ -773,9 +763,9 @@ const LayoutManager = new Lang.Class({ | ||||
|     // monitor (it will be hidden whenever a fullscreen window is visible, | ||||
|     // and shown otherwise) | ||||
|     addChrome: function(actor, params) { | ||||
|         this.uiGroup.add_actor(actor); | ||||
|         if (this.uiGroup.contains(global.top_window_group)) | ||||
|             this.uiGroup.set_child_below_sibling(actor, global.top_window_group); | ||||
|         this.sessionGroup.add_actor(actor); | ||||
|         if (this.sessionGroup.contains(global.top_window_group)) | ||||
|             this.sessionGroup.set_child_below_sibling(actor, global.top_window_group); | ||||
|         this._trackActor(actor, params); | ||||
|     }, | ||||
|  | ||||
| @@ -826,7 +816,7 @@ const LayoutManager = new Lang.Class({ | ||||
|     // | ||||
|     // Removes @actor from the chrome | ||||
|     removeChrome: function(actor) { | ||||
|         this.uiGroup.remove_actor(actor); | ||||
|         this.sessionGroup.remove_actor(actor); | ||||
|         this._untrackActor(actor); | ||||
|     }, | ||||
|  | ||||
| @@ -849,8 +839,6 @@ const LayoutManager = new Lang.Class({ | ||||
|                                             Lang.bind(this, this._queueUpdateRegions)); | ||||
|         actorData.allocationId = actor.connect('notify::allocation', | ||||
|                                                Lang.bind(this, this._queueUpdateRegions)); | ||||
|         actorData.destroyId = actor.connect('destroy', | ||||
|                                             Lang.bind(this, this._untrackActor)); | ||||
|         // Note that destroying actor will unset its parent, so we don't | ||||
|         // need to connect to 'destroy' too. | ||||
|  | ||||
| @@ -868,7 +856,7 @@ const LayoutManager = new Lang.Class({ | ||||
|         this._trackedActors.splice(i, 1); | ||||
|         actor.disconnect(actorData.visibleId); | ||||
|         actor.disconnect(actorData.allocationId); | ||||
|         actor.disconnect(actorData.destroyId); | ||||
|         actor.disconnect(actorData.parentSetId); | ||||
|  | ||||
|         this._queueUpdateRegions(); | ||||
|     }, | ||||
| @@ -876,9 +864,6 @@ const LayoutManager = new Lang.Class({ | ||||
|     _updateVisibility: function() { | ||||
|         let windowsVisible = Main.sessionMode.hasWindows && !this._inOverview; | ||||
|  | ||||
|         global.window_group.visible = windowsVisible; | ||||
|         global.top_window_group.visible = windowsVisible; | ||||
|  | ||||
|         for (let i = 0; i < this._trackedActors.length; i++) { | ||||
|             let actorData = this._trackedActors[i], visible; | ||||
|             if (!actorData.trackFullscreen) | ||||
| @@ -922,8 +907,8 @@ const LayoutManager = new Lang.Class({ | ||||
|             return; | ||||
|  | ||||
|         if (!this._updateRegionIdle) | ||||
|             this._updateRegionIdle = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, | ||||
|                                                     Lang.bind(this, this._updateRegions)); | ||||
|             this._updateRegionIdle = Mainloop.idle_add(Lang.bind(this, this._updateRegions), | ||||
|                                                        Meta.PRIORITY_BEFORE_REDRAW); | ||||
|     }, | ||||
|  | ||||
|     _getWindowActorsForWorkspace: function(workspace) { | ||||
| @@ -954,7 +939,7 @@ const LayoutManager = new Lang.Class({ | ||||
|         let rects = [], struts = [], i; | ||||
|  | ||||
|         if (this._updateRegionIdle) { | ||||
|             Meta.later_remove(this._updateRegionIdle); | ||||
|             Mainloop.source_remove(this._updateRegionIdle); | ||||
|             delete this._updateRegionIdle; | ||||
|         } | ||||
|  | ||||
| @@ -1027,6 +1012,23 @@ const LayoutManager = new Lang.Class({ | ||||
|                 else | ||||
|                     continue; | ||||
|  | ||||
|                 // Ensure that the strut rects goes all the way to the screen edge, | ||||
|                 // as this really what mutter expects. | ||||
|                 switch (side) { | ||||
|                 case Meta.Side.TOP: | ||||
|                     y1 = 0; | ||||
|                     break; | ||||
|                 case Meta.Side.BOTTOM: | ||||
|                     y2 = global.screen_height; | ||||
|                     break; | ||||
|                 case Meta.Side.LEFT: | ||||
|                     x1 = 0; | ||||
|                     break; | ||||
|                 case Meta.Side.RIGHT: | ||||
|                     x2 = global.screen_width; | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 let strutRect = new Meta.Rectangle({ x: x1, y: y1, width: x2 - x1, height: y2 - y1}); | ||||
|                 let strut = new Meta.Strut({ rect: strutRect, side: side }); | ||||
|                 struts.push(strut); | ||||
| @@ -1080,9 +1082,9 @@ const HotCorner = new Lang.Class({ | ||||
|         this._ripple2 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0, visible: false }); | ||||
|         this._ripple3 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0, visible: false }); | ||||
|  | ||||
|         layoutManager.uiGroup.add_actor(this._ripple1); | ||||
|         layoutManager.uiGroup.add_actor(this._ripple2); | ||||
|         layoutManager.uiGroup.add_actor(this._ripple3); | ||||
|         layoutManager.sessionGroup.add_actor(this._ripple1); | ||||
|         layoutManager.sessionGroup.add_actor(this._ripple2); | ||||
|         layoutManager.sessionGroup.add_actor(this._ripple3); | ||||
|     }, | ||||
|  | ||||
|     setBarrierSize: function(size) { | ||||
|   | ||||
| @@ -11,60 +11,30 @@ const Params = imports.misc.params; | ||||
| const Tweener = imports.ui.tweener; | ||||
|  | ||||
| const DEFAULT_FADE_FACTOR = 0.4; | ||||
| const VIGNETTE_BRIGHTNESS = 0.8; | ||||
| const VIGNETTE_SHARPNESS = 0.7; | ||||
|  | ||||
| const VIGNETTE_DECLARATIONS = '\ | ||||
| uniform float brightness;\n\ | ||||
| uniform float vignette_sharpness;\n'; | ||||
|  | ||||
| const VIGNETTE_CODE = '\ | ||||
| cogl_color_out.a = cogl_color_in.a;\n\ | ||||
| cogl_color_out.rgb = vec3(0.0, 0.0, 0.0);\n\ | ||||
| vec2 position = cogl_tex_coord_in[0].xy - 0.5;\n\ | ||||
| float t = length(2.0 * position);\n\ | ||||
| t = clamp(t, 0.0, 1.0);\n\ | ||||
| float pixel_brightness = mix(1.0, 1.0 - vignette_sharpness, t);\n\ | ||||
| cogl_color_out.a = cogl_color_out.a * (1 - pixel_brightness * brightness);'; | ||||
| const GLSL_DIM_EFFECT_DECLARATIONS = '\ | ||||
| float compute_dim_factor (const vec2 coords) {\ | ||||
|    vec2 dist = coords - vec2(0.5, 0.5); \ | ||||
|    float elipse_radius = 0.5; \ | ||||
|    /* interpolate darkening value, based on distance from screen center */ \ | ||||
|    float val = min(length(dist), elipse_radius); \ | ||||
|    return mix(0.3, 1.0, val / elipse_radius) * 0.4; \ | ||||
| }'; | ||||
| const GLSL_DIM_EFFECT_CODE = '\ | ||||
|    float a = compute_dim_factor (cogl_tex_coord0_in.xy);\ | ||||
|    cogl_color_out = vec4(0, 0, 0, cogl_color_in.a * a);' | ||||
| ; | ||||
|  | ||||
| const RadialShaderQuad = new Lang.Class({ | ||||
|     Name: 'RadialShaderQuad', | ||||
|     Extends: Shell.GLSLQuad, | ||||
|  | ||||
|     _init: function(params) { | ||||
|         this.parent(params); | ||||
|  | ||||
|         this._brightnessLocation = this.get_uniform_location('brightness'); | ||||
|         this._sharpnessLocation = this.get_uniform_location('vignette_sharpness'); | ||||
|  | ||||
|         this.brightness = 1.0; | ||||
|         this.vignetteSharpness = 0.0; | ||||
|     }, | ||||
|  | ||||
|     vfunc_build_pipeline: function() { | ||||
|         this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, | ||||
|                               VIGNETTE_DECLARATIONS, VIGNETTE_CODE, true); | ||||
|                               GLSL_DIM_EFFECT_DECLARATIONS, | ||||
|                               GLSL_DIM_EFFECT_CODE, | ||||
|                               true); | ||||
|     }, | ||||
|  | ||||
|     get brightness() { | ||||
|         return this._brightness; | ||||
|     }, | ||||
|  | ||||
|     set brightness(v) { | ||||
|         this._brightness = v; | ||||
|         this.set_uniform_float(this._brightnessLocation, | ||||
|                                1, [this._brightness]); | ||||
|     }, | ||||
|  | ||||
|     get vignetteSharpness() { | ||||
|         return this._sharpness; | ||||
|     }, | ||||
|  | ||||
|     set vignetteSharpness(v) { | ||||
|         this._sharpness = v; | ||||
|         this.set_uniform_float(this._sharpnessLocation, | ||||
|                                1, [this._sharpness]); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| /** | ||||
| @@ -105,15 +75,13 @@ const Lightbox = new Lang.Class({ | ||||
|         this._container = container; | ||||
|         this._children = container.get_children(); | ||||
|         this._fadeFactor = params.fadeFactor; | ||||
|         this._radialEffect = Clutter.feature_available(Clutter.FeatureFlags.SHADERS_GLSL) && params.radialEffect; | ||||
|         if (this._radialEffect) | ||||
|         if (params.radialEffect) | ||||
|             this.actor = new RadialShaderQuad({ x: 0, | ||||
|                                                 y: 0, | ||||
|                                                 reactive: params.inhibitEvents }); | ||||
|         else | ||||
|             this.actor = new St.Bin({ x: 0, | ||||
|                                       y: 0, | ||||
|                                       opacity: 0, | ||||
|                                       style_class: 'lightbox', | ||||
|                                       reactive: params.inhibitEvents }); | ||||
|  | ||||
| @@ -165,18 +133,9 @@ const Lightbox = new Lang.Class({ | ||||
|         fadeInTime = fadeInTime || 0; | ||||
|  | ||||
|         Tweener.removeTweens(this.actor); | ||||
|         if (this._radialEffect) { | ||||
|             Tweener.addTween(this.actor, | ||||
|                              { brightness: VIGNETTE_BRIGHTNESS, | ||||
|                                vignetteSharpness: VIGNETTE_SHARPNESS, | ||||
|                                time: fadeInTime, | ||||
|                                transition: 'easeOutQuad', | ||||
|                                onComplete: Lang.bind(this, function() { | ||||
|                                    this.shown = true; | ||||
|                                    this.emit('shown'); | ||||
|                                }) | ||||
|                              }); | ||||
|         } else { | ||||
|         if (fadeInTime != 0) { | ||||
|             this.shown = false; | ||||
|             this.actor.opacity = 0; | ||||
|             Tweener.addTween(this.actor, | ||||
|                              { opacity: 255 * this._fadeFactor, | ||||
|                                time: fadeInTime, | ||||
| @@ -186,8 +145,11 @@ const Lightbox = new Lang.Class({ | ||||
|                                    this.emit('shown'); | ||||
|                                }) | ||||
|                              }); | ||||
|         } else { | ||||
|             this.actor.opacity = 255 * this._fadeFactor; | ||||
|             this.shown = true; | ||||
|             this.emit('shown'); | ||||
|         } | ||||
|  | ||||
|         this.actor.show(); | ||||
|     }, | ||||
|  | ||||
| @@ -196,18 +158,7 @@ const Lightbox = new Lang.Class({ | ||||
|  | ||||
|         this.shown = false; | ||||
|         Tweener.removeTweens(this.actor); | ||||
|         if (this._radialEffect) { | ||||
|             Tweener.addTween(this.actor, | ||||
|                              { brightness: 1.0, | ||||
|                                vignetteSharpness: 0.0, | ||||
|                                opacity: 0, | ||||
|                                time: fadeOutTime, | ||||
|                                transition: 'easeOutQuad', | ||||
|                                onComplete: Lang.bind(this, function() { | ||||
|                                    this.actor.hide(); | ||||
|                                }) | ||||
|                              }); | ||||
|         } else { | ||||
|         if (fadeOutTime != 0) { | ||||
|             Tweener.addTween(this.actor, | ||||
|                              { opacity: 0, | ||||
|                                time: fadeOutTime, | ||||
| @@ -216,6 +167,8 @@ const Lightbox = new Lang.Class({ | ||||
|                                    this.actor.hide(); | ||||
|                                }) | ||||
|                              }); | ||||
|         } else { | ||||
|             this.actor.hide(); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|   | ||||
| @@ -27,8 +27,6 @@ const CHEVRON = '>>> '; | ||||
| /* Imports...feel free to add here as needed */ | ||||
| var commandHeader = 'const Clutter = imports.gi.Clutter; ' + | ||||
|                     'const GLib = imports.gi.GLib; ' + | ||||
|                     'const GObject = imports.gi.GObject; ' + | ||||
|                     'const Gio = imports.gi.Gio; ' + | ||||
|                     'const Gtk = imports.gi.Gtk; ' + | ||||
|                     'const Mainloop = imports.mainloop; ' + | ||||
|                     'const Meta = imports.gi.Meta; ' + | ||||
| @@ -505,7 +503,7 @@ const Inspector = new Lang.Class({ | ||||
|         let container = new Shell.GenericContainer({ width: 0, | ||||
|                                                      height: 0 }); | ||||
|         container.connect('allocate', Lang.bind(this, this._allocate)); | ||||
|         Main.uiGroup.add_actor(container); | ||||
|         Main.layoutManager.sessionGroup.add_actor(container); | ||||
|  | ||||
|         let eventHandler = new St.BoxLayout({ name: 'LookingGlassDialog', | ||||
|                                               vertical: false, | ||||
| @@ -797,22 +795,20 @@ const LookingGlass = new Lang.Class({ | ||||
|                                         reactive: true }); | ||||
|         this.actor.connect('key-press-event', Lang.bind(this, this._globalKeyPressEvent)); | ||||
|  | ||||
|         this._interfaceSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' }); | ||||
|         this._interfaceSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' }); | ||||
|         this._interfaceSettings.connect('changed::monospace-font-name', | ||||
|                                         Lang.bind(this, this._updateFont)); | ||||
|         this._updateFont(); | ||||
|  | ||||
|         // We want it to appear to slide out from underneath the panel | ||||
|         Main.uiGroup.add_actor(this.actor); | ||||
|         Main.uiGroup.set_child_below_sibling(this.actor, | ||||
|                                              Main.layoutManager.panelBox); | ||||
|         Main.layoutManager.panelBox.connect('allocation-changed', | ||||
|                                             Lang.bind(this, this._queueResize)); | ||||
|         Main.layoutManager.sessionGroup.add_actor(this.actor); | ||||
|         Main.layoutManager.panelGroup.connect('allocation-changed', | ||||
|                                               Lang.bind(this, this._queueResize)); | ||||
|         Main.layoutManager.keyboardBox.connect('allocation-changed', | ||||
|                                                Lang.bind(this, this._queueResize)); | ||||
|  | ||||
|         this._objInspector = new ObjInspector(this); | ||||
|         Main.uiGroup.add_actor(this._objInspector.actor); | ||||
|         Main.layoutManager.sessionGroup.add_actor(this._objInspector.actor); | ||||
|         this._objInspector.actor.hide(); | ||||
|  | ||||
|         let toolbar = new St.BoxLayout({ name: 'Toolbar' }); | ||||
| @@ -843,10 +839,9 @@ const LookingGlass = new Lang.Class({ | ||||
|            System.gc(); | ||||
|            this._timeoutId = Mainloop.timeout_add(500, Lang.bind(this, function () { | ||||
|                 gcIcon.icon_name = 'gnome-fs-trash-full'; | ||||
|                 this._timeoutId = 0; | ||||
|                 Mainloop.source_remove(this._timeoutId); | ||||
|                 return GLib.SOURCE_REMOVE; | ||||
|            })); | ||||
|            GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] gcIcon.icon_name = \'gnome-fs-trash-full\''); | ||||
|            return Clutter.EVENT_PROPAGATE; | ||||
|         })); | ||||
|  | ||||
| @@ -1040,7 +1035,7 @@ const LookingGlass = new Lang.Class({ | ||||
|         let availableHeight = primary.height - Main.layoutManager.keyboardBox.height; | ||||
|         let myHeight = Math.min(primary.height * 0.7, availableHeight * 0.9); | ||||
|         this.actor.x = primary.x + (primary.width - myWidth) / 2; | ||||
|         this._hiddenY = primary.y + Main.layoutManager.panelBox.height - myHeight - 4; // -4 to hide the top corners | ||||
|         this._hiddenY = primary.y + Main.layoutManager.panelGroup.height - myHeight - 4; // -4 to hide the top corners | ||||
|         this._targetY = this._hiddenY + myHeight; | ||||
|         this.actor.y = this._hiddenY; | ||||
|         this.actor.width = myWidth; | ||||
|   | ||||
| @@ -11,7 +11,6 @@ const Mainloop = imports.mainloop; | ||||
| const Meta = imports.gi.Meta; | ||||
| const Signals = imports.signals; | ||||
|  | ||||
| const Background = imports.ui.background; | ||||
| const FocusCaretTracker = imports.ui.focusCaretTracker; | ||||
| const Main = imports.ui.main; | ||||
| const MagnifierDBus = imports.ui.magnifierDBus; | ||||
| @@ -58,6 +57,20 @@ const Magnifier = new Lang.Class({ | ||||
|         // Magnifier is a manager of ZoomRegions. | ||||
|         this._zoomRegions = []; | ||||
|  | ||||
|         // Export to dbus. | ||||
|         magDBusService = new MagnifierDBus.ShellMagnifier(); | ||||
|  | ||||
|         let showAtLaunch = this._settingsInit(); | ||||
|         this.setActive(showAtLaunch); | ||||
|     }, | ||||
|  | ||||
|     _initialize: function() { | ||||
|         if (this._initialized) | ||||
|             return; | ||||
|         this._initialized = true; | ||||
|  | ||||
|         this._settingsInitLate(); | ||||
|  | ||||
|         // Create small clutter tree for the magnified mouse. | ||||
|         let cursorTracker = Meta.CursorTracker.get_for_screen(global.screen); | ||||
|         this._mouseSprite = new Clutter.Texture(); | ||||
| @@ -73,15 +86,11 @@ const Magnifier = new Lang.Class({ | ||||
|  | ||||
|         let aZoomRegion = new ZoomRegion(this, this._cursorRoot); | ||||
|         this._zoomRegions.push(aZoomRegion); | ||||
|         let showAtLaunch = this._settingsInit(aZoomRegion); | ||||
|         this._settingsInitRegion(aZoomRegion); | ||||
|         aZoomRegion.scrollContentsTo(this.xMouse, this.yMouse); | ||||
|  | ||||
|         cursorTracker.connect('cursor-changed', Lang.bind(this, this._updateMouseSprite)); | ||||
|         this._cursorTracker = cursorTracker; | ||||
|  | ||||
|         // Export to dbus. | ||||
|         magDBusService = new MagnifierDBus.ShellMagnifier(); | ||||
|         this.setActive(showAtLaunch); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
| @@ -106,21 +115,20 @@ const Magnifier = new Lang.Class({ | ||||
|      * @activate:   Boolean to activate or de-activate the magnifier. | ||||
|      */ | ||||
|     setActive: function(activate) { | ||||
|         let isActive = this.isActive(); | ||||
|         if (activate == this.isActive()) | ||||
|             return; | ||||
|  | ||||
|         if (activate) | ||||
|             this._initialize(); | ||||
|  | ||||
|         this._zoomRegions.forEach (function(zoomRegion, index, array) { | ||||
|             zoomRegion.setActive(activate); | ||||
|         }); | ||||
|  | ||||
|         if (isActive != activate) { | ||||
|             if (activate) { | ||||
|                 Meta.disable_unredirect_for_screen(global.screen); | ||||
|                 this.startTrackingMouse(); | ||||
|             } else { | ||||
|                 Meta.enable_unredirect_for_screen(global.screen); | ||||
|                 this.stopTrackingMouse(); | ||||
|             } | ||||
|         } | ||||
|         if (activate) | ||||
|             this.startTrackingMouse(); | ||||
|         else | ||||
|             this.stopTrackingMouse(); | ||||
|  | ||||
|         // Make sure system mouse pointer is shown when all zoom regions are | ||||
|         // invisible. | ||||
| @@ -440,64 +448,68 @@ const Magnifier = new Lang.Class({ | ||||
|         this._mouseSprite.set_anchor_point(xHot, yHot); | ||||
|     }, | ||||
|  | ||||
|     _settingsInit: function(zoomRegion) { | ||||
|         this._appSettings = new Gio.Settings({ schema_id: APPLICATIONS_SCHEMA }); | ||||
|         this._settings = new Gio.Settings({ schema_id: MAGNIFIER_SCHEMA }); | ||||
|     _settingsInitRegion: function(zoomRegion) { | ||||
|         // Mag factor is accurate to two decimal places. | ||||
|         let aPref = parseFloat(this._settings.get_double(MAG_FACTOR_KEY).toFixed(2)); | ||||
|         if (aPref != 0.0) | ||||
|             zoomRegion.setMagFactor(aPref, aPref); | ||||
|  | ||||
|         if (zoomRegion) { | ||||
|             // Mag factor is accurate to two decimal places. | ||||
|             let aPref = parseFloat(this._settings.get_double(MAG_FACTOR_KEY).toFixed(2)); | ||||
|             if (aPref != 0.0) | ||||
|                 zoomRegion.setMagFactor(aPref, aPref); | ||||
|         aPref = this._settings.get_enum(SCREEN_POSITION_KEY); | ||||
|         if (aPref) | ||||
|             zoomRegion.setScreenPosition(aPref); | ||||
|  | ||||
|             aPref = this._settings.get_enum(SCREEN_POSITION_KEY); | ||||
|             if (aPref) | ||||
|                 zoomRegion.setScreenPosition(aPref); | ||||
|         zoomRegion.setLensMode(this._settings.get_boolean(LENS_MODE_KEY)); | ||||
|         zoomRegion.setClampScrollingAtEdges(!this._settings.get_boolean(CLAMP_MODE_KEY)); | ||||
|  | ||||
|             zoomRegion.setLensMode(this._settings.get_boolean(LENS_MODE_KEY)); | ||||
|             zoomRegion.setClampScrollingAtEdges(!this._settings.get_boolean(CLAMP_MODE_KEY)); | ||||
|         aPref = this._settings.get_enum(MOUSE_TRACKING_KEY); | ||||
|         if (aPref) | ||||
|             zoomRegion.setMouseTrackingMode(aPref); | ||||
|  | ||||
|             aPref = this._settings.get_enum(MOUSE_TRACKING_KEY); | ||||
|             if (aPref) | ||||
|                 zoomRegion.setMouseTrackingMode(aPref); | ||||
|         aPref = this._settings.get_enum(FOCUS_TRACKING_KEY); | ||||
|         if (aPref) | ||||
|             zoomRegion.setFocusTrackingMode(aPref); | ||||
|  | ||||
|             aPref = this._settings.get_enum(FOCUS_TRACKING_KEY); | ||||
|             if (aPref) | ||||
|                 zoomRegion.setFocusTrackingMode(aPref); | ||||
|         aPref = this._settings.get_enum(CARET_TRACKING_KEY); | ||||
|         if (aPref) | ||||
|             zoomRegion.setCaretTrackingMode(aPref); | ||||
|  | ||||
|             aPref = this._settings.get_enum(CARET_TRACKING_KEY); | ||||
|             if (aPref) | ||||
|                 zoomRegion.setCaretTrackingMode(aPref); | ||||
|         aPref = this._settings.get_boolean(INVERT_LIGHTNESS_KEY); | ||||
|         if (aPref) | ||||
|             zoomRegion.setInvertLightness(aPref); | ||||
|  | ||||
|             aPref = this._settings.get_boolean(INVERT_LIGHTNESS_KEY); | ||||
|             if (aPref) | ||||
|                 zoomRegion.setInvertLightness(aPref); | ||||
|         aPref = this._settings.get_double(COLOR_SATURATION_KEY); | ||||
|         if (aPref) | ||||
|             zoomRegion.setColorSaturation(aPref); | ||||
|  | ||||
|             aPref = this._settings.get_double(COLOR_SATURATION_KEY); | ||||
|             if (aPref) | ||||
|                 zoomRegion.setColorSaturation(aPref); | ||||
|         let bc = {}; | ||||
|         bc.r = this._settings.get_double(BRIGHT_RED_KEY); | ||||
|         bc.g = this._settings.get_double(BRIGHT_GREEN_KEY); | ||||
|         bc.b = this._settings.get_double(BRIGHT_BLUE_KEY); | ||||
|         zoomRegion.setBrightness(bc); | ||||
|  | ||||
|             let bc = {}; | ||||
|             bc.r = this._settings.get_double(BRIGHT_RED_KEY); | ||||
|             bc.g = this._settings.get_double(BRIGHT_GREEN_KEY); | ||||
|             bc.b = this._settings.get_double(BRIGHT_BLUE_KEY); | ||||
|             zoomRegion.setBrightness(bc); | ||||
|         bc.r = this._settings.get_double(CONTRAST_RED_KEY); | ||||
|         bc.g = this._settings.get_double(CONTRAST_GREEN_KEY); | ||||
|         bc.b = this._settings.get_double(CONTRAST_BLUE_KEY); | ||||
|         zoomRegion.setContrast(bc); | ||||
|     }, | ||||
|  | ||||
|             bc.r = this._settings.get_double(CONTRAST_RED_KEY); | ||||
|             bc.g = this._settings.get_double(CONTRAST_GREEN_KEY); | ||||
|             bc.b = this._settings.get_double(CONTRAST_BLUE_KEY); | ||||
|             zoomRegion.setContrast(bc); | ||||
|         } | ||||
|     _settingsInit: function() { | ||||
|         this._appSettings = new Gio.Settings({ schema: APPLICATIONS_SCHEMA }); | ||||
|         this._settings = new Gio.Settings({ schema: MAGNIFIER_SCHEMA }); | ||||
|  | ||||
|         this._appSettings.connect('changed::' + SHOW_KEY, Lang.bind(this, function() { | ||||
|             let active = this._appSettings.get_boolean(SHOW_KEY); | ||||
|             this.setActive(active); | ||||
|         })); | ||||
|  | ||||
|         return this._appSettings.get_boolean(SHOW_KEY); | ||||
|     }, | ||||
|  | ||||
|     _settingsInitLate: function() { | ||||
|         let showCrosshairs = this._settings.get_boolean(SHOW_CROSS_HAIRS_KEY); | ||||
|         this.addCrosshairs(); | ||||
|         this.setCrosshairsVisible(showCrosshairs); | ||||
|  | ||||
|         this._appSettings.connect('changed::' + SHOW_KEY, | ||||
|                                   Lang.bind(this, function() { | ||||
|             this.setActive(this._appSettings.get_boolean(SHOW_KEY)); | ||||
|         })); | ||||
|  | ||||
|         this._settings.connect('changed::' + SCREEN_POSITION_KEY, | ||||
|                                Lang.bind(this, this._updateScreenPosition)); | ||||
|         this._settings.connect('changed::' + MAG_FACTOR_KEY, | ||||
| @@ -561,7 +573,6 @@ const Magnifier = new Lang.Class({ | ||||
|                                Lang.bind(this, function() { | ||||
|             this.setCrosshairsClip(this._settings.get_boolean(CROSS_HAIRS_CLIP_KEY)); | ||||
|         })); | ||||
|         return this._appSettings.get_boolean(SHOW_KEY); | ||||
|    }, | ||||
|  | ||||
|     _updateScreenPosition: function() { | ||||
| @@ -720,16 +731,8 @@ const ZoomRegion = new Lang.Class({ | ||||
|         let component = event.source.get_component_iface(); | ||||
|         if (!component || event.detail1 != 1) | ||||
|             return; | ||||
|         let extents; | ||||
|         try { | ||||
|             extents = component.get_extents(Atspi.CoordType.SCREEN); | ||||
|         } catch(e) { | ||||
|             log('Failed to read extents of focused component: ' + e.message); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         [this._xFocus, this._yFocus] = [extents.x + (extents.width / 2), | ||||
|                                         extents.y + (extents.height / 2)]; | ||||
|         let extents = component.get_extents(Atspi.CoordType.SCREEN); | ||||
|         [this._xFocus, this._yFocus] = [extents.x, extents.y] | ||||
|         this._centerFromFocusPosition(); | ||||
|     }, | ||||
|  | ||||
| @@ -737,14 +740,7 @@ const ZoomRegion = new Lang.Class({ | ||||
|         let text = event.source.get_text_iface(); | ||||
|         if (!text) | ||||
|             return; | ||||
|         let extents; | ||||
|         try { | ||||
|             extents = text.get_character_extents(text.get_caret_offset(), 0); | ||||
|         } catch(e) { | ||||
|             log('Failed to read extents of text caret: ' + e.message); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let extents = text.get_character_extents(text.get_caret_offset(), 0); | ||||
|         [this._xCaret, this._yCaret] = [extents.x, extents.y]; | ||||
|         this._centerFromCaretPosition(); | ||||
|     }, | ||||
| @@ -767,9 +763,6 @@ const ZoomRegion = new Lang.Class({ | ||||
|         } else { | ||||
|             this._destroyActors(); | ||||
|         } | ||||
|  | ||||
|         this._syncCaretTracking(); | ||||
|         this._syncFocusTracking(); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
| @@ -829,7 +822,10 @@ const ZoomRegion = new Lang.Class({ | ||||
|      */ | ||||
|     setFocusTrackingMode: function(mode) { | ||||
|         this._focusTrackingMode = mode; | ||||
|         this._syncFocusTracking(); | ||||
|         if (this._focusTrackingMode == GDesktopEnums.MagnifierFocusTrackingMode.NONE) | ||||
|             this._focusCaretTracker.deregisterFocusListener(); | ||||
|         else | ||||
|             this._focusCaretTracker.registerFocusListener(); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
| @@ -838,27 +834,10 @@ const ZoomRegion = new Lang.Class({ | ||||
|      */ | ||||
|     setCaretTrackingMode: function(mode) { | ||||
|         this._caretTrackingMode = mode; | ||||
|         this._syncCaretTracking(); | ||||
|     }, | ||||
|  | ||||
|     _syncFocusTracking: function() { | ||||
|         let enabled = this._focusTrackingMode != GDesktopEnums.MagnifierFocusTrackingMode.NONE && | ||||
|             this.isActive(); | ||||
|  | ||||
|         if (enabled) | ||||
|             this._focusCaretTracker.registerFocusListener(); | ||||
|         else | ||||
|             this._focusCaretTracker.deregisterFocusListener(); | ||||
|     }, | ||||
|  | ||||
|     _syncCaretTracking: function() { | ||||
|         let enabled = this._caretTrackingMode != GDesktopEnums.MagnifierCaretTrackingMode.NONE && | ||||
|             this.isActive(); | ||||
|  | ||||
|         if (enabled) | ||||
|             this._focusCaretTracker.registerCaretListener(); | ||||
|         else | ||||
|         if (this._caretTrackingMode == GDesktopEnums.MagnifierCaretTrackingMode.NONE) | ||||
|             this._focusCaretTracker.deregisterCaretListener(); | ||||
|         else | ||||
|             this._focusCaretTracker.registerCaretListener(); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
| @@ -1199,17 +1178,13 @@ const ZoomRegion = new Lang.Class({ | ||||
|         // 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, | ||||
|                                                layout_manager: new Clutter.BinLayout(), | ||||
|                                                width: global.screen_width, | ||||
|                                                height: global.screen_height }); | ||||
|         let noiseTexture = (new Background.SystemBackground()).actor; | ||||
|         this._background.add_actor(noiseTexture); | ||||
|         mainGroup.add_actor(this._background); | ||||
|  | ||||
|         // 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, | ||||
|                                                  clip_to_allocation: true }); | ||||
|         this._uiGroupClone = new Clutter.Clone({ source: Main.layoutManager.uiGroup }); | ||||
|         mainGroup.add_actor(this._uiGroupClone); | ||||
|  | ||||
|         // Add either the given mouseSourceActor to the ZoomRegion, or a clone of | ||||
|   | ||||
							
								
								
									
										113
									
								
								js/ui/main.js
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								js/ui/main.js
									
									
									
									
									
								
							| @@ -18,7 +18,6 @@ const ExtensionSystem = imports.ui.extensionSystem; | ||||
| const ExtensionDownloader = imports.ui.extensionDownloader; | ||||
| const Keyboard = imports.ui.keyboard; | ||||
| const MessageTray = imports.ui.messageTray; | ||||
| const ModalDialog = imports.ui.modalDialog; | ||||
| const OsdWindow = imports.ui.osdWindow; | ||||
| const Overview = imports.ui.overview; | ||||
| const Panel = imports.ui.panel; | ||||
| @@ -44,7 +43,6 @@ const DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff); | ||||
|  | ||||
| const A11Y_SCHEMA = 'org.gnome.desktop.a11y.keyboard'; | ||||
| const STICKY_KEYS_ENABLE = 'stickykeys-enable'; | ||||
| const GNOMESHELL_STARTED_MESSAGE_ID = 'f3ea493c22934e26811cd62abe8e203a'; | ||||
|  | ||||
| let componentManager = null; | ||||
| let panel = null; | ||||
| @@ -57,7 +55,7 @@ let screenShield = null; | ||||
| let notificationDaemon = null; | ||||
| let windowAttentionHandler = null; | ||||
| let ctrlAltTabManager = null; | ||||
| let osdWindowManager = null; | ||||
| let osdWindow = null; | ||||
| let sessionMode = null; | ||||
| let shellDBusService = null; | ||||
| let shellMountOpDBusService = null; | ||||
| @@ -66,7 +64,6 @@ let screencastService = null; | ||||
| let modalCount = 0; | ||||
| let keybindingMode = Shell.KeyBindingMode.NONE; | ||||
| let modalActorFocusStack = []; | ||||
| let uiGroup = null; | ||||
| let magnifier = null; | ||||
| let xdndHandler = null; | ||||
| let keyboard = null; | ||||
| @@ -75,6 +72,7 @@ let _startDate; | ||||
| let _defaultCssStylesheet = null; | ||||
| let _cssStylesheet = null; | ||||
| let _a11ySettings = null; | ||||
| let dynamicWorkspacesSchema = null; | ||||
|  | ||||
| function _sessionUpdated() { | ||||
|     _loadDefaultStylesheet(); | ||||
| @@ -104,6 +102,9 @@ function start() { | ||||
|     global.logError = window.log; | ||||
|     global.log = window.log; | ||||
|  | ||||
|     if (!Meta.is_wayland_compositor) | ||||
|         Meta.is_wayland_compositor = function () { return false; }; | ||||
|  | ||||
|     // Chain up async errors reported from C | ||||
|     global.connect('notify-error', function (global, msg, detail) { notifyError(msg, detail); }); | ||||
|  | ||||
| @@ -111,6 +112,7 @@ function start() { | ||||
|  | ||||
|     sessionMode = new SessionMode.SessionMode(); | ||||
|     sessionMode.connect('updated', _sessionUpdated); | ||||
|     _initializePrefs(); | ||||
|     _initializeUI(); | ||||
|  | ||||
|     shellDBusService = new ShellDBus.GnomeShell(); | ||||
| @@ -119,6 +121,17 @@ function start() { | ||||
|     _sessionUpdated(); | ||||
| } | ||||
|  | ||||
| function _initializePrefs() { | ||||
|     let keys = new Gio.Settings({ schema: sessionMode.overridesSchema }).list_keys(); | ||||
|     for (let i = 0; i < keys.length; i++) | ||||
|         Meta.prefs_override_preference_schema(keys[i], sessionMode.overridesSchema); | ||||
|  | ||||
|     if (keys.indexOf('dynamic-workspaces') > -1) | ||||
|         dynamicWorkspacesSchema = sessionMode.overridesSchema; | ||||
|     else | ||||
|         dynamicWorkspacesSchema = 'org.gnome.mutter'; | ||||
| } | ||||
|  | ||||
| function _initializeUI() { | ||||
|     // Ensure ShellWindowTracker and ShellAppUsage are initialized; this will | ||||
|     // also initialize ShellAppSystem first.  ShellAppSystem | ||||
| @@ -136,15 +149,10 @@ function _initializeUI() { | ||||
|     // Setup the stage hierarchy early | ||||
|     layoutManager = new Layout.LayoutManager(); | ||||
|  | ||||
|     // Various parts of the codebase still refers to Main.uiGroup | ||||
|     // instead using the layoutManager.  This keeps that code | ||||
|     // working until it's updated. | ||||
|     uiGroup = layoutManager.uiGroup; | ||||
|  | ||||
|     screencastService = new Screencast.ScreencastService(); | ||||
|     xdndHandler = new XdndHandler.XdndHandler(); | ||||
|     ctrlAltTabManager = new CtrlAltTab.CtrlAltTabManager(); | ||||
|     osdWindowManager = new OsdWindow.OsdWindowManager(); | ||||
|     osdWindow = new OsdWindow.OsdWindow(); | ||||
|     overview = new Overview.Overview(); | ||||
|     wm = new WindowManager.WindowManager(); | ||||
|     magnifier = new Magnifier.Magnifier(); | ||||
| @@ -158,26 +166,29 @@ function _initializeUI() { | ||||
|     windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler(); | ||||
|     componentManager = new Components.ComponentManager(); | ||||
|  | ||||
|     if (sessionMode.isGreeter && screenShield) { | ||||
|         layoutManager.connect('startup-prepared', function() { | ||||
|             screenShield.showDialog(); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     layoutManager.connect('startup-complete', function() { | ||||
|         if (keybindingMode == Shell.KeyBindingMode.NONE) | ||||
|             keybindingMode = Shell.KeyBindingMode.NORMAL; | ||||
|         if (screenShield) | ||||
|             screenShield.lockIfWasLocked(); | ||||
|     }); | ||||
|  | ||||
|     layoutManager.init(); | ||||
|     overview.init(); | ||||
|  | ||||
|     _a11ySettings = new Gio.Settings({ schema_id: A11Y_SCHEMA }); | ||||
|     _a11ySettings = new Gio.Settings({ schema: A11Y_SCHEMA }); | ||||
|  | ||||
|     global.display.connect('overlay-key', Lang.bind(overview, function () { | ||||
|         if (!_a11ySettings.get_boolean (STICKY_KEYS_ENABLE)) | ||||
|             overview.toggle(); | ||||
|     })); | ||||
|  | ||||
|     global.display.connect('show-restart-message', function(display, message) { | ||||
|         showRestartMessage(message); | ||||
|         return true; | ||||
|     }); | ||||
|  | ||||
|     global.display.connect('restart', function() { | ||||
|         global.reexec_self(); | ||||
|         return true; | ||||
|     }); | ||||
|  | ||||
|     // Provide the bus object for gnome-session to | ||||
|     // initiate logouts. | ||||
|     EndSessionDialog.init(); | ||||
| @@ -187,6 +198,8 @@ function _initializeUI() { | ||||
|  | ||||
|     _startDate = new Date(); | ||||
|  | ||||
|     log('GNOME Shell started at ' + _startDate); | ||||
|  | ||||
|     let perfModuleName = GLib.getenv("SHELL_PERF_MODULE"); | ||||
|     if (perfModuleName) { | ||||
|         let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT"); | ||||
| @@ -196,32 +209,6 @@ function _initializeUI() { | ||||
|  | ||||
|     ExtensionDownloader.init(); | ||||
|     ExtensionSystem.init(); | ||||
|  | ||||
|     if (sessionMode.isGreeter && screenShield) { | ||||
|         layoutManager.connect('startup-prepared', function() { | ||||
|             screenShield.showDialog(); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     layoutManager.connect('startup-complete', function() { | ||||
|                               if (keybindingMode == Shell.KeyBindingMode.NONE) { | ||||
|                                   keybindingMode = Shell.KeyBindingMode.NORMAL; | ||||
|                               } | ||||
|                               if (screenShield) { | ||||
|                                   screenShield.lockIfWasLocked(); | ||||
|                               } | ||||
|                               if (LoginManager.haveSystemd() && | ||||
|                                   sessionMode.currentMode != 'gdm' && | ||||
|                                   sessionMode.currentMode != 'initial-setup') { | ||||
|                                   // Do not import globally to not depend | ||||
|                                   // on systemd on non-systemd systems. | ||||
|                                   let GSystem = imports.gi.GSystem; | ||||
|                                   GSystem.log_structured_print('GNOME Shell started at ' + _startDate, | ||||
|                                                                ['MESSAGE_ID=' + GNOMESHELL_STARTED_MESSAGE_ID]); | ||||
|                               } else { | ||||
|                                   log('GNOME Shell started at ' + _startDate); | ||||
|                               } | ||||
|                           }); | ||||
| } | ||||
|  | ||||
| function _loadDefaultStylesheet() { | ||||
| @@ -244,7 +231,8 @@ function _loadDefaultStylesheet() { | ||||
|  * Returns: A file path that contains the theme CSS, | ||||
|  *          null if using the default | ||||
|  */ | ||||
| function getThemeStylesheet() { | ||||
| function getThemeStylesheet() | ||||
| { | ||||
|     return _cssStylesheet; | ||||
| } | ||||
|  | ||||
| @@ -255,7 +243,8 @@ function getThemeStylesheet() { | ||||
|  * | ||||
|  * Set the theme CSS file that the shell will load | ||||
|  */ | ||||
| function setThemeStylesheet(cssStylesheet) { | ||||
| function setThemeStylesheet(cssStylesheet) | ||||
| { | ||||
|     _cssStylesheet = cssStylesheet; | ||||
| } | ||||
|  | ||||
| @@ -614,31 +603,5 @@ function queueDeferredWork(workId) { | ||||
|             _deferredTimeoutId = 0; | ||||
|             return GLib.SOURCE_REMOVE; | ||||
|         }); | ||||
|         GLib.Source.set_name_by_id(_deferredTimeoutId, '[gnome-shell] _runAllDeferredWork'); | ||||
|     } | ||||
| } | ||||
|  | ||||
| const RestartMessage = new Lang.Class({ | ||||
|     Name: 'RestartMessage', | ||||
|     Extends: ModalDialog.ModalDialog, | ||||
|  | ||||
|     _init : function(message) { | ||||
|         this.parent({ shellReactive: true, | ||||
|                       styleClass: 'restart-message', | ||||
|                       shouldFadeIn: false, | ||||
|                       destroyOnClose: true }); | ||||
|  | ||||
|         let label = new St.Label({ text: message }); | ||||
|  | ||||
|         this.contentLayout.add(label, { x_fill: false, | ||||
|                                         y_fill: false, | ||||
|                                         x_align: St.Align.MIDDLE, | ||||
|                                         y_align: St.Align.MIDDLE }); | ||||
|         this.buttonLayout.hide(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| function showRestartMessage(message) { | ||||
|     let restartMessage = new RestartMessage(message); | ||||
|     restartMessage.open(); | ||||
| } | ||||
|   | ||||
| @@ -15,7 +15,6 @@ const Signals = imports.signals; | ||||
| const St = imports.gi.St; | ||||
| const Tp = imports.gi.TelepathyGLib; | ||||
|  | ||||
| const EdgeDragAction = imports.ui.edgeDragAction; | ||||
| const BoxPointer = imports.ui.boxpointer; | ||||
| const CtrlAltTab = imports.ui.ctrlAltTab; | ||||
| const GnomeSession = imports.misc.gnomeSession; | ||||
| @@ -112,6 +111,7 @@ const FocusGrabber = new Lang.Class({ | ||||
|         if (this._focused) | ||||
|             return; | ||||
|  | ||||
|         this._prevFocusedWindow = global.display.focus_window; | ||||
|         this._prevKeyFocusActor = global.stage.get_key_focus(); | ||||
|  | ||||
|         this._focusActorChangedId = global.stage.connect('notify::key-focus', Lang.bind(this, this._focusActorChanged)); | ||||
| @@ -316,7 +316,7 @@ const NotificationGenericPolicy = new Lang.Class({ | ||||
|  | ||||
|         this.id = 'generic'; | ||||
|  | ||||
|         this._masterSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.notifications' }); | ||||
|         this._masterSettings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications' }); | ||||
|         this._masterSettings.connect('changed', Lang.bind(this, this._changed)); | ||||
|     }, | ||||
|  | ||||
| @@ -366,8 +366,8 @@ const NotificationApplicationPolicy = new Lang.Class({ | ||||
|         this.id = id; | ||||
|         this._canonicalId = this._canonicalizeId(id); | ||||
|  | ||||
|         this._masterSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.notifications' }); | ||||
|         this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.notifications.application', | ||||
|         this._masterSettings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications' }); | ||||
|         this._settings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications.application', | ||||
|                                             path: '/org/gnome/desktop/notifications/application/' + this._canonicalId + '/' }); | ||||
|  | ||||
|         this._masterSettings.connect('changed', Lang.bind(this, this._changed)); | ||||
| @@ -504,6 +504,7 @@ const Notification = new Lang.Class({ | ||||
|         this.bannerBodyMarkup = false; | ||||
|         this._bannerBodyAdded = false; | ||||
|         this._titleFitsInBannerMode = true; | ||||
|         this._titleDirection = Clutter.TextDirection.DEFAULT; | ||||
|         this._spacing = 0; | ||||
|         this._scrollPolicy = Gtk.PolicyType.AUTOMATIC; | ||||
|         this._imageBin = null; | ||||
| @@ -642,11 +643,10 @@ const Notification = new Lang.Class({ | ||||
|         title = title ? _fixMarkup(title.replace(/\n/g, ' '), false) : ''; | ||||
|         this._titleLabel.clutter_text.set_markup('<b>' + title + '</b>'); | ||||
|  | ||||
|         let titleDirection; | ||||
|         if (Pango.find_base_dir(title, -1) == Pango.Direction.RTL) | ||||
|             titleDirection = Clutter.TextDirection.RTL; | ||||
|             this._titleDirection = Clutter.TextDirection.RTL; | ||||
|         else | ||||
|             titleDirection = Clutter.TextDirection.LTR; | ||||
|             this._titleDirection = Clutter.TextDirection.LTR; | ||||
|  | ||||
|         // Let the title's text direction control the overall direction | ||||
|         // of the notification - in case where different scripts are used | ||||
| @@ -654,7 +654,7 @@ const Notification = new Lang.Class({ | ||||
|         // arguably for action buttons as well. Labels other than the title | ||||
|         // will be allocated at the available width, so that their alignment | ||||
|         // is done correctly automatically. | ||||
|         this._table.set_text_direction(titleDirection); | ||||
|         this._table.set_text_direction(this._titleDirection); | ||||
|  | ||||
|         // Unless the notification has custom content, we save this.bannerBodyText | ||||
|         // to add it to the content of the notification if the notification is | ||||
| @@ -923,7 +923,7 @@ const Notification = new Lang.Class({ | ||||
|         let [titleMinH, titleNatH] = this._titleLabel.get_preferred_height(availWidth); | ||||
|         let [bannerMinW, bannerNatW] = this._bannerLabel.get_preferred_width(availWidth); | ||||
|  | ||||
|         let rtl = (this._table.text_direction == Clutter.TextDirection.RTL); | ||||
|         let rtl = (this._titleDirection == Clutter.TextDirection.RTL); | ||||
|         let x = rtl ? availWidth : 0; | ||||
|  | ||||
|         if (this._secondaryIcon) { | ||||
| @@ -1162,12 +1162,32 @@ const SourceActor = new Lang.Class({ | ||||
|         })); | ||||
|         this._actorDestroyed = false; | ||||
|  | ||||
|         let scale_factor = St.ThemeContext.get_for_stage(global.stage).scale_factor; | ||||
|         this._iconBin = new St.Bin({ x_fill: true, | ||||
|                                      height: size * scale_factor, | ||||
|                                      width: size * scale_factor }); | ||||
|         this._counterLabel = new St.Label({ x_align: Clutter.ActorAlign.CENTER, | ||||
|                                             x_expand: true, | ||||
|                                             y_align: Clutter.ActorAlign.CENTER, | ||||
|                                             y_expand: true }); | ||||
|  | ||||
|         this._counterBin = new St.Bin({ style_class: 'summary-source-counter', | ||||
|                                         child: this._counterLabel, | ||||
|                                         layout_manager: new Clutter.BinLayout() }); | ||||
|         this._counterBin.hide(); | ||||
|  | ||||
|         this._counterBin.connect('style-changed', Lang.bind(this, function() { | ||||
|             let themeNode = this._counterBin.get_theme_node(); | ||||
|             this._counterBin.translation_x = themeNode.get_length('-shell-counter-overlap-x'); | ||||
|             this._counterBin.translation_y = themeNode.get_length('-shell-counter-overlap-y'); | ||||
|         })); | ||||
|  | ||||
|         this._iconBin = new St.Bin({ width: size, | ||||
|                                      height: size, | ||||
|                                      x_fill: true, | ||||
|                                      y_fill: true }); | ||||
|  | ||||
|         this.actor.add_actor(this._iconBin); | ||||
|         this.actor.add_actor(this._counterBin); | ||||
|  | ||||
|         this._source.connect('count-updated', Lang.bind(this, this._updateCount)); | ||||
|         this._updateCount(); | ||||
|  | ||||
|         this._source.connect('icon-updated', Lang.bind(this, this._updateIcon)); | ||||
|         this._updateIcon(); | ||||
| @@ -1191,48 +1211,6 @@ const SourceActor = new Lang.Class({ | ||||
|     _allocate: function(actor, box, flags) { | ||||
|         // the iconBin should fill our entire box | ||||
|         this._iconBin.allocate(box, flags); | ||||
|     }, | ||||
|  | ||||
|     _updateIcon: function() { | ||||
|         if (this._actorDestroyed) | ||||
|             return; | ||||
|  | ||||
|         if (!this._iconSet) | ||||
|             this._iconBin.child = this._source.createIcon(this._size); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const SourceActorWithLabel = new Lang.Class({ | ||||
|     Name: 'SourceActorWithLabel', | ||||
|     Extends: SourceActor, | ||||
|  | ||||
|     _init: function(source, size) { | ||||
|         this.parent(source, size); | ||||
|  | ||||
|         this._counterLabel = new St.Label({ x_align: Clutter.ActorAlign.CENTER, | ||||
|                                             x_expand: true, | ||||
|                                             y_align: Clutter.ActorAlign.CENTER, | ||||
|                                             y_expand: true }); | ||||
|  | ||||
|         this._counterBin = new St.Bin({ style_class: 'summary-source-counter', | ||||
|                                         child: this._counterLabel, | ||||
|                                         layout_manager: new Clutter.BinLayout() }); | ||||
|         this._counterBin.hide(); | ||||
|  | ||||
|         this._counterBin.connect('style-changed', Lang.bind(this, function() { | ||||
|             let themeNode = this._counterBin.get_theme_node(); | ||||
|             this._counterBin.translation_x = themeNode.get_length('-shell-counter-overlap-x'); | ||||
|             this._counterBin.translation_y = themeNode.get_length('-shell-counter-overlap-y'); | ||||
|         })); | ||||
|  | ||||
|         this.actor.add_actor(this._counterBin); | ||||
|  | ||||
|         this._source.connect('count-updated', Lang.bind(this, this._updateCount)); | ||||
|         this._updateCount(); | ||||
|     }, | ||||
|  | ||||
|     _allocate: function(actor, box, flags) { | ||||
|         this.parent(actor, box, flags); | ||||
|  | ||||
|         let childBox = new Clutter.ActorBox(); | ||||
|  | ||||
| @@ -1255,6 +1233,14 @@ const SourceActorWithLabel = new Lang.Class({ | ||||
|         this._counterBin.allocate(childBox, flags); | ||||
|     }, | ||||
|  | ||||
|     _updateIcon: function() { | ||||
|         if (this._actorDestroyed) | ||||
|             return; | ||||
|  | ||||
|         if (!this._iconSet) | ||||
|             this._iconBin.child = this._source.createIcon(this._size); | ||||
|     }, | ||||
|  | ||||
|     _updateCount: function() { | ||||
|         if (this._actorDestroyed) | ||||
|             return; | ||||
| @@ -1367,7 +1353,7 @@ const Source = new Lang.Class({ | ||||
|         if (this._mainIcon) | ||||
|             return; | ||||
|  | ||||
|         this._mainIcon = new SourceActorWithLabel(this, this.SOURCE_ICON_SIZE); | ||||
|         this._mainIcon = new SourceActor(this, this.SOURCE_ICON_SIZE); | ||||
|     }, | ||||
|  | ||||
|     // Unlike createIcon, this always returns the same actor; | ||||
| @@ -1625,7 +1611,7 @@ const MessageTrayMenu = new Lang.Class({ | ||||
|         this._accountManager.prepare_async(null, Lang.bind(this, this._onIMPresenceChanged)); | ||||
|  | ||||
|         this.actor.hide(); | ||||
|         Main.layoutManager.addChrome(this.actor); | ||||
|         Main.layoutManager.menuGroup.add_child(this.actor); | ||||
|  | ||||
|         this._busyItem = new PopupMenu.PopupSwitchMenuItem(_("Notifications")); | ||||
|         this._busyItem.connect('toggled', Lang.bind(this, this._updatePresence)); | ||||
| @@ -1901,14 +1887,14 @@ const MessageTray = new Lang.Class({ | ||||
|         Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated)); | ||||
|  | ||||
|         Main.wm.addKeybinding('toggle-message-tray', | ||||
|                               new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }), | ||||
|                               new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }), | ||||
|                               Meta.KeyBindingFlags.NONE, | ||||
|                               Shell.KeyBindingMode.NORMAL | | ||||
|                               Shell.KeyBindingMode.MESSAGE_TRAY | | ||||
|                               Shell.KeyBindingMode.OVERVIEW, | ||||
|                               Lang.bind(this, this.toggleAndNavigate)); | ||||
|         Main.wm.addKeybinding('focus-active-notification', | ||||
|                               new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }), | ||||
|                               new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }), | ||||
|                               Meta.KeyBindingFlags.NONE, | ||||
|                               Shell.KeyBindingMode.NORMAL | | ||||
|                               Shell.KeyBindingMode.MESSAGE_TRAY | | ||||
| @@ -1934,10 +1920,6 @@ const MessageTray = new Lang.Class({ | ||||
|  | ||||
|         this._messageTrayMenuButton = new MessageTrayMenuButton(this); | ||||
|         this.actor.add_actor(this._messageTrayMenuButton.actor); | ||||
|  | ||||
|         let gesture = new EdgeDragAction.EdgeDragAction(St.Side.BOTTOM); | ||||
|         gesture.connect('activated', Lang.bind(this, this.toggle)); | ||||
|         global.stage.add_action(gesture); | ||||
|     }, | ||||
|  | ||||
|     close: function() { | ||||
| @@ -1991,7 +1973,6 @@ const MessageTray = new Lang.Class({ | ||||
|  | ||||
|                 this._trayDwellTimeoutId = Mainloop.timeout_add(TRAY_DWELL_TIME, | ||||
|                                                                 Lang.bind(this, this._trayDwellTimeout)); | ||||
|                 GLib.Source.set_name_by_id(this._trayDwellTimeoutId, '[gnome-shell] this._trayDwellTimeout'); | ||||
|             } | ||||
|             this._trayDwelling = true; | ||||
|         } else { | ||||
| @@ -2032,18 +2013,13 @@ const MessageTray = new Lang.Class({ | ||||
|  | ||||
|     _onNotificationKeyRelease: function(actor, event) { | ||||
|         if (event.get_key_symbol() == Clutter.KEY_Escape && event.get_state() == 0) { | ||||
|             this._expireNotification(); | ||||
|             this._closeNotification(); | ||||
|             return Clutter.EVENT_STOP; | ||||
|         } | ||||
|  | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     }, | ||||
|  | ||||
|     _expireNotification: function() { | ||||
|         this._notificationExpired = true; | ||||
|         this._updateState(); | ||||
|     }, | ||||
|  | ||||
|     _closeNotification: function() { | ||||
|         if (this._notificationState == State.SHOWN) { | ||||
|             this._closeButton.hide(); | ||||
| @@ -2272,16 +2248,6 @@ const MessageTray = new Lang.Class({ | ||||
|             this._grabHelper.addActor(corner.actor); | ||||
|     }, | ||||
|  | ||||
|     _resetNotificationLeftTimeout: function() { | ||||
|         this._useLongerNotificationLeftTimeout = false; | ||||
|         if (this._notificationLeftTimeoutId) { | ||||
|             Mainloop.source_remove(this._notificationLeftTimeoutId); | ||||
|             this._notificationLeftTimeoutId = 0; | ||||
|             this._notificationLeftMouseX = -1; | ||||
|             this._notificationLeftMouseY = -1; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _onNotificationHoverChanged: function() { | ||||
|         if (this._notificationWidget.hover == this._notificationHovered) | ||||
|             return; | ||||
| @@ -2291,7 +2257,14 @@ const MessageTray = new Lang.Class({ | ||||
|             // No dwell inside notifications at the bottom of the screen | ||||
|             this._cancelTrayDwell(); | ||||
|  | ||||
|             this._resetNotificationLeftTimeout(); | ||||
|             this._useLongerNotificationLeftTimeout = false; | ||||
|             if (this._notificationLeftTimeoutId) { | ||||
|                 Mainloop.source_remove(this._notificationLeftTimeoutId); | ||||
|                 this._notificationLeftTimeoutId = 0; | ||||
|                 this._notificationLeftMouseX = -1; | ||||
|                 this._notificationLeftMouseY = -1; | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             if (this._showNotificationMouseX >= 0) { | ||||
|                 let actorAtShowNotificationPosition = | ||||
| @@ -2308,7 +2281,6 @@ const MessageTray = new Lang.Class({ | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             this._pointerInNotification = true; | ||||
|             this._updateState(); | ||||
|         } else { | ||||
| @@ -2325,7 +2297,6 @@ const MessageTray = new Lang.Class({ | ||||
|             // That gives the user more time to mouse away from the notification and mouse back in in order to expand it. | ||||
|             let timeout = this._useLongerNotificationLeftTimeout ? LONGER_HIDE_TIMEOUT * 1000 : HIDE_TIMEOUT * 1000; | ||||
|             this._notificationLeftTimeoutId = Mainloop.timeout_add(timeout, Lang.bind(this, this._onNotificationLeftTimeout)); | ||||
|             GLib.Source.set_name_by_id(this._notificationLeftTimeoutId, '[gnome-shell] this._onNotificationLeftTimeout'); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
| @@ -2361,7 +2332,6 @@ const MessageTray = new Lang.Class({ | ||||
|             this._notificationLeftMouseX = -1; | ||||
|             this._notificationLeftTimeoutId = Mainloop.timeout_add(LONGER_HIDE_TIMEOUT * 1000, | ||||
|                                                              Lang.bind(this, this._onNotificationLeftTimeout)); | ||||
|             GLib.Source.set_name_by_id(this._notificationLeftTimeoutId, '[gnome-shell] this._onNotificationLeftTimeout'); | ||||
|         } else { | ||||
|             this._notificationLeftTimeoutId = 0; | ||||
|             this._useLongerNotificationLeftTimeout = false; | ||||
| @@ -2414,7 +2384,7 @@ const MessageTray = new Lang.Class({ | ||||
|                            this._notificationTimeoutId == 0 && | ||||
|                            this._notification.urgency != Urgency.CRITICAL && | ||||
|                            !this._notification.focused && | ||||
|                            !this._pointerInNotification) || this._notificationExpired; | ||||
|                            !this._pointerInNotification); | ||||
|             let mustClose = (this._notificationRemoved || !hasNotifications || expired || this._traySummoned); | ||||
|  | ||||
|             if (mustClose) { | ||||
| @@ -2475,10 +2445,6 @@ const MessageTray = new Lang.Class({ | ||||
|             this._hideDesktopClone(); | ||||
|  | ||||
|         this._updatingState = false; | ||||
|  | ||||
|         // Clean transient variables that are used to communicate actions | ||||
|         // to updateState() | ||||
|         this._notificationExpired = false; | ||||
|     }, | ||||
|  | ||||
|     _tween: function(actor, statevar, value, params) { | ||||
| @@ -2546,7 +2512,7 @@ const MessageTray = new Lang.Class({ | ||||
|         let cloneSource = Main.overview.visible ? Main.layoutManager.overviewGroup : global.window_group; | ||||
|         this._desktopClone = new Clutter.Clone({ source: cloneSource, | ||||
|                                                  clip: new Clutter.Geometry(this._bottomMonitorGeometry) }); | ||||
|         Main.uiGroup.insert_child_above(this._desktopClone, cloneSource); | ||||
|         Main.layoutManager.sessionGroup.insert_child_above(this._desktopClone, cloneSource); | ||||
|         this._desktopClone.x = 0; | ||||
|         this._desktopClone.y = 0; | ||||
|         this._desktopClone.show(); | ||||
| @@ -2635,8 +2601,6 @@ const MessageTray = new Lang.Class({ | ||||
|         // the mouse is moving towards it or within it. | ||||
|         this._lastSeenMouseX = x; | ||||
|         this._lastSeenMouseY = y; | ||||
|  | ||||
|         this._resetNotificationLeftTimeout(); | ||||
|     }, | ||||
|  | ||||
|     _updateShowingNotification: function() { | ||||
| @@ -2681,12 +2645,10 @@ const MessageTray = new Lang.Class({ | ||||
|             Mainloop.source_remove(this._notificationTimeoutId); | ||||
|             this._notificationTimeoutId = 0; | ||||
|         } | ||||
|         if (timeout > 0) { | ||||
|         if (timeout > 0) | ||||
|             this._notificationTimeoutId = | ||||
|                 Mainloop.timeout_add(timeout, | ||||
|                                      Lang.bind(this, this._notificationTimeout)); | ||||
|             GLib.Source.set_name_by_id(this._notificationTimeoutId, '[gnome-shell] this._notificationTimeout'); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _notificationTimeout: function() { | ||||
| @@ -2729,7 +2691,13 @@ const MessageTray = new Lang.Class({ | ||||
|             this._notificationUnfocusedId = 0; | ||||
|         } | ||||
|  | ||||
|         this._resetNotificationLeftTimeout(); | ||||
|         this._useLongerNotificationLeftTimeout = false; | ||||
|         if (this._notificationLeftTimeoutId) { | ||||
|             Mainloop.source_remove(this._notificationLeftTimeoutId); | ||||
|             this._notificationLeftTimeoutId = 0; | ||||
|             this._notificationLeftMouseX = -1; | ||||
|             this._notificationLeftMouseY = -1; | ||||
|         } | ||||
|  | ||||
|         if (animate) { | ||||
|             this._tween(this._notificationWidget, '_notificationState', State.HIDDEN, | ||||
| @@ -2799,12 +2767,7 @@ const MessageTray = new Lang.Class({ | ||||
|                              { y: expandedY, | ||||
|                                opacity: 255, | ||||
|                                time: ANIMATION_TIME, | ||||
|                                transition: 'easeOutQuad', | ||||
|                                // HACK: Drive the state machine here better, | ||||
|                                // instead of overwriting tweens | ||||
|                                onComplete: Lang.bind(this, function() { | ||||
|                                    this._notificationState = State.SHOWN; | ||||
|                                }), | ||||
|                                transition: 'easeOutQuad' | ||||
|                              }); | ||||
|         } | ||||
|     }, | ||||
|   | ||||
| @@ -41,9 +41,9 @@ const ModalDialog = new Lang.Class({ | ||||
|     _init: function(params) { | ||||
|         params = Params.parse(params, { shellReactive: false, | ||||
|                                         styleClass: null, | ||||
|                                         parentActor: Main.layoutManager.dialogGroup, | ||||
|                                         keybindingMode: Shell.KeyBindingMode.SYSTEM_MODAL, | ||||
|                                         shouldFadeIn: true, | ||||
|                                         shouldFadeOut: true, | ||||
|                                         destroyOnClose: true }); | ||||
|  | ||||
|         this.state = State.CLOSED; | ||||
| @@ -51,14 +51,13 @@ const ModalDialog = new Lang.Class({ | ||||
|         this._keybindingMode = params.keybindingMode; | ||||
|         this._shellReactive = params.shellReactive; | ||||
|         this._shouldFadeIn = params.shouldFadeIn; | ||||
|         this._shouldFadeOut = params.shouldFadeOut; | ||||
|         this._destroyOnClose = params.destroyOnClose; | ||||
|  | ||||
|         this._group = new St.Widget({ visible: false, | ||||
|                                       x: 0, | ||||
|                                       y: 0, | ||||
|                                       accessible_role: Atk.Role.DIALOG }); | ||||
|         Main.layoutManager.modalDialogGroup.add_actor(this._group); | ||||
|         params.parentActor.add_actor(this._group); | ||||
|  | ||||
|         let constraint = new Clutter.BindConstraint({ source: global.stage, | ||||
|                                                       coordinate: Clutter.BindCoordinate.ALL }); | ||||
| @@ -309,15 +308,6 @@ const ModalDialog = new Lang.Class({ | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     _closeComplete: function() { | ||||
|         this.state = State.CLOSED; | ||||
|         this._group.hide(); | ||||
|         this.emit('closed'); | ||||
|  | ||||
|         if (this._destroyOnClose) | ||||
|             this.destroy(); | ||||
|     }, | ||||
|  | ||||
|     close: function(timestamp) { | ||||
|         if (this.state == State.CLOSED || this.state == State.CLOSING) | ||||
|             return; | ||||
| @@ -326,16 +316,20 @@ const ModalDialog = new Lang.Class({ | ||||
|         this.popModal(timestamp); | ||||
|         this._savedKeyFocus = null; | ||||
|  | ||||
|         if (this._shouldFadeOut) | ||||
|             Tweener.addTween(this._group, | ||||
|                              { opacity: 0, | ||||
|                                time: OPEN_AND_CLOSE_TIME, | ||||
|                                transition: 'easeOutQuad', | ||||
|                                onComplete: Lang.bind(this, | ||||
|                                                      this._closeComplete) | ||||
|                              }) | ||||
|         else | ||||
|             this._closeComplete(); | ||||
|         Tweener.addTween(this._group, | ||||
|                          { opacity: 0, | ||||
|                            time: OPEN_AND_CLOSE_TIME, | ||||
|                            transition: 'easeOutQuad', | ||||
|                            onComplete: Lang.bind(this, | ||||
|                                function() { | ||||
|                                    this.state = State.CLOSED; | ||||
|                                    this._group.hide(); | ||||
|                                    this.emit('closed'); | ||||
|  | ||||
|                                    if (this._destroyOnClose) | ||||
|                                        this.destroy(); | ||||
|                                }) | ||||
|                          }); | ||||
|     }, | ||||
|  | ||||
|     // Drop modal status without closing the dialog; this makes the | ||||
|   | ||||
| @@ -120,12 +120,15 @@ const FdoNotificationDaemon = new Lang.Class({ | ||||
|  | ||||
|         this._nextNotificationId = 1; | ||||
|  | ||||
|         Shell.WindowTracker.get_default().connect('notify::focus-app', Lang.bind(this, this._onFocusAppChanged)); | ||||
|         Main.overview.connect('hidden', Lang.bind(this, this._onFocusAppChanged)); | ||||
|  | ||||
|         this._trayManager = new Shell.TrayManager(); | ||||
|         this._trayIconAddedId = this._trayManager.connect('tray-icon-added', Lang.bind(this, this._onTrayIconAdded)); | ||||
|         this._trayIconRemovedId = this._trayManager.connect('tray-icon-removed', Lang.bind(this, this._onTrayIconRemoved)); | ||||
|  | ||||
|         Shell.WindowTracker.get_default().connect('notify::focus-app', | ||||
|             Lang.bind(this, this._onFocusAppChanged)); | ||||
|         Main.overview.connect('hidden', | ||||
|             Lang.bind(this, this._onFocusAppChanged)); | ||||
|  | ||||
|         this._trayManager.manage_screen(global.screen, Main.messageTray.actor); | ||||
|     }, | ||||
|  | ||||
| @@ -241,12 +244,11 @@ const FdoNotificationDaemon = new Lang.Class({ | ||||
|             // Ignore replacesId since we already sent back a | ||||
|             // NotificationClosed for that id. | ||||
|             id = this._nextNotificationId++; | ||||
|             let idle_id = Mainloop.idle_add(Lang.bind(this, | ||||
|                                             function () { | ||||
|                                                 this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED); | ||||
|                                                 return GLib.SOURCE_REMOVE; | ||||
|                                             })); | ||||
|             GLib.Source.set_name_by_id(idle_id, '[gnome-shell] this._emitNotificationClosed'); | ||||
|             Mainloop.idle_add(Lang.bind(this, | ||||
|                                         function () { | ||||
|                                             this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED); | ||||
|                                             return GLib.SOURCE_REMOVE; | ||||
|                                         })); | ||||
|             return invocation.return_value(GLib.Variant.new('(u)', [id])); | ||||
|         } | ||||
|  | ||||
| @@ -689,12 +691,6 @@ const FdoNotificationDaemonSource = new Lang.Class({ | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const PRIORITY_URGENCY_MAP = { | ||||
|     low: MessageTray.Urgency.LOW, | ||||
|     normal: MessageTray.Urgency.NORMAL, | ||||
|     high: MessageTray.Urgency.HIGH, | ||||
|     urgent: MessageTray.Urgency.CRITICAL | ||||
| }; | ||||
|  | ||||
| const GtkNotificationDaemonNotification = new Lang.Class({ | ||||
|     Name: 'GtkNotificationDaemonNotification', | ||||
| @@ -708,20 +704,12 @@ const GtkNotificationDaemonNotification = new Lang.Class({ | ||||
|               "body": body, | ||||
|               "icon": gicon, | ||||
|               "urgent": urgent, | ||||
|               "priority": priority, | ||||
|               "buttons": buttons, | ||||
|               "default-action": defaultAction, | ||||
|               "default-action-target": defaultActionTarget } = notification; | ||||
|  | ||||
|         if (priority) { | ||||
|             let urgency = PRIORITY_URGENCY_MAP[priority.unpack()]; | ||||
|             this.setUrgency(urgency != undefined ? urgency : MessageTray.Urgency.NORMAL); | ||||
|         } else if (urgent) { | ||||
|             this.setUrgency(urgent.unpack() ? MessageTray.Urgency.CRITICAL | ||||
|                             : MessageTray.Urgency.NORMAL); | ||||
|         } else { | ||||
|             this.setUrgency(MessageTray.Urgency.NORMAL); | ||||
|         } | ||||
|         this.setUrgency(urgent.unpack() ? MessageTray.Urgency.CRITICAL | ||||
|                                         : MessageTray.Urgency.NORMAL); | ||||
|  | ||||
|         if (buttons) { | ||||
|             buttons.deep_unpack().forEach(Lang.bind(this, function(button) { | ||||
|   | ||||
| @@ -73,17 +73,14 @@ const LevelBar = new Lang.Class({ | ||||
| const OsdWindow = new Lang.Class({ | ||||
|     Name: 'OsdWindow', | ||||
|  | ||||
|     _init: function(monitorIndex) { | ||||
|     _init: function() { | ||||
|         this._popupSize = 0; | ||||
|         this.actor = new St.Widget({ x_expand: true, | ||||
|                                      y_expand: true, | ||||
|                                      x_align: Clutter.ActorAlign.CENTER, | ||||
|                                      y_align: Clutter.ActorAlign.CENTER }); | ||||
|  | ||||
|         this._monitorIndex = monitorIndex; | ||||
|         let constraint = new Layout.MonitorConstraint({ index: monitorIndex }); | ||||
|         this.actor.add_constraint(constraint); | ||||
|  | ||||
|         this._currentMonitor = undefined; | ||||
|         this.setMonitor (-1); | ||||
|         this._box = new St.BoxLayout({ style_class: 'osd-window', | ||||
|                                        vertical: true }); | ||||
|         this.actor.add_actor(this._box); | ||||
| @@ -112,7 +109,8 @@ const OsdWindow = new Lang.Class({ | ||||
|         Main.layoutManager.connect('monitors-changed', | ||||
|                                    Lang.bind(this, this._monitorsChanged)); | ||||
|         this._monitorsChanged(); | ||||
|         Main.uiGroup.add_child(this.actor); | ||||
|  | ||||
|         Main.layoutManager.osdGroup.add_child(this.actor); | ||||
|     }, | ||||
|  | ||||
|     setIcon: function(icon) { | ||||
| @@ -127,7 +125,7 @@ const OsdWindow = new Lang.Class({ | ||||
|  | ||||
|     setLevel: function(level) { | ||||
|         this._level.actor.visible = (level != undefined); | ||||
|         if (level != undefined) { | ||||
|         if (level) { | ||||
|             if (this.actor.visible) | ||||
|                 Tweener.addTween(this._level, | ||||
|                                  { level: level, | ||||
| @@ -158,7 +156,6 @@ const OsdWindow = new Lang.Class({ | ||||
|             Mainloop.source_remove(this._hideTimeoutId); | ||||
|         this._hideTimeoutId = Mainloop.timeout_add(HIDE_TIMEOUT, | ||||
|                                                    Lang.bind(this, this._hide)); | ||||
|         GLib.Source.set_name_by_id(this._hideTimeoutId, '[gnome-shell] this._hide'); | ||||
|     }, | ||||
|  | ||||
|     cancel: function() { | ||||
| @@ -191,18 +188,20 @@ const OsdWindow = new Lang.Class({ | ||||
|  | ||||
|     _monitorsChanged: function() { | ||||
|         /* assume 110x110 on a 640x480 display and scale from there */ | ||||
|         let monitor = Main.layoutManager.monitors[this._monitorIndex]; | ||||
|         if (!monitor) | ||||
|             return; // we are about to be removed | ||||
|         let monitor; | ||||
|  | ||||
|         if (this._currentMonitor >= 0) | ||||
|             monitor = Main.layoutManager.monitors[this._currentMonitor]; | ||||
|         else | ||||
|             monitor = Main.layoutManager.primaryMonitor; | ||||
|  | ||||
|         let scalew = monitor.width / 640.0; | ||||
|         let scaleh = monitor.height / 480.0; | ||||
|         let scale = Math.min(scalew, scaleh); | ||||
|         this._popupSize = 110 * Math.max(1, scale); | ||||
|  | ||||
|         let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; | ||||
|         this._icon.icon_size = this._popupSize / (2 * scaleFactor); | ||||
|         this._box.translation_y = monitor.height / 4; | ||||
|         this._icon.icon_size = this._popupSize / 2; | ||||
|         this._box.style_changed(); | ||||
|     }, | ||||
|  | ||||
| @@ -218,60 +217,24 @@ const OsdWindow = new Lang.Class({ | ||||
|         let minWidth = this._popupSize - verticalPadding - leftBorder - rightBorder; | ||||
|         let minHeight = this._popupSize - horizontalPadding - topBorder - bottomBorder; | ||||
|  | ||||
|         // minWidth/minHeight here are in real pixels, | ||||
|         // but the theme takes measures in unscaled dimensions | ||||
|         let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; | ||||
|         this._box.style = 'min-height: %dpx;'.format(Math.max(minWidth, minHeight) / scaleFactor); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const OsdWindowManager = new Lang.Class({ | ||||
|     Name: 'OsdWindowManager', | ||||
|  | ||||
|     _init: function() { | ||||
|         this._osdWindows = []; | ||||
|         Main.layoutManager.connect('monitors-changed', | ||||
|                                     Lang.bind(this, this._monitorsChanged)); | ||||
|         this._monitorsChanged(); | ||||
|     }, | ||||
|  | ||||
|     _monitorsChanged: function() { | ||||
|         for (let i = 0; i < Main.layoutManager.monitors.length; i++) { | ||||
|             if (this._osdWindows[i] == undefined) | ||||
|                 this._osdWindows[i] = new OsdWindow(i); | ||||
|         } | ||||
|  | ||||
|         for (let i = Main.layoutManager.monitors.length; i < this._osdWindows.length; i++) { | ||||
|             this._osdWindows[i].actor.destroy(); | ||||
|             this._osdWindows[i] = null; | ||||
|         } | ||||
|  | ||||
|         this._osdWindows.length = Main.layoutManager.monitors.length; | ||||
|     }, | ||||
|  | ||||
|     _showOsdWindow: function(monitorIndex, icon, label, level) { | ||||
|         this._osdWindows[monitorIndex].setIcon(icon); | ||||
|         this._osdWindows[monitorIndex].setLabel(label); | ||||
|         this._osdWindows[monitorIndex].setLevel(level); | ||||
|         this._osdWindows[monitorIndex].show(); | ||||
|     }, | ||||
|  | ||||
|     show: function(monitorIndex, icon, label, level) { | ||||
|         if (monitorIndex != -1) { | ||||
|             for (let i = 0; i < this._osdWindows.length; i++) { | ||||
|                 if (i == monitorIndex) | ||||
|                     this._showOsdWindow(i, icon, label, level); | ||||
|                 else | ||||
|                     this._osdWindows[i].cancel(); | ||||
|             } | ||||
|         } else { | ||||
|             for (let i = 0; i < this._osdWindows.length; i++) | ||||
|                 this._showOsdWindow(i, icon, label, level); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     hideAll: function() { | ||||
|         for (let i = 0; i < this._osdWindows.length; i++) | ||||
|             this._osdWindows[i].cancel(); | ||||
|         this._box.style = 'min-height: %dpx;'.format(Math.max(minWidth, minHeight)); | ||||
|     }, | ||||
|  | ||||
|     setMonitor: function(index) { | ||||
|         let constraint; | ||||
|  | ||||
|         if (index < 0) | ||||
|             index = -1; | ||||
|         if (this._currentMonitor == index) | ||||
|             return; | ||||
|  | ||||
|         if (index < 0) | ||||
|             constraint = new Layout.MonitorConstraint({ primary: true }); | ||||
|         else | ||||
|             constraint = new Layout.MonitorConstraint({ index: index }); | ||||
|  | ||||
|         this.actor.clear_constraints(); | ||||
|         this.actor.add_constraint(constraint); | ||||
|         this._currentMonitor = index; | ||||
|     } | ||||
| }); | ||||
|   | ||||
| @@ -14,7 +14,6 @@ const Gdk = imports.gi.Gdk; | ||||
| const Background = imports.ui.background; | ||||
| const DND = imports.ui.dnd; | ||||
| const LayoutManager = imports.ui.layout; | ||||
| const Lightbox = imports.ui.lightbox; | ||||
| const Main = imports.ui.main; | ||||
| const MessageTray = imports.ui.messageTray; | ||||
| const OverviewControls = imports.ui.overviewControls; | ||||
| @@ -185,7 +184,7 @@ const Overview = new Lang.Class({ | ||||
|         for (let i = 0; i < Main.layoutManager.monitors.length; i++) { | ||||
|             let bgManager = new Background.BackgroundManager({ container: this._backgroundGroup, | ||||
|                                                                monitorIndex: i, | ||||
|                                                                vignette: true }); | ||||
|                                                                effects: Meta.BackgroundEffects.VIGNETTE }); | ||||
|             this._bgManagers.push(bgManager); | ||||
|         } | ||||
|     }, | ||||
| @@ -193,9 +192,15 @@ const Overview = new Lang.Class({ | ||||
|     _unshadeBackgrounds: function() { | ||||
|         let backgrounds = this._backgroundGroup.get_children(); | ||||
|         for (let i = 0; i < backgrounds.length; i++) { | ||||
|             Tweener.addTween(backgrounds[i], | ||||
|             let background = backgrounds[i]._delegate; | ||||
|  | ||||
|             Tweener.addTween(background, | ||||
|                              { brightness: 1.0, | ||||
|                                vignette_sharpness: 0.0, | ||||
|                                time: SHADE_ANIMATION_TIME, | ||||
|                                transition: 'easeOutQuad' | ||||
|                              }); | ||||
|             Tweener.addTween(background, | ||||
|                              { vignetteSharpness: 0.0, | ||||
|                                time: SHADE_ANIMATION_TIME, | ||||
|                                transition: 'easeOutQuad' | ||||
|                              }); | ||||
| @@ -205,9 +210,15 @@ const Overview = new Lang.Class({ | ||||
|     _shadeBackgrounds: function() { | ||||
|         let backgrounds = this._backgroundGroup.get_children(); | ||||
|         for (let i = 0; i < backgrounds.length; i++) { | ||||
|             Tweener.addTween(backgrounds[i], | ||||
|                              { brightness: Lightbox.VIGNETTE_BRIGHTNESS, | ||||
|                                vignette_sharpness: Lightbox.VIGNETTE_SHARPNESS, | ||||
|             let background = backgrounds[i]._delegate; | ||||
|  | ||||
|             Tweener.addTween(background, | ||||
|                              { brightness: 0.8, | ||||
|                                time: SHADE_ANIMATION_TIME, | ||||
|                                transition: 'easeOutQuad' | ||||
|                              }); | ||||
|             Tweener.addTween(background, | ||||
|                              { vignetteSharpness: 0.7, | ||||
|                                time: SHADE_ANIMATION_TIME, | ||||
|                                transition: 'easeOutQuad' | ||||
|                              }); | ||||
| @@ -238,7 +249,7 @@ const Overview = new Lang.Class({ | ||||
|                                         opacity: 0 }); | ||||
|         this._overview.add_actor(this._panelGhost); | ||||
|  | ||||
|         this._searchEntry = new St.Entry({ style_class: 'search-entry', | ||||
|         this._searchEntry = new St.Entry({ name: 'searchEntry', | ||||
|                                            /* Translators: this is the text displayed | ||||
|                                               in the search entry when no search is | ||||
|                                               active; it should not exceed ~30 | ||||
| @@ -361,7 +372,6 @@ const Overview = new Lang.Class({ | ||||
|                                                 this._lastHoveredWindow = null; | ||||
|                                                 return GLib.SOURCE_REMOVE; | ||||
|                                             })); | ||||
|             GLib.Source.set_name_by_id(this._windowSwitchTimeoutId, '[gnome-shell] Main.activateWindow'); | ||||
|         } | ||||
|  | ||||
|         return DND.DragMotionResult.CONTINUE; | ||||
| @@ -421,6 +431,8 @@ const Overview = new Lang.Class({ | ||||
|         this.emit('windows-restacked', stackIndices); | ||||
|     }, | ||||
|  | ||||
|     //// Public methods //// | ||||
|  | ||||
|     beginItemDrag: function(source) { | ||||
|         this.emit('item-drag-begin'); | ||||
|         this._inDrag = true; | ||||
| @@ -449,6 +461,23 @@ const Overview = new Lang.Class({ | ||||
|         this._inDrag = false; | ||||
|     }, | ||||
|  | ||||
|     // show: | ||||
|     // | ||||
|     // Animates the overview visible and grabs mouse and keyboard input | ||||
|     show: function() { | ||||
|         if (this.isDummy) | ||||
|             return; | ||||
|         if (this._shown) | ||||
|             return; | ||||
|         this._shown = true; | ||||
|  | ||||
|         if (!this._syncGrab()) | ||||
|             return; | ||||
|  | ||||
|         Main.layoutManager.showOverview(); | ||||
|         this._animateVisible(); | ||||
|     }, | ||||
|  | ||||
|     focusSearch: function() { | ||||
|         this.show(); | ||||
|         this._searchEntry.grab_key_focus(); | ||||
| @@ -464,13 +493,8 @@ const Overview = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     fadeOutDesktop: function() { | ||||
|         if (!this._desktopFade.get_n_children()) { | ||||
|             let clone = this._getDesktopClone(); | ||||
|             if (!clone) | ||||
|                 return; | ||||
|  | ||||
|             this._desktopFade.add_child(clone); | ||||
|         } | ||||
|         if (!this._desktopFade.get_n_children()) | ||||
|             this._desktopFade.add_child(this._getDesktopClone()); | ||||
|  | ||||
|         this._desktopFade.opacity = 255; | ||||
|         this._desktopFade.show(); | ||||
| @@ -481,6 +505,69 @@ const Overview = new Lang.Class({ | ||||
|                          }); | ||||
|     }, | ||||
|  | ||||
|     _animateVisible: function() { | ||||
|         if (this.visible || this.animationInProgress) | ||||
|             return; | ||||
|  | ||||
|         this.visible = true; | ||||
|         this.animationInProgress = true; | ||||
|         this.visibleTarget = true; | ||||
|         this._activationTime = Date.now() / 1000; | ||||
|  | ||||
|         Meta.disable_unredirect_for_screen(global.screen); | ||||
|         this.viewSelector.show(); | ||||
|  | ||||
|         this._stack.opacity = 0; | ||||
|         Tweener.addTween(this._stack, | ||||
|                          { opacity: 255, | ||||
|                            transition: 'easeOutQuad', | ||||
|                            time: ANIMATION_TIME, | ||||
|                            onComplete: this._showDone, | ||||
|                            onCompleteScope: this | ||||
|                          }); | ||||
|         this._shadeBackgrounds(); | ||||
|  | ||||
|         this._coverPane.raise_top(); | ||||
|         this._coverPane.show(); | ||||
|         this.emit('showing'); | ||||
|     }, | ||||
|  | ||||
|     // hide: | ||||
|     // | ||||
|     // Reverses the effect of show() | ||||
|     hide: function() { | ||||
|         if (this.isDummy) | ||||
|             return; | ||||
|  | ||||
|         if (!this._shown) | ||||
|             return; | ||||
|  | ||||
|         let event = Clutter.get_current_event(); | ||||
|         if (event) { | ||||
|             let type = event.type(); | ||||
|             let button = (type == Clutter.EventType.BUTTON_PRESS || | ||||
|                           type == Clutter.EventType.BUTTON_RELEASE); | ||||
|             let ctrl = (event.get_state() & Clutter.ModifierType.CONTROL_MASK) != 0; | ||||
|             if (button && ctrl) | ||||
|                 return; | ||||
|         } | ||||
|  | ||||
|         this._animateNotVisible(); | ||||
|  | ||||
|         this._shown = false; | ||||
|         this._syncGrab(); | ||||
|     }, | ||||
|  | ||||
|     toggle: function() { | ||||
|         if (this.isDummy) | ||||
|             return; | ||||
|  | ||||
|         if (this.visible) | ||||
|             this.hide(); | ||||
|         else | ||||
|             this.show(); | ||||
|     }, | ||||
|  | ||||
|     // Checks if the Activities button is currently sensitive to | ||||
|     // clicks. The first call to this function within the | ||||
|     // OVERVIEW_ACTIVATION_TIMEOUT time of the hot corner being | ||||
| @@ -497,6 +584,8 @@ const Overview = new Lang.Class({ | ||||
|         return false; | ||||
|     }, | ||||
|  | ||||
|     //// Private methods //// | ||||
|  | ||||
|     _syncGrab: function() { | ||||
|         // We delay grab changes during animation so that when removing the | ||||
|         // overview we don't have a problem with the release of a press/release | ||||
| @@ -526,92 +615,6 @@ const Overview = new Lang.Class({ | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     // show: | ||||
|     // | ||||
|     // Animates the overview visible and grabs mouse and keyboard input | ||||
|     show: function() { | ||||
|         if (this.isDummy) | ||||
|             return; | ||||
|         if (this._shown) | ||||
|             return; | ||||
|         this._shown = true; | ||||
|  | ||||
|         if (!this._syncGrab()) | ||||
|             return; | ||||
|  | ||||
|         Main.layoutManager.showOverview(); | ||||
|         this._animateVisible(); | ||||
|     }, | ||||
|  | ||||
|  | ||||
|     _animateVisible: function() { | ||||
|         if (this.visible || this.animationInProgress) | ||||
|             return; | ||||
|  | ||||
|         this.visible = true; | ||||
|         this.animationInProgress = true; | ||||
|         this.visibleTarget = true; | ||||
|         this._activationTime = Date.now() / 1000; | ||||
|  | ||||
|         Meta.disable_unredirect_for_screen(global.screen); | ||||
|         this.viewSelector.show(); | ||||
|  | ||||
|         this._stack.opacity = 0; | ||||
|         Tweener.addTween(this._stack, | ||||
|                          { opacity: 255, | ||||
|                            transition: 'easeOutQuad', | ||||
|                            time: ANIMATION_TIME, | ||||
|                            onComplete: this._showDone, | ||||
|                            onCompleteScope: this | ||||
|                          }); | ||||
|         this._shadeBackgrounds(); | ||||
|  | ||||
|         this._coverPane.raise_top(); | ||||
|         this._coverPane.show(); | ||||
|         this.emit('showing'); | ||||
|     }, | ||||
|  | ||||
|     _showDone: function() { | ||||
|         this.animationInProgress = false; | ||||
|         this._desktopFade.hide(); | ||||
|         this._coverPane.hide(); | ||||
|  | ||||
|         this.emit('shown'); | ||||
|         // Handle any calls to hide* while we were showing | ||||
|         if (!this._shown) | ||||
|             this._animateNotVisible(); | ||||
|  | ||||
|         this._syncGrab(); | ||||
|         global.sync_pointer(); | ||||
|     }, | ||||
|  | ||||
|     // hide: | ||||
|     // | ||||
|     // Reverses the effect of show() | ||||
|     hide: function() { | ||||
|         if (this.isDummy) | ||||
|             return; | ||||
|  | ||||
|         if (!this._shown) | ||||
|             return; | ||||
|  | ||||
|         let event = Clutter.get_current_event(); | ||||
|         if (event) { | ||||
|             let type = event.type(); | ||||
|             let button = (type == Clutter.EventType.BUTTON_PRESS || | ||||
|                           type == Clutter.EventType.BUTTON_RELEASE); | ||||
|             let ctrl = (event.get_state() & Clutter.ModifierType.CONTROL_MASK) != 0; | ||||
|             if (button && ctrl) | ||||
|                 return; | ||||
|         } | ||||
|  | ||||
|         this._animateNotVisible(); | ||||
|  | ||||
|         this._shown = false; | ||||
|         this._syncGrab(); | ||||
|     }, | ||||
|  | ||||
|  | ||||
|     _animateNotVisible: function() { | ||||
|         if (!this.visible || this.animationInProgress) | ||||
|             return; | ||||
| @@ -619,7 +622,7 @@ const Overview = new Lang.Class({ | ||||
|         this.animationInProgress = true; | ||||
|         this.visibleTarget = false; | ||||
|  | ||||
|         this.viewSelector.animateFromOverview(); | ||||
|         this.viewSelector.leaveOverview(); | ||||
|  | ||||
|         // Make other elements fade out. | ||||
|         Tweener.addTween(this._stack, | ||||
| @@ -636,6 +639,20 @@ const Overview = new Lang.Class({ | ||||
|         this.emit('hiding'); | ||||
|     }, | ||||
|  | ||||
|     _showDone: function() { | ||||
|         this.animationInProgress = false; | ||||
|         this._desktopFade.hide(); | ||||
|         this._coverPane.hide(); | ||||
|  | ||||
|         this.emit('shown'); | ||||
|         // Handle any calls to hide* while we were showing | ||||
|         if (!this._shown) | ||||
|             this._animateNotVisible(); | ||||
|  | ||||
|         this._syncGrab(); | ||||
|         global.sync_pointer(); | ||||
|     }, | ||||
|  | ||||
|     _hideDone: function() { | ||||
|         // Re-enable unredirection | ||||
|         Meta.enable_unredirect_for_screen(global.screen); | ||||
| @@ -661,20 +678,6 @@ const Overview = new Lang.Class({ | ||||
|             this._fakePointerEvent(); | ||||
|             this._needsFakePointerEvent = false; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     toggle: function() { | ||||
|         if (this.isDummy) | ||||
|             return; | ||||
|  | ||||
|         if (this.visible) | ||||
|             this.hide(); | ||||
|         else | ||||
|             this.show(); | ||||
|     }, | ||||
|  | ||||
|     getShowAppsButton: function() { | ||||
|         return this._dash.showAppsButton; | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(Overview.prototype); | ||||
|   | ||||
| @@ -36,7 +36,7 @@ const SlideLayout = new Lang.Class({ | ||||
|  | ||||
|     _init: function(params) { | ||||
|         this._slideX = 1; | ||||
|         this._translationX = undefined; | ||||
|         this._translationX = 0; | ||||
|         this._direction = SlideDirection.LEFT; | ||||
|  | ||||
|         this.parent(params); | ||||
| @@ -118,6 +118,7 @@ const SlidingControl = new Lang.Class({ | ||||
|                                      style_class: 'overview-controls', | ||||
|                                      clip_to_allocation: true }); | ||||
|  | ||||
|         Main.overview.connect('showing', Lang.bind(this, this._onOverviewShowing)); | ||||
|         Main.overview.connect('hiding', Lang.bind(this, this._onOverviewHiding)); | ||||
|  | ||||
|         Main.overview.connect('item-drag-begin', Lang.bind(this, this._onDragBegin)); | ||||
| @@ -161,8 +162,7 @@ const SlidingControl = new Lang.Class({ | ||||
|         let translationEnd = 0; | ||||
|         let translation = this._getTranslation(); | ||||
|  | ||||
|         let shouldShow = (this._getSlide() > 0); | ||||
|         if (shouldShow) { | ||||
|         if (this._visible) { | ||||
|             translationStart = translation; | ||||
|         } else { | ||||
|             translationEnd = translation; | ||||
| @@ -177,9 +177,14 @@ const SlidingControl = new Lang.Class({ | ||||
|                                         transition: 'easeOutQuad' }); | ||||
|     }, | ||||
|  | ||||
|     _onOverviewShowing: function() { | ||||
|         this._visible = true; | ||||
|         this.layout.slideX = this._getSlide(); | ||||
|         this.layout.translationX = this._getTranslation(); | ||||
|         this.slideIn(); | ||||
|     }, | ||||
|  | ||||
|     _onOverviewHiding: function() { | ||||
|         // We need to explicitly slideOut since showing pages | ||||
|         // doesn't imply sliding out, instead, hiding the overview does. | ||||
|         this.slideOut(); | ||||
|     }, | ||||
|  | ||||
| @@ -193,7 +198,7 @@ const SlidingControl = new Lang.Class({ | ||||
|  | ||||
|     _onDragBegin: function() { | ||||
|         this._inDrag = true; | ||||
|         this._updateTranslation(); | ||||
|         this.layout.translationX = 0; | ||||
|         this._updateSlide(); | ||||
|     }, | ||||
|  | ||||
| @@ -218,6 +223,7 @@ const SlidingControl = new Lang.Class({ | ||||
|  | ||||
|     slideIn: function() { | ||||
|         this._visible = true; | ||||
|         this._updateTranslation(); | ||||
|         // we will update slideX and the translation from pageEmpty | ||||
|     }, | ||||
|  | ||||
| @@ -253,18 +259,13 @@ const ThumbnailsSlider = new Lang.Class({ | ||||
|  | ||||
|         Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._updateSlide)); | ||||
|         this.actor.connect('notify::hover', Lang.bind(this, this._updateSlide)); | ||||
|         global.window_manager.connect('switch-workspace', Lang.bind(this, this._updateSlide)); | ||||
|         this._thumbnailsBox.actor.bind_property('visible', this.actor, 'visible', GObject.BindingFlags.SYNC_CREATE); | ||||
|     }, | ||||
|  | ||||
|     _getAlwaysZoomOut: function() { | ||||
|         // Always show the pager when hover, during a drag, or if workspaces are | ||||
|         // actually used, e.g. there are windows on any non-active workspace | ||||
|         let alwaysZoomOut = this.actor.hover || | ||||
|                             this._inDrag || | ||||
|                             !Meta.prefs_get_dynamic_workspaces() || | ||||
|                             global.screen.n_workspaces > 2 || | ||||
|                             global.screen.get_active_workspace_index() != 0; | ||||
|         // actually used, e.g. there are windows on more than one | ||||
|         let alwaysZoomOut = this.actor.hover || this._inDrag || !Meta.prefs_get_dynamic_workspaces() || global.screen.n_workspaces > 2; | ||||
|  | ||||
|         if (!alwaysZoomOut) { | ||||
|             let monitors = Main.layoutManager.monitors; | ||||
|   | ||||
| @@ -14,6 +14,7 @@ const St = imports.gi.St; | ||||
| const Signals = imports.signals; | ||||
| const Atk = imports.gi.Atk; | ||||
|  | ||||
|  | ||||
| const Animation = imports.ui.animation; | ||||
| const Config = imports.misc.config; | ||||
| const CtrlAltTab = imports.ui.ctrlAltTab; | ||||
| @@ -212,7 +213,7 @@ const AppMenuButton = new Lang.Class({ | ||||
|         this._label = new TextShadower(); | ||||
|         this._label.actor.y_align = Clutter.ActorAlign.CENTER; | ||||
|         this._hbox.add_actor(this._label.actor); | ||||
|         this._arrow = PopupMenu.arrowIcon(St.Side.BOTTOM); | ||||
|         this._arrow = PopupMenu.unicodeArrow(St.Side.BOTTOM); | ||||
|         this._hbox.add_actor(this._arrow); | ||||
|  | ||||
|         this._iconBottomClip = 0; | ||||
| @@ -571,6 +572,7 @@ const ActivitiesButton = new Lang.Class({ | ||||
|         this.actor.label_actor = this._label; | ||||
|  | ||||
|         this.actor.connect('captured-event', Lang.bind(this, this._onCapturedEvent)); | ||||
|         this.actor.connect_after('button-release-event', Lang.bind(this, this._onButtonRelease)); | ||||
|         this.actor.connect_after('key-release-event', Lang.bind(this, this._onKeyRelease)); | ||||
|  | ||||
|         Main.overview.connect('showing', Lang.bind(this, function() { | ||||
| @@ -593,27 +595,21 @@ const ActivitiesButton = new Lang.Class({ | ||||
|             Mainloop.source_remove(this._xdndTimeOut); | ||||
|         this._xdndTimeOut = Mainloop.timeout_add(BUTTON_DND_ACTIVATION_TIMEOUT, | ||||
|                                                  Lang.bind(this, this._xdndToggleOverview, actor)); | ||||
|         GLib.Source.set_name_by_id(this._xdndTimeOut, '[gnome-shell] this._xdndToggleOverview'); | ||||
|  | ||||
|         return DND.DragMotionResult.CONTINUE; | ||||
|     }, | ||||
|  | ||||
|     _onCapturedEvent: function(actor, event) { | ||||
|         if (event.type() == Clutter.EventType.BUTTON_PRESS || | ||||
|             event.type() == Clutter.EventType.TOUCH_BEGIN) { | ||||
|         if (event.type() == Clutter.EventType.BUTTON_PRESS) { | ||||
|             if (!Main.overview.shouldToggleByCornerOrButton()) | ||||
|                 return Clutter.EVENT_STOP; | ||||
|         } | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     }, | ||||
|  | ||||
|     _onEvent: function(actor, event) { | ||||
|         this.parent(actor, event); | ||||
|  | ||||
|         if (event.type() == Clutter.EventType.TOUCH_END || | ||||
|             event.type() == Clutter.EventType.BUTTON_RELEASE) | ||||
|             Main.overview.toggle(); | ||||
|  | ||||
|     _onButtonRelease: function() { | ||||
|         Main.overview.toggle(); | ||||
|         this.menu.close(); | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     }, | ||||
|  | ||||
| @@ -816,11 +812,7 @@ const AggregateMenu = new Lang.Class({ | ||||
|         this._indicators = new St.BoxLayout({ style_class: 'panel-status-indicators-box' }); | ||||
|         this.actor.add_child(this._indicators); | ||||
|  | ||||
|         if (Config.HAVE_NETWORKMANAGER) { | ||||
|             this._network = new imports.ui.status.network.NMApplet(); | ||||
|         } else { | ||||
|             this._network = null; | ||||
|         } | ||||
|         this._network = new imports.ui.status.network.NMApplet(); | ||||
|         if (Config.HAVE_BLUETOOTH) { | ||||
|             this._bluetooth = new imports.ui.status.bluetooth.Indicator(); | ||||
|         } else { | ||||
| @@ -837,27 +829,22 @@ const AggregateMenu = new Lang.Class({ | ||||
|  | ||||
|         this._indicators.add_child(this._screencast.indicators); | ||||
|         this._indicators.add_child(this._location.indicators); | ||||
|         if (this._network) { | ||||
|             this._indicators.add_child(this._network.indicators); | ||||
|         } | ||||
|         this._indicators.add_child(this._network.indicators); | ||||
|         if (this._bluetooth) { | ||||
|             this._indicators.add_child(this._bluetooth.indicators); | ||||
|         } | ||||
|         this._indicators.add_child(this._rfkill.indicators); | ||||
|         this._indicators.add_child(this._volume.indicators); | ||||
|         this._indicators.add_child(this._power.indicators); | ||||
|         this._indicators.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM)); | ||||
|         this._indicators.add_child(PopupMenu.unicodeArrow(St.Side.BOTTOM)); | ||||
|  | ||||
|         this.menu.addMenuItem(this._volume.menu); | ||||
|         this.menu.addMenuItem(this._brightness.menu); | ||||
|         this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); | ||||
|         if (this._network) { | ||||
|             this.menu.addMenuItem(this._network.menu); | ||||
|         } | ||||
|         this.menu.addMenuItem(this._network.menu); | ||||
|         if (this._bluetooth) { | ||||
|             this.menu.addMenuItem(this._bluetooth.menu); | ||||
|         } | ||||
|         this.menu.addMenuItem(this._location.menu); | ||||
|         this.menu.addMenuItem(this._rfkill.menu); | ||||
|         this.menu.addMenuItem(this._power.menu); | ||||
|         this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); | ||||
| @@ -914,7 +901,7 @@ const Panel = new Lang.Class({ | ||||
|             this.actor.remove_style_pseudo_class('overview'); | ||||
|         })); | ||||
|  | ||||
|         Main.layoutManager.panelBox.add(this.actor); | ||||
|         Main.layoutManager.panelGroup.add_child(this.actor); | ||||
|         Main.ctrlAltTabManager.addGroup(this.actor, _("Top Bar"), 'emblem-system-symbolic', | ||||
|                                         { sortGroup: CtrlAltTab.SortGroup.TOP }); | ||||
|  | ||||
|   | ||||
| @@ -41,7 +41,8 @@ const ButtonBox = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _getPreferredWidth: function(actor, forHeight, alloc) { | ||||
|         let child = actor.get_first_child(); | ||||
|         let children = actor.get_children(); | ||||
|         let child = children.length > 0 ? children[0] : null; | ||||
|  | ||||
|         if (child) { | ||||
|             [alloc.min_size, alloc.natural_size] = child.get_preferred_width(-1); | ||||
| @@ -54,7 +55,8 @@ const ButtonBox = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _getPreferredHeight: function(actor, forWidth, alloc) { | ||||
|         let child = actor.get_first_child(); | ||||
|         let children = actor.get_children(); | ||||
|         let child = children.length > 0 ? children[0] : null; | ||||
|  | ||||
|         if (child) { | ||||
|             [alloc.min_size, alloc.natural_size] = child.get_preferred_height(-1); | ||||
| @@ -64,11 +66,13 @@ const ButtonBox = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _allocate: function(actor, box, flags) { | ||||
|         let child = actor.get_first_child(); | ||||
|         if (!child) | ||||
|         let children = actor.get_children(); | ||||
|         if (children.length == 0) | ||||
|             return; | ||||
|  | ||||
|         let child = children[0]; | ||||
|         let [minWidth, natWidth] = child.get_preferred_width(-1); | ||||
|         let [minHeight, natHeight] = child.get_preferred_height(-1); | ||||
|  | ||||
|         let availWidth = box.x2 - box.x1; | ||||
|         let availHeight = box.y2 - box.y1; | ||||
| @@ -100,7 +104,8 @@ const Button = new Lang.Class({ | ||||
|                       accessible_name: nameText ? nameText : "", | ||||
|                       accessible_role: Atk.Role.MENU }); | ||||
|  | ||||
|         this.actor.connect('event', Lang.bind(this, this._onEvent)); | ||||
|         this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress)); | ||||
|         this.actor.connect('key-press-event', Lang.bind(this, this._onSourceKeyPress)); | ||||
|         this.actor.connect('notify::visible', Lang.bind(this, this._onVisibilityChanged)); | ||||
|  | ||||
|         if (dontCreateMenu) | ||||
| @@ -125,20 +130,39 @@ const Button = new Lang.Class({ | ||||
|             this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged)); | ||||
|             this.menu.actor.connect('key-press-event', Lang.bind(this, this._onMenuKeyPress)); | ||||
|  | ||||
|             Main.uiGroup.add_actor(this.menu.actor); | ||||
|             Main.layoutManager.menuGroup.add_child(this.menu.actor); | ||||
|             this.menu.actor.hide(); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _onEvent: function(actor, event) { | ||||
|         if (this.menu && | ||||
|             (event.type() == Clutter.EventType.TOUCH_BEGIN || | ||||
|              event.type() == Clutter.EventType.BUTTON_PRESS)) | ||||
|             this.menu.toggle(); | ||||
|     _onButtonPress: function(actor, event) { | ||||
|         if (!this.menu) | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|         this.menu.toggle(); | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     }, | ||||
|  | ||||
|     _onSourceKeyPress: function(actor, event) { | ||||
|         if (!this.menu) | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|         let symbol = event.get_key_symbol(); | ||||
|         if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) { | ||||
|             this.menu.toggle(); | ||||
|             return Clutter.EVENT_STOP; | ||||
|         } else if (symbol == Clutter.KEY_Escape && this.menu.isOpen) { | ||||
|             this.menu.close(); | ||||
|             return Clutter.EVENT_STOP; | ||||
|         } else if (symbol == Clutter.KEY_Down) { | ||||
|             if (!this.menu.isOpen) | ||||
|                 this.menu.toggle(); | ||||
|             this.menu.actor.navigate_focus(this.actor, Gtk.DirectionType.DOWN, false); | ||||
|             return Clutter.EVENT_STOP; | ||||
|         } else | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|     }, | ||||
|  | ||||
|     _onVisibilityChanged: function() { | ||||
|         if (!this.menu) | ||||
|             return; | ||||
|   | ||||
| @@ -107,7 +107,6 @@ const PointerWatcher = new Lang.Class({ | ||||
|  | ||||
|         this._timeoutId = Mainloop.timeout_add(minInterval, | ||||
|                                                Lang.bind(this, this._onTimeout)); | ||||
|         GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] this._onTimeout'); | ||||
|     }, | ||||
|  | ||||
|     _onTimeout: function() { | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
|  | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const GLib = imports.gi.GLib; | ||||
| const Gtk = imports.gi.Gtk; | ||||
| const Gio = imports.gi.Gio; | ||||
| const Lang = imports.lang; | ||||
| const Shell = imports.gi.Shell; | ||||
| const Signals = imports.signals; | ||||
| @@ -13,6 +15,7 @@ const GrabHelper = imports.ui.grabHelper; | ||||
| const Main = imports.ui.main; | ||||
| const Params = imports.misc.params; | ||||
| const Separator = imports.ui.separator; | ||||
| const Slider = imports.ui.slider; | ||||
| const Tweener = imports.ui.tweener; | ||||
|  | ||||
| const Ornament = { | ||||
| @@ -21,6 +24,17 @@ const Ornament = { | ||||
|     CHECK: 2, | ||||
| }; | ||||
|  | ||||
| function _ensureStyle(actor) { | ||||
|     if (actor.get_children) { | ||||
|         let children = actor.get_children(); | ||||
|         for (let i = 0; i < children.length; i++) | ||||
|             _ensureStyle(children[i]); | ||||
|     } | ||||
|  | ||||
|     if (actor instanceof St.Widget) | ||||
|         actor.ensure_style(); | ||||
| } | ||||
|  | ||||
| function isPopupMenuItemVisible(child) { | ||||
|     if (child._delegate instanceof PopupMenuSection) | ||||
|         if (child._delegate.isEmpty()) | ||||
| @@ -31,30 +45,28 @@ function isPopupMenuItemVisible(child) { | ||||
| /** | ||||
|  * @side Side to which the arrow points. | ||||
|  */ | ||||
| function arrowIcon(side) { | ||||
|     let iconName; | ||||
| function unicodeArrow(side) { | ||||
|     let arrowChar; | ||||
|     switch (side) { | ||||
|         case St.Side.TOP: | ||||
|             iconName = 'pan-up-symbolic'; | ||||
|             arrowChar = '\u25B4'; | ||||
|             break; | ||||
|         case St.Side.RIGHT: | ||||
|             iconName = 'pan-end-symbolic'; | ||||
|             arrowChar = '\u25B8'; | ||||
|             break; | ||||
|         case St.Side.BOTTOM: | ||||
|             iconName = 'pan-down-symbolic'; | ||||
|             arrowChar = '\u25BE'; | ||||
|             break; | ||||
|         case St.Side.LEFT: | ||||
|             iconName = 'pan-start-symbolic'; | ||||
|             arrowChar = '\u25C2'; | ||||
|             break; | ||||
|     } | ||||
|  | ||||
|     let arrow = new St.Icon({ style_class: 'popup-menu-arrow', | ||||
|                               icon_name: iconName, | ||||
|                               accessible_role: Atk.Role.ARROW, | ||||
|                               y_expand: true, | ||||
|                               y_align: Clutter.ActorAlign.CENTER }); | ||||
|  | ||||
|     return arrow; | ||||
|     return new St.Label({ text: arrowChar, | ||||
|                           style_class: 'unicode-arrow', | ||||
|                           accessible_role: Atk.Role.ARROW, | ||||
|                           y_expand: true, | ||||
|                           y_align: Clutter.ActorAlign.CENTER }); | ||||
| } | ||||
|  | ||||
| const PopupBaseMenuItem = new Lang.Class({ | ||||
| @@ -92,7 +104,6 @@ const PopupBaseMenuItem = new Lang.Class({ | ||||
|  | ||||
|         if (this._activatable) { | ||||
|             this.actor.connect('button-release-event', Lang.bind(this, this._onButtonReleaseEvent)); | ||||
|             this.actor.connect('touch-event', Lang.bind(this, this._onTouchEvent)); | ||||
|             this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent)); | ||||
|         } | ||||
|         if (params.reactive && params.hover) | ||||
| @@ -100,7 +111,6 @@ const PopupBaseMenuItem = new Lang.Class({ | ||||
|  | ||||
|         this.actor.connect('key-focus-in', Lang.bind(this, this._onKeyFocusIn)); | ||||
|         this.actor.connect('key-focus-out', Lang.bind(this, this._onKeyFocusOut)); | ||||
|         this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); | ||||
|     }, | ||||
|  | ||||
|     _getTopMenu: function() { | ||||
| @@ -119,14 +129,6 @@ const PopupBaseMenuItem = new Lang.Class({ | ||||
|         return Clutter.EVENT_STOP; | ||||
|     }, | ||||
|  | ||||
|     _onTouchEvent: function (actor, event) { | ||||
|         if (event.type() == Clutter.EventType.TOUCH_END) { | ||||
|             this.activate(event); | ||||
|             return Clutter.EVENT_STOP; | ||||
|         } | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     }, | ||||
|  | ||||
|     _onKeyPressEvent: function (actor, event) { | ||||
|         let symbol = event.get_key_symbol(); | ||||
|  | ||||
| @@ -190,9 +192,6 @@ const PopupBaseMenuItem = new Lang.Class({ | ||||
|  | ||||
|     destroy: function() { | ||||
|         this.actor.destroy(); | ||||
|     }, | ||||
|  | ||||
|     _onDestroy: function() { | ||||
|         this.emit('destroy'); | ||||
|     }, | ||||
|  | ||||
| @@ -241,16 +240,8 @@ const PopupSeparatorMenuItem = new Lang.Class({ | ||||
|         this.actor.add(this.label); | ||||
|         this.actor.label_actor = this.label; | ||||
|  | ||||
|         this.label.connect('notify::text', | ||||
|                            Lang.bind(this, this._syncVisibility)); | ||||
|         this._syncVisibility(); | ||||
|  | ||||
|         this._separator = new Separator.HorizontalSeparator({ style_class: 'popup-separator-menu-item' }); | ||||
|         this.actor.add(this._separator.actor, { expand: true }); | ||||
|     }, | ||||
|  | ||||
|     _syncVisibility: function() { | ||||
|         this.label.visible = this.label.text != ''; | ||||
|     } | ||||
| }); | ||||
|  | ||||
| @@ -373,9 +364,9 @@ const PopupImageMenuItem = new Lang.Class({ | ||||
|         this.parent(params); | ||||
|  | ||||
|         this.label = new St.Label({ text: text }); | ||||
|         this.actor.add_child(this.label); | ||||
|         this.addActor(this.label); | ||||
|         this._icon = new St.Icon({ style_class: 'popup-menu-icon' }); | ||||
|         this.actor.add_child(this._icon, { align: St.Align.END }); | ||||
|         this.addActor(this._icon, { align: St.Align.END }); | ||||
|  | ||||
|         this.setIcon(iconName); | ||||
|     }, | ||||
| @@ -731,10 +722,6 @@ const PopupMenu = new Lang.Class({ | ||||
|         global.focus_manager.add_group(this.actor); | ||||
|         this.actor.reactive = true; | ||||
|  | ||||
|         if (this.sourceActor) | ||||
|             this._keyPressId = this.sourceActor.connect('key-press-event', | ||||
|                                                         Lang.bind(this, this._onKeyPress)); | ||||
|  | ||||
|         this._openedSubMenu = null; | ||||
|     }, | ||||
|  | ||||
| @@ -745,40 +732,6 @@ const PopupMenu = new Lang.Class({ | ||||
|         this._openedSubMenu = submenu; | ||||
|     }, | ||||
|  | ||||
|     _onKeyPress: function(actor, event) { | ||||
|         let navKey; | ||||
|         switch (this._boxPointer.arrowSide) { | ||||
|             case St.Side.TOP: | ||||
|                 navKey = Clutter.KEY_Down; | ||||
|                 break; | ||||
|             case St.Side.BOTTOM: | ||||
|                 navKey = Clutter.KEY_Up; | ||||
|                 break; | ||||
|             case St.Side.LEFT: | ||||
|                 navKey = Clutter.KEY_Right; | ||||
|                 break; | ||||
|             case St.Side.RIGHT: | ||||
|                 navKey = Clutter.KEY_Left; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         let symbol = event.get_key_symbol(); | ||||
|         if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) { | ||||
|             this.toggle(); | ||||
|             return Clutter.EVENT_STOP; | ||||
|         } else if (symbol == Clutter.KEY_Escape && this.isOpen) { | ||||
|             this.close(); | ||||
|             return Clutter.EVENT_STOP; | ||||
|         } else if (symbol == navKey) { | ||||
|             if (!this.isOpen) | ||||
|                 this.toggle(); | ||||
|             this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); | ||||
|             return Clutter.EVENT_STOP; | ||||
|         } else | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|     }, | ||||
|  | ||||
|  | ||||
|     setArrowOrigin: function(origin) { | ||||
|         this._boxPointer.setArrowOrigin(origin); | ||||
|     }, | ||||
| @@ -819,12 +772,6 @@ const PopupMenu = new Lang.Class({ | ||||
|  | ||||
|         this.isOpen = false; | ||||
|         this.emit('open-state-changed', false); | ||||
|     }, | ||||
|  | ||||
|     destroy: function() { | ||||
|         if (this._keyPressId) | ||||
|             this.sourceActor.disconnect(this._keyPressId); | ||||
|         this.parent(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| @@ -921,16 +868,14 @@ const PopupSubMenu = new Lang.Class({ | ||||
|         if (animate) { | ||||
|             let [minHeight, naturalHeight] = this.actor.get_preferred_height(-1); | ||||
|             this.actor.height = 0; | ||||
|             this.actor._arrowRotation = this._arrow.rotation_angle_z; | ||||
|             let angle = this.actor._arrowRotation; | ||||
|             // animate to the first multiple of 90 greater than current angle | ||||
|             this.actor._arrow_rotation = this._arrow.rotation_angle_z; | ||||
|             Tweener.addTween(this.actor, | ||||
|                              { _arrowRotation: angle - angle % 90 + 90, | ||||
|                              { _arrow_rotation: 90, | ||||
|                                height: naturalHeight, | ||||
|                                time: 0.25, | ||||
|                                onUpdateScope: this, | ||||
|                                onUpdate: function() { | ||||
|                                    this._arrow.rotation_angle_z = this.actor._arrowRotation; | ||||
|                                    this._arrow.rotation_angle_z = this.actor._arrow_rotation; | ||||
|                                }, | ||||
|                                onCompleteScope: this, | ||||
|                                onComplete: function() { | ||||
| @@ -938,7 +883,7 @@ const PopupSubMenu = new Lang.Class({ | ||||
|                                } | ||||
|                              }); | ||||
|         } else { | ||||
|             this._arrow.rotation_angle_z = this.actor._arrowRotation + 90; | ||||
|             this._arrow.rotation_angle_z = 90; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
| @@ -956,16 +901,14 @@ const PopupSubMenu = new Lang.Class({ | ||||
|             animate = false; | ||||
|  | ||||
|         if (animate) { | ||||
|             this.actor._arrowRotation = this._arrow.rotation_angle_z; | ||||
|             let angle = this.actor._arrowRotation; | ||||
|             // animate to the first multiple of 90 less than current angle | ||||
|             this.actor._arrow_rotation = this._arrow.rotation_angle_z; | ||||
|             Tweener.addTween(this.actor, | ||||
|                              { _arrowRotation: (angle - 1) - (angle - 1) % 90, | ||||
|                              { _arrow_rotation: 0, | ||||
|                                height: 0, | ||||
|                                time: 0.25, | ||||
|                                onUpdateScope: this, | ||||
|                                onUpdate: function() { | ||||
|                                    this._arrow.rotation_angle_z = this.actor._arrowRotation; | ||||
|                                    this._arrow.rotation_angle_z = this.actor._arrow_rotation; | ||||
|                                }, | ||||
|                                onCompleteScope: this, | ||||
|                                onComplete: function() { | ||||
| @@ -974,7 +917,7 @@ const PopupSubMenu = new Lang.Class({ | ||||
|                                }, | ||||
|                              }); | ||||
|         } else { | ||||
|             this._arrow.rotation_angle_z = this.actor._arrowRotation - 90; | ||||
|             this._arrow.rotation_angle_z = 0; | ||||
|             this.actor.hide(); | ||||
|         } | ||||
|     }, | ||||
| @@ -1046,7 +989,7 @@ const PopupSubMenuMenuItem = new Lang.Class({ | ||||
|                                      y_align: Clutter.ActorAlign.CENTER }); | ||||
|         this.actor.add_child(this.status); | ||||
|  | ||||
|         this._triangle = arrowIcon(St.Side.RIGHT); | ||||
|         this._triangle = unicodeArrow(St.Side.RIGHT); | ||||
|         this._triangle.pivot_point = new Clutter.Point({ x: 0.5, y: 0.6 }); | ||||
|  | ||||
|         this._triangleBin = new St.Widget({ y_expand: true, | ||||
|   | ||||
| @@ -110,13 +110,6 @@ function loadRemoteSearchProviders(callback) { | ||||
|             else | ||||
|                 remoteProvider = new RemoteSearchProvider(appInfo, busName, objectPath); | ||||
|  | ||||
|             remoteProvider.defaultEnabled = true; | ||||
|             try { | ||||
|                 remoteProvider.defaultEnabled = !keyfile.get_boolean(group, 'DefaultDisabled'); | ||||
|             } catch(e) { | ||||
|                 // ignore error | ||||
|             } | ||||
|  | ||||
|             objectPaths[objectPath] = remoteProvider; | ||||
|             loadedProviders.push(remoteProvider); | ||||
|         } catch(e) { | ||||
| @@ -124,7 +117,7 @@ function loadRemoteSearchProviders(callback) { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     let searchSettings = new Gio.Settings({ schema_id: Search.SEARCH_PROVIDERS_SCHEMA }); | ||||
|     let searchSettings = new Gio.Settings({ schema: Search.SEARCH_PROVIDERS_SCHEMA }); | ||||
|     if (searchSettings.get_boolean('disable-external')) { | ||||
|         callback([]); | ||||
|         return; | ||||
| @@ -139,14 +132,8 @@ function loadRemoteSearchProviders(callback) { | ||||
|  | ||||
|     loadedProviders = loadedProviders.filter(function(provider) { | ||||
|         let appId = provider.appInfo.get_id(); | ||||
|  | ||||
|         if (provider.defaultEnabled) { | ||||
|             let disabled = searchSettings.get_strv('disabled'); | ||||
|             return disabled.indexOf(appId) == -1; | ||||
|         } else { | ||||
|             let enabled = searchSettings.get_strv('enabled'); | ||||
|             return enabled.indexOf(appId) != -1; | ||||
|         } | ||||
|         let disabled = searchSettings.get_strv('disabled'); | ||||
|         return disabled.indexOf(appId) == -1; | ||||
|     }); | ||||
|  | ||||
|     loadedProviders.sort(function(providerA, providerB) { | ||||
|   | ||||
| @@ -38,8 +38,8 @@ const RunDialog = new Lang.Class({ | ||||
|         this.parent({ styleClass: 'run-dialog', | ||||
|                       destroyOnClose: false }); | ||||
|  | ||||
|         this._lockdownSettings = new Gio.Settings({ schema_id: LOCKDOWN_SCHEMA }); | ||||
|         this._terminalSettings = new Gio.Settings({ schema_id: TERMINAL_SCHEMA }); | ||||
|         this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA }); | ||||
|         this._terminalSettings = new Gio.Settings({ schema: TERMINAL_SCHEMA }); | ||||
|         global.settings.connect('changed::development-tools', Lang.bind(this, function () { | ||||
|             this._enableInternalCommands = global.settings.get_boolean('development-tools'); | ||||
|         })); | ||||
| @@ -50,10 +50,14 @@ const RunDialog = new Lang.Class({ | ||||
|                                        Main.createLookingGlass().open(); | ||||
|                                    }), | ||||
|  | ||||
|                                    'r': Lang.bind(this, this._restart), | ||||
|                                    'r': Lang.bind(this, function() { | ||||
|                                        global.reexec_self(); | ||||
|                                    }), | ||||
|  | ||||
|                                    // Developer brain backwards compatibility | ||||
|                                    'restart': Lang.bind(this, this._restart), | ||||
|                                    'restart': Lang.bind(this, function() { | ||||
|                                        global.reexec_self(); | ||||
|                                    }), | ||||
|  | ||||
|                                    'debugexit': Lang.bind(this, function() { | ||||
|                                        Meta.quit(Meta.ExitCode.ERROR); | ||||
| @@ -182,10 +186,6 @@ const RunDialog = new Lang.Class({ | ||||
|         let results = someResults.reduce(function(a, b) { | ||||
|             return a.concat(b); | ||||
|         }, []); | ||||
|  | ||||
|         if (!results.length) | ||||
|             return null; | ||||
|  | ||||
|         let common = results.reduce(_getCommon, null); | ||||
|         return common.substr(text.length); | ||||
|     }, | ||||
| @@ -271,12 +271,6 @@ const RunDialog = new Lang.Class({ | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _restart: function() { | ||||
|         this._shouldFadeOut = false; | ||||
|         this.close(); | ||||
|         Meta.restart(_("Restarting…")); | ||||
|     }, | ||||
|  | ||||
|     open: function() { | ||||
|         this._history.lastItem(); | ||||
|         this._errorBox.hide(); | ||||
|   | ||||
| @@ -301,7 +301,7 @@ const NotificationsBox = new Lang.Class({ | ||||
|                              }); | ||||
|  | ||||
|             this._updateVisibility(); | ||||
|             this.emit('wake-up-screen'); | ||||
|             Shell.util_wake_up_screen(); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
| @@ -327,7 +327,7 @@ const NotificationsBox = new Lang.Class({ | ||||
|  | ||||
|         this._updateVisibility(); | ||||
|         if (obj.sourceBox.visible) | ||||
|             this.emit('wake-up-screen'); | ||||
|             Shell.util_wake_up_screen(); | ||||
|     }, | ||||
|  | ||||
|     _visibleChanged: function(source, obj) { | ||||
| @@ -342,7 +342,7 @@ const NotificationsBox = new Lang.Class({ | ||||
|  | ||||
|         this._updateVisibility(); | ||||
|         if (obj.sourceBox.visible) | ||||
|             this.emit('wake-up-screen'); | ||||
|             Shell.util_wake_up_screen(); | ||||
|     }, | ||||
|  | ||||
|     _detailedChanged: function(source, obj) { | ||||
| @@ -380,7 +380,6 @@ const NotificationsBox = new Lang.Class({ | ||||
|         this._sources.delete(source); | ||||
|     }, | ||||
| }); | ||||
| Signals.addSignalMethods(NotificationsBox.prototype); | ||||
|  | ||||
| const Arrow = new Lang.Class({ | ||||
|     Name: 'Arrow', | ||||
| @@ -444,19 +443,19 @@ function clamp(value, min, max) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * To test screen shield, make sure to kill gnome-screensaver. | ||||
|  * | ||||
|  * If you are setting org.gnome.desktop.session.idle-delay directly in dconf, | ||||
|  * rather than through System Settings, you also need to set | ||||
|  * org.gnome.settings-daemon.plugins.power.sleep-display-ac and | ||||
|  * org.gnome.settings-daemon.plugins.power.sleep-display-battery to the same value. | ||||
|  * This will ensure that the screen blanks at the right time when it fades out. | ||||
|  * https://bugzilla.gnome.org/show_bug.cgi?id=668703 explains the dependency. | ||||
|  * https://bugzilla.gnome.org/show_bug.cgi?id=668703 explains the dependance. | ||||
|  */ | ||||
| const ScreenShield = new Lang.Class({ | ||||
|     Name: 'ScreenShield', | ||||
|  | ||||
|     _init: function() { | ||||
|         this.actor = Main.layoutManager.screenShieldGroup; | ||||
|  | ||||
|         this._lockScreenState = MessageTray.State.HIDDEN; | ||||
|         this._lockScreenGroup = new St.Widget({ x_expand: true, | ||||
|                                                 y_expand: true, | ||||
| @@ -465,6 +464,7 @@ const ScreenShield = new Lang.Class({ | ||||
|                                                 name: 'lockScreenGroup', | ||||
|                                                 visible: false, | ||||
|                                               }); | ||||
|  | ||||
|         this._lockScreenGroup.connect('key-press-event', | ||||
|                                       Lang.bind(this, this._onLockScreenKeyPress)); | ||||
|         this._lockScreenGroup.connect('scroll-event', | ||||
| @@ -515,10 +515,9 @@ const ScreenShield = new Lang.Class({ | ||||
|                                                 reactive: true, | ||||
|                                                 pivot_point: new Clutter.Point({ x: 0.5, y: 0.5 }), | ||||
|                                                 name: 'lockDialogGroup' }); | ||||
|         Main.layoutManager.systemGroup.add_child(this._lockDialogGroup); | ||||
|  | ||||
|         this.actor.add_actor(this._lockDialogGroup); | ||||
|         this.actor.add_actor(this._lockScreenGroup); | ||||
|  | ||||
|         Main.layoutManager.screenShieldGroup.add_child(this._lockScreenGroup); | ||||
|         this._presence = new GnomeSession.Presence(Lang.bind(this, function(proxy, error) { | ||||
|             if (error) { | ||||
|                 logError(error, 'Error while reading gnome-session presence'); | ||||
| @@ -535,7 +534,7 @@ const ScreenShield = new Lang.Class({ | ||||
|  | ||||
|         this._smartcardManager = SmartcardManager.getSmartcardManager(); | ||||
|         this._smartcardManager.connect('smartcard-inserted', | ||||
|                                        Lang.bind(this, function(manager, token) { | ||||
|                                        Lang.bind(this, function(token) { | ||||
|                                            if (this._isLocked && token.UsedToLogin) | ||||
|                                                this._liftShield(true, 0); | ||||
|                                        })); | ||||
| @@ -561,7 +560,7 @@ const ScreenShield = new Lang.Class({ | ||||
|                 this._loginSession.connectSignal('Unlock', Lang.bind(this, function() { this.deactivate(false); })); | ||||
|             })); | ||||
|  | ||||
|         this._settings = new Gio.Settings({ schema_id: SCREENSAVER_SCHEMA }); | ||||
|         this._settings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA }); | ||||
|  | ||||
|         this._isModal = false; | ||||
|         this._hasLockScreen = false; | ||||
| @@ -576,19 +575,27 @@ const ScreenShield = new Lang.Class({ | ||||
|         // The "long" lightbox is used for the longer (20 seconds) fade from session | ||||
|         // to idle status, the "short" is used for quickly fading to black when locking | ||||
|         // manually | ||||
|         this._longLightbox = new Lightbox.Lightbox(Main.uiGroup, | ||||
|         this._longLightbox = new Lightbox.Lightbox(Main.layoutManager.overlayGroup, | ||||
|                                                    { inhibitEvents: true, | ||||
|                                                      fadeFactor: 1 }); | ||||
|         this._longLightbox.connect('shown', Lang.bind(this, this._onLongLightboxShown)); | ||||
|         this._shortLightbox = new Lightbox.Lightbox(Main.uiGroup, | ||||
|         this._shortLightbox = new Lightbox.Lightbox(Main.layoutManager.overlayGroup, | ||||
|                                                     { inhibitEvents: true, | ||||
|                                                       fadeFactor: 1 }); | ||||
|         this._shortLightbox.connect('shown', Lang.bind(this, this._onShortLightboxShown)); | ||||
|  | ||||
|         Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._monitorsChanged)); | ||||
|         this._monitorsChanged(); | ||||
|  | ||||
|         this.idleMonitor = Meta.IdleMonitor.get_core(); | ||||
|         this._cursorTracker = Meta.CursorTracker.get_for_screen(global.screen); | ||||
|     }, | ||||
|  | ||||
|     _monitorsChanged: function() { | ||||
|         this._longLightbox.actor.set_size(global.screen_width, global.screen_height); | ||||
|         this._shortLightbox.actor.set_size(global.screen_width, global.screen_height); | ||||
|     }, | ||||
|  | ||||
|     _createBackground: function(monitorIndex) { | ||||
|         let monitor = Main.layoutManager.monitors[monitorIndex]; | ||||
|         let widget = new St.Widget({ style_class: 'screen-shield-background', | ||||
| @@ -646,14 +653,14 @@ const ScreenShield = new Lang.Class({ | ||||
|         if (this._isModal) | ||||
|             return true; | ||||
|  | ||||
|         this._isModal = Main.pushModal(this.actor, { keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN }); | ||||
|         this._isModal = Main.pushModal(this._lockDialogGroup, { keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN }); | ||||
|         if (this._isModal) | ||||
|             return true; | ||||
|  | ||||
|         // We failed to get a pointer grab, it means that | ||||
|         // something else has it. Try with a keyboard grab only | ||||
|         this._isModal = Main.pushModal(this.actor, { options: Meta.ModalOptions.POINTER_ALREADY_GRABBED, | ||||
|                                                      keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN }); | ||||
|         this._isModal = Main.pushModal(this._lockDialogGroup, { options: Meta.ModalOptions.POINTER_ALREADY_GRABBED, | ||||
|                                                                 keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN }); | ||||
|         return this._isModal; | ||||
|     }, | ||||
|  | ||||
| @@ -687,10 +694,10 @@ const ScreenShield = new Lang.Class({ | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|         let delta = 0; | ||||
|         if (event.get_scroll_direction() == Clutter.ScrollDirection.SMOOTH) | ||||
|             delta = Math.abs(event.get_scroll_delta()[0]); | ||||
|         else | ||||
|         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]); | ||||
|  | ||||
|         this._lockScreenScrollCounter += delta; | ||||
|  | ||||
| @@ -727,7 +734,7 @@ const ScreenShield = new Lang.Class({ | ||||
|         } else { | ||||
|             this._inhibitSuspend(); | ||||
|  | ||||
|             this._wakeUpScreen(); | ||||
|             this._onUserBecameActive(); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
| @@ -848,7 +855,6 @@ const ScreenShield = new Lang.Class({ | ||||
|                                                            this.lock(false); | ||||
|                                                            return GLib.SOURCE_REMOVE; | ||||
|                                                        })); | ||||
|             GLib.Source.set_name_by_id(this._lockTimeoutId, '[gnome-shell] this.lock'); | ||||
|         } | ||||
|  | ||||
|         this._activateFade(this._longLightbox, STANDARD_FADE_TIME); | ||||
| @@ -900,13 +906,19 @@ const ScreenShield = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     showDialog: function() { | ||||
|         if (!this._becomeModal()) { | ||||
|             // In the login screen, this is a hard error. Fail-whale | ||||
|             log('Could not acquire modal grab for the login screen. Aborting login process.'); | ||||
|             Meta.quit(Meta.ExitCode.ERROR); | ||||
|         } | ||||
|         // Ensure that the stage window is mapped, before taking a grab | ||||
|         // otherwise X errors out | ||||
|         Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { | ||||
|             if (!this._becomeModal()) { | ||||
|                 // In the login screen, this is a hard error. Fail-whale | ||||
|                 log('Could not acquire modal grab for the login screen. Aborting login process.'); | ||||
|                 Meta.quit(Meta.ExitCode.ERROR); | ||||
|             } | ||||
|  | ||||
|         this.actor.show(); | ||||
|             return false; | ||||
|         })); | ||||
|  | ||||
|         this._lockDialogGroup.show(); | ||||
|         this._isGreeter = Main.sessionMode.isGreeter; | ||||
|         this._isLocked = true; | ||||
|         if (this._ensureUnlockDialog(true, true)) | ||||
| @@ -996,6 +1008,7 @@ const ScreenShield = new Lang.Class({ | ||||
|             return; | ||||
|  | ||||
|         this._ensureLockScreen(); | ||||
|         this._lockDialogGroup.hide(); | ||||
|         this._lockDialogGroup.scale_x = 1; | ||||
|         this._lockDialogGroup.scale_y = 1; | ||||
|  | ||||
| @@ -1034,7 +1047,6 @@ const ScreenShield = new Lang.Class({ | ||||
|  | ||||
|         if (!this._arrowAnimationId) { | ||||
|             this._arrowAnimationId = Mainloop.timeout_add(6000, Lang.bind(this, this._animateArrows)); | ||||
|             GLib.Source.set_name_by_id(this._arrowAnimationId, '[gnome-shell] this._animateArrows'); | ||||
|             this._animateArrows(); | ||||
|         } | ||||
|  | ||||
| @@ -1095,18 +1107,19 @@ const ScreenShield = new Lang.Class({ | ||||
|         })); | ||||
|         this._cursorTracker.set_pointer_visible(false); | ||||
|  | ||||
|         this._lockScreenState = MessageTray.State.SHOWN; | ||||
|         this._lockDialogGroup.show(); | ||||
|         this._lockScreenGroup.fixed_position_set = false; | ||||
|         this._lockScreenState = MessageTray.State.SHOWN; | ||||
|         Main.layoutManager.sessionGroup.hide(); | ||||
|         this._lockScreenScrollCounter = 0; | ||||
|  | ||||
|         if (params.fadeToBlack && params.animateFade) { | ||||
|             // Take a beat | ||||
|  | ||||
|             let id = Mainloop.timeout_add(1000 * MANUAL_FADE_TIME, Lang.bind(this, function() { | ||||
|             Mainloop.timeout_add(1000 * MANUAL_FADE_TIME, Lang.bind(this, function() { | ||||
|                 this._activateFade(this._shortLightbox, MANUAL_FADE_TIME); | ||||
|                 return GLib.SOURCE_REMOVE; | ||||
|             })); | ||||
|             GLib.Source.set_name_by_id(id, '[gnome-shell] this._activateFade'); | ||||
|         } else { | ||||
|             if (params.fadeToBlack) | ||||
|                 this._activateFade(this._shortLightbox, 0); | ||||
| @@ -1147,7 +1160,6 @@ const ScreenShield = new Lang.Class({ | ||||
|         this._lockScreenContents.add_actor(this._lockScreenContentsBox); | ||||
|  | ||||
|         this._notificationsBox = new NotificationsBox(); | ||||
|         this._wakeUpScreenId = this._notificationsBox.connect('wake-up-screen', Lang.bind(this, this._wakeUpScreen)); | ||||
|         this._lockScreenContentsBox.add(this._notificationsBox.actor, { x_fill: true, | ||||
|                                                                         y_fill: true, | ||||
|                                                                         expand: true }); | ||||
| @@ -1155,17 +1167,11 @@ const ScreenShield = new Lang.Class({ | ||||
|         this._hasLockScreen = true; | ||||
|     }, | ||||
|  | ||||
|     _wakeUpScreen: function() { | ||||
|         this._onUserBecameActive(); | ||||
|         this.emit('wake-up-screen'); | ||||
|     }, | ||||
|  | ||||
|     _clearLockScreen: function() { | ||||
|         this._clock.destroy(); | ||||
|         this._clock = null; | ||||
|  | ||||
|         if (this._notificationsBox) { | ||||
|             this._notificationsBox.disconnect(this._wakeUpScreenId); | ||||
|             this._notificationsBox.destroy(); | ||||
|             this._notificationsBox = null; | ||||
|         } | ||||
| @@ -1227,10 +1233,11 @@ const ScreenShield = new Lang.Class({ | ||||
|             this._dialog.popModal(); | ||||
|  | ||||
|         if (this._isModal) { | ||||
|             Main.popModal(this.actor); | ||||
|             Main.popModal(this._lockDialogGroup); | ||||
|             this._isModal = false; | ||||
|         } | ||||
|  | ||||
|         Main.layoutManager.sessionGroup.show(); | ||||
|         Tweener.addTween(this._lockDialogGroup, { | ||||
|             scale_x: 0, | ||||
|             scale_y: 0, | ||||
| @@ -1249,7 +1256,7 @@ const ScreenShield = new Lang.Class({ | ||||
|  | ||||
|         this._longLightbox.hide(); | ||||
|         this._shortLightbox.hide(); | ||||
|         this.actor.hide(); | ||||
|         this._lockScreenGroup.hide(); | ||||
|  | ||||
|         if (this._becameActiveId != 0) { | ||||
|             this.idleMonitor.remove_watch(this._becameActiveId); | ||||
| @@ -1273,7 +1280,7 @@ const ScreenShield = new Lang.Class({ | ||||
|         if (this._activationTime == 0) | ||||
|             this._activationTime = GLib.get_monotonic_time(); | ||||
|  | ||||
|         this.actor.show(); | ||||
|         this._lockScreenGroup.show(); | ||||
|  | ||||
|         if (Main.sessionMode.currentMode != 'unlock-dialog' && | ||||
|             Main.sessionMode.currentMode != 'lock-screen') { | ||||
|   | ||||
| @@ -11,7 +11,6 @@ const Shell = imports.gi.Shell; | ||||
| const Signals = imports.signals; | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| const GrabHelper = imports.ui.grabHelper; | ||||
| const Lightbox = imports.ui.lightbox; | ||||
| const Main = imports.ui.main; | ||||
| const Tweener = imports.ui.tweener; | ||||
| @@ -68,13 +67,6 @@ const ScreenshotService = new Lang.Class({ | ||||
|         Gio.DBus.session.own_name('org.gnome.Shell.Screenshot', Gio.BusNameOwnerFlags.REPLACE, null, null); | ||||
|     }, | ||||
|  | ||||
|     _checkArea: function(x, y, width, height) { | ||||
|         return x >= 0 && y >= 0 && | ||||
|                width > 0 && height > 0 && | ||||
|                x + width <= global.screen_width && | ||||
|                y + height <= global.screen_height; | ||||
|     }, | ||||
|  | ||||
|     _onScreenshotComplete: function(obj, result, area, filenameUsed, flash, invocation) { | ||||
|         if (flash && result) { | ||||
|             let flashspot = new Flashspot(area); | ||||
| @@ -85,31 +77,13 @@ const ScreenshotService = new Lang.Class({ | ||||
|         invocation.return_value(retval); | ||||
|     }, | ||||
|  | ||||
|     _scaleArea: function(x, y, width, height) { | ||||
|         let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; | ||||
|         x *= scaleFactor; | ||||
|         y *= scaleFactor; | ||||
|         width *= scaleFactor; | ||||
|         height *= scaleFactor; | ||||
|         return [x, y, width, height]; | ||||
|     }, | ||||
|  | ||||
|     _unscaleArea: function(x, y, width, height) { | ||||
|         let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; | ||||
|         x /= scaleFactor; | ||||
|         y /= scaleFactor; | ||||
|         width /= scaleFactor; | ||||
|         height /= scaleFactor; | ||||
|         return [x, y, width, height]; | ||||
|     }, | ||||
|  | ||||
|     ScreenshotAreaAsync : function (params, invocation) { | ||||
|         let [x, y, width, height, flash, filename, callback] = params; | ||||
|         [x, y, width, height] = this._scaleArea(x, y, width, height); | ||||
|         if (!this._checkArea(x, y, width, height)) { | ||||
|             invocation.return_error_literal(Gio.IOErrorEnum, | ||||
|                                             Gio.IOErrorEnum.CANCELLED, | ||||
|                                             "Invalid params"); | ||||
|         if (x < 0 || y < 0 || | ||||
|             width <= 0 || height <= 0 || | ||||
|             x + width > global.screen_width || y + height > global.screen_height) { | ||||
|             invocation.return_error_literal(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED, | ||||
|                         "Invalid params"); | ||||
|             return; | ||||
|         } | ||||
|         let screenshot = new Shell.Screenshot(); | ||||
| @@ -140,9 +114,9 @@ const ScreenshotService = new Lang.Class({ | ||||
|         selectArea.connect('finished', Lang.bind(this, | ||||
|             function(selectArea, areaRectangle) { | ||||
|                 if (areaRectangle) { | ||||
|                     let retRectangle = this._unscaleArea(areaRectangle.x, areaRectangle.y, | ||||
|                         areaRectangle.width, areaRectangle.height); | ||||
|                     let retval = GLib.Variant.new('(iiii)', retRectangle); | ||||
|                     let retval = GLib.Variant.new('(iiii)', | ||||
|                         [areaRectangle.x, areaRectangle.y, | ||||
|                          areaRectangle.width, areaRectangle.height]); | ||||
|                     invocation.return_value(retval); | ||||
|                 } else { | ||||
|                     invocation.return_error_literal(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED, | ||||
| @@ -151,18 +125,9 @@ const ScreenshotService = new Lang.Class({ | ||||
|             })); | ||||
|     }, | ||||
|  | ||||
|     FlashAreaAsync: function(params, invocation) { | ||||
|         let [x, y, width, height] = params; | ||||
|         [x, y, width, height] = this._scaleArea(x, y, width, height); | ||||
|         if (!this._checkArea(x, y, width, height)) { | ||||
|             invocation.return_error_literal(Gio.IOErrorEnum, | ||||
|                                             Gio.IOErrorEnum.CANCELLED, | ||||
|                                             "Invalid params"); | ||||
|             return; | ||||
|         } | ||||
|     FlashArea: function(x, y, width, height) { | ||||
|         let flashspot = new Flashspot({ x : x, y : y, width: width, height: height}); | ||||
|         flashspot.fire(); | ||||
|         invocation.return_value(null); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| @@ -174,7 +139,6 @@ const SelectArea = new Lang.Class({ | ||||
|         this._startY = -1; | ||||
|         this._lastX = 0; | ||||
|         this._lastY = 0; | ||||
|         this._result = null; | ||||
|  | ||||
|         this._initRubberbandColors(); | ||||
|  | ||||
| @@ -182,14 +146,14 @@ const SelectArea = new Lang.Class({ | ||||
|                                       reactive: true, | ||||
|                                       x: 0, | ||||
|                                       y: 0 }); | ||||
|         Main.uiGroup.add_actor(this._group); | ||||
|  | ||||
|         this._grabHelper = new GrabHelper.GrabHelper(this._group); | ||||
|         Main.layoutManager.osdGroup.add_actor(this._group); | ||||
|  | ||||
|         this._group.connect('button-press-event', | ||||
|                             Lang.bind(this, this._onButtonPress)); | ||||
|         this._group.connect('button-release-event', | ||||
|                             Lang.bind(this, this._onButtonRelease)); | ||||
|         this._group.connect('key-press-event', | ||||
|                             Lang.bind(this, this._onKeyPress)); | ||||
|         this._group.connect('motion-event', | ||||
|                             Lang.bind(this, this._onMotionEvent)); | ||||
|  | ||||
| @@ -205,12 +169,10 @@ const SelectArea = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     show: function() { | ||||
|         if (!this._grabHelper.grab({ actor: this._group, | ||||
|                                      onUngrab: Lang.bind(this, this._onUngrab) })) | ||||
|         if (!Main.pushModal(this._group) || this._group.visible) | ||||
|             return; | ||||
|  | ||||
|         global.screen.set_cursor(Meta.Cursor.CROSSHAIR); | ||||
|         Main.uiGroup.set_child_above_sibling(this._group, null); | ||||
|         this._group.visible = true; | ||||
|     }, | ||||
|  | ||||
| @@ -240,6 +202,13 @@ const SelectArea = new Lang.Class({ | ||||
|                  height: Math.abs(this._startY - this._lastY) }; | ||||
|     }, | ||||
|  | ||||
|     _onKeyPress: function(actor, event) { | ||||
|         if (event.get_key_symbol() == Clutter.Escape) | ||||
|             this._destroy(null, false); | ||||
|  | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     }, | ||||
|  | ||||
|     _onMotionEvent: function(actor, event) { | ||||
|         if (this._startX == -1 || this._startY == -1) | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
| @@ -261,28 +230,24 @@ const SelectArea = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _onButtonRelease: function(actor, event) { | ||||
|         this._result = this._getGeometry(); | ||||
|         Tweener.addTween(this._group, | ||||
|                          { opacity: 0, | ||||
|                            time: 0.2, | ||||
|                            transition: 'easeOutQuad', | ||||
|                            onComplete: Lang.bind(this, | ||||
|                                function() { | ||||
|                                    this._grabHelper.ungrab(); | ||||
|                                }) | ||||
|                          }); | ||||
|         this._destroy(this._getGeometry(), true); | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     }, | ||||
|  | ||||
|     _onUngrab: function() { | ||||
|         global.screen.set_cursor(Meta.Cursor.DEFAULT); | ||||
|         this.emit('finished', this._result); | ||||
|     _destroy: function(geometry, fade) { | ||||
|         Tweener.addTween(this._group, | ||||
|                          { opacity: 0, | ||||
|                            time: fade ? 0.2 : 0, | ||||
|                            transition: 'easeOutQuad', | ||||
|                            onComplete: Lang.bind(this, | ||||
|                                function() { | ||||
|                                    Main.popModal(this._group); | ||||
|                                    this._group.destroy(); | ||||
|                                    global.screen.set_cursor(Meta.Cursor.DEFAULT); | ||||
|  | ||||
|         GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, | ||||
|             function() { | ||||
|                 this._group.destroy(); | ||||
|                 return GLib.SOURCE_REMOVE; | ||||
|             })); | ||||
|                                    this.emit('finished', geometry); | ||||
|                                }) | ||||
|                          }); | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(SelectArea.prototype); | ||||
| @@ -294,9 +259,9 @@ const Flashspot = new Lang.Class({ | ||||
|     Extends: Lightbox.Lightbox, | ||||
|  | ||||
|     _init: function(area) { | ||||
|         this.parent(Main.uiGroup, { inhibitEvents: true, | ||||
|                                     width: area.width, | ||||
|                                     height: area.height }); | ||||
|         this.parent(Main.layoutManager.osdGroup, { inhibitEvents: true, | ||||
|                                                    width: area.width, | ||||
|                                                    height: area.height }); | ||||
|  | ||||
|         this.actor.style_class = 'flashspot'; | ||||
|         this.actor.set_position(area.x, area.y); | ||||
|   | ||||
| @@ -7,7 +7,6 @@ const Meta = imports.gi.Meta; | ||||
| const Shell = imports.gi.Shell; | ||||
|  | ||||
| const Main = imports.ui.main; | ||||
| const Params = imports.misc.params; | ||||
|  | ||||
| // This module provides functionality for driving the shell user interface | ||||
| // in an automated fashion. The primary current use case for this is | ||||
| @@ -40,12 +39,11 @@ const Params = imports.misc.params; | ||||
| function sleep(milliseconds) { | ||||
|     let cb; | ||||
|  | ||||
|     let id = Mainloop.timeout_add(milliseconds, function() { | ||||
|     Mainloop.timeout_add(milliseconds, function() { | ||||
|                              if (cb) | ||||
|                                  cb(); | ||||
|                              return GLib.SOURCE_REMOVE; | ||||
|                          }); | ||||
|     GLib.Source.set_name_by_id(id, '[gnome-shell] sleep'); | ||||
|  | ||||
|     return function(callback) { | ||||
|         cb = callback; | ||||
| @@ -79,7 +77,6 @@ const PerfHelperIface = '<node> \ | ||||
|     <arg type="i" direction="in" /> \ | ||||
|     <arg type="b" direction="in" /> \ | ||||
|     <arg type="b" direction="in" /> \ | ||||
|     <arg type="b" direction="in" /> \ | ||||
| </method> \ | ||||
| <method name="WaitWindows" /> \ | ||||
| <method name="DestroyWindows" /> \ | ||||
| @@ -99,36 +96,11 @@ function _getPerfHelper() { | ||||
|     return _perfHelper; | ||||
| } | ||||
|  | ||||
| function _callRemote(obj, method, ...args) { | ||||
|     let cb; | ||||
|     let errcb; | ||||
|  | ||||
|     args.push(function(result, excp) { | ||||
|                   if (excp) { | ||||
|                       if (errcb) | ||||
|                           errcb(excp); | ||||
|                   } else { | ||||
|                       if (cb) | ||||
|                           cb(); | ||||
|                   } | ||||
|              }); | ||||
|  | ||||
|     method.apply(obj, args); | ||||
|  | ||||
|     return function(callback, error_callback) { | ||||
|         cb = callback; | ||||
|         errcb = error_callback; | ||||
|     }; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * createTestWindow: | ||||
|  * @params: options for window creation. | ||||
|  *   width - width of window, in pixels (default 640) | ||||
|  *   height - height of window, in pixels (default 480) | ||||
|  *   alpha - whether the window should have an alpha channel (default false) | ||||
|  *   maximized - whether the window should be created maximized (default false) | ||||
|  *   redraws - whether the window should continually redraw itself (default false) | ||||
|  * @width: width of window, in pixels | ||||
|  * @height: height of window, in pixels | ||||
|  * @alpha: whether the window should be alpha transparent | ||||
|  * @maximized: whethe the window should be created maximized | ||||
|  * | ||||
|  * Creates a window using gnome-shell-perf-helper for testing purposes. | ||||
| @@ -137,17 +109,19 @@ function _callRemote(obj, method, ...args) { | ||||
|  * because of the normal X asynchronous mapping process, to actually wait | ||||
|  * until the window has been mapped and exposed, use waitTestWindows(). | ||||
|  */ | ||||
| function createTestWindow(width, height, params) { | ||||
|     params = Params.parse(params, { width: 640, | ||||
|                                     height: 480, | ||||
|                                     alpha: false, | ||||
|                                     maximized: false, | ||||
|                                     redraws: false }); | ||||
|  | ||||
| function createTestWindow(width, height, alpha, maximized) { | ||||
|     let cb; | ||||
|     let perfHelper = _getPerfHelper(); | ||||
|     return _callRemote(perfHelper, perfHelper.CreateWindowRemote, | ||||
|                        params.width, params.height, | ||||
|                        params.alpha, params.maximized, params.redraws); | ||||
|  | ||||
|     perfHelper.CreateWindowRemote(width, height, alpha, maximized, | ||||
|                                   function(result, excp) { | ||||
|                                       if (cb) | ||||
|                                           cb(); | ||||
|                                   }); | ||||
|  | ||||
|     return function(callback) { | ||||
|         cb = callback; | ||||
|     }; | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -157,8 +131,17 @@ function createTestWindow(width, height, params) { | ||||
|  * created with createTestWindow have been mapped and exposed. | ||||
|  */ | ||||
| function waitTestWindows() { | ||||
|     let cb; | ||||
|     let perfHelper = _getPerfHelper(); | ||||
|     return _callRemote(perfHelper, perfHelper.WaitWindowsRemote); | ||||
|  | ||||
|     perfHelper.WaitWindowsRemote(function(result, excp) { | ||||
|                                      if (cb) | ||||
|                                          cb(); | ||||
|                                  }); | ||||
|  | ||||
|     return function(callback) { | ||||
|         cb = callback; | ||||
|     }; | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -171,8 +154,17 @@ function waitTestWindows() { | ||||
|  * process because of normal X asynchronicity. | ||||
|  */ | ||||
| function destroyTestWindows() { | ||||
|     let cb; | ||||
|     let perfHelper = _getPerfHelper(); | ||||
|     return _callRemote(perfHelper, perfHelper.DestroyWindowsRemote); | ||||
|  | ||||
|     perfHelper.DestroyWindowsRemote(function(result, excp) { | ||||
|                                         if (cb) | ||||
|                                             cb(); | ||||
|                                     }); | ||||
|  | ||||
|     return function(callback) { | ||||
|         cb = callback; | ||||
|     }; | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -215,10 +207,6 @@ function _step(g, finish, onError) { | ||||
|         let waitFunction = g.next(); | ||||
|         waitFunction(function() { | ||||
|                          _step(g, finish, onError); | ||||
|                      }, | ||||
|                      function(err) { | ||||
|                          if (onError) | ||||
|                              onError(err); | ||||
|                      }); | ||||
|     } catch (err if err instanceof StopIteration) { | ||||
|         if (finish) | ||||
| @@ -317,8 +305,8 @@ function _collect(scriptModule, outputFile) { | ||||
|         print ('------------------------------------------------------------'); | ||||
|         for (let i = 0; i < metrics.length; i++) { | ||||
|             let metric = metrics[i]; | ||||
|             print ('# ' + scriptModule.METRICS[metric].description); | ||||
|             print (metric + ': ' +  scriptModule.METRICS[metric].value + scriptModule.METRICS[metric].units); | ||||
|             print ('# ' + scriptModule.METRIC_DESCRIPTIONS[metric]); | ||||
|             print (metric + ': ' +  scriptModule.METRICS[metric]); | ||||
|         } | ||||
|         print ('------------------------------------------------------------'); | ||||
|     } | ||||
| @@ -371,12 +359,7 @@ function runPerfScript(scriptModule, outputFile) { | ||||
|  | ||||
|     _step(g, | ||||
|           function() { | ||||
|               try { | ||||
|                   _collect(scriptModule, outputFile); | ||||
|               } catch (err) { | ||||
|                   log("Script failed: " + err + "\n" + err.stack); | ||||
|                   Meta.exit(Meta.ExitCode.ERROR); | ||||
|               } | ||||
|               _collect(scriptModule, outputFile); | ||||
|               Meta.exit(Meta.ExitCode.SUCCESS); | ||||
|           }, | ||||
|          function(err) { | ||||
|   | ||||
							
								
								
									
										156
									
								
								js/ui/search.js
									
									
									
									
									
								
							
							
						
						
									
										156
									
								
								js/ui/search.js
									
									
									
									
									
								
							| @@ -6,7 +6,6 @@ const Gio = imports.gi.Gio; | ||||
| const Gtk = imports.gi.Gtk; | ||||
| const Meta = imports.gi.Meta; | ||||
| const Signals = imports.signals; | ||||
| const Shell = imports.gi.Shell; | ||||
| const St = imports.gi.St; | ||||
| const Atk = imports.gi.Atk; | ||||
|  | ||||
| @@ -32,8 +31,7 @@ const SearchSystem = new Lang.Class({ | ||||
|  | ||||
|         this._registerProvider(new AppDisplay.AppSearchProvider()); | ||||
|  | ||||
|         this._searchSettings = new Gio.Settings({ schema_id: SEARCH_PROVIDERS_SCHEMA }); | ||||
|         this._searchSettings.connect('changed::enabled', Lang.bind(this, this._reloadRemoteProviders)); | ||||
|         this._searchSettings = new Gio.Settings({ schema: SEARCH_PROVIDERS_SCHEMA }); | ||||
|         this._searchSettings.connect('changed::disabled', Lang.bind(this, this._reloadRemoteProviders)); | ||||
|         this._searchSettings.connect('changed::disable-external', Lang.bind(this, this._reloadRemoteProviders)); | ||||
|         this._searchSettings.connect('changed::sort-order', Lang.bind(this, this._reloadRemoteProviders)); | ||||
| @@ -70,9 +68,6 @@ const SearchSystem = new Lang.Class({ | ||||
|     _unregisterProvider: function (provider) { | ||||
|         let index = this._providers.indexOf(provider); | ||||
|         this._providers.splice(index, 1); | ||||
|  | ||||
|         if (provider.display) | ||||
|             provider.display.destroy(); | ||||
|     }, | ||||
|  | ||||
|     getProviders: function() { | ||||
| @@ -165,6 +160,13 @@ const SearchResult = new Lang.Class({ | ||||
|  | ||||
|     activate: function() { | ||||
|         this.emit('activate', this.metaInfo.id); | ||||
|     }, | ||||
|  | ||||
|     setSelected: function(selected) { | ||||
|         if (selected) | ||||
|             this.actor.add_style_pseudo_class('selected'); | ||||
|         else | ||||
|             this.actor.remove_style_pseudo_class('selected'); | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(SearchResult.prototype); | ||||
| @@ -225,11 +227,59 @@ const GridSearchResult = new Lang.Class({ | ||||
|  | ||||
|         this.actor.style_class = 'grid-search-result'; | ||||
|  | ||||
|         this.icon = new IconGrid.BaseIcon(this.metaInfo['name'], | ||||
|                                           { createIcon: this.metaInfo['createIcon'] }); | ||||
|         let content = new St.Bin({ child: this.icon.actor }); | ||||
|         this.actor.set_child(content); | ||||
|         this.actor.label_actor = this.icon.label; | ||||
|         let content = provider.createResultObject(metaInfo); | ||||
|         let dragSource = null; | ||||
|  | ||||
|         if (content == null) { | ||||
|             let actor = new St.Bin(); | ||||
|             let icon = new IconGrid.BaseIcon(this.metaInfo['name'], | ||||
|                                              { createIcon: this.metaInfo['createIcon'] }); | ||||
|             actor.set_child(icon.actor); | ||||
|             actor.label_actor = icon.label; | ||||
|             dragSource = icon.icon; | ||||
|             content = { actor: actor, icon: icon }; | ||||
|         } else { | ||||
|             if (content._delegate && content._delegate.getDragActorSource) | ||||
|                 dragSource = content._delegate.getDragActorSource(); | ||||
|         } | ||||
|  | ||||
|         this.actor.set_child(content.actor); | ||||
|         this.actor.label_actor = content.actor.label_actor; | ||||
|         this.icon = content.icon; | ||||
|  | ||||
|         let draggable = DND.makeDraggable(this.actor); | ||||
|         draggable.connect('drag-begin', | ||||
|                           Lang.bind(this, function() { | ||||
|                               Main.overview.beginItemDrag(this); | ||||
|                           })); | ||||
|         draggable.connect('drag-cancelled', | ||||
|                           Lang.bind(this, function() { | ||||
|                               Main.overview.cancelledItemDrag(this); | ||||
|                           })); | ||||
|         draggable.connect('drag-end', | ||||
|                           Lang.bind(this, function() { | ||||
|                               Main.overview.endItemDrag(this); | ||||
|                           })); | ||||
|  | ||||
|         if (!dragSource) | ||||
|             // not exactly right, but alignment problems are hard to notice | ||||
|             dragSource = content; | ||||
|         this._dragActorSource = dragSource; | ||||
|     }, | ||||
|  | ||||
|     getDragActorSource: function() { | ||||
|         return this._dragActorSource; | ||||
|     }, | ||||
|  | ||||
|     getDragActor: function() { | ||||
|         return this.metaInfo['createIcon'](Main.overview.dashIconSize); | ||||
|     }, | ||||
|  | ||||
|     shellWorkspaceLaunch: function(params) { | ||||
|         if (this.provider.dragActivateResult) | ||||
|             this.provider.dragActivateResult(this.metaInfo.id, params); | ||||
|         else | ||||
|             this.provider.activateResult(this.metaInfo.id, this.terms); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| @@ -261,16 +311,10 @@ const SearchResultsBase = new Lang.Class({ | ||||
|         this._terms = []; | ||||
|     }, | ||||
|  | ||||
|     _createResultDisplay: function(meta) { | ||||
|         if (this.provider.createResultObject) | ||||
|             return this.provider.createResultObject(meta); | ||||
|  | ||||
|         return null; | ||||
|     _clearResultDisplay: function() { | ||||
|     }, | ||||
|  | ||||
|     clear: function() { | ||||
|         for (let resultId in this._resultDisplays) | ||||
|             this._resultDisplays[resultId].actor.destroy(); | ||||
|         this._resultDisplays = {}; | ||||
|         this._clearResultDisplay(); | ||||
|         this.actor.hide(); | ||||
| @@ -294,22 +338,12 @@ const SearchResultsBase = new Lang.Class({ | ||||
|         })); | ||||
|  | ||||
|         if (metasNeeded.length === 0) { | ||||
|             callback(true); | ||||
|             callback(); | ||||
|         } else { | ||||
|             this._cancellable.cancel(); | ||||
|             this._cancellable.reset(); | ||||
|  | ||||
|             this.provider.getResultMetas(metasNeeded, Lang.bind(this, function(metas) { | ||||
|                 if (metas.length == 0) { | ||||
|                     callback(false); | ||||
|                     return; | ||||
|                 } | ||||
|                 if (metas.length != metasNeeded.length) { | ||||
|                     log('Wrong number of result metas returned by search provider'); | ||||
|                     callback(false); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 metasNeeded.forEach(Lang.bind(this, function(resultId, i) { | ||||
|                     let meta = metas[i]; | ||||
|                     let display = this._createResultDisplay(meta); | ||||
| @@ -317,7 +351,7 @@ const SearchResultsBase = new Lang.Class({ | ||||
|                     display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn)); | ||||
|                     this._resultDisplays[resultId] = display; | ||||
|                 })); | ||||
|                 callback(true); | ||||
|                 callback(); | ||||
|             }), this._cancellable); | ||||
|         } | ||||
|     }, | ||||
| @@ -334,10 +368,8 @@ const SearchResultsBase = new Lang.Class({ | ||||
|             let results = this.provider.filterResults(providerResults, maxResults); | ||||
|             let hasMoreResults = results.length < providerResults.length; | ||||
|  | ||||
|             this._ensureResultActors(results, Lang.bind(this, function(successful) { | ||||
|             this._ensureResultActors(results, Lang.bind(this, function() { | ||||
|                 this._clearResultDisplay(); | ||||
|                 if (!successful) | ||||
|                     return; | ||||
|  | ||||
|                 // To avoid CSS transitions causing flickering when | ||||
|                 // the first search result stays the same, we hide the | ||||
| @@ -367,7 +399,6 @@ const ListSearchResults = new Lang.Class({ | ||||
|         this.providerIcon.connect('key-focus-in', Lang.bind(this, this._keyFocusIn)); | ||||
|         this.providerIcon.connect('clicked', Lang.bind(this, | ||||
|             function() { | ||||
|                 this.providerIcon.animateLaunch(); | ||||
|                 provider.launchSearch(this._terms); | ||||
|                 Main.overview.toggle(); | ||||
|             })); | ||||
| @@ -385,7 +416,7 @@ const ListSearchResults = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _setMoreIconVisible: function(visible) { | ||||
|         this.providerIcon.moreIcon.visible = visible; | ||||
|         this.providerIcon.moreIcon.visible = true; | ||||
|     }, | ||||
|  | ||||
|     _getMaxDisplayedResults: function() { | ||||
| @@ -397,7 +428,7 @@ const ListSearchResults = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _createResultDisplay: function(meta) { | ||||
|         return this.parent(meta) || new ListSearchResult(this.provider, meta); | ||||
|         return new ListSearchResult(this.provider, meta); | ||||
|     }, | ||||
|  | ||||
|     _addItem: function(display) { | ||||
| @@ -417,14 +448,8 @@ const GridSearchResults = new Lang.Class({ | ||||
|     Name: 'GridSearchResults', | ||||
|     Extends: SearchResultsBase, | ||||
|  | ||||
|     _init: function(provider, parentContainer) { | ||||
|     _init: function(provider) { | ||||
|         this.parent(provider); | ||||
|         // We need to use the parent container to know how much results we can show. | ||||
|         // None of the actors in this class can be used for that, since the main actor | ||||
|         // goes hidden when no results are displayed, and then it lost its allocation. | ||||
|         // Then on the next use of _getMaxDisplayedResults allocation is 0, en therefore | ||||
|         // it doesn't show any result although we have some. | ||||
|         this._parentContainer = parentContainer; | ||||
|  | ||||
|         this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS, | ||||
|                                              xAlign: St.Align.START }); | ||||
| @@ -435,9 +460,16 @@ const GridSearchResults = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _getMaxDisplayedResults: function() { | ||||
|         let parentThemeNode = this._parentContainer.get_theme_node(); | ||||
|         let availableWidth = parentThemeNode.adjust_for_width(this._parentContainer.width); | ||||
|         return this._grid.columnsForWidth(availableWidth) * this._grid.getRowLimit(); | ||||
|         return this._grid.columnsForWidth(this._bin.width) * this._grid.getRowLimit(); | ||||
|     }, | ||||
|  | ||||
|     _renderResults: function(metas) { | ||||
|         for (let i = 0; i < metas.length; i++) { | ||||
|             let display = new GridSearchResult(this.provider, metas[i]); | ||||
|             display.connect('activate', Lang.bind(this, this._activateResult)); | ||||
|             display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn)); | ||||
|             this._grid.addItem(display); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _clearResultDisplay: function () { | ||||
| @@ -445,7 +477,7 @@ const GridSearchResults = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _createResultDisplay: function(meta) { | ||||
|         return this.parent(meta) || new GridSearchResult(this.provider, meta); | ||||
|         return new GridSearchResult(this.provider, meta); | ||||
|     }, | ||||
|  | ||||
|     _addItem: function(display) { | ||||
| @@ -528,7 +560,7 @@ const SearchResults = new Lang.Class({ | ||||
|         if (provider.appInfo) | ||||
|             providerDisplay = new ListSearchResults(provider); | ||||
|         else | ||||
|             providerDisplay = new GridSearchResults(provider, this._content); | ||||
|             providerDisplay = new GridSearchResults(provider); | ||||
|  | ||||
|         providerDisplay.connect('key-focus-in', Lang.bind(this, this._keyFocusIn)); | ||||
|         this._content.add(providerDisplay.actor); | ||||
| @@ -581,8 +613,10 @@ const SearchResults = new Lang.Class({ | ||||
|         } | ||||
|  | ||||
|         if (newDefaultResult != this._defaultResult) { | ||||
|             this._setSelected(this._defaultResult, false); | ||||
|             this._setSelected(newDefaultResult, this._highlightDefault); | ||||
|             if (this._defaultResult) | ||||
|                 this._defaultResult.setSelected(false); | ||||
|             if (newDefaultResult) | ||||
|                 newDefaultResult.setSelected(this._highlightDefault); | ||||
|  | ||||
|             this._defaultResult = newDefaultResult; | ||||
|         } | ||||
| @@ -619,7 +653,8 @@ const SearchResults = new Lang.Class({ | ||||
|  | ||||
|     highlightDefault: function(highlight) { | ||||
|         this._highlightDefault = highlight; | ||||
|         this._setSelected(this._defaultResult, highlight); | ||||
|         if (this._defaultResult) | ||||
|             this._defaultResult.setSelected(highlight); | ||||
|     }, | ||||
|  | ||||
|     navigateFocus: function(direction) { | ||||
| @@ -634,18 +669,6 @@ const SearchResults = new Lang.Class({ | ||||
|  | ||||
|         let from = this._defaultResult ? this._defaultResult.actor : null; | ||||
|         this.actor.navigate_focus(from, direction, false); | ||||
|     }, | ||||
|  | ||||
|     _setSelected: function(result, selected) { | ||||
|         if (!result) | ||||
|             return; | ||||
|  | ||||
|         if (selected) { | ||||
|             result.actor.add_style_pseudo_class('selected'); | ||||
|             Util.ensureActorVisibleInScrollView(this._scrollView, result.actor); | ||||
|         } else { | ||||
|             result.actor.remove_style_pseudo_class('selected'); | ||||
|         } | ||||
|     } | ||||
| }); | ||||
|  | ||||
| @@ -679,12 +702,5 @@ const ProviderIcon = new Lang.Class({ | ||||
|                                  gicon: provider.appInfo.get_icon() }); | ||||
|         this._content.add_actor(icon); | ||||
|         this._content.add_actor(this.moreIcon); | ||||
|     }, | ||||
|  | ||||
|     animateLaunch: function() { | ||||
|         let appSys = Shell.AppSystem.get_default(); | ||||
|         let app = appSys.lookup_app(this.provider.appInfo.get_id()); | ||||
|         if (app.state == Shell.AppState.STOPPED) | ||||
|             IconGrid.zoomOutActor(this._content); | ||||
|     } | ||||
| }); | ||||
|   | ||||
| @@ -10,14 +10,13 @@ const FileUtils = imports.misc.fileUtils; | ||||
| const Main = imports.ui.main; | ||||
| const Params = imports.misc.params; | ||||
|  | ||||
| const Config = imports.misc.config; | ||||
|  | ||||
| const DEFAULT_MODE = 'restrictive'; | ||||
|  | ||||
| const _modes = { | ||||
|     'restrictive': { | ||||
|         parentMode: null, | ||||
|         stylesheetName: 'gnome-shell.css', | ||||
|         overridesSchema: 'org.gnome.shell.overrides', | ||||
|         hasOverview: false, | ||||
|         showCalendarEvents: false, | ||||
|         allowSettings: false, | ||||
| @@ -93,12 +92,8 @@ const _modes = { | ||||
|         isLocked: false, | ||||
|         isPrimary: true, | ||||
|         unlockDialog: imports.ui.unlockDialog.UnlockDialog, | ||||
|         components: Config.HAVE_NETWORKMANAGER ? | ||||
|                     ['networkAgent', 'polkitAgent', 'telepathyClient', | ||||
|                      'keyring', 'autorunManager', 'automountManager'] : | ||||
|                     ['polkitAgent', 'telepathyClient', | ||||
|         components: ['networkAgent', 'polkitAgent', 'telepathyClient', | ||||
|                      'keyring', 'autorunManager', 'automountManager'], | ||||
|  | ||||
|         panel: { | ||||
|             left: ['activities', 'appMenu'], | ||||
|             center: ['dateMenu'], | ||||
| @@ -139,14 +134,13 @@ function _loadModes() { | ||||
|  | ||||
| function listModes() { | ||||
|     _loadModes(); | ||||
|     let id = Mainloop.idle_add(function() { | ||||
|     Mainloop.idle_add(function() { | ||||
|         let names = Object.getOwnPropertyNames(_modes); | ||||
|         for (let i = 0; i < names.length; i++) | ||||
|             if (_modes[names[i]].isPrimary) | ||||
|                 print(names[i]); | ||||
|         Mainloop.quit('listModes'); | ||||
|     }); | ||||
|     GLib.Source.set_name_by_id(id, '[gnome-shell] listModes'); | ||||
|     Mainloop.run('listModes'); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -69,7 +69,6 @@ const ScreenSaverIface = '<node> \ | ||||
| <signal name="ActiveChanged"> \ | ||||
|     <arg name="new_value" type="b" /> \ | ||||
| </signal> \ | ||||
| <signal name="WakeUpScreen" /> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| @@ -141,7 +140,12 @@ const GnomeShell = new Lang.Class({ | ||||
|         if (params['icon']) | ||||
|             icon = Gio.Icon.new_for_string(params['icon']); | ||||
|  | ||||
|         Main.osdWindowManager.show(monitorIndex, icon, params['label'], params['level']); | ||||
|         Main.osdWindow.setIcon(icon); | ||||
|         Main.osdWindow.setMonitor (monitorIndex); | ||||
|         Main.osdWindow.setLabel(params['label']); | ||||
|         Main.osdWindow.setLevel(params['level']); | ||||
|  | ||||
|         Main.osdWindow.show(); | ||||
|     }, | ||||
|  | ||||
|     FocusApp: function(id) { | ||||
| @@ -367,10 +371,8 @@ const GnomeShellExtensions = new Lang.Class({ | ||||
|     LaunchExtensionPrefs: function(uuid) { | ||||
|         let appSys = Shell.AppSystem.get_default(); | ||||
|         let app = appSys.lookup_app('gnome-shell-extension-prefs.desktop'); | ||||
|         let info = app.get_app_info(); | ||||
|         let timestamp = global.display.get_current_time_roundtrip(); | ||||
|         info.launch_uris(['extension:///' + uuid], | ||||
|                          global.create_app_launch_context(timestamp, -1)); | ||||
|         app.launch(global.display.get_current_time_roundtrip(), | ||||
|                    ['extension:///' + uuid], -1, null); | ||||
|     }, | ||||
|  | ||||
|     ReloadExtension: function(uuid) { | ||||
| @@ -403,9 +405,6 @@ const ScreenSaverDBus = new Lang.Class({ | ||||
|         screenShield.connect('active-changed', Lang.bind(this, function(shield) { | ||||
|             this._dbusImpl.emit_signal('ActiveChanged', GLib.Variant.new('(b)', [shield.active])); | ||||
|         })); | ||||
|         screenShield.connect('wake-up-screen', Lang.bind(this, function(shield) { | ||||
|             this._dbusImpl.emit_signal('WakeUpScreen', null); | ||||
|         })); | ||||
|  | ||||
|         this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ScreenSaverIface, this); | ||||
|         this._dbusImpl.export(Gio.DBus.session, '/org/gnome/ScreenSaver'); | ||||
|   | ||||
| @@ -36,7 +36,7 @@ const EntryMenu = new Lang.Class({ | ||||
|  | ||||
|         this._passwordItem = null; | ||||
|  | ||||
|         Main.uiGroup.add_actor(this.actor); | ||||
|         Main.layoutManager.menuGroup.add_actor(this.actor); | ||||
|         this.actor.hide(); | ||||
|     }, | ||||
|  | ||||
|   | ||||
| @@ -1,11 +1,11 @@ | ||||
| /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ | ||||
|  | ||||
| const Atk = imports.gi.Atk; | ||||
| const Cairo = imports.cairo; | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const Lang = imports.lang; | ||||
| const St = imports.gi.St; | ||||
| const Signals = imports.signals; | ||||
| const Atk = imports.gi.Atk; | ||||
|  | ||||
| const SLIDER_SCROLL_STEP = 0.05; /* Slider scrolling step in % */ | ||||
|  | ||||
| @@ -24,7 +24,6 @@ const Slider = new Lang.Class({ | ||||
|                                           accessible_role: Atk.Role.SLIDER }); | ||||
|         this.actor.connect('repaint', Lang.bind(this, this._sliderRepaint)); | ||||
|         this.actor.connect('button-press-event', Lang.bind(this, this._startDragging)); | ||||
|         this.actor.connect('touch-event', Lang.bind(this, this._touchDragging)); | ||||
|         this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent)); | ||||
|         this.actor.connect('key-press-event', Lang.bind(this, this.onKeyPressEvent)); | ||||
|  | ||||
| @@ -122,21 +121,11 @@ const Slider = new Lang.Class({ | ||||
|         this._dragging = true; | ||||
|  | ||||
|         let device = event.get_device(); | ||||
|         let sequence = event.get_event_sequence(); | ||||
|  | ||||
|         if (sequence != null) | ||||
|             device.sequence_grab(sequence, this.actor); | ||||
|         else | ||||
|             device.grab(this.actor); | ||||
|  | ||||
|         device.grab(this.actor); | ||||
|         this._grabbedDevice = device; | ||||
|         this._grabbedSequence = sequence; | ||||
|  | ||||
|         if (sequence == null) { | ||||
|             this._releaseId = this.actor.connect('button-release-event', Lang.bind(this, this._endDragging)); | ||||
|             this._motionId = this.actor.connect('motion-event', Lang.bind(this, this._motionEvent)); | ||||
|         } | ||||
|  | ||||
|         this._releaseId = this.actor.connect('button-release-event', Lang.bind(this, this._endDragging)); | ||||
|         this._motionId = this.actor.connect('motion-event', Lang.bind(this, this._motionEvent)); | ||||
|         let absX, absY; | ||||
|         [absX, absY] = event.get_coords(); | ||||
|         this._moveHandle(absX, absY); | ||||
| @@ -145,17 +134,10 @@ const Slider = new Lang.Class({ | ||||
|  | ||||
|     _endDragging: function() { | ||||
|         if (this._dragging) { | ||||
|             if (this._releaseId) | ||||
|                 this.actor.disconnect(this._releaseId); | ||||
|             if (this._motionId) | ||||
|                 this.actor.disconnect(this._motionId); | ||||
|             this.actor.disconnect(this._releaseId); | ||||
|             this.actor.disconnect(this._motionId); | ||||
|  | ||||
|             if (this._grabbedSequence != null) | ||||
|                 this._grabbedDevice.sequence_ungrab(this._grabbedSequence); | ||||
|             else | ||||
|                 this._grabbedDevice.ungrab(); | ||||
|  | ||||
|             this._grabbedSequence = null; | ||||
|             this._grabbedDevice.ungrab(); | ||||
|             this._grabbedDevice = null; | ||||
|             this._dragging = false; | ||||
|  | ||||
| @@ -164,24 +146,6 @@ const Slider = new Lang.Class({ | ||||
|         return Clutter.EVENT_STOP; | ||||
|     }, | ||||
|  | ||||
|     _touchDragging: function(actor, event) { | ||||
|         let device = event.get_device(); | ||||
|         let sequence = event.get_event_sequence(); | ||||
|  | ||||
|         if (!this._dragging && | ||||
|             event.type() == Clutter.EventType.TOUCH_BEGIN) { | ||||
|             this.startDragging(event); | ||||
|             return Clutter.EVENT_STOP; | ||||
|         } else if (device.sequence_get_grabbed_actor(sequence) == actor) { | ||||
|             if (event.type() == Clutter.EventType.TOUCH_UPDATE) | ||||
|                 return this._motionEvent(actor, event); | ||||
|             else if (event.type() == Clutter.EventType.TOUCH_END) | ||||
|                 return this._endDragging(); | ||||
|         } | ||||
|  | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     }, | ||||
|  | ||||
|     scroll: function(event) { | ||||
|         let direction = event.get_scroll_direction(); | ||||
|         let delta; | ||||
|   | ||||
| @@ -44,11 +44,11 @@ const ATIndicator = new Lang.Class({ | ||||
|         this._hbox = new St.BoxLayout({ style_class: 'panel-status-menu-box' }); | ||||
|         this._hbox.add_child(new St.Icon({ style_class: 'system-status-icon', | ||||
|                                            icon_name: 'preferences-desktop-accessibility-symbolic' })); | ||||
|         this._hbox.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM)); | ||||
|         this._hbox.add_child(PopupMenu.unicodeArrow(St.Side.BOTTOM)); | ||||
|  | ||||
|         this.actor.add_child(this._hbox); | ||||
|  | ||||
|         this._a11ySettings = new Gio.Settings({ schema_id: A11Y_SCHEMA }); | ||||
|         this._a11ySettings = new Gio.Settings({ schema: A11Y_SCHEMA }); | ||||
|         this._a11ySettings.connect('changed::' + KEY_ALWAYS_SHOW, Lang.bind(this, this._queueSyncMenuVisibility)); | ||||
|  | ||||
|         let highContrast = this._buildHCItem(); | ||||
| @@ -103,7 +103,6 @@ const ATIndicator = new Lang.Class({ | ||||
|             return; | ||||
|  | ||||
|         this._syncMenuVisbilityIdle = Mainloop.idle_add(Lang.bind(this, this._syncMenuVisibility)); | ||||
|         GLib.Source.set_name_by_id(this._syncMenuVisbilityIdle, '[gnome-shell] this._syncMenuVisibility'); | ||||
|     }, | ||||
|  | ||||
|     _buildItemExtended: function(string, initial_value, writable, on_set) { | ||||
| @@ -118,7 +117,7 @@ const ATIndicator = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _buildItem: function(string, schema, key) { | ||||
|         let settings = new Gio.Settings({ schema_id: schema }); | ||||
|         let settings = new Gio.Settings({ schema: schema }); | ||||
|         let widget = this._buildItemExtended(string, | ||||
|             settings.get_boolean(key), | ||||
|             settings.is_writable(key), | ||||
| @@ -134,8 +133,8 @@ const ATIndicator = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _buildHCItem: function() { | ||||
|         let interfaceSettings = new Gio.Settings({ schema_id: DESKTOP_INTERFACE_SCHEMA }); | ||||
|         let wmSettings = new Gio.Settings({ schema_id: WM_SCHEMA }); | ||||
|         let interfaceSettings = new Gio.Settings({ schema: DESKTOP_INTERFACE_SCHEMA }); | ||||
|         let wmSettings = new Gio.Settings({ schema: WM_SCHEMA }); | ||||
|         let gtkTheme = interfaceSettings.get_string(KEY_GTK_THEME); | ||||
|         let iconTheme = interfaceSettings.get_string(KEY_ICON_THEME); | ||||
|         let wmTheme = wmSettings.get_string(KEY_WM_THEME); | ||||
| @@ -186,7 +185,7 @@ const ATIndicator = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _buildFontItem: function() { | ||||
|         let settings = new Gio.Settings({ schema_id: DESKTOP_INTERFACE_SCHEMA }); | ||||
|         let settings = new Gio.Settings({ schema: DESKTOP_INTERFACE_SCHEMA }); | ||||
|  | ||||
|         let factor = settings.get_double(KEY_TEXT_SCALING_FACTOR); | ||||
|         let initial_setting = (factor > 1.0); | ||||
|   | ||||
| @@ -17,7 +17,6 @@ const OBJECT_PATH = '/org/gnome/SettingsDaemon/Rfkill'; | ||||
| const RfkillManagerInterface = '<node> \ | ||||
| <interface name="org.gnome.SettingsDaemon.Rfkill"> \ | ||||
| <property name="BluetoothAirplaneMode" type="b" access="readwrite" /> \ | ||||
| <property name="BluetoothHasAirplaneMode" type="b" access="read" /> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| @@ -39,10 +38,7 @@ const Indicator = new Lang.Class({ | ||||
|                                                      log(error.message); | ||||
|                                                      return; | ||||
|                                                  } | ||||
|  | ||||
|                                                  this._sync(); | ||||
|                                              })); | ||||
|         this._proxy.connect('g-properties-changed', Lang.bind(this, this._sync)); | ||||
|  | ||||
|         // The Bluetooth menu only appears when Bluetooth is in use, | ||||
|         // so just statically build it with a "Turn Off" menu item. | ||||
| @@ -59,7 +55,6 @@ const Indicator = new Lang.Class({ | ||||
|         this._model.connect('row-changed', Lang.bind(this, this._sync)); | ||||
|         this._model.connect('row-deleted', Lang.bind(this, this._sync)); | ||||
|         this._model.connect('row-inserted', Lang.bind(this, this._sync)); | ||||
|         Main.sessionMode.connect('updated', Lang.bind(this, this._sync)); | ||||
|         this._sync(); | ||||
|     }, | ||||
|  | ||||
| @@ -94,15 +89,12 @@ const Indicator = new Lang.Class({ | ||||
|  | ||||
|     _sync: function() { | ||||
|         let nDevices = this._getNConnectedDevices(); | ||||
|         let sensitive = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter; | ||||
|  | ||||
|         this.menu.setSensitive(sensitive); | ||||
|         this._indicator.visible = nDevices > 0; | ||||
|         this._item.actor.visible = this._proxy.BluetoothHasAirplaneMode && !this._proxy.BluetoothAirplaneMode; | ||||
|         let on = nDevices > 0; | ||||
|         this._indicator.visible = on; | ||||
|         this._item.actor.visible = on; | ||||
|  | ||||
|         if (nDevices > 0) | ||||
|         if (on) | ||||
|             this._item.status.text = ngettext("%d Connected Device", "%d Connected Devices", nDevices).format(nDevices); | ||||
|         else | ||||
|             this._item.status.text = _("Not Connected"); | ||||
|     }, | ||||
| }); | ||||
|   | ||||
| @@ -283,19 +283,15 @@ const InputSourcePopup = new Lang.Class({ | ||||
|         this._select(this._selectedIndex); | ||||
|     }, | ||||
|  | ||||
|     _keyPressHandler: function(keysym, action) { | ||||
|     _keyPressHandler: function(keysym, backwards, action) { | ||||
|         if (action == this._action) | ||||
|             this._select(this._next()); | ||||
|             this._select(backwards ? this._previous() : this._next()); | ||||
|         else if (action == this._actionBackward) | ||||
|             this._select(this._previous()); | ||||
|             this._select(backwards ? this._next() : this._previous()); | ||||
|         else if (keysym == Clutter.Left) | ||||
|             this._select(this._previous()); | ||||
|         else if (keysym == Clutter.Right) | ||||
|             this._select(this._next()); | ||||
|         else | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|         return Clutter.EVENT_STOP; | ||||
|     }, | ||||
|  | ||||
|     _finish : function() { | ||||
| @@ -345,7 +341,7 @@ const InputSourceIndicator = new Lang.Class({ | ||||
|  | ||||
|         this._hbox = new St.BoxLayout({ style_class: 'panel-status-menu-box' }); | ||||
|         this._hbox.add_child(this._container); | ||||
|         this._hbox.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM)); | ||||
|         this._hbox.add_child(PopupMenu.unicodeArrow(St.Side.BOTTOM)); | ||||
|  | ||||
|         this.actor.add_child(this._hbox); | ||||
|         this.actor.add_style_class_name('panel-status-button'); | ||||
| @@ -365,17 +361,18 @@ const InputSourceIndicator = new Lang.Class({ | ||||
|         this._mruSources = []; | ||||
|         this._keybindingAction = | ||||
|             Main.wm.addKeybinding('switch-input-source', | ||||
|                                   new Gio.Settings({ schema_id: "org.gnome.desktop.wm.keybindings" }), | ||||
|                                   Meta.KeyBindingFlags.NONE, | ||||
|                                   new Gio.Settings({ schema: "org.gnome.desktop.wm.keybindings" }), | ||||
|                                   Meta.KeyBindingFlags.REVERSES, | ||||
|                                   Shell.KeyBindingMode.ALL, | ||||
|                                   Lang.bind(this, this._switchInputSource)); | ||||
|         this._keybindingActionBackward = | ||||
|             Main.wm.addKeybinding('switch-input-source-backward', | ||||
|                                   new Gio.Settings({ schema_id: "org.gnome.desktop.wm.keybindings" }), | ||||
|                                   Meta.KeyBindingFlags.IS_REVERSED, | ||||
|                                   new Gio.Settings({ schema: "org.gnome.desktop.wm.keybindings" }), | ||||
|                                   Meta.KeyBindingFlags.REVERSES | | ||||
|                                   Meta.KeyBindingFlags.REVERSED, | ||||
|                                   Shell.KeyBindingMode.ALL, | ||||
|                                   Lang.bind(this, this._switchInputSource)); | ||||
|         this._settings = new Gio.Settings({ schema_id: DESKTOP_INPUT_SOURCES_SCHEMA }); | ||||
|         this._settings = new Gio.Settings({ schema: DESKTOP_INPUT_SOURCES_SCHEMA }); | ||||
|         this._settings.connect('changed::' + KEY_CURRENT_INPUT_SOURCE, Lang.bind(this, this._currentInputSourceChanged)); | ||||
|         this._settings.connect('changed::' + KEY_INPUT_SOURCES, Lang.bind(this, this._inputSourcesChanged)); | ||||
|  | ||||
| @@ -472,7 +469,8 @@ const InputSourceIndicator = new Lang.Class({ | ||||
|  | ||||
|         let popup = new InputSourcePopup(this._mruSources, this._keybindingAction, this._keybindingActionBackward); | ||||
|         let modifiers = binding.get_modifiers(); | ||||
|         if (!popup.show(binding.is_reversed(), binding.get_name(), binding.get_mask())) | ||||
|         let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK; | ||||
|         if (!popup.show(backwards, binding.get_name(), binding.get_mask())) | ||||
|             popup.destroy(); | ||||
|     }, | ||||
|  | ||||
|   | ||||
| @@ -1,42 +1,18 @@ | ||||
| // -*- 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 Main = imports.ui.main; | ||||
| const PanelMenu = imports.ui.panelMenu; | ||||
| const PopupMenu = imports.ui.popupMenu; | ||||
| const Shell = imports.gi.Shell; | ||||
|  | ||||
| const LOCATION_SCHEMA = 'org.gnome.system.location'; | ||||
| const MAX_ACCURACY_LEVEL = 'max-accuracy-level'; | ||||
| const ENABLED = 'enabled'; | ||||
|  | ||||
| var GeoclueIface = '<node> \ | ||||
|   <interface name="org.freedesktop.GeoClue2.Manager"> \ | ||||
|     <property name="InUse" type="b" access="read"/> \ | ||||
|     <property name="AvailableAccuracyLevel" type="u" access="read"/> \ | ||||
|     <method name="AddAgent"> \ | ||||
|       <arg name="id" type="s" direction="in"/> \ | ||||
|     </method> \ | ||||
|   </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| const GeoclueManager = Gio.DBusProxy.makeProxyWrapper(GeoclueIface); | ||||
|  | ||||
| var AgentIface = '<node> \ | ||||
|   <interface name="org.freedesktop.GeoClue2.Agent"> \ | ||||
|     <property name="MaxAccuracyLevel" type="u" access="read"/> \ | ||||
|     <method name="AuthorizeApp"> \ | ||||
|       <arg name="desktop_id" type="s" direction="in"/> \ | ||||
|       <arg name="req_accuracy_level" type="u" direction="in"/> \ | ||||
|       <arg name="authorized" type="b" direction="out"/> \ | ||||
|       <arg name="allowed_accuracy_level" type="u" direction="out"/> \ | ||||
|     </method> \ | ||||
|   </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| const Indicator = new Lang.Class({ | ||||
|     Name: 'LocationIndicator', | ||||
|     Extends: PanelMenu.SystemIndicator, | ||||
| @@ -44,161 +20,39 @@ const Indicator = new Lang.Class({ | ||||
|     _init: function() { | ||||
|         this.parent(); | ||||
|  | ||||
|         this._settings = new Gio.Settings({ schema_id: LOCATION_SCHEMA }); | ||||
|         this._settings.connect('changed::' + ENABLED, | ||||
|                                Lang.bind(this, this._onMaxAccuracyLevelChanged)); | ||||
|         this._settings.connect('changed::' + MAX_ACCURACY_LEVEL, | ||||
|                                Lang.bind(this, this._onMaxAccuracyLevelChanged)); | ||||
|  | ||||
|         this._indicator = this._addIndicator(); | ||||
|         this._indicator.icon_name = 'find-location-symbolic'; | ||||
|  | ||||
|         this._item = new PopupMenu.PopupSubMenuMenuItem(_("Location"), true); | ||||
|         this._item.icon.icon_name = 'find-location-symbolic'; | ||||
|  | ||||
|         this._agent = Gio.DBusExportedObject.wrapJSObject(AgentIface, this); | ||||
|         this._agent.export(Gio.DBus.system, '/org/freedesktop/GeoClue2/Agent'); | ||||
|  | ||||
|         this._item.status.text = _("Enabled"); | ||||
|         this._onOffAction = this._item.menu.addAction(_("Disable"), Lang.bind(this, this._onOnOffAction)); | ||||
|  | ||||
|         this.menu.addMenuItem(this._item); | ||||
|         this._sync(); | ||||
|  | ||||
|         this._watchId = Gio.bus_watch_name(Gio.BusType.SYSTEM, | ||||
|                                            'org.freedesktop.GeoClue2', | ||||
|                                            0, | ||||
|                                            Lang.bind(this, this._connectToGeoclue), | ||||
|                                            Lang.bind(this, this._onGeoclueAppeared), | ||||
|                                            Lang.bind(this, this._onGeoclueVanished)); | ||||
|         Main.sessionMode.connect('updated', Lang.bind(this, this._onSessionUpdated)); | ||||
|         this._onSessionUpdated(); | ||||
|         this._onMaxAccuracyLevelChanged(); | ||||
|         this._connectToGeoclue(); | ||||
|     }, | ||||
|  | ||||
|     get MaxAccuracyLevel() { | ||||
|         return this._getMaxAccuracyLevel(); | ||||
|     }, | ||||
|  | ||||
|     // We (and geoclue) have currently no way to reliably identifying apps so | ||||
|     // for now, lets just authorize all apps as long as they provide a valid | ||||
|     // desktop ID. We also ensure they don't get more accuracy than global max. | ||||
|     AuthorizeApp: function(desktop_id, reqAccuracyLevel) { | ||||
|         var appSystem = Shell.AppSystem.get_default(); | ||||
|         var app = appSystem.lookup_app(desktop_id + ".desktop"); | ||||
|         if (app == null) { | ||||
|             return [false, 0]; | ||||
|         } | ||||
|  | ||||
|         let allowedAccuracyLevel = clamp(reqAccuracyLevel, 0, this._getMaxAccuracyLevel()); | ||||
|         return [true, allowedAccuracyLevel]; | ||||
|     }, | ||||
|  | ||||
|     _syncIndicator: function() { | ||||
|     _sync: function() { | ||||
|         if (this._proxy == null) { | ||||
|             this._indicator.visible = false; | ||||
|             this._item.actor.visible = false; | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         this._indicator.visible = this._proxy.InUse; | ||||
|         this._item.actor.visible = this._indicator.visible; | ||||
|         this._updateMenuLabels(); | ||||
|     }, | ||||
|  | ||||
|     _connectToGeoclue: function() { | ||||
|         if (this._proxy != null || this._connecting) | ||||
|             return false; | ||||
|     _onGeoclueAppeared: function() { | ||||
|         // FIXME: This should be done async | ||||
|         this._proxy = new GeoclueManager(Gio.DBus.system, | ||||
|                                          'org.freedesktop.GeoClue2', | ||||
|                                          '/org/freedesktop/GeoClue2/Manager'); | ||||
|         this._proxy.connect('g-properties-changed', Lang.bind(this, this._sync)); | ||||
|  | ||||
|         this._connecting = true; | ||||
|         new GeoclueManager(Gio.DBus.system, | ||||
|                            'org.freedesktop.GeoClue2', | ||||
|                            '/org/freedesktop/GeoClue2/Manager', | ||||
|                            Lang.bind(this, this._onProxyReady)); | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     _onProxyReady: function(proxy, error) { | ||||
|         if (error != null) { | ||||
|             log(error.message); | ||||
|             this._connecting = false; | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         this._proxy = proxy; | ||||
|         this._propertiesChangedId = this._proxy.connect('g-properties-changed', | ||||
|                                                         Lang.bind(this, this._onGeocluePropsChanged)); | ||||
|  | ||||
|         this._syncIndicator(); | ||||
|  | ||||
|         this._proxy.AddAgentRemote('gnome-shell', Lang.bind(this, this._onAgentRegistered)); | ||||
|     }, | ||||
|  | ||||
|     _onAgentRegistered: function(result, error) { | ||||
|         this._connecting = false; | ||||
|         this._notifyMaxAccuracyLevel(); | ||||
|  | ||||
|         if (error != null) | ||||
|             log(error.message); | ||||
|         this._sync(); | ||||
|     }, | ||||
|  | ||||
|     _onGeoclueVanished: function() { | ||||
|         if (this._propertiesChangedId) { | ||||
|             this._proxy.disconnect(this._propertiesChangedId); | ||||
|             this._propertiesChangedId = 0; | ||||
|         } | ||||
|         this._proxy = null; | ||||
|  | ||||
|         this._syncIndicator(); | ||||
|     }, | ||||
|  | ||||
|     _onOnOffAction: function() { | ||||
|         let enabled = this._settings.get_boolean(ENABLED); | ||||
|         this._settings.set_boolean(ENABLED, !enabled); | ||||
|     }, | ||||
|  | ||||
|     _onSessionUpdated: function() { | ||||
|         let sensitive = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter; | ||||
|         this.menu.setSensitive(sensitive); | ||||
|     }, | ||||
|  | ||||
|     _updateMenuLabels: function() { | ||||
|         if (this._settings.get_boolean(ENABLED)) { | ||||
|             this._item.status.text = this._indicator.visible ? _("In Use") : _("Enabled"); | ||||
|             this._onOffAction.label.text = _("Disable"); | ||||
|         } else { | ||||
|             this._item.status.text = _("Disabled"); | ||||
|             this._onOffAction.label.text = _("Enable"); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _onMaxAccuracyLevelChanged: function() { | ||||
|         this._updateMenuLabels(); | ||||
|  | ||||
|         // Gotta ensure geoclue is up and we are registered as agent to it | ||||
|         // before we emit the notify for this property change. | ||||
|         if (!this._connectToGeoclue()) | ||||
|             this._notifyMaxAccuracyLevel(); | ||||
|     }, | ||||
|  | ||||
|     _getMaxAccuracyLevel: function() { | ||||
|         if (this._settings.get_boolean(ENABLED)) | ||||
|             return this._settings.get_enum(MAX_ACCURACY_LEVEL); | ||||
|         else | ||||
|             return 0; | ||||
|     }, | ||||
|  | ||||
|     _notifyMaxAccuracyLevel: function() { | ||||
|         let variant = new GLib.Variant('u', this._getMaxAccuracyLevel()); | ||||
|         this._agent.emit_property_changed('MaxAccuracyLevel', variant); | ||||
|     }, | ||||
|  | ||||
|     _onGeocluePropsChanged: function(proxy, properties) { | ||||
|         let unpacked = properties.deep_unpack(); | ||||
|         if ("InUse" in unpacked) | ||||
|             this._syncIndicator(); | ||||
|         this._sync(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| function clamp(value, min, max) { | ||||
|     return Math.max(min, Math.min(max, value)); | ||||
| } | ||||
|   | ||||
| @@ -9,17 +9,14 @@ const NetworkManager = imports.gi.NetworkManager; | ||||
| const NMClient = imports.gi.NMClient; | ||||
| const NMGtk = imports.gi.NMGtk; | ||||
| const Signals = imports.signals; | ||||
| const Shell = imports.gi.Shell; | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| const Animation = imports.ui.animation; | ||||
| const Main = imports.ui.main; | ||||
| const PanelMenu = imports.ui.panelMenu; | ||||
| const PopupMenu = imports.ui.popupMenu; | ||||
| const MessageTray = imports.ui.messageTray; | ||||
| const ModalDialog = imports.ui.modalDialog; | ||||
| const ModemManager = imports.misc.modemManager; | ||||
| const Rfkill = imports.ui.status.rfkill; | ||||
| const Util = imports.misc.util; | ||||
|  | ||||
| const NMConnectionCategory = { | ||||
| @@ -44,33 +41,6 @@ const NM80211Mode = NetworkManager['80211Mode']; | ||||
| const NM80211ApFlags = NetworkManager['80211ApFlags']; | ||||
| const NM80211ApSecurityFlags = NetworkManager['80211ApSecurityFlags']; | ||||
|  | ||||
| const PortalHelperResult = { | ||||
|     CANCELLED: 0, | ||||
|     COMPLETED: 1, | ||||
|     RECHECK: 2 | ||||
| }; | ||||
|  | ||||
| const PortalHelperIface = '<node> \ | ||||
| <interface name="org.gnome.Shell.PortalHelper"> \ | ||||
| <method name="Authenticate"> \ | ||||
|     <arg type="o" direction="in" name="connection" /> \ | ||||
|     <arg type="s" direction="in" name="url" /> \ | ||||
|     <arg type="u" direction="in" name="timestamp" /> \ | ||||
| </method> \ | ||||
| <method name="Close"> \ | ||||
|     <arg type="o" direction="in" name="connection" /> \ | ||||
| </method> \ | ||||
| <method name="Refresh"> \ | ||||
|     <arg type="o" direction="in" name="connection" /> \ | ||||
| </method> \ | ||||
| <signal name="Done"> \ | ||||
|     <arg type="o" name="connection" /> \ | ||||
|     <arg type="u" name="result" /> \ | ||||
| </signal> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
| const PortalHelperProxy = Gio.DBusProxy.makeProxyWrapper(PortalHelperIface); | ||||
|  | ||||
| function ssidCompare(one, two) { | ||||
|     if (!one || !two) | ||||
|         return false; | ||||
| @@ -132,34 +102,18 @@ const NMConnectionItem = new Lang.Class({ | ||||
|         this._activeConnection = null; | ||||
|         this._activeConnectionChangedId = 0; | ||||
|  | ||||
|         this._buildUI(); | ||||
|         this._sync(); | ||||
|     }, | ||||
|  | ||||
|     _buildUI: function() { | ||||
|         this.labelItem = new PopupMenu.PopupMenuItem(''); | ||||
|         this.labelItem.connect('activate', Lang.bind(this, this._toggle)); | ||||
|  | ||||
|         this.radioItem = new PopupMenu.PopupMenuItem(this._connection.get_id(), false); | ||||
|         this.radioItem.connect('activate', Lang.bind(this, this._activate)); | ||||
|         this.switchItem = new PopupMenu.PopupSwitchMenuItem(connection.get_id(), false); | ||||
|         this.switchItem.connect('toggled', Lang.bind(this, this._toggle)); | ||||
|  | ||||
|         this._sync(); | ||||
|     }, | ||||
|  | ||||
|     destroy: function() { | ||||
|         this.labelItem.destroy(); | ||||
|         this.radioItem.destroy(); | ||||
|     }, | ||||
|  | ||||
|     updateForConnection: function(connection) { | ||||
|         // connection should always be the same object | ||||
|         // (and object path) as this._connection, but | ||||
|         // this can be false if NetworkManager was restarted | ||||
|         // and picked up connections in a different order | ||||
|         // Just to be safe, we set it here again | ||||
|  | ||||
|         this._connection = connection; | ||||
|         this.radioItem.label.text = connection.get_id(); | ||||
|         this._sync(); | ||||
|         this.emit('name-changed'); | ||||
|         this.switchItem.destroy(); | ||||
|     }, | ||||
|  | ||||
|     getName: function() { | ||||
| @@ -175,8 +129,9 @@ const NMConnectionItem = new Lang.Class({ | ||||
|  | ||||
|     _sync: function() { | ||||
|         let isActive = this.isActive(); | ||||
|         this.labelItem.label.text = isActive ? _("Turn Off") : this._section.getConnectLabel(); | ||||
|         this.radioItem.setOrnament(isActive ? PopupMenu.Ornament.DOT : PopupMenu.Ornament.NONE); | ||||
|         this.labelItem.label.text = isActive ? _("Turn Off") : _("Connect"); | ||||
|         this.switchItem.setToggleState(isActive); | ||||
|         this.switchItem.setStatus(this._getStatus()); | ||||
|         this.emit('icon-changed'); | ||||
|     }, | ||||
|  | ||||
| @@ -189,11 +144,8 @@ const NMConnectionItem = new Lang.Class({ | ||||
|         this._sync(); | ||||
|     }, | ||||
|  | ||||
|     _activate: function() { | ||||
|         if (this._activeConnection == null) | ||||
|             this._section.activateConnection(this._connection); | ||||
|  | ||||
|         this._sync(); | ||||
|     _getStatus: function() { | ||||
|         return null; | ||||
|     }, | ||||
|  | ||||
|     _connectionStateChanged: function(ac, newstate, reason) { | ||||
| @@ -228,33 +180,23 @@ const NMConnectionSection = new Lang.Class({ | ||||
|         this._connections = []; | ||||
|  | ||||
|         this._labelSection = new PopupMenu.PopupMenuSection(); | ||||
|         this._radioSection = new PopupMenu.PopupMenuSection(); | ||||
|         this._switchSection = new PopupMenu.PopupMenuSection(); | ||||
|  | ||||
|         this.item = new PopupMenu.PopupSubMenuMenuItem('', true); | ||||
|         this.item.menu.addMenuItem(this._labelSection); | ||||
|         this.item.menu.addMenuItem(this._radioSection); | ||||
|         this.item.menu.addMenuItem(this._switchSection); | ||||
|  | ||||
|         this._notifyConnectivityId = this._client.connect('notify::connectivity', Lang.bind(this, this._iconChanged)); | ||||
|         this.connect('icon-changed', Lang.bind(this, this._sync)); | ||||
|     }, | ||||
|  | ||||
|     destroy: function() { | ||||
|         if (this._notifyConnectivityId != 0) { | ||||
|             this._client.disconnect(this._notifyConnectivityId); | ||||
|             this._notifyConnectivityId = 0; | ||||
|         } | ||||
|  | ||||
|         this.item.destroy(); | ||||
|     }, | ||||
|  | ||||
|     _iconChanged: function() { | ||||
|         this._sync(); | ||||
|         this.emit('icon-changed'); | ||||
|     }, | ||||
|  | ||||
|     _sync: function() { | ||||
|         let nItems = this._connectionItems.size; | ||||
|  | ||||
|         this._radioSection.actor.visible = (nItems > 1); | ||||
|         this._switchSection.actor.visible = (nItems > 1); | ||||
|         this._labelSection.actor.visible = (nItems == 1); | ||||
|  | ||||
|         this.item.status.text = this._getStatus(); | ||||
| @@ -269,12 +211,18 @@ const NMConnectionSection = new Lang.Class({ | ||||
|             this.item.label.text = ''; | ||||
|     }, | ||||
|  | ||||
|     _getMenuIcon: function() { | ||||
|         return this.getIndicatorIcon(); | ||||
|     _getStatus: function() { | ||||
|         let values = this._connectionItems.values(); | ||||
|         for (let item of values) { | ||||
|             if (item.isActive()) | ||||
|                 return item.getName(); | ||||
|         } | ||||
|  | ||||
|         return _("Off"); | ||||
|     }, | ||||
|  | ||||
|     getConnectLabel: function() { | ||||
|         return _("Connect"); | ||||
|     _hasConnection: function(connection) { | ||||
|         return this._connectionItems.has(connection.get_uuid()); | ||||
|     }, | ||||
|  | ||||
|     _connectionValid: function(connection) { | ||||
| @@ -282,7 +230,10 @@ const NMConnectionSection = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _connectionSortFunction: function(one, two) { | ||||
|         return GLib.utf8_collate(one.get_id(), two.get_id()); | ||||
|         if (one._timestamp == two._timestamp) | ||||
|             return GLib.utf8_collate(one.get_id(), two.get_id()); | ||||
|  | ||||
|         return two._timestamp - one._timestamp; | ||||
|     }, | ||||
|  | ||||
|     _makeConnectionItem: function(connection) { | ||||
| @@ -293,20 +244,10 @@ const NMConnectionSection = new Lang.Class({ | ||||
|         if (!this._connectionValid(connection)) | ||||
|             return; | ||||
|  | ||||
|         // This function is called everytime connection is added or updated | ||||
|         // In the usual case, we already added this connection and UUID | ||||
|         // didn't change. So we need to check if we already have an item, | ||||
|         // and update it for properties in the connection that changed | ||||
|         // (the only one we care about is the name) | ||||
|         // But it's also possible we didn't know about this connection | ||||
|         // (eg, during coldplug, or because it was updated and suddenly | ||||
|         // it's valid for this device), in which case we add a new item | ||||
|         if (this._hasConnection(connection)) | ||||
|             return; | ||||
|  | ||||
|         let item = this._connectionItems.get(connection.get_uuid()); | ||||
|         if (item) | ||||
|             item.updateForConnection(connection); | ||||
|         else | ||||
|             this._addConnection(connection); | ||||
|         this._addConnection(connection); | ||||
|     }, | ||||
|  | ||||
|     _addConnection: function(connection) { | ||||
| @@ -315,28 +256,22 @@ const NMConnectionSection = new Lang.Class({ | ||||
|             return; | ||||
|  | ||||
|         item.connect('icon-changed', Lang.bind(this, function() { | ||||
|             this._iconChanged(); | ||||
|             this.emit('icon-changed'); | ||||
|         })); | ||||
|         item.connect('activation-failed', Lang.bind(this, function(item, reason) { | ||||
|             this.emit('activation-failed', reason); | ||||
|         })); | ||||
|         item.connect('name-changed', Lang.bind(this, this._sync)); | ||||
|  | ||||
|         let pos = Util.insertSorted(this._connections, connection, Lang.bind(this, this._connectionSortFunction)); | ||||
|         this._labelSection.addMenuItem(item.labelItem, pos); | ||||
|         this._radioSection.addMenuItem(item.radioItem, pos); | ||||
|         this._switchSection.addMenuItem(item.switchItem, pos); | ||||
|         this._connectionItems.set(connection.get_uuid(), item); | ||||
|         this._sync(); | ||||
|     }, | ||||
|  | ||||
|     removeConnection: function(connection) { | ||||
|         let uuid = connection.get_uuid(); | ||||
|         let item = this._connectionItems.get(uuid); | ||||
|         if (item == undefined) | ||||
|             return; | ||||
|  | ||||
|         item.destroy(); | ||||
|         this._connectionItems.delete(uuid); | ||||
|         this._connectionItems.get(connection.get_uuid()).destroy(); | ||||
|         this._connectionItems.delete(connection.get_uuid()); | ||||
|  | ||||
|         let pos = this._connections.indexOf(connection); | ||||
|         this._connections.splice(pos, 1); | ||||
| @@ -357,19 +292,11 @@ const NMConnectionDevice = new Lang.Class({ | ||||
|         this._settings = settings; | ||||
|  | ||||
|         this._autoConnectItem = this.item.menu.addAction(_("Connect"), Lang.bind(this, this._autoConnect)); | ||||
|         this._deactivateItem = this._radioSection.addAction(_("Turn Off"), Lang.bind(this, this.deactivateConnection)); | ||||
|  | ||||
|         this._stateChangedId = this._device.connect('state-changed', Lang.bind(this, this._deviceStateChanged)); | ||||
|         this._activeConnectionChangedId = this._device.connect('notify::active-connection', Lang.bind(this, this._activeConnectionChanged)); | ||||
|     }, | ||||
|  | ||||
|     _canReachInternet: function() { | ||||
|         if (this._client.primary_connection != this._device.active_connection) | ||||
|             return true; | ||||
|  | ||||
|         return this._client.connectivity == NetworkManager.ConnectivityState.FULL; | ||||
|     }, | ||||
|  | ||||
|     _autoConnect: function() { | ||||
|         let connection = new NetworkManager.Connection(); | ||||
|         this._client.add_and_activate_connection(connection, this._device, null, null); | ||||
| @@ -444,7 +371,6 @@ const NMConnectionDevice = new Lang.Class({ | ||||
|     _sync: function() { | ||||
|         let nItems = this._connectionItems.size; | ||||
|         this._autoConnectItem.actor.visible = (nItems == 0); | ||||
|         this._deactivateItem.actor.visible = this._device.state > NetworkManager.DeviceState.DISCONNECTED; | ||||
|         this.parent(); | ||||
|     }, | ||||
|  | ||||
| @@ -456,22 +382,22 @@ const NMConnectionDevice = new Lang.Class({ | ||||
|         case NetworkManager.DeviceState.DISCONNECTED: | ||||
|             return _("Off"); | ||||
|         case NetworkManager.DeviceState.ACTIVATED: | ||||
|             return _("Connected"); | ||||
|             return this.parent(); | ||||
|         case NetworkManager.DeviceState.UNMANAGED: | ||||
|             /* 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) */ | ||||
|             return _("Unmanaged"); | ||||
|             return _("unmanaged"); | ||||
|         case NetworkManager.DeviceState.DEACTIVATING: | ||||
|             return _("Disconnecting"); | ||||
|             return _("disconnecting..."); | ||||
|         case NetworkManager.DeviceState.PREPARE: | ||||
|         case NetworkManager.DeviceState.CONFIG: | ||||
|         case NetworkManager.DeviceState.IP_CONFIG: | ||||
|         case NetworkManager.DeviceState.IP_CHECK: | ||||
|         case NetworkManager.DeviceState.SECONDARIES: | ||||
|             return _("Connecting"); | ||||
|             return _("connecting..."); | ||||
|         case NetworkManager.DeviceState.NEED_AUTH: | ||||
|             /* Translators: this is for network connections that require some kind of key or password */ | ||||
|             return _("Authentication required"); | ||||
|             return _("authentication required"); | ||||
|         case NetworkManager.DeviceState.UNAVAILABLE: | ||||
|             // This state is actually a compound of various states (generically unavailable, | ||||
|             // firmware missing), that are exposed by different properties (whose state may | ||||
| @@ -479,13 +405,13 @@ const NMConnectionDevice = new Lang.Class({ | ||||
|             if (this._device.firmware_missing) { | ||||
|                 /* Translators: this is for devices that require some kind of firmware or kernel | ||||
|                    module, which is missing */ | ||||
|                 return _("Firmware missing"); | ||||
|                 return _("firmware missing"); | ||||
|             } | ||||
|             /* Translators: this is for a network device that cannot be activated (for example it | ||||
|                is disabled by rfkill, or it has no coverage */ | ||||
|             return _("Unavailable"); | ||||
|             return _("unavailable"); | ||||
|         case NetworkManager.DeviceState.FAILED: | ||||
|             return _("Connection failed"); | ||||
|             return _("connection failed"); | ||||
|         default: | ||||
|             log('Device state invalid, is %d'.format(this._device.state)); | ||||
|             return 'invalid'; | ||||
| @@ -504,33 +430,33 @@ const NMDeviceWired = new Lang.Class({ | ||||
|         this.item.menu.addMenuItem(createSettingsAction(_("Wired Settings"), device)); | ||||
|     }, | ||||
|  | ||||
|     _hasCarrier: function() { | ||||
|         if (this._device instanceof NMClient.DeviceEthernet) | ||||
|             return this._device.carrier; | ||||
|         else | ||||
|             return true; | ||||
|     _isConnected: function() { | ||||
|         if (!this._device.active_connection) | ||||
|             return false; | ||||
|  | ||||
|         let state = this._device.active_connection.state; | ||||
|         return state >= NetworkManager.ActiveConnectionState.ACTIVATING; | ||||
|     }, | ||||
|  | ||||
|     _sync: function() { | ||||
|         this.item.actor.visible = this._hasCarrier(); | ||||
|         this.item.actor.visible = this._isConnected(); | ||||
|         this.parent(); | ||||
|     }, | ||||
|  | ||||
|     getIndicatorIcon: function() { | ||||
|         if (this._device.active_connection) { | ||||
|             let state = this._device.active_connection.state; | ||||
|     _getMenuIcon: function() { | ||||
|         if (this._device.active_connection) | ||||
|             return this.getIndicatorIcon(); | ||||
|         else | ||||
|             return 'network-wired-disconnected-symbolic'; | ||||
|     }, | ||||
|  | ||||
|             if (state == NetworkManager.ActiveConnectionState.ACTIVATING) { | ||||
|                 return 'network-wired-acquiring-symbolic'; | ||||
|             } else if (state == NetworkManager.ActiveConnectionState.ACTIVATED) { | ||||
|                 if (this._canReachInternet()) | ||||
|                     return 'network-wired-symbolic'; | ||||
|                 else | ||||
|                     return 'network-wired-no-route-symbolic'; | ||||
|             } else { | ||||
|                 return 'network-wired-disconnected-symbolic'; | ||||
|             } | ||||
|         } else | ||||
|     getIndicatorIcon: function() { | ||||
|         let state = this._device.active_connection.state; | ||||
|         if (state == NetworkManager.ActiveConnectionState.ACTIVATING) | ||||
|             return 'network-wired-acquiring-symbolic'; | ||||
|         else if (state == NetworkManager.ActiveConnectionState.ACTIVATED) | ||||
|             return 'network-wired-symbolic'; | ||||
|         else | ||||
|             return 'network-wired-disconnected-symbolic'; | ||||
|     } | ||||
| }); | ||||
| @@ -560,7 +486,7 @@ const NMDeviceModem = new Lang.Class({ | ||||
|         if (this._mobileDevice) { | ||||
|             this._operatorNameId = this._mobileDevice.connect('notify::operator-name', Lang.bind(this, this._sync)); | ||||
|             this._signalQualityId = this._mobileDevice.connect('notify::signal-quality', Lang.bind(this, function() { | ||||
|                 this._iconChanged(); | ||||
|                 this.emit('icon-changed'); | ||||
|             })); | ||||
|         } | ||||
|     }, | ||||
| @@ -597,20 +523,28 @@ const NMDeviceModem = new Lang.Class({ | ||||
|             return this.parent(); | ||||
|     }, | ||||
|  | ||||
|     getIndicatorIcon: function() { | ||||
|         if (this._device.active_connection) { | ||||
|             if (this._device.active_connection.state == NetworkManager.ActiveConnectionState.ACTIVATING) | ||||
|                 return 'network-cellular-acquiring-symbolic'; | ||||
|  | ||||
|             return this._getSignalIcon(); | ||||
|         } else { | ||||
|     _getMenuIcon: function() { | ||||
|         if (this._device.active_connection) | ||||
|             return this.getIndicatorIcon(); | ||||
|         else | ||||
|             return 'network-cellular-signal-none-symbolic'; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _getSignalIcon: function() { | ||||
|         return 'network-cellular-signal-' + signalToIcon(this._mobileDevice.signal_quality) + '-symbolic'; | ||||
|     }, | ||||
|  | ||||
|     getIndicatorIcon: function() { | ||||
|         if (this._device.active_connection.state == NetworkManager.ActiveConnectionState.ACTIVATING) | ||||
|             return 'network-cellular-acquiring-symbolic'; | ||||
|  | ||||
|         if (!this._mobileDevice) { | ||||
|             // this can happen for bluetooth in PAN mode | ||||
|             return 'network-cellular-connected-symbolic'; | ||||
|         } | ||||
|  | ||||
|         return this._getSignalIcon(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const NMDeviceBluetooth = new Lang.Class({ | ||||
| @@ -624,26 +558,21 @@ const NMDeviceBluetooth = new Lang.Class({ | ||||
|         this.item.menu.addMenuItem(createSettingsAction(_("Mobile Broadband Settings"), device)); | ||||
|     }, | ||||
|  | ||||
|     _getDescription: function() { | ||||
|         return this._device.name; | ||||
|     }, | ||||
|  | ||||
|     getConnectLabel: function() { | ||||
|         return _("Use as Internet connection"); | ||||
|     _getMenuIcon: function() { | ||||
|         if (this._device.active_connection) | ||||
|             return this.getIndicatorIcon(); | ||||
|         else | ||||
|             return 'network-cellular-signal-none-symbolic'; | ||||
|     }, | ||||
|  | ||||
|     getIndicatorIcon: function() { | ||||
|         if (this._device.active_connection) { | ||||
|             let state = this._device.active_connection.state; | ||||
|             if (state == NetworkManager.ActiveConnectionState.ACTIVATING) | ||||
|                 return 'network-cellular-acquiring-symbolic'; | ||||
|             else if (state == NetworkManager.ActiveConnectionState.ACTIVATED) | ||||
|                 return 'network-cellular-connected-symbolic'; | ||||
|             else | ||||
|                 return 'network-cellular-signal-none-symbolic'; | ||||
|         } else { | ||||
|         let state = this._device.active_connection.state; | ||||
|         if (state == NetworkManager.ActiveConnectionState.ACTIVATING) | ||||
|             return 'network-cellular-acquiring-symbolic'; | ||||
|         else if (state == NetworkManager.ActiveConnectionState.ACTIVATED) | ||||
|             return 'network-cellular-connected-symbolic'; | ||||
|         else | ||||
|             return 'network-cellular-signal-none-symbolic'; | ||||
|         } | ||||
|     } | ||||
| }); | ||||
|  | ||||
| @@ -716,26 +645,16 @@ const NMWirelessDialog = new Lang.Class({ | ||||
|     Name: 'NMWirelessDialog', | ||||
|     Extends: ModalDialog.ModalDialog, | ||||
|  | ||||
|     _init: function(client, device, settings) { | ||||
|     _init: function(client, device) { | ||||
|         this.parent({ styleClass: 'nm-dialog' }); | ||||
|  | ||||
|         this._client = client; | ||||
|         this._device = device; | ||||
|  | ||||
|         this._wirelessEnabledChangedId = this._client.connect('notify::wireless-enabled', | ||||
|                                                               Lang.bind(this, this._syncView)); | ||||
|  | ||||
|         this._rfkill = Rfkill.getRfkillManager(); | ||||
|         this._airplaneModeChangedId = this._rfkill.connect('airplane-mode-changed', | ||||
|                                                            Lang.bind(this, this._syncView)); | ||||
|  | ||||
|         this._networks = []; | ||||
|         this._buildLayout(); | ||||
|  | ||||
|         let connections = settings.list_connections(); | ||||
|         this._connections = connections.filter(Lang.bind(this, function(connection) { | ||||
|             return device.connection_valid(connection); | ||||
|         })); | ||||
|         this._connections = device.get_available_connections(); | ||||
|  | ||||
|         this._apAddedId = device.connect('access-point-added', Lang.bind(this, this._accessPointAdded)); | ||||
|         this._apRemovedId = device.connect('access-point-removed', Lang.bind(this, this._accessPointRemoved)); | ||||
| @@ -750,12 +669,6 @@ const NMWirelessDialog = new Lang.Class({ | ||||
|         this._selectedNetwork = null; | ||||
|         this._activeApChanged(); | ||||
|         this._updateSensitivity(); | ||||
|         this._syncView(); | ||||
|  | ||||
|         if (accessPoints.length == 0) { | ||||
|             /* If there are no visible access points, request a scan */ | ||||
|             this._device.request_scan_simple(null); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     destroy: function() { | ||||
| @@ -771,14 +684,6 @@ const NMWirelessDialog = new Lang.Class({ | ||||
|             GObject.Object.prototype.disconnect.call(this._device, this._activeApChangedId); | ||||
|             this._activeApChangedId = 0; | ||||
|         } | ||||
|         if (this._wirelessEnabledChangedId) { | ||||
|             this._client.disconnect(this._wirelessEnabledChangedId); | ||||
|             this._wirelessEnabledChangedId = 0; | ||||
|         } | ||||
|         if (this._airplaneModeChangedId) { | ||||
|             this._rfkill.disconnect(this._airplaneModeChangedId); | ||||
|             this._airplaneModeChangedId = 0; | ||||
|         } | ||||
|  | ||||
|         this.parent(); | ||||
|     }, | ||||
| @@ -800,44 +705,13 @@ const NMWirelessDialog = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _updateSensitivity: function() { | ||||
|         let connectSensitive = this._client.wireless_enabled && this._selectedNetwork && (this._selectedNetwork != this._activeNetwork); | ||||
|         let connectSensitive = this._selectedNetwork && (this._selectedNetwork != this._activeNetwork); | ||||
|         this._connectButton.reactive = connectSensitive; | ||||
|         this._connectButton.can_focus = connectSensitive; | ||||
|     }, | ||||
|  | ||||
|     _syncView: function() { | ||||
|         if (this._rfkill.airplaneMode) { | ||||
|             this._airplaneBox.show(); | ||||
|  | ||||
|             this._airplaneIcon.icon_name = 'airplane-mode-symbolic'; | ||||
|             this._airplaneHeadline.text = _("Airplane Mode is On"); | ||||
|             this._airplaneText.text = _("Wi-Fi is disabled when airplane mode is on."); | ||||
|             this._airplaneButton.label = _("Turn Off Airplane Mode"); | ||||
|  | ||||
|             this._airplaneButton.visible = !this._rfkill.hwAirplaneMode; | ||||
|             this._airplaneInactive.visible = this._rfkill.hwAirplaneMode; | ||||
|             this._noNetworksBox.hide(); | ||||
|         } else if (!this._client.wireless_enabled) { | ||||
|             this._airplaneBox.show(); | ||||
|  | ||||
|             this._airplaneIcon.icon_name = 'dialog-information-symbolic'; | ||||
|             this._airplaneHeadline.text = _("Wi-Fi is Off"); | ||||
|             this._airplaneText.text = _("Wi-Fi needs to be turned on in order to connect to a network."); | ||||
|             this._airplaneButton.label = _("Turn On Wi-Fi"); | ||||
|  | ||||
|             this._airplaneButton.show(); | ||||
|             this._airplaneInactive.hide(); | ||||
|             this._noNetworksBox.hide(); | ||||
|         } else { | ||||
|             this._airplaneBox.hide(); | ||||
|  | ||||
|             this._noNetworksBox.visible = (this._networks.length == 0); | ||||
|         } | ||||
|  | ||||
|         if (this._noNetworksBox.visible) | ||||
|             this._noNetworksSpinner.play(); | ||||
|         else | ||||
|             this._noNetworksSpinner.stop(); | ||||
|     _updateVisibility: function() { | ||||
|         this._noNetworksLabel.visible = (this._networks.length == 0); | ||||
|     }, | ||||
|  | ||||
|     _buildLayout: function() { | ||||
| @@ -871,43 +745,11 @@ const NMWirelessDialog = new Lang.Class({ | ||||
|         this._scrollView.add_actor(this._itemBox); | ||||
|         this._stack.add_child(this._scrollView); | ||||
|  | ||||
|         this._noNetworksBox = new St.BoxLayout({ vertical: true, | ||||
|                                                  style_class: 'no-networks-box', | ||||
|                                                  x_align: Clutter.ActorAlign.CENTER, | ||||
|                                                  y_align: Clutter.ActorAlign.CENTER }); | ||||
|  | ||||
|         this._noNetworksSpinner = new Animation.AnimatedIcon(global.datadir + '/theme/process-working.svg', 24, 24); | ||||
|         this._noNetworksBox.add_actor(this._noNetworksSpinner.actor); | ||||
|         this._noNetworksBox.add_actor(new St.Label({ style_class: 'no-networks-label', | ||||
|                                                      text: _("No Networks") })); | ||||
|         this._stack.add_child(this._noNetworksBox); | ||||
|  | ||||
|         this._airplaneBox = new St.BoxLayout({ vertical: true, | ||||
|                                                style_class: 'nm-dialog-airplane-box', | ||||
|         this._noNetworksLabel = new St.Label({ style_class: 'no-networks-label', | ||||
|                                                x_align: Clutter.ActorAlign.CENTER, | ||||
|                                                y_align: Clutter.ActorAlign.CENTER }); | ||||
|         this._airplaneIcon = new St.Icon({ icon_size: 48 }); | ||||
|         this._airplaneHeadline = new St.Label({ style_class: 'nm-dialog-airplane-headline' }); | ||||
|         this._airplaneText = new St.Label({ style_class: 'nm-dialog-airplane-text' }); | ||||
|  | ||||
|         let airplaneSubStack = new St.Widget({ layout_manager: new Clutter.BinLayout }); | ||||
|         this._airplaneButton = new St.Button({ style_class: 'modal-dialog-button' }); | ||||
|         this._airplaneButton.connect('clicked', Lang.bind(this, function() { | ||||
|             if (this._rfkill.airplaneMode) | ||||
|                 this._rfkill.airplaneMode = false; | ||||
|             else | ||||
|                 this._client.wireless_enabled = true; | ||||
|         })); | ||||
|         airplaneSubStack.add_actor(this._airplaneButton); | ||||
|         this._airplaneInactive = new St.Label({ style_class: 'nm-dialog-airplane-text', | ||||
|                                                 text: _("Use hardware switch to turn off") }); | ||||
|         airplaneSubStack.add_actor(this._airplaneInactive); | ||||
|  | ||||
|         this._airplaneBox.add(this._airplaneIcon, { x_align: St.Align.MIDDLE }); | ||||
|         this._airplaneBox.add(this._airplaneHeadline, { x_align: St.Align.MIDDLE }); | ||||
|         this._airplaneBox.add(this._airplaneText, { x_align: St.Align.MIDDLE }); | ||||
|         this._airplaneBox.add(airplaneSubStack, { x_align: St.Align.MIDDLE }); | ||||
|         this._stack.add_child(this._airplaneBox); | ||||
|                                                y_align: Clutter.ActorAlign.CENTER, | ||||
|                                                text: _("No Networks") }); | ||||
|         this._stack.add_child(this._noNetworksLabel); | ||||
|  | ||||
|         this.contentLayout.add(this._stack, { expand: true }); | ||||
|  | ||||
| @@ -1100,7 +942,7 @@ const NMWirelessDialog = new Lang.Class({ | ||||
|             this._itemBox.insert_child_at_index(network.item.actor, newPos); | ||||
|         } | ||||
|  | ||||
|         this._syncView(); | ||||
|         this._updateVisibility(); | ||||
|     }, | ||||
|  | ||||
|     _accessPointRemoved: function(device, accessPoint) { | ||||
| @@ -1115,14 +957,14 @@ const NMWirelessDialog = new Lang.Class({ | ||||
|         network.accessPoints.splice(res.ap, 1); | ||||
|  | ||||
|         if (network.accessPoints.length == 0) { | ||||
|             network.item.actor.destroy(); | ||||
|             network.item.destroy(); | ||||
|             this._networks.splice(res.network, 1); | ||||
|         } else { | ||||
|             network.item.updateBestAP(network.accessPoints[0]); | ||||
|             this._resortItems(); | ||||
|         } | ||||
|  | ||||
|         this._syncView(); | ||||
|         this._updateVisibility(); | ||||
|     }, | ||||
|  | ||||
|     _resortItems: function() { | ||||
| @@ -1162,10 +1004,9 @@ const NMDeviceWireless = new Lang.Class({ | ||||
|     Name: 'NMDeviceWireless', | ||||
|     category: NMConnectionCategory.WIRELESS, | ||||
|  | ||||
|     _init: function(client, device, settings) { | ||||
|     _init: function(client, device) { | ||||
|         this._client = client; | ||||
|         this._device = device; | ||||
|         this._settings = settings; | ||||
|  | ||||
|         this._description = ''; | ||||
|  | ||||
| @@ -1182,16 +1023,10 @@ const NMDeviceWireless = new Lang.Class({ | ||||
|         this._wirelessHwEnabledChangedId = this._client.connect('notify::wireless-hardware-enabled', Lang.bind(this, this._sync)); | ||||
|         this._activeApChangedId = this._device.connect('notify::active-access-point', Lang.bind(this, this._activeApChanged)); | ||||
|         this._stateChangedId = this._device.connect('state-changed', Lang.bind(this, this._deviceStateChanged)); | ||||
|         this._notifyConnectivityId = this._client.connect('notify::connectivity', Lang.bind(this, this._iconChanged)); | ||||
|  | ||||
|         this._sync(); | ||||
|     }, | ||||
|  | ||||
|     _iconChanged: function() { | ||||
|         this._sync(); | ||||
|         this.emit('icon-changed'); | ||||
|     }, | ||||
|  | ||||
|     destroy: function() { | ||||
|         if (this._activeApChangedId) { | ||||
|             GObject.Object.prototype.disconnect.call(this._device, this._activeApChangedId); | ||||
| @@ -1213,14 +1048,6 @@ const NMDeviceWireless = new Lang.Class({ | ||||
|             this._client.disconnect(this._wirelessHwEnabledChangedId); | ||||
|             this._wirelessHwEnabledChangedId = 0; | ||||
|         } | ||||
|         if (this._dialog) { | ||||
|             this._dialog.destroy(); | ||||
|             this._dialog = null; | ||||
|         } | ||||
|         if (this._notifyConnectivityId) { | ||||
|             this._client.disconnect(this._notifyConnectivityId); | ||||
|             this._notifyConnectivityId = 0; | ||||
|         } | ||||
|  | ||||
|         this.item.destroy(); | ||||
|     }, | ||||
| @@ -1247,7 +1074,7 @@ const NMDeviceWireless = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _showDialog: function() { | ||||
|         this._dialog = new NMWirelessDialog(this._client, this._device, this._settings); | ||||
|         this._dialog = new NMWirelessDialog(this._client, this._device); | ||||
|         this._dialog.connect('closed', Lang.bind(this, this._dialogClosed)); | ||||
|         this._dialog.open(); | ||||
|     }, | ||||
| @@ -1258,7 +1085,7 @@ const NMDeviceWireless = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _strengthChanged: function() { | ||||
|         this._iconChanged(); | ||||
|         this.emit('icon-changed'); | ||||
|     }, | ||||
|  | ||||
|     _activeApChanged: function() { | ||||
| @@ -1294,12 +1121,7 @@ const NMDeviceWireless = new Lang.Class({ | ||||
|     _getStatus: function() { | ||||
|         let ap = this._device.active_access_point; | ||||
|  | ||||
|         if (this._isHotSpotMaster()) | ||||
|             return _("Hotspot Active"); | ||||
|         else if (this._device.state >= NetworkManager.DeviceState.PREPARE && | ||||
|                  this._device.state < NetworkManager.DeviceState.ACTIVATED) | ||||
|             return _("Connecting"); | ||||
|         else if (ap) | ||||
|         if (ap) | ||||
|             return ssidToLabel(ap.get_ssid()); | ||||
|         else if (!this._client.wireless_hardware_enabled) | ||||
|             return _("Hardware Disabled"); | ||||
| @@ -1318,52 +1140,20 @@ const NMDeviceWireless = new Lang.Class({ | ||||
|             return 'network-wireless-signal-none-symbolic'; | ||||
|     }, | ||||
|  | ||||
|     _canReachInternet: function() { | ||||
|         if (this._client.primary_connection != this._device.active_connection) | ||||
|             return true; | ||||
|  | ||||
|         return this._client.connectivity == NetworkManager.ConnectivityState.FULL; | ||||
|     }, | ||||
|  | ||||
|     _isHotSpotMaster: function() { | ||||
|         if (!this._device.active_connection) | ||||
|             return false; | ||||
|  | ||||
|         let connection = this._settings.get_connection_by_path(this._device.active_connection.connection); | ||||
|         if (!connection) | ||||
|             return false; | ||||
|  | ||||
|         let ip4config = connection.get_setting_ip4_config(); | ||||
|         if (!ip4config) | ||||
|             return false; | ||||
|  | ||||
|         return ip4config.get_method() == NetworkManager.SETTING_IP4_CONFIG_METHOD_SHARED; | ||||
|     }, | ||||
|  | ||||
|     getIndicatorIcon: function() { | ||||
|         if (this._device.state < NetworkManager.DeviceState.PREPARE) | ||||
|             return 'network-wireless-disconnected-symbolic'; | ||||
|         if (this._device.state < NetworkManager.DeviceState.ACTIVATED) | ||||
|         if (this._device.state >= NetworkManager.DeviceState.PREPARE && | ||||
|             this._device.state < NetworkManager.DeviceState.ACTIVATED) | ||||
|             return 'network-wireless-acquiring-symbolic'; | ||||
|  | ||||
|         if (this._isHotSpotMaster()) | ||||
|             return 'network-wireless-hotspot-symbolic'; | ||||
|  | ||||
|         let ap = this._device.active_access_point; | ||||
|         if (!ap) { | ||||
|             if (this._device.mode != NM80211Mode.ADHOC) | ||||
|                 log('An active wireless connection, in infrastructure mode, involves no access point?'); | ||||
|  | ||||
|             if (this._canReachInternet()) | ||||
|                 return 'network-wireless-connected-symbolic'; | ||||
|             else | ||||
|                 return 'network-wireless-no-route-symbolic'; | ||||
|             return 'network-wireless-connected-symbolic'; | ||||
|         } | ||||
|  | ||||
|         if (this._canReachInternet()) | ||||
|             return 'network-wireless-signal-' + signalToIcon(ap.strength) + '-symbolic'; | ||||
|         else | ||||
|             return 'network-wireless-no-route-symbolic'; | ||||
|         return 'network-wireless-signal-' + signalToIcon(ap.strength) + '-symbolic'; | ||||
|     }, | ||||
| }); | ||||
| Signals.addSignalMethods(NMDeviceWireless.prototype); | ||||
| @@ -1379,22 +1169,6 @@ const NMVPNConnectionItem = new Lang.Class({ | ||||
|         return this._activeConnection.vpn_state != NetworkManager.VPNConnectionState.DISCONNECTED; | ||||
|     }, | ||||
|  | ||||
|     _buildUI: function() { | ||||
|         this.labelItem = new PopupMenu.PopupMenuItem(''); | ||||
|         this.labelItem.connect('activate', Lang.bind(this, this._toggle)); | ||||
|  | ||||
|         this.radioItem = new PopupMenu.PopupSwitchMenuItem(this._connection.get_id(), false); | ||||
|         this.radioItem.connect('toggled', Lang.bind(this, this._toggle)); | ||||
|     }, | ||||
|  | ||||
|     _sync: function() { | ||||
|         let isActive = this.isActive(); | ||||
|         this.labelItem.label.text = isActive ? _("Turn Off") : this._section.getConnectLabel(); | ||||
|         this.radioItem.setToggleState(isActive); | ||||
|         this.radioItem.setStatus(this._getStatus()); | ||||
|         this.emit('icon-changed'); | ||||
|     }, | ||||
|  | ||||
|     _getStatus: function() { | ||||
|         if (this._activeConnection == null) | ||||
|             return null; | ||||
| @@ -1464,53 +1238,19 @@ const NMVPNSection = new Lang.Class({ | ||||
|  | ||||
|     _init: function(client) { | ||||
|         this.parent(client); | ||||
|  | ||||
|         this._vpnSettings = new PopupMenu.PopupMenuItem(''); | ||||
|         this.item.menu.addMenuItem(this._vpnSettings); | ||||
|         this._vpnSettings.connect('activate', Lang.bind(this, this._onSettingsActivate)); | ||||
|  | ||||
|         this._sync(); | ||||
|     }, | ||||
|  | ||||
|     _sync: function() { | ||||
|         let nItems = this._connectionItems.size; | ||||
|         this.item.actor.visible = (nItems > 0); | ||||
|  | ||||
|         if (nItems > 1) | ||||
|             this._vpnSettings.label.text = _("Network Settings"); | ||||
|         else | ||||
|             this._vpnSettings.label.text = _("VPN Settings"); | ||||
|  | ||||
|         this.parent(); | ||||
|     }, | ||||
|  | ||||
|     _onSettingsActivate: function() { | ||||
|         let nItems = this._connectionItems.size; | ||||
|         if (nItems > 1) { | ||||
|             let appSys = Shell.AppSystem.get_default(); | ||||
|             let app = appSys.lookup_app('gnome-network-panel.desktop'); | ||||
|             app.launch(0, -1); | ||||
|         } else { | ||||
|             let connection = this._connections[0]; | ||||
|             Util.spawnApp(['gnome-control-center', 'network', 'show-device', | ||||
|                            connection.get_path()]); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _getDescription: function() { | ||||
|         return _("VPN"); | ||||
|     }, | ||||
|  | ||||
|     _getStatus: function() { | ||||
|         let values = this._connectionItems.values(); | ||||
|         for (let item of values) { | ||||
|             if (item.isActive()) | ||||
|                 return item.getName(); | ||||
|         } | ||||
|  | ||||
|         return _("Off"); | ||||
|     }, | ||||
|  | ||||
|     _getMenuIcon: function() { | ||||
|         return this.getIndicatorIcon() || 'network-vpn-symbolic'; | ||||
|     }, | ||||
| @@ -1608,7 +1348,6 @@ const NMApplet = new Lang.Class({ | ||||
|  | ||||
|         this._activeConnections = [ ]; | ||||
|         this._connections = [ ]; | ||||
|         this._connectivityQueue = [ ]; | ||||
|  | ||||
|         this._mainConnection = null; | ||||
|         this._mainConnectionIconChangedId = 0; | ||||
| @@ -1637,7 +1376,6 @@ const NMApplet = new Lang.Class({ | ||||
|         this._client.connect('notify::primary-connection', Lang.bind(this, this._syncMainConnection)); | ||||
|         this._client.connect('notify::activating-connection', Lang.bind(this, this._syncMainConnection)); | ||||
|         this._client.connect('notify::active-connections', Lang.bind(this, this._syncVPNConnections)); | ||||
|         this._client.connect('notify::connectivity', Lang.bind(this, this._syncConnectivity)); | ||||
|         this._client.connect('device-added', Lang.bind(this, this._deviceAdded)); | ||||
|         this._client.connect('device-removed', Lang.bind(this, this._deviceRemoved)); | ||||
|         this._settings.connect('new-connection', Lang.bind(this, this._newConnection)); | ||||
| @@ -1806,7 +1544,6 @@ const NMApplet = new Lang.Class({ | ||||
|         } | ||||
|  | ||||
|         this._updateIcon(); | ||||
|         this._syncConnectivity(); | ||||
|     }, | ||||
|  | ||||
|     _syncVPNConnections: function() { | ||||
| @@ -1892,6 +1629,7 @@ const NMApplet = new Lang.Class({ | ||||
|         let connectionSettings = connection.get_setting_by_name(NetworkManager.SETTING_CONNECTION_SETTING_NAME); | ||||
|         connection._type = connectionSettings.type; | ||||
|         connection._section = this._ctypes[connection._type] || NMConnectionCategory.INVALID; | ||||
|         connection._timestamp = connectionSettings.timestamp; | ||||
|  | ||||
|         let section = connection._section; | ||||
|  | ||||
| @@ -1912,102 +1650,12 @@ const NMApplet = new Lang.Class({ | ||||
|     _syncNMState: function() { | ||||
|         this.indicators.visible = this._client.manager_running; | ||||
|         this.menu.actor.visible = this._client.networking_enabled; | ||||
|  | ||||
|         this._syncConnectivity(); | ||||
|     }, | ||||
|  | ||||
|     _flushConnectivityQueue: function() { | ||||
|         if (this._portalHelperProxy) { | ||||
|             for (let item of this._connectivityQueue) | ||||
|                 this._portalHelperProxy.CloseRemote(item); | ||||
|         } | ||||
|  | ||||
|         this._connectivityQueue = []; | ||||
|     }, | ||||
|  | ||||
|     _closeConnectivityCheck: function(path) { | ||||
|         let index = this._connectivityQueue.indexOf(path); | ||||
|  | ||||
|         if (index >= 0) { | ||||
|             if (this._portalHelperProxy) | ||||
|                 this._portalHelperProxy.CloseRemote(path); | ||||
|  | ||||
|             this._connectivityQueue.splice(index, 1); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _portalHelperDone: function(proxy, emitter, parameters) { | ||||
|         let [path, result] = parameters; | ||||
|  | ||||
|         if (result == PortalHelperResult.CANCELLED) { | ||||
|             // Keep the connection in the queue, so the user is not | ||||
|             // spammed with more logins until we next flush the queue, | ||||
|             // which will happen once he chooses a better connection | ||||
|             // or we get to full connectivity through other means | ||||
|         } else if (result == PortalHelperResult.COMPLETED) { | ||||
|             this._closeConnectivityCheck(path); | ||||
|             return; | ||||
|         } else if (result == PortalHelperResult.RECHECK) { | ||||
|             this._client.check_connectivity_async(null, Lang.bind(this, function(client, result) { | ||||
|                 try { | ||||
|                     let state = client.check_connectivity_finish(result); | ||||
|                     if (state >= NetworkManager.ConnectivityState.FULL) | ||||
|                         this._closeConnectivityCheck(path); | ||||
|                 } catch(e) { } | ||||
|             })); | ||||
|         } else { | ||||
|             log('Invalid result from portal helper: ' + result); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _syncConnectivity: function() { | ||||
|         if (this._mainConnection == null || | ||||
|             this._mainConnection.state != NetworkManager.ActiveConnectionState.ACTIVATED) { | ||||
|             this._flushConnectivityQueue(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let isPortal = this._client.connectivity == NetworkManager.ConnectivityState.PORTAL; | ||||
|         // For testing, allow interpreting any value != FULL as PORTAL, because | ||||
|         // LIMITED (no upstream route after the default gateway) is easy to obtain | ||||
|         // with a tethered phone | ||||
|         // NONE is also possible, with a connection configured to force no default route | ||||
|         // (but in general we should only prompt a portal if we know there is a portal) | ||||
|         if (GLib.getenv('GNOME_SHELL_CONNECTIVITY_TEST') != null) | ||||
|             isPortal = isPortal || this._client.connectivity < NetworkManager.ConnectivityState.FULL; | ||||
|         if (!isPortal) | ||||
|             return; | ||||
|  | ||||
|         let path = this._mainConnection.get_path(); | ||||
|         for (let item of this._connectivityQueue) { | ||||
|             if (item == path) | ||||
|                 return; | ||||
|         } | ||||
|  | ||||
|         let timestamp = global.get_current_time(); | ||||
|         if (this._portalHelperProxy) { | ||||
|             this._portalHelperProxy.AuthenticateRemote(path, '', timestamp); | ||||
|         } else { | ||||
|             new PortalHelperProxy(Gio.DBus.session, 'org.gnome.Shell.PortalHelper', | ||||
|                                   '/org/gnome/Shell/PortalHelper', Lang.bind(this, function (proxy, error) { | ||||
|                                       if (error) { | ||||
|                                           log('Error launching the portal helper: ' + error); | ||||
|                                           return; | ||||
|                                       } | ||||
|  | ||||
|                                       this._portalHelperProxy = proxy; | ||||
|                                       proxy.connectSignal('Done', Lang.bind(this, this._portalHelperDone)); | ||||
|  | ||||
|                                       proxy.AuthenticateRemote(path, '', timestamp); | ||||
|                                   })); | ||||
|         } | ||||
|  | ||||
|         this._connectivityQueue.push(path); | ||||
|     }, | ||||
|  | ||||
|     _updateIcon: function() { | ||||
|         if (!this._client.networking_enabled || !this._mainConnection) { | ||||
|             this._primaryIndicator.visible = false; | ||||
|             this._primaryIndicator.icon_name = 'network-offline-symbolic'; | ||||
|             this._primaryIndicator.visible = true; | ||||
|         } else { | ||||
|             let dev = this._mainConnection._primaryDevice; | ||||
|             this._primaryIndicator.visible = (dev != null); | ||||
|   | ||||
| @@ -2,9 +2,7 @@ | ||||
|  | ||||
| const Gio = imports.gi.Gio; | ||||
| const Lang = imports.lang; | ||||
| const Signals = imports.signals; | ||||
|  | ||||
| const Main = imports.ui.main; | ||||
| const PanelMenu = imports.ui.panelMenu; | ||||
| const PopupMenu = imports.ui.popupMenu; | ||||
|  | ||||
| @@ -14,55 +12,11 @@ const OBJECT_PATH = '/org/gnome/SettingsDaemon/Rfkill'; | ||||
| const RfkillManagerInterface = '<node> \ | ||||
| <interface name="org.gnome.SettingsDaemon.Rfkill"> \ | ||||
| <property name="AirplaneMode" type="b" access="readwrite" /> \ | ||||
| <property name="HardwareAirplaneMode" type="b" access="read" /> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| const RfkillManagerProxy = Gio.DBusProxy.makeProxyWrapper(RfkillManagerInterface); | ||||
|  | ||||
| const RfkillManager = new Lang.Class({ | ||||
|     Name: 'RfkillManager', | ||||
|  | ||||
|     _init: function() { | ||||
|         this._proxy = new RfkillManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH, | ||||
|                                              Lang.bind(this, function(proxy, error) { | ||||
|                                                  if (error) { | ||||
|                                                      log(error.message); | ||||
|                                                      return; | ||||
|                                                  } | ||||
|                                                  this._proxy.connect('g-properties-changed', | ||||
|                                                                      Lang.bind(this, this._changed)); | ||||
|                                                  this._changed(); | ||||
|                                              })); | ||||
|     }, | ||||
|  | ||||
|     get airplaneMode() { | ||||
|         return this._proxy.AirplaneMode; | ||||
|     }, | ||||
|  | ||||
|     set airplaneMode(v) { | ||||
|         this._proxy.AirplaneMode = v; | ||||
|     }, | ||||
|  | ||||
|     get hwAirplaneMode() { | ||||
|         return this._proxy.HardwareAirplaneMode; | ||||
|     }, | ||||
|  | ||||
|     _changed: function() { | ||||
|         this.emit('airplane-mode-changed'); | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(RfkillManager.prototype); | ||||
|  | ||||
| var _manager; | ||||
| function getRfkillManager() { | ||||
|     if (_manager != null) | ||||
|         return _manager; | ||||
|  | ||||
|     _manager = new RfkillManager(); | ||||
|     return _manager; | ||||
| } | ||||
|  | ||||
| const Indicator = new Lang.Class({ | ||||
|     Name: 'RfkillIndicator', | ||||
|     Extends: PanelMenu.SystemIndicator, | ||||
| @@ -70,8 +24,16 @@ const Indicator = new Lang.Class({ | ||||
|     _init: function() { | ||||
|         this.parent(); | ||||
|  | ||||
|         this._manager = getRfkillManager(); | ||||
|         this._manager.connect('airplane-mode-changed', Lang.bind(this, this._sync)); | ||||
|         this._proxy = new RfkillManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH, | ||||
|                                              Lang.bind(this, function(proxy, error) { | ||||
|                                                  if (error) { | ||||
|                                                      log(error.message); | ||||
|                                                      return; | ||||
|                                                  } | ||||
|                                                  this._proxy.connect('g-properties-changed', | ||||
|                                                                      Lang.bind(this, this._sync)); | ||||
|                                                  this._sync(); | ||||
|                                              })); | ||||
|  | ||||
|         this._indicator = this._addIndicator(); | ||||
|         this._indicator.icon_name = 'airplane-mode-symbolic'; | ||||
| @@ -83,34 +45,16 @@ const Indicator = new Lang.Class({ | ||||
|         this._item = new PopupMenu.PopupSubMenuMenuItem(_("Airplane Mode"), true); | ||||
|         this._item.icon.icon_name = 'airplane-mode-symbolic'; | ||||
|         this._item.status.text = _("On"); | ||||
|         this._offItem = this._item.menu.addAction(_("Turn Off"), Lang.bind(this, function() { | ||||
|             this._manager.airplaneMode = false; | ||||
|         this._item.menu.addAction(_("Turn Off"), Lang.bind(this, function() { | ||||
|             this._proxy.AirplaneMode = false; | ||||
|         })); | ||||
|         this._item.menu.addSettingsAction(_("Network Settings"), 'gnome-network-panel.desktop'); | ||||
|         this.menu.addMenuItem(this._item); | ||||
|  | ||||
|         Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated)); | ||||
|         this._sessionUpdated(); | ||||
|     }, | ||||
|  | ||||
|     _sessionUpdated: function() { | ||||
|         let sensitive = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter; | ||||
|         this.menu.setSensitive(sensitive); | ||||
|     }, | ||||
|  | ||||
|     _sync: function() { | ||||
|         let airplaneMode = this._manager.airplaneMode; | ||||
|         let hwAirplaneMode = this._manager.hwAirplaneMode; | ||||
|         let changed = (airplaneMode != this._indicator.visible) || | ||||
|             (hwAirplaneMode != this._offItem.actor.visible); | ||||
|  | ||||
|         let airplaneMode = this._proxy.AirplaneMode; | ||||
|         this._indicator.visible = airplaneMode; | ||||
|         this._item.actor.visible = airplaneMode; | ||||
|         this._offItem.setSensitive(!hwAirplaneMode); | ||||
|  | ||||
|         if (hwAirplaneMode) | ||||
|             this._offItem.label.text = _("Use hardware switch to turn off"); | ||||
|         else | ||||
|             this._offItem.label.text = _("Turn Off"); | ||||
|     }, | ||||
| }); | ||||
|   | ||||
| @@ -56,10 +56,7 @@ const AltSwitcher = new Lang.Class({ | ||||
|         } | ||||
|  | ||||
|         if (this.actor.get_child() != childToShow) { | ||||
|             let hasFocus = this.actor.contains(global.stage.get_key_focus()); | ||||
|             this.actor.set_child(childToShow); | ||||
|             if (hasFocus) | ||||
|                 childToShow.grab_key_focus(); | ||||
|  | ||||
|             // The actors might respond to hover, so | ||||
|             // sync the pointer to make sure they update. | ||||
| @@ -95,11 +92,11 @@ const Indicator = new Lang.Class({ | ||||
|     _init: function() { | ||||
|         this.parent(); | ||||
|  | ||||
|         this._screenSaverSettings = new Gio.Settings({ schema_id: SCREENSAVER_SCHEMA }); | ||||
|         this._loginScreenSettings = new Gio.Settings({ schema_id: LOGIN_SCREEN_SCHEMA }); | ||||
|         this._lockdownSettings = new Gio.Settings({ schema_id: LOCKDOWN_SCHEMA }); | ||||
|         this._privacySettings = new Gio.Settings({ schema_id: PRIVACY_SCHEMA }); | ||||
|         this._orientationSettings = new Gio.Settings({ schema_id: 'org.gnome.settings-daemon.peripherals.touchscreen' }); | ||||
|         this._screenSaverSettings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA }); | ||||
|         this._loginScreenSettings = new Gio.Settings({ schema: LOGIN_SCREEN_SCHEMA }); | ||||
|         this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA }); | ||||
|         this._privacySettings = new Gio.Settings({ schema: PRIVACY_SCHEMA }); | ||||
|         this._orientationSettings = new Gio.Settings({ schema: 'org.gnome.settings-daemon.peripherals.touchscreen' }); | ||||
|  | ||||
|         this._session = new GnomeSession.SessionManager(); | ||||
|         this._loginManager = LoginManager.getLoginManager(); | ||||
| @@ -151,11 +148,11 @@ const Indicator = new Lang.Class({ | ||||
|         Gio.DBus.session.watch_name('org.gnome.SettingsDaemon.Orientation', | ||||
|                                     Gio.BusNameWatcherFlags.NONE, | ||||
|                                     Lang.bind(this, function() { | ||||
|                                         this._orientationExists = true; | ||||
|                                         this._orentationExists = true; | ||||
|                                         this._updateOrientationLock(); | ||||
|                                     }), | ||||
|                                     Lang.bind(this, function() { | ||||
|                                         this._orientationExists = false; | ||||
|                                         this._orentationExists = false; | ||||
|                                         this._updateOrientationLock(); | ||||
|                                     })); | ||||
|         this._updateOrientationLock(); | ||||
|   | ||||
| @@ -54,7 +54,7 @@ const SwitcherPopup = new Lang.Class({ | ||||
|         this.actor.connect('allocate', Lang.bind(this, this._allocate)); | ||||
|         this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); | ||||
|  | ||||
|         Main.uiGroup.add_actor(this.actor); | ||||
|         Main.layoutManager.switcherPopupGroup.add_child(this.actor); | ||||
|  | ||||
|         this._haveModal = false; | ||||
|         this._modifierMask = 0; | ||||
| @@ -161,12 +161,11 @@ const SwitcherPopup = new Lang.Class({ | ||||
|         // disturbed by the popup briefly flashing. | ||||
|         this._initialDelayTimeoutId = Mainloop.timeout_add(POPUP_DELAY_TIMEOUT, | ||||
|                                                            Lang.bind(this, function () { | ||||
|                                                                Main.osdWindowManager.hideAll(); | ||||
|                                                                Main.osdWindow.cancel(); | ||||
|                                                                this.actor.opacity = 255; | ||||
|                                                                this._initialDelayTimeoutId = 0; | ||||
|                                                                return GLib.SOURCE_REMOVE; | ||||
|                                                            })); | ||||
|         GLib.Source.set_name_by_id(this._initialDelayTimeoutId, '[gnome-shell] Main.osdWindow.cancel'); | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
| @@ -178,21 +177,22 @@ const SwitcherPopup = new Lang.Class({ | ||||
|         return mod(this._selectedIndex - 1, this._items.length); | ||||
|     }, | ||||
|  | ||||
|     _keyPressHandler: function(keysym, action) { | ||||
|     _keyPressHandler: function(keysym, backwards, action) { | ||||
|         throw new Error('Not implemented'); | ||||
|     }, | ||||
|  | ||||
|     _keyPressEvent: function(actor, event) { | ||||
|         let keysym = event.get_key_symbol(); | ||||
|         let action = global.display.get_keybinding_action(event.get_key_code(), event.get_state()); | ||||
|         let event_state = event.get_state(); | ||||
|         let backwards = event_state & Clutter.ModifierType.SHIFT_MASK; | ||||
|         let action = global.display.get_keybinding_action(event.get_key_code(), event_state); | ||||
|  | ||||
|         this._disableHover(); | ||||
|  | ||||
|         if (this._keyPressHandler(keysym, action) != Clutter.EVENT_PROPAGATE) | ||||
|             return Clutter.EVENT_STOP; | ||||
|  | ||||
|         if (keysym == Clutter.Escape) | ||||
|             this.destroy(); | ||||
|         else | ||||
|             this._keyPressHandler(keysym, backwards, action); | ||||
|  | ||||
|         return Clutter.EVENT_STOP; | ||||
|     }, | ||||
| @@ -250,7 +250,6 @@ const SwitcherPopup = new Lang.Class({ | ||||
|             Mainloop.source_remove(this._motionTimeoutId); | ||||
|  | ||||
|         this._motionTimeoutId = Mainloop.timeout_add(DISABLE_HOVER_TIMEOUT, Lang.bind(this, this._mouseTimedOut)); | ||||
|         GLib.Source.set_name_by_id(this._motionTimeoutId, '[gnome-shell] this._mouseTimedOut'); | ||||
|     }, | ||||
|  | ||||
|     _mouseTimedOut: function() { | ||||
|   | ||||
| @@ -53,10 +53,8 @@ function _wrapTweening(target, tweeningParameters) { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (!Gtk.Settings.get_default().gtk_enable_animations) { | ||||
|     if (!Gtk.Settings.get_default().gtk_enable_animations) | ||||
|         tweeningParameters['time'] = 0.000001; | ||||
|         tweeningParameters['delay'] = 0.000001; | ||||
|     } | ||||
|  | ||||
|     _addHandler(target, tweeningParameters, 'onComplete', _tweenCompleted); | ||||
| } | ||||
|   | ||||
| @@ -62,7 +62,7 @@ const UnlockDialog = new Lang.Class({ | ||||
|  | ||||
|         this.allowCancel = false; | ||||
|  | ||||
|         let screenSaverSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.screensaver' }); | ||||
|         let screenSaverSettings = new Gio.Settings({ schema: 'org.gnome.desktop.screensaver' }); | ||||
|         if (screenSaverSettings.get_boolean('user-switch-enabled')) { | ||||
|             let otherUserLabel = new St.Label({ text: _("Log in as another user"), | ||||
|                                                 style_class: 'login-dialog-not-listed-label' }); | ||||
|   | ||||
| @@ -19,8 +19,6 @@ const Search = imports.ui.search; | ||||
| const ShellEntry = imports.ui.shellEntry; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const WorkspacesView = imports.ui.workspacesView; | ||||
| const EdgeDragAction = imports.ui.edgeDragAction; | ||||
| const IconGrid = imports.ui.iconGrid; | ||||
|  | ||||
| const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings'; | ||||
|  | ||||
| @@ -51,74 +49,13 @@ function getTermsForSearchString(searchString) { | ||||
|     return terms; | ||||
| } | ||||
|  | ||||
| const ShowOverviewAction = new Lang.Class({ | ||||
|     Name: 'ShowOverviewAction', | ||||
|     Extends: Clutter.GestureAction, | ||||
|  | ||||
|     _init : function() { | ||||
|         this.parent(); | ||||
|         this.set_n_touch_points(3); | ||||
|  | ||||
|         global.display.connect('grab-op-begin', Lang.bind(this, function() { | ||||
|             this.cancel(); | ||||
|         })); | ||||
|     }, | ||||
|  | ||||
|     vfunc_gesture_prepare : function(action, actor) { | ||||
|         return this.get_n_current_points() == this.get_n_touch_points(); | ||||
|     }, | ||||
|  | ||||
|     _getBoundingRect : function(motion) { | ||||
|         let minX, minY, maxX, maxY; | ||||
|  | ||||
|         for (let i = 0; i < this.get_n_current_points(); i++) { | ||||
|             let x, y; | ||||
|  | ||||
|             if (motion == true) { | ||||
|                 [x, y] = this.get_motion_coords(i); | ||||
|             } else { | ||||
|                 [x, y] = this.get_press_coords(i); | ||||
|             } | ||||
|  | ||||
|             if (i == 0) { | ||||
|                 minX = maxX = x; | ||||
|                 minY = maxY = y; | ||||
|             } else { | ||||
|                 minX = Math.min(minX, x); | ||||
|                 minY = Math.min(minY, y); | ||||
|                 maxX = Math.max(maxX, x); | ||||
|                 maxY = Math.max(maxY, y); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return new Meta.Rectangle({ x: minX, | ||||
|                                     y: minY, | ||||
|                                     width: maxX - minX, | ||||
|                                     height: maxY - minY }); | ||||
|     }, | ||||
|  | ||||
|     vfunc_gesture_begin : function(action, actor) { | ||||
|         this._initialRect = this._getBoundingRect(false); | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     vfunc_gesture_end : function(action, actor) { | ||||
|         let rect = this._getBoundingRect(true); | ||||
|         let oldArea = this._initialRect.width * this._initialRect.height; | ||||
|         let newArea = rect.width * rect.height; | ||||
|         let areaDiff = newArea / oldArea; | ||||
|  | ||||
|         this.emit('activated', areaDiff); | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(ShowOverviewAction.prototype); | ||||
|  | ||||
| const ViewSelector = new Lang.Class({ | ||||
|     Name: 'ViewSelector', | ||||
|  | ||||
|     _init : function(searchEntry, showAppsButton) { | ||||
|         this.actor = new Shell.Stack({ name: 'viewSelector' }); | ||||
|  | ||||
|         this._showAppsBlocked = false; | ||||
|         this._showAppsButton = showAppsButton; | ||||
|         this._showAppsButton.connect('notify::checked', Lang.bind(this, this._onShowAppsButtonToggled)); | ||||
|  | ||||
| @@ -146,10 +83,10 @@ const ViewSelector = new Lang.Class({ | ||||
|                                                    icon_name: 'edit-find-symbolic' })); | ||||
|         if (this._entry.get_text_direction() == Clutter.TextDirection.RTL) | ||||
|             this._clearIcon = new St.Icon({ style_class: 'search-entry-icon', | ||||
|                                             icon_name: 'edit-clear-symbolic-rtl' }); | ||||
|                                             icon_name: 'edit-clear-rtl-symbolic' }); | ||||
|         else | ||||
|             this._clearIcon = new St.Icon({ style_class: 'search-entry-icon', | ||||
|                                             icon_name: 'edit-clear-symbolic-ltr' }); | ||||
|                                             icon_name: 'edit-clear-symbolic' }); | ||||
|  | ||||
|         this._iconClickedId = 0; | ||||
|         this._capturedEventId = 0; | ||||
| @@ -191,84 +128,56 @@ const ViewSelector = new Lang.Class({ | ||||
|                     this._stageKeyPressId = 0; | ||||
|                 } | ||||
|             })); | ||||
|         Main.overview.connect('shown', Lang.bind(this, | ||||
|             function() { | ||||
|                 // If we were animating from the desktop view to the | ||||
|                 // apps page the workspace page was visible, allowing | ||||
|                 // the windows to animate, but now we no longer want to | ||||
|                 // show it given that we are now on the apps page or | ||||
|                 // search page. | ||||
|                 if (this._activePage != this._workspacesPage) | ||||
|                     this._workspacesPage.opacity = 0; | ||||
|             })); | ||||
|  | ||||
|         Main.wm.addKeybinding('toggle-application-view', | ||||
|                               new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }), | ||||
|                               new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }), | ||||
|                               Meta.KeyBindingFlags.NONE, | ||||
|                               Shell.KeyBindingMode.NORMAL | | ||||
|                               Shell.KeyBindingMode.OVERVIEW, | ||||
|                               Lang.bind(this, this._toggleAppsPage)); | ||||
|  | ||||
|         Main.wm.addKeybinding('toggle-overview', | ||||
|                               new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }), | ||||
|                               new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }), | ||||
|                               Meta.KeyBindingFlags.NONE, | ||||
|                               Shell.KeyBindingMode.NORMAL | | ||||
|                               Shell.KeyBindingMode.OVERVIEW, | ||||
|                               Lang.bind(Main.overview, Main.overview.toggle)); | ||||
|  | ||||
|         let gesture; | ||||
|  | ||||
|         gesture = new EdgeDragAction.EdgeDragAction(St.Side.LEFT); | ||||
|         gesture.connect('activated', Lang.bind(this, function() { | ||||
|             if (Main.overview.visible) | ||||
|                 Main.overview.hide(); | ||||
|             else | ||||
|                 this.showApps(); | ||||
|         })); | ||||
|         global.stage.add_action(gesture); | ||||
|  | ||||
|         gesture = new ShowOverviewAction(); | ||||
|         gesture.connect('activated', Lang.bind(this, function(action, areaDiff) { | ||||
|             if (areaDiff < 0.7) | ||||
|                 Main.overview.show(); | ||||
|         })); | ||||
|         global.stage.add_action(gesture); | ||||
|     }, | ||||
|  | ||||
|     _toggleAppsPage: function() { | ||||
|         this._showAppsButton.checked = !this._showAppsButton.checked; | ||||
|         Main.overview.show(); | ||||
|         this._showAppsButton.checked = !this._showAppsButton.checked; | ||||
|     }, | ||||
|  | ||||
|     showApps: function() { | ||||
|         this._showAppsButton.checked = true; | ||||
|         Main.overview.show(); | ||||
|         this._showAppsButton.checked = true; | ||||
|     }, | ||||
|  | ||||
|     show: function() { | ||||
|         this.reset(); | ||||
|         this._workspacesDisplay.show(this._showAppsButton.checked); | ||||
|  | ||||
|         this._showAppsBlocked = true; | ||||
|         this._showAppsButton.checked = false; | ||||
|         this._showAppsBlocked = false; | ||||
|  | ||||
|         this._workspacesPage.opacity = 255; | ||||
|         this._workspacesDisplay.show(); | ||||
|         this._activePage = null; | ||||
|         if (this._showAppsButton.checked) | ||||
|             this._showPage(this._appsPage); | ||||
|         else | ||||
|             this._showPage(this._workspacesPage); | ||||
|         this._syncActivePage(); | ||||
|  | ||||
|         if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows()) | ||||
|             Main.overview.fadeOutDesktop(); | ||||
|     }, | ||||
|  | ||||
|     animateFromOverview: function() { | ||||
|         // Make sure workspace page is fully visible to allow | ||||
|         // workspace.js do the animation of the windows | ||||
|         this._workspacesPage.opacity = 255; | ||||
|  | ||||
|         this._workspacesDisplay.animateFromOverview(this._activePage != this._workspacesPage); | ||||
|  | ||||
|         this._showAppsButton.checked = false; | ||||
|  | ||||
|     leaveOverview: function() { | ||||
|         if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows()) | ||||
|             Main.overview.fadeInDesktop(); | ||||
|  | ||||
|         // If we're not on the windows page, don't zoom back the primary monitor. | ||||
|         let zoomPrimary = (this._activePage == this._workspacesPage); | ||||
|         this._workspacesDisplay.leaveOverview(zoomPrimary); | ||||
|     }, | ||||
|  | ||||
|     setWorkspacesFullGeometry: function(geom) { | ||||
| @@ -277,12 +186,16 @@ const ViewSelector = new Lang.Class({ | ||||
|  | ||||
|     hide: function() { | ||||
|         this._workspacesDisplay.hide(); | ||||
|         if (this._activePage) | ||||
|             this._activePage.hide(); | ||||
|         this._activePage = null; | ||||
|     }, | ||||
|  | ||||
|     _addPage: function(actor, name, a11yIcon, params) { | ||||
|         params = Params.parse(params, { a11yFocus: null }); | ||||
|  | ||||
|         let page = new St.Bin({ child: actor, | ||||
|                                 visible: false, | ||||
|                                 x_align: St.Align.START, | ||||
|                                 y_align: St.Align.START, | ||||
|                                 x_fill: true, | ||||
| @@ -302,7 +215,13 @@ const ViewSelector = new Lang.Class({ | ||||
|         return page; | ||||
|     }, | ||||
|  | ||||
|     _fadePageIn: function() { | ||||
|     _fadePageIn: function(oldPage) { | ||||
|         if (oldPage) | ||||
|             oldPage.hide(); | ||||
|  | ||||
|         this.emit('page-empty'); | ||||
|         this._activePage.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); | ||||
|         this._activePage.show(); | ||||
|         Tweener.addTween(this._activePage, | ||||
|                          { opacity: 255, | ||||
|                            time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME, | ||||
| @@ -310,53 +229,7 @@ const ViewSelector = new Lang.Class({ | ||||
|                          }); | ||||
|     }, | ||||
|  | ||||
|     _fadePageOut: function(page) { | ||||
|         let oldPage = page; | ||||
|         Tweener.addTween(page, | ||||
|                          { opacity: 0, | ||||
|                            time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME, | ||||
|                            transition: 'easeOutQuad', | ||||
|                            onComplete: Lang.bind(this, function() { | ||||
|                                this._animateIn(oldPage); | ||||
|                            }) | ||||
|                          }); | ||||
|     }, | ||||
|  | ||||
|     _animateIn: function(oldPage) { | ||||
|         if (oldPage) | ||||
|             oldPage.hide(); | ||||
|  | ||||
|         this.emit('page-empty'); | ||||
|  | ||||
|         this._activePage.show(); | ||||
|  | ||||
|         if (this._activePage == this._appsPage && oldPage == this._workspacesPage) { | ||||
|             // Restore opacity, in case we animated via _fadePageOut | ||||
|             this._activePage.opacity = 255; | ||||
|             this.appDisplay.animate(IconGrid.AnimationDirection.IN); | ||||
|         } else { | ||||
|             this._fadePageIn(); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _animateOut: function(page) { | ||||
|         let oldPage = page; | ||||
|         if (page == this._appsPage && | ||||
|             this._activePage == this._workspacesPage && | ||||
|             !Main.overview.animationInProgress) { | ||||
|             this.appDisplay.animate(IconGrid.AnimationDirection.OUT, Lang.bind(this, | ||||
|                 function() { | ||||
|                     this._animateIn(oldPage) | ||||
|                 })); | ||||
|         } else { | ||||
|             this._fadePageOut(page); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _showPage: function(page) { | ||||
|         if (!Main.overview.visible) | ||||
|             return; | ||||
|  | ||||
|     _setActivePage: function(page) { | ||||
|         if (page == this._activePage) | ||||
|             return; | ||||
|  | ||||
| @@ -365,9 +238,17 @@ const ViewSelector = new Lang.Class({ | ||||
|         this.emit('page-changed'); | ||||
|  | ||||
|         if (oldPage) | ||||
|             this._animateOut(oldPage) | ||||
|             Tweener.addTween(oldPage, | ||||
|                              { opacity: 0, | ||||
|                                time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME, | ||||
|                                transition: 'easeOutQuad', | ||||
|                                onComplete: Lang.bind(this, | ||||
|                                    function() { | ||||
|                                        this._fadePageIn(oldPage); | ||||
|                                    }) | ||||
|                              }); | ||||
|         else | ||||
|             this._animateIn(); | ||||
|             this._fadePageIn(oldPage); | ||||
|     }, | ||||
|  | ||||
|     _a11yFocusPage: function(page) { | ||||
| @@ -375,9 +256,25 @@ const ViewSelector = new Lang.Class({ | ||||
|         page.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); | ||||
|     }, | ||||
|  | ||||
|     _getActivePage: function() { | ||||
|         if (this._searchActive) | ||||
|             return this._searchPage; | ||||
|         else if (this._showAppsButton.checked) | ||||
|             return this._appsPage; | ||||
|         else | ||||
|             return this._workspacesPage; | ||||
|     }, | ||||
|  | ||||
|     _syncActivePage: function() { | ||||
|         let activePage = this._getActivePage(); | ||||
|         if (activePage == this._activePage) | ||||
|             return; | ||||
|         this._setActivePage(activePage); | ||||
|     }, | ||||
|  | ||||
|     _onShowAppsButtonToggled: function() { | ||||
|         this._showPage(this._showAppsButton.checked ? | ||||
|                        this._appsPage : this._workspacesPage); | ||||
|         if (!this._showAppsBlocked) | ||||
|             this._syncActivePage(); | ||||
|     }, | ||||
|  | ||||
|     _onStageKeyPress: function(actor, event) { | ||||
| @@ -399,32 +296,10 @@ const ViewSelector = new Lang.Class({ | ||||
|             return Clutter.EVENT_STOP; | ||||
|         } else if (this._shouldTriggerSearch(symbol)) { | ||||
|             this.startSearch(event); | ||||
|         } else if (!this._searchActive && !global.stage.key_focus) { | ||||
|             if (symbol == Clutter.Tab || symbol == Clutter.Down) { | ||||
|                 this._activePage.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); | ||||
|                 return Clutter.EVENT_STOP; | ||||
|             } else if (symbol == Clutter.ISO_Left_Tab) { | ||||
|                 this._activePage.navigate_focus(null, Gtk.DirectionType.TAB_BACKWARD, false); | ||||
|                 return Clutter.EVENT_STOP; | ||||
|             } | ||||
|         } | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     }, | ||||
|  | ||||
|     _searchCancelled: function() { | ||||
|         this._showPage(this._showAppsButton.checked ? this._appsPage | ||||
|                                                     : this._workspacesPage); | ||||
|  | ||||
|         // Leave the entry focused when it doesn't have any text; | ||||
|         // when replacing a selected search term, Clutter emits | ||||
|         // two 'text-changed' signals, one for deleting the previous | ||||
|         // text and one for the new one - the second one is handled | ||||
|         // incorrectly when we remove focus | ||||
|         // (https://bugzilla.gnome.org/show_bug.cgi?id=636341) */ | ||||
|         if (this._text.text != '') | ||||
|             this.reset(); | ||||
|     }, | ||||
|  | ||||
|     reset: function () { | ||||
|         global.stage.set_key_focus(null); | ||||
|  | ||||
| @@ -475,10 +350,7 @@ const ViewSelector = new Lang.Class({ | ||||
|  | ||||
|     startSearch: function(event) { | ||||
|         global.stage.set_key_focus(this._text); | ||||
|  | ||||
|         let synthEvent = event.copy(); | ||||
|         synthEvent.set_source(this._text); | ||||
|         this._text.event(synthEvent, true); | ||||
|         this._text.event(event, true); | ||||
|     }, | ||||
|  | ||||
|     // the entry does not show the hint | ||||
| @@ -503,11 +375,9 @@ const ViewSelector = new Lang.Class({ | ||||
|                 this._iconClickedId = this._entry.connect('secondary-icon-clicked', | ||||
|                     Lang.bind(this, this.reset)); | ||||
|  | ||||
|             if (this._searchTimeoutId == 0) { | ||||
|             if (this._searchTimeoutId == 0) | ||||
|                 this._searchTimeoutId = Mainloop.timeout_add(150, | ||||
|                     Lang.bind(this, this._doSearch)); | ||||
|                 GLib.Source.set_name_by_id(this._searchTimeoutId, '[gnome-shell] this._doSearch'); | ||||
|             } | ||||
|         } else { | ||||
|             if (this._iconClickedId > 0) { | ||||
|                 this._entry.disconnect(this._iconClickedId); | ||||
| @@ -520,8 +390,18 @@ const ViewSelector = new Lang.Class({ | ||||
|             } | ||||
|  | ||||
|             this._entry.set_secondary_icon(null); | ||||
|             this._searchCancelled(); | ||||
|  | ||||
|             // Leave the entry focused when it doesn't have any text; | ||||
|             // when replacing a selected search term, Clutter emits | ||||
|             // two 'text-changed' signals, one for deleting the previous | ||||
|             // text and one for the new one - the second one is handled | ||||
|             // incorrectly when we remove focus | ||||
|             // (https://bugzilla.gnome.org/show_bug.cgi?id=636341) */ | ||||
|             if (this._text.text != '') | ||||
|                 this.reset(); | ||||
|         } | ||||
|  | ||||
|         this._syncActivePage(); | ||||
|     }, | ||||
|  | ||||
|     _onKeyPress: function(entry, event) { | ||||
| @@ -588,9 +468,7 @@ const ViewSelector = new Lang.Class({ | ||||
|         this._searchTimeoutId = 0; | ||||
|  | ||||
|         let terms = getTermsForSearchString(this._entry.get_text()); | ||||
|  | ||||
|         this._searchResults.setTerms(terms); | ||||
|         this._showPage(this._searchPage); | ||||
|  | ||||
|         return GLib.SOURCE_REMOVE; | ||||
|     }, | ||||
|   | ||||
| @@ -9,24 +9,14 @@ const Meta = imports.gi.Meta; | ||||
| const Pango = imports.gi.Pango; | ||||
| const St = imports.gi.St; | ||||
| const Shell = imports.gi.Shell; | ||||
| const Signals = imports.signals; | ||||
|  | ||||
| const AltTab = imports.ui.altTab; | ||||
| const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup; | ||||
| const Main = imports.ui.main; | ||||
| const ModalDialog = imports.ui.modalDialog; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const WindowMenu = imports.ui.windowMenu; | ||||
| const Wobbly = imports.ui.wobbly; | ||||
|  | ||||
| const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings'; | ||||
| const MAXIMIZE_WINDOW_ANIMATION_TIME = 0.15; | ||||
| const UNMAXIMIZE_WINDOW_ANIMATION_TIME = 0.15; | ||||
| const MINIMIZE_WINDOW_ANIMATION_TIME = 0.2; | ||||
| const SHOW_WINDOW_ANIMATION_TIME = 0.15; | ||||
| const DIALOG_SHOW_WINDOW_ANIMATION_TIME = 0.1; | ||||
| const DESTROY_WINDOW_ANIMATION_TIME = 0.15; | ||||
| const DIALOG_DESTROY_WINDOW_ANIMATION_TIME = 0.1; | ||||
| const WINDOW_ANIMATION_TIME = 0.25; | ||||
| const DIM_BRIGHTNESS = -0.3; | ||||
| const DIM_TIME = 0.500; | ||||
| @@ -92,7 +82,6 @@ const DisplayChangeDialog = new Lang.Class({ | ||||
|                                         { expand: false, x_fill: false, x_align: St.Align.END }); | ||||
|  | ||||
|         this._timeoutId = Mainloop.timeout_add(ONE_SECOND, Lang.bind(this, this._tick)); | ||||
|         GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] this._tick'); | ||||
|     }, | ||||
|  | ||||
|     close: function(timestamp) { | ||||
| @@ -202,25 +191,17 @@ const WorkspaceTracker = new Lang.Class({ | ||||
|         tracker.connect('startup-sequence-changed', Lang.bind(this, this._queueCheckWorkspaces)); | ||||
|  | ||||
|         global.screen.connect('notify::n-workspaces', Lang.bind(this, this._nWorkspacesChanged)); | ||||
|         global.window_manager.connect('switch-workspace', Lang.bind(this, this._queueCheckWorkspaces)); | ||||
|  | ||||
|         global.screen.connect('window-entered-monitor', Lang.bind(this, this._windowEnteredMonitor)); | ||||
|         global.screen.connect('window-left-monitor', Lang.bind(this, this._windowLeftMonitor)); | ||||
|         global.screen.connect('restacked', Lang.bind(this, this._windowsRestacked)); | ||||
|  | ||||
|         this._workspaceSettings = this._getWorkspaceSettings(); | ||||
|         this._workspaceSettings = new Gio.Settings({ schema: Main.dynamicWorkspacesSchema }); | ||||
|         this._workspaceSettings.connect('changed::dynamic-workspaces', Lang.bind(this, this._queueCheckWorkspaces)); | ||||
|  | ||||
|         this._nWorkspacesChanged(); | ||||
|     }, | ||||
|  | ||||
|     _getWorkspaceSettings: function() { | ||||
|         let settings = global.get_overrides_settings(); | ||||
|         if (settings.list_keys().indexOf('dynamic-workspaces') > -1) | ||||
|             return settings; | ||||
|         return new Gio.Settings({ schema_id: 'org.gnome.mutter' }); | ||||
|     }, | ||||
|  | ||||
|     _checkWorkspaces: function() { | ||||
|         let i; | ||||
|         let emptyWorkspaces = []; | ||||
| @@ -268,7 +249,13 @@ const WorkspaceTracker = new Lang.Class({ | ||||
|         } | ||||
|  | ||||
|         let activeWorkspaceIndex = global.screen.get_active_workspace_index(); | ||||
|         emptyWorkspaces[activeWorkspaceIndex] = false; | ||||
|         let removingCurrentWorkspace = (emptyWorkspaces[activeWorkspaceIndex] && | ||||
|                                         activeWorkspaceIndex < emptyWorkspaces.length - 1); | ||||
|  | ||||
|         if (removingCurrentWorkspace) { | ||||
|             // "Merge" the empty workspace we are removing with the one at the end | ||||
|             this._wm.blockAnimations(); | ||||
|         } | ||||
|  | ||||
|         // Delete other empty workspaces; do it from the end to avoid index changes | ||||
|         for (i = emptyWorkspaces.length - 2; i >= 0; i--) { | ||||
| @@ -276,6 +263,11 @@ const WorkspaceTracker = new Lang.Class({ | ||||
|                 global.screen.remove_workspace(this._workspaces[i], global.get_current_time()); | ||||
|         } | ||||
|  | ||||
|         if (removingCurrentWorkspace) { | ||||
|             global.screen.get_workspace_by_index(global.screen.n_workspaces - 1).activate(global.get_current_time()); | ||||
|             this._wm.unblockAnimations(); | ||||
|         } | ||||
|  | ||||
|         this._checkWorkspacesId = 0; | ||||
|         return false; | ||||
|     }, | ||||
| @@ -289,20 +281,18 @@ const WorkspaceTracker = new Lang.Class({ | ||||
|             this._queueCheckWorkspaces(); | ||||
|             return GLib.SOURCE_REMOVE; | ||||
|         })); | ||||
|         GLib.Source.set_name_by_id(workspace._keepAliveId, '[gnome-shell] this._queueCheckWorkspaces'); | ||||
|     }, | ||||
|  | ||||
|     _windowRemoved: function(workspace, window) { | ||||
|         workspace._lastRemovedWindow = window; | ||||
|         this._queueCheckWorkspaces(); | ||||
|         let id = Mainloop.timeout_add(LAST_WINDOW_GRACE_TIME, Lang.bind(this, function() { | ||||
|         Mainloop.timeout_add(LAST_WINDOW_GRACE_TIME, Lang.bind(this, function() { | ||||
|             if (workspace._lastRemovedWindow == window) { | ||||
|                 workspace._lastRemovedWindow = null; | ||||
|                 this._queueCheckWorkspaces(); | ||||
|             } | ||||
|             return GLib.SOURCE_REMOVE; | ||||
|         })); | ||||
|         GLib.Source.set_name_by_id(id, '[gnome-shell] this._queueCheckWorkspaces'); | ||||
|     }, | ||||
|  | ||||
|     _windowLeftMonitor: function(metaScreen, monitorIndex, metaWin) { | ||||
| @@ -378,202 +368,6 @@ const WorkspaceTracker = new Lang.Class({ | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const TilePreview = new Lang.Class({ | ||||
|     Name: 'TilePreview', | ||||
|  | ||||
|     _init: function() { | ||||
|         this.actor = new St.Widget(); | ||||
|         global.window_group.add_actor(this.actor); | ||||
|  | ||||
|         this._reset(); | ||||
|         this._showing = false; | ||||
|     }, | ||||
|  | ||||
|     show: function(window, tileRect, monitorIndex) { | ||||
|         let windowActor = window.get_compositor_private(); | ||||
|         if (!windowActor) | ||||
|             return; | ||||
|  | ||||
|         global.window_group.set_child_below_sibling(this.actor, windowActor); | ||||
|  | ||||
|         if (this._rect && this._rect.equal(tileRect)) | ||||
|             return; | ||||
|  | ||||
|         let changeMonitor = (this._monitorIndex == -1 || | ||||
|                              this._monitorIndex != monitorIndex); | ||||
|  | ||||
|         this._monitorIndex = monitorIndex; | ||||
|         this._rect = tileRect; | ||||
|  | ||||
|         let monitor = Main.layoutManager.monitors[monitorIndex]; | ||||
|  | ||||
|         this._updateStyle(monitor); | ||||
|  | ||||
|         if (!this._showing || changeMonitor) { | ||||
|             let monitorRect = new Meta.Rectangle({ x: monitor.x, | ||||
|                                                    y: monitor.y, | ||||
|                                                    width: monitor.width, | ||||
|                                                    height: monitor.height }); | ||||
|             let [, rect] = window.get_outer_rect().intersect(monitorRect); | ||||
|             this.actor.set_size(rect.width, rect.height); | ||||
|             this.actor.set_position(rect.x, rect.y); | ||||
|             this.actor.opacity = 0; | ||||
|         } | ||||
|  | ||||
|         this._showing = true; | ||||
|         this.actor.show(); | ||||
|         Tweener.addTween(this.actor, | ||||
|                          { x: tileRect.x, | ||||
|                            y: tileRect.y, | ||||
|                            width: tileRect.width, | ||||
|                            height: tileRect.height, | ||||
|                            opacity: 255, | ||||
|                            time: WINDOW_ANIMATION_TIME, | ||||
|                            transition: 'easeOutQuad' | ||||
|                          }); | ||||
|     }, | ||||
|  | ||||
|     hide: function() { | ||||
|         if (!this._showing) | ||||
|             return; | ||||
|  | ||||
|         this._showing = false; | ||||
|         Tweener.addTween(this.actor, | ||||
|                          { opacity: 0, | ||||
|                            time: WINDOW_ANIMATION_TIME, | ||||
|                            transition: 'easeOutQuad', | ||||
|                            onComplete: Lang.bind(this, this._reset) | ||||
|                          }); | ||||
|     }, | ||||
|  | ||||
|     _reset: function() { | ||||
|         this.actor.hide(); | ||||
|         this._rect = null; | ||||
|         this._monitorIndex = -1; | ||||
|     }, | ||||
|  | ||||
|     _updateStyle: function(monitor) { | ||||
|         let styles = ['tile-preview']; | ||||
|         if (this._monitorIndex == Main.layoutManager.primaryIndex) | ||||
|             styles.push('on-primary'); | ||||
|         if (this._rect.x == monitor.x) | ||||
|             styles.push('tile-preview-left'); | ||||
|         if (this._rect.x + this._rect.width == monitor.x + monitor.width) | ||||
|             styles.push('tile-preview-right'); | ||||
|  | ||||
|         this.actor.style_class = styles.join(' '); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const WorkspaceSwitchAction = new Lang.Class({ | ||||
|     Name: 'WorkspaceSwitchAction', | ||||
|     Extends: Clutter.GestureAction, | ||||
|  | ||||
|     _init : function() { | ||||
|         this.parent(); | ||||
|         this.set_n_touch_points(4); | ||||
|  | ||||
|         global.display.connect('grab-op-begin', Lang.bind(this, function() { | ||||
|             this.cancel(); | ||||
|         })); | ||||
|     }, | ||||
|  | ||||
|     vfunc_gesture_prepare : function(action, actor) { | ||||
|         return this.get_n_current_points() == this.get_n_touch_points(); | ||||
|     }, | ||||
|  | ||||
|     vfunc_gesture_end : function(action, actor) { | ||||
|         const MOTION_THRESHOLD = 50; | ||||
|  | ||||
|         // Just check one touchpoint here | ||||
|         let [startX, startY] = this.get_press_coords(0); | ||||
|         let [x, y] = this.get_motion_coords(0); | ||||
|         let offsetX = x - startX; | ||||
|         let offsetY = y - startY; | ||||
|         let direction; | ||||
|  | ||||
|         if (Math.abs(offsetX) < MOTION_THRESHOLD && | ||||
|             Math.abs(offsetY) < MOTION_THRESHOLD) | ||||
|             return; | ||||
|  | ||||
|         if (Math.abs(offsetY) > Math.abs(offsetX)) { | ||||
|             if (offsetY > 0) | ||||
|                 direction = Meta.MotionDirection.UP; | ||||
|             else | ||||
|                 direction = Meta.MotionDirection.DOWN; | ||||
|         } else { | ||||
|             if (offsetX > 0) | ||||
|                 direction = Meta.MotionDirection.LEFT; | ||||
|             else | ||||
|                 direction = Meta.MotionDirection.RIGHT; | ||||
|         } | ||||
|  | ||||
|         this.emit('activated', direction); | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(WorkspaceSwitchAction.prototype); | ||||
|  | ||||
| const AppSwitchAction = new Lang.Class({ | ||||
|     Name: 'AppSwitchAction', | ||||
|     Extends: Clutter.GestureAction, | ||||
|  | ||||
|     _init : function() { | ||||
|         this.parent(); | ||||
|         this.set_n_touch_points(3); | ||||
|  | ||||
|         global.display.connect('grab-op-begin', Lang.bind(this, function() { | ||||
|             this.cancel(); | ||||
|         })); | ||||
|     }, | ||||
|  | ||||
|     vfunc_gesture_prepare : function(action, actor) { | ||||
|         return this.get_n_current_points() <= 4; | ||||
|     }, | ||||
|  | ||||
|     vfunc_gesture_begin : function(action, actor) { | ||||
|         // in milliseconds | ||||
|         const LONG_PRESS_TIMEOUT = 250; | ||||
|  | ||||
|         let nPoints = this.get_n_current_points(); | ||||
|         let event = this.get_last_event (nPoints - 1); | ||||
|  | ||||
|         if (nPoints == 3) | ||||
|             this._longPressStartTime = event.get_time(); | ||||
|         else if (nPoints == 4) { | ||||
|             // Check whether the 4th finger press happens after a 3-finger long press, | ||||
|             // this only needs to be checked on the first 4th finger press | ||||
|             if (this._longPressStartTime != null && | ||||
|                 event.get_time() < this._longPressStartTime + LONG_PRESS_TIMEOUT) | ||||
|                 this.cancel(); | ||||
|             else { | ||||
|                 this._longPressStartTime = null; | ||||
|                 this.emit('activated'); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return this.get_n_current_points() <= 4; | ||||
|     }, | ||||
|  | ||||
|     vfunc_gesture_progress : function(action, actor) { | ||||
|         const MOTION_THRESHOLD = 30; | ||||
|  | ||||
|         if (this.get_n_current_points() == 3) { | ||||
|             for (let i = 0; i < this.get_n_current_points(); i++) { | ||||
|                 [startX, startY] = this.get_press_coords(i); | ||||
|                 [x, y] = this.get_motion_coords(i); | ||||
|  | ||||
|                 if (Math.abs(x - startX) > MOTION_THRESHOLD || | ||||
|                     Math.abs(y - startY) > MOTION_THRESHOLD) | ||||
|                     return false; | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(AppSwitchAction.prototype); | ||||
|  | ||||
| const WindowManager = new Lang.Class({ | ||||
|     Name: 'WindowManager', | ||||
|  | ||||
| @@ -589,6 +383,8 @@ const WindowManager = new Lang.Class({ | ||||
|  | ||||
|         this._dimmedWindows = []; | ||||
|  | ||||
|         this._animationBlockCount = 0; | ||||
|  | ||||
|         this._allowedKeybindings = {}; | ||||
|  | ||||
|         this._switchData = null; | ||||
| @@ -602,9 +398,6 @@ const WindowManager = new Lang.Class({ | ||||
|         })); | ||||
|  | ||||
|         this._shellwm.connect('switch-workspace', Lang.bind(this, this._switchWorkspace)); | ||||
|         this._shellwm.connect('show-tile-preview', Lang.bind(this, this._showTilePreview)); | ||||
|         this._shellwm.connect('hide-tile-preview', Lang.bind(this, this._hideTilePreview)); | ||||
|         this._shellwm.connect('show-window-menu', Lang.bind(this, this._showWindowMenu)); | ||||
|         this._shellwm.connect('minimize', Lang.bind(this, this._minimizeWindow)); | ||||
|         this._shellwm.connect('maximize', Lang.bind(this, this._maximizeWindow)); | ||||
|         this._shellwm.connect('unmaximize', Lang.bind(this, this._unmaximizeWindow)); | ||||
| @@ -614,8 +407,6 @@ const WindowManager = new Lang.Class({ | ||||
|         this._shellwm.connect('confirm-display-change', Lang.bind(this, this._confirmDisplayChange)); | ||||
|  | ||||
|         this._workspaceSwitcherPopup = null; | ||||
|         this._tilePreview = null; | ||||
|  | ||||
|         this.setCustomKeybindingHandler('switch-to-workspace-left', | ||||
|                                         Shell.KeyBindingMode.NORMAL | | ||||
|                                         Shell.KeyBindingMode.OVERVIEW, | ||||
| @@ -632,10 +423,6 @@ const WindowManager = new Lang.Class({ | ||||
|                                         Shell.KeyBindingMode.NORMAL | | ||||
|                                         Shell.KeyBindingMode.OVERVIEW, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-to-workspace-last', | ||||
|                                         Shell.KeyBindingMode.NORMAL | | ||||
|                                         Shell.KeyBindingMode.OVERVIEW, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('move-to-workspace-left', | ||||
|                                         Shell.KeyBindingMode.NORMAL | | ||||
|                                         Shell.KeyBindingMode.OVERVIEW, | ||||
| @@ -736,9 +523,6 @@ const WindowManager = new Lang.Class({ | ||||
|         this.setCustomKeybindingHandler('move-to-workspace-12', | ||||
|                                         Shell.KeyBindingMode.NORMAL, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('move-to-workspace-last', | ||||
|                                         Shell.KeyBindingMode.NORMAL, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-applications', | ||||
|                                         Shell.KeyBindingMode.NORMAL, | ||||
|                                         Lang.bind(this, this._startAppSwitcher)); | ||||
| @@ -773,13 +557,13 @@ const WindowManager = new Lang.Class({ | ||||
|                                         Lang.bind(this, this._startA11ySwitcher)); | ||||
|  | ||||
|         this.addKeybinding('pause-resume-tweens', | ||||
|                            new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }), | ||||
|                            new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }), | ||||
|                            Meta.KeyBindingFlags.NONE, | ||||
|                            Shell.KeyBindingMode.ALL, | ||||
|                            Lang.bind(this, this._toggleTweens)); | ||||
|  | ||||
|         this.addKeybinding('open-application-menu', | ||||
|                            new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }), | ||||
|                            new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }), | ||||
|                            Meta.KeyBindingFlags.NONE, | ||||
|                            Shell.KeyBindingMode.NORMAL | | ||||
|                            Shell.KeyBindingMode.TOPBAR_POPUP, | ||||
| @@ -794,62 +578,11 @@ const WindowManager = new Lang.Class({ | ||||
|                 this._dimWindow(this._dimmedWindows[i]); | ||||
|         })); | ||||
|  | ||||
|         this._windowMenuManager = new WindowMenu.WindowMenuManager(); | ||||
|  | ||||
|         if (Main.sessionMode.hasWorkspaces) | ||||
|             this._workspaceTracker = new WorkspaceTracker(this); | ||||
|  | ||||
|         global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT, | ||||
|                                                 false, -1, 1); | ||||
|  | ||||
|         let gesture = new WorkspaceSwitchAction(); | ||||
|         gesture.connect('activated', Lang.bind(this, function(action, direction) { | ||||
|             let newWs = global.screen.get_active_workspace().get_neighbor(direction); | ||||
|             this.actionMoveWorkspace(newWs); | ||||
|         })); | ||||
|         global.stage.add_action(gesture); | ||||
|  | ||||
|         gesture = new AppSwitchAction(); | ||||
|         gesture.connect('activated', Lang.bind(this, this._switchApp)); | ||||
|         global.stage.add_action(gesture); | ||||
|  | ||||
|         this._wobblyWindows = new Wobbly.WobblyWindowManager(); | ||||
|     }, | ||||
|  | ||||
|     _lookupIndex: function (windows, metaWindow) { | ||||
|         for (let i = 0; i < windows.length; i++) { | ||||
|             if (windows[i].metaWindow == metaWindow) { | ||||
|                 return i; | ||||
|             } | ||||
|         } | ||||
|         return -1; | ||||
|     }, | ||||
|  | ||||
|     _switchApp : function () { | ||||
|         let windows = global.get_window_actors().filter(Lang.bind(this, function(actor) { | ||||
|             let win = actor.metaWindow; | ||||
|             return (!win.is_override_redirect() && | ||||
|                     win.located_on_workspace(global.screen.get_active_workspace())); | ||||
|         })); | ||||
|  | ||||
|         if (windows.length == 0) | ||||
|             return; | ||||
|  | ||||
|         let focusWindow = global.display.focus_window; | ||||
|         let nextWindow; | ||||
|  | ||||
|         if (focusWindow == null) | ||||
|             nextWindow = windows[0].metaWindow; | ||||
|         else { | ||||
|             let index = this._lookupIndex (windows, focusWindow) + 1; | ||||
|  | ||||
|             if (index >= windows.length) | ||||
|                 index = 0; | ||||
|  | ||||
|             nextWindow = windows[index].metaWindow; | ||||
|         } | ||||
|  | ||||
|         Main.activateWindow(nextWindow); | ||||
|     }, | ||||
|  | ||||
|     keepWorkspaceAlive: function(workspace, duration) { | ||||
| @@ -880,16 +613,24 @@ const WindowManager = new Lang.Class({ | ||||
|         this._allowedKeybindings[name] = modes; | ||||
|     }, | ||||
|  | ||||
|     _shouldAnimate: function() { | ||||
|         return !Main.overview.visible; | ||||
|     blockAnimations: function() { | ||||
|         this._animationBlockCount++; | ||||
|     }, | ||||
|  | ||||
|     _shouldAnimateActor: function(actor, types) { | ||||
|     unblockAnimations: function() { | ||||
|         this._animationBlockCount = Math.max(0, this._animationBlockCount - 1); | ||||
|     }, | ||||
|  | ||||
|     _shouldAnimate: function() { | ||||
|         return !(Main.overview.visible || this._animationBlockCount > 0); | ||||
|     }, | ||||
|  | ||||
|     _shouldAnimateActor: function(actor) { | ||||
|         if (!this._shouldAnimate()) | ||||
|             return false; | ||||
|  | ||||
|         let type = actor.meta_window.get_window_type(); | ||||
|         return types.indexOf(type) >= 0; | ||||
|         let windowType = actor.meta_window.get_window_type(); | ||||
|         return windowType == Meta.WindowType.NORMAL || | ||||
|             windowType == Meta.WindowType.MODAL_DIALOG; | ||||
|     }, | ||||
|  | ||||
|     _removeEffect : function(list, actor) { | ||||
| @@ -902,10 +643,7 @@ const WindowManager = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _minimizeWindow : function(shellwm, actor) { | ||||
|         let types = [Meta.WindowType.NORMAL, | ||||
|                      Meta.WindowType.MODAL_DIALOG, | ||||
|                      Meta.WindowType.DIALOG]; | ||||
|         if (!this._shouldAnimateActor(actor, types)) { | ||||
|         if (!this._shouldAnimateActor(actor)) { | ||||
|             shellwm.completed_minimize(actor); | ||||
|             return; | ||||
|         } | ||||
| @@ -917,7 +655,7 @@ const WindowManager = new Lang.Class({ | ||||
|         if (actor.meta_window.is_monitor_sized()) { | ||||
|             Tweener.addTween(actor, | ||||
|                          { opacity: 0, | ||||
|                            time: MINIMIZE_WINDOW_ANIMATION_TIME, | ||||
|                            time: WINDOW_ANIMATION_TIME, | ||||
|                            transition: 'easeOutQuad', | ||||
|                            onComplete: this._minimizeWindowDone, | ||||
|                            onCompleteScope: this, | ||||
| @@ -949,8 +687,8 @@ const WindowManager = new Lang.Class({ | ||||
|                                scale_y: yScale, | ||||
|                                x: xDest, | ||||
|                                y: yDest, | ||||
|                                time: MINIMIZE_WINDOW_ANIMATION_TIME, | ||||
|                                transition: 'easeInExpo', | ||||
|                                time: WINDOW_ANIMATION_TIME, | ||||
|                                transition: 'easeOutQuad', | ||||
|                                onComplete: this._minimizeWindowDone, | ||||
|                                onCompleteScope: this, | ||||
|                                onCompleteParams: [shellwm, actor], | ||||
| @@ -966,7 +704,7 @@ const WindowManager = new Lang.Class({ | ||||
|             Tweener.removeTweens(actor); | ||||
|             actor.set_scale(1.0, 1.0); | ||||
|             actor.set_opacity(255); | ||||
|             actor.set_pivot_point(0, 0); | ||||
|             actor.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_WEST); | ||||
|  | ||||
|             shellwm.completed_minimize(actor); | ||||
|         } | ||||
| @@ -1064,10 +802,7 @@ const WindowManager = new Lang.Class({ | ||||
|             actor._windowType = type; | ||||
|         })); | ||||
|  | ||||
|         let types = [Meta.WindowType.NORMAL, | ||||
|                      Meta.WindowType.DIALOG, | ||||
|                      Meta.WindowType.MODAL_DIALOG]; | ||||
|         if (!this._shouldAnimateActor(actor, types)) { | ||||
|         if (!this._shouldAnimateActor(actor)) { | ||||
|             shellwm.completed_map(actor); | ||||
|             return; | ||||
|         } | ||||
| @@ -1075,23 +810,15 @@ const WindowManager = new Lang.Class({ | ||||
|         if (actor.meta_window.is_attached_dialog()) { | ||||
|             /* Scale the window from the center of the parent */ | ||||
|             this._checkDimming(actor.get_meta_window().get_transient_for()); | ||||
|         } | ||||
|  | ||||
|         switch (actor._windowType) { | ||||
|         case Meta.WindowType.NORMAL: | ||||
|             actor.set_pivot_point(0.5, 1.0); | ||||
|             actor.scale_x = 0.01; | ||||
|             actor.scale_y = 0.05; | ||||
|             actor.opacity = 0; | ||||
|             actor.set_scale(1.0, 0.0); | ||||
|             actor.scale_gravity = Clutter.Gravity.CENTER; | ||||
|             actor.show(); | ||||
|             this._mapping.push(actor); | ||||
|  | ||||
|             Tweener.addTween(actor, | ||||
|                              { opacity: 255, | ||||
|                                scale_x: 1, | ||||
|                                scale_y: 1, | ||||
|                                time: SHOW_WINDOW_ANIMATION_TIME, | ||||
|                                transition: 'easeOutExpo', | ||||
|                              { scale_y: 1, | ||||
|                                time: WINDOW_ANIMATION_TIME, | ||||
|                                transition: "easeOutQuad", | ||||
|                                onComplete: this._mapWindowDone, | ||||
|                                onCompleteScope: this, | ||||
|                                onCompleteParams: [shellwm, actor], | ||||
| @@ -1099,20 +826,15 @@ const WindowManager = new Lang.Class({ | ||||
|                                onOverwriteScope: this, | ||||
|                                onOverwriteParams: [shellwm, actor] | ||||
|                              }); | ||||
|             break; | ||||
|         case Meta.WindowType.MODAL_DIALOG: | ||||
|         case Meta.WindowType.DIALOG: | ||||
|             actor.set_pivot_point(0.5, 0.5); | ||||
|             actor.scale_y = 0; | ||||
|         } else { | ||||
|             /* Fade window in */ | ||||
|             actor.opacity = 0; | ||||
|             actor.show(); | ||||
|             this._mapping.push(actor); | ||||
|  | ||||
|             Tweener.addTween(actor, | ||||
|                              { opacity: 255, | ||||
|                                scale_x: 1, | ||||
|                                scale_y: 1, | ||||
|                                time: DIALOG_SHOW_WINDOW_ANIMATION_TIME, | ||||
|                                time: WINDOW_ANIMATION_TIME, | ||||
|                                transition: 'easeOutQuad', | ||||
|                                onComplete: this._mapWindowDone, | ||||
|                                onCompleteScope: this, | ||||
| @@ -1121,10 +843,6 @@ const WindowManager = new Lang.Class({ | ||||
|                                onOverwriteScope: this, | ||||
|                                onOverwriteParams: [shellwm, actor] | ||||
|                              }); | ||||
|             break; | ||||
|         default: | ||||
|             shellwm.completed_map(actor); | ||||
|             return; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
| @@ -1132,11 +850,7 @@ const WindowManager = new Lang.Class({ | ||||
|         if (this._removeEffect(this._mapping, actor)) { | ||||
|             Tweener.removeTweens(actor); | ||||
|             actor.opacity = 255; | ||||
|             actor.set_pivot_point(0, 0); | ||||
|             actor.scale_y = 1; | ||||
|             actor.scale_x = 1; | ||||
|             actor.translation_y = 0; | ||||
|             actor.translation_x = 0; | ||||
|             shellwm.completed_map(actor); | ||||
|         } | ||||
|     }, | ||||
| @@ -1159,51 +873,30 @@ const WindowManager = new Lang.Class({ | ||||
|                                                              }); | ||||
|         } | ||||
|  | ||||
|         let types = [Meta.WindowType.NORMAL, | ||||
|                      Meta.WindowType.DIALOG, | ||||
|                      Meta.WindowType.MODAL_DIALOG]; | ||||
|         if (!this._shouldAnimateActor(actor, types)) { | ||||
|         if (!this._shouldAnimateActor(actor)) { | ||||
|             shellwm.completed_destroy(actor); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         switch (actor._windowType) { | ||||
|         case Meta.WindowType.NORMAL: | ||||
|             actor.set_pivot_point(0.5, 0.5); | ||||
|             this._destroying.push(actor); | ||||
|         this._destroying.push(actor); | ||||
|  | ||||
|             Tweener.addTween(actor, | ||||
|                              { opacity: 0, | ||||
|                                scale_x: 0.8, | ||||
|                                scale_y: 0.8, | ||||
|                                time: DESTROY_WINDOW_ANIMATION_TIME, | ||||
|                                transition: 'easeOutQuad', | ||||
|                                onComplete: this._destroyWindowDone, | ||||
|                                onCompleteScope: this, | ||||
|                                onCompleteParams: [shellwm, actor], | ||||
|                                onOverwrite: this._destroyWindowDone, | ||||
|                                onOverwriteScope: this, | ||||
|                                onOverwriteParams: [shellwm, actor] | ||||
|                              }); | ||||
|             break; | ||||
|         case Meta.WindowType.MODAL_DIALOG: | ||||
|         case Meta.WindowType.DIALOG: | ||||
|             actor.set_pivot_point(0.5, 0.5); | ||||
|             this._destroying.push(actor); | ||||
|         if (window.is_attached_dialog()) { | ||||
|             let parent = window.get_transient_for(); | ||||
|             this._checkDimming(parent, window); | ||||
|  | ||||
|             if (window.is_attached_dialog()) { | ||||
|                 let parent = window.get_transient_for(); | ||||
|                 this._checkDimming(parent, window); | ||||
|                 actor._parentDestroyId = parent.connect('unmanaged', Lang.bind(this, function () { | ||||
|                     Tweener.removeTweens(actor); | ||||
|                     this._destroyWindowDone(shellwm, actor); | ||||
|                 })); | ||||
|             } | ||||
|             actor.set_scale(1.0, 1.0); | ||||
|             actor.scale_gravity = Clutter.Gravity.CENTER; | ||||
|             actor.show(); | ||||
|  | ||||
|             actor._parentDestroyId = parent.connect('unmanaged', Lang.bind(this, function () { | ||||
|                 Tweener.removeTweens(actor); | ||||
|                 this._destroyWindowDone(shellwm, actor); | ||||
|             })); | ||||
|  | ||||
|             Tweener.addTween(actor, | ||||
|                              { scale_y: 0, | ||||
|                                time: DIALOG_DESTROY_WINDOW_ANIMATION_TIME, | ||||
|                                transition: 'easeOutQuad', | ||||
|                                time: WINDOW_ANIMATION_TIME, | ||||
|                                transition: "easeOutQuad", | ||||
|                                onComplete: this._destroyWindowDone, | ||||
|                                onCompleteScope: this, | ||||
|                                onCompleteParams: [shellwm, actor], | ||||
| @@ -1211,11 +904,9 @@ const WindowManager = new Lang.Class({ | ||||
|                                onOverwriteScope: this, | ||||
|                                onOverwriteParams: [shellwm, actor] | ||||
|                              }); | ||||
|             break; | ||||
|         default: | ||||
|             shellwm.completed_destroy(actor); | ||||
|             return; | ||||
|         } | ||||
|         shellwm.completed_destroy(actor); | ||||
|     }, | ||||
|  | ||||
|     _destroyWindowDone : function(shellwm, actor) { | ||||
| @@ -1365,22 +1056,6 @@ const WindowManager = new Lang.Class({ | ||||
|         shellwm.completed_switch_workspace(); | ||||
|     }, | ||||
|  | ||||
|     _showTilePreview: function(shellwm, window, tileRect, monitorIndex) { | ||||
|         if (!this._tilePreview) | ||||
|             this._tilePreview = new TilePreview(); | ||||
|         this._tilePreview.show(window, tileRect, monitorIndex); | ||||
|     }, | ||||
|  | ||||
|     _hideTilePreview: function(shellwm) { | ||||
|         if (!this._tilePreview) | ||||
|             return; | ||||
|         this._tilePreview.hide(); | ||||
|     }, | ||||
|  | ||||
|     _showWindowMenu: function(shellwm, window, menu, rect) { | ||||
|         this._windowMenuManager.showWindowMenuForWindow(window, menu, rect); | ||||
|     }, | ||||
|  | ||||
|     _startAppSwitcher : function(display, screen, window, binding) { | ||||
|         /* prevent a corner case where both popups show up at once */ | ||||
|         if (this._workspaceSwitcherPopup != null) | ||||
| @@ -1388,7 +1063,9 @@ const WindowManager = new Lang.Class({ | ||||
|  | ||||
|         let tabPopup = new AltTab.AppSwitcherPopup(); | ||||
|  | ||||
|         if (!tabPopup.show(binding.is_reversed(), binding.get_name(), binding.get_mask())) | ||||
|         let modifiers = binding.get_modifiers(); | ||||
|         let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK; | ||||
|         if (!tabPopup.show(backwards, binding.get_name(), binding.get_mask())) | ||||
|             tabPopup.destroy(); | ||||
|     }, | ||||
|  | ||||
| @@ -1399,12 +1076,16 @@ const WindowManager = new Lang.Class({ | ||||
|  | ||||
|         let tabPopup = new AltTab.WindowSwitcherPopup(); | ||||
|  | ||||
|         if (!tabPopup.show(binding.is_reversed(), binding.get_name(), binding.get_mask())) | ||||
|         let modifiers = binding.get_modifiers(); | ||||
|         let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK; | ||||
|         if (!tabPopup.show(backwards, binding.get_name(), binding.get_mask())) | ||||
|             tabPopup.destroy(); | ||||
|     }, | ||||
|  | ||||
|     _startA11ySwitcher : function(display, screen, window, binding) { | ||||
|         Main.ctrlAltTabManager.popup(binding.is_reversed(), binding.get_name(), binding.get_mask()); | ||||
|         let modifiers = binding.get_modifiers(); | ||||
|         let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK; | ||||
|         Main.ctrlAltTabManager.popup(backwards, binding.get_name(), binding.get_mask()); | ||||
|     }, | ||||
|  | ||||
|     _toggleAppMenu : function(display, screen, window, event, binding) { | ||||
| @@ -1431,10 +1112,7 @@ const WindowManager = new Lang.Class({ | ||||
|         let newWs; | ||||
|         let direction; | ||||
|  | ||||
|         if (target == 'last') { | ||||
|             direction = Meta.MotionDirection.DOWN; | ||||
|             newWs = screen.get_workspace_by_index(screen.n_workspaces - 1); | ||||
|         } else if (isNaN(target)) { | ||||
|         if (isNaN(target)) { | ||||
|             direction = Meta.MotionDirection[target.toUpperCase()]; | ||||
|             newWs = screen.get_active_workspace().get_neighbor(direction); | ||||
|         } else if (target > 0) { | ||||
|   | ||||
| @@ -1,185 +0,0 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -* | ||||
|  | ||||
| const Gtk = imports.gi.Gtk; | ||||
| const Lang = imports.lang; | ||||
| const Meta = imports.gi.Meta; | ||||
| const St = imports.gi.St; | ||||
| const Shell = imports.gi.Shell; | ||||
|  | ||||
| const BoxPointer = imports.ui.boxpointer; | ||||
| const Main = imports.ui.main; | ||||
| const PopupMenu = imports.ui.popupMenu; | ||||
| const RemoteMenu = imports.ui.remoteMenu; | ||||
|  | ||||
| const WindowMenu = new Lang.Class({ | ||||
|     Name: 'WindowMenu', | ||||
|     Extends: PopupMenu.PopupMenu, | ||||
|  | ||||
|     _init: function(window, sourceActor) { | ||||
|         this.parent(sourceActor, 0, St.Side.TOP); | ||||
|  | ||||
|         this.actor.add_style_class_name('window-menu'); | ||||
|  | ||||
|         Main.layoutManager.uiGroup.add_actor(this.actor); | ||||
|         this.actor.hide(); | ||||
|  | ||||
|         this._buildMenu(window); | ||||
|     }, | ||||
|  | ||||
|     _buildMenu: function(window) { | ||||
|         let type = window.get_window_type(); | ||||
|  | ||||
|         let item; | ||||
|  | ||||
|         item = this.addAction(_("Minimize"), Lang.bind(this, function(event) { | ||||
|             window.minimize(); | ||||
|         })); | ||||
|         if (!window.can_minimize()) | ||||
|             item.setSensitive(false); | ||||
|  | ||||
|         if (window.get_maximized()) { | ||||
|             item = this.addAction(_("Unmaximize"), Lang.bind(this, function() { | ||||
|                 window.unmaximize(Meta.MaximizeFlags.BOTH); | ||||
|             })); | ||||
|         } else { | ||||
|             item = this.addAction(_("Maximize"), Lang.bind(this, function() { | ||||
|                 window.maximize(Meta.MaximizeFlags.BOTH); | ||||
|             })); | ||||
|         } | ||||
|         if (!window.can_maximize()) | ||||
|             item.setSensitive(false); | ||||
|  | ||||
|         item = this.addAction(_("Move"), Lang.bind(this, function(event) { | ||||
|             window.begin_grab_op(Meta.GrabOp.KEYBOARD_MOVING, true, event.get_time()); | ||||
|         })); | ||||
|         if (!window.allows_move()) | ||||
|             item.setSensitive(false); | ||||
|  | ||||
|         item = this.addAction(_("Resize"), Lang.bind(this, function(event) { | ||||
|             window.begin_grab_op(Meta.GrabOp.KEYBOARD_RESIZING_UNKNOWN, true, event.get_time()); | ||||
|         })); | ||||
|         if (!window.allows_resize()) | ||||
|             item.setSensitive(false); | ||||
|  | ||||
|         if (!window.titlebar_is_onscreen() && type != Meta.WindowType.DOCK && type != Meta.WindowType.DESKTOP) { | ||||
|             this.addAction(_("Move Titlebar Onscreen"), Lang.bind(this, function(event) { | ||||
|                 window.shove_titlebar_onscreen(); | ||||
|             })); | ||||
|         } | ||||
|  | ||||
|         item = this.addAction(_("Always on Top"), Lang.bind(this, function() { | ||||
|             if (window.is_above()) | ||||
|                 window.unmake_above(); | ||||
|             else | ||||
|                 window.make_above(); | ||||
|         })); | ||||
|         if (window.is_above()) | ||||
|             item.setOrnament(PopupMenu.Ornament.DOT); | ||||
|         if (window.get_maximized() || | ||||
|             type == Meta.WindowType.DOCK || | ||||
|             type == Meta.WindowType.DESKTOP || | ||||
|             type == Meta.WindowType.SPLASHSCREEN) | ||||
|             item.setSensitive(false); | ||||
|  | ||||
|         if (Main.sessionMode.hasWorkspaces && | ||||
|             (!Meta.prefs_get_workspaces_only_on_primary() || | ||||
|              window.is_on_primary_monitor())) { | ||||
|             let isSticky = window.is_on_all_workspaces(); | ||||
|  | ||||
|             item = this.addAction(_("Always on Visible Workspace"), Lang.bind(this, function() { | ||||
|                 if (isSticky) | ||||
|                     window.unstick(); | ||||
|                 else | ||||
|                     window.stick(); | ||||
|             })); | ||||
|             if (isSticky) | ||||
|                 item.setOrnament(PopupMenu.Ornament.DOT); | ||||
|             if (window.is_always_on_all_workspaces()) | ||||
|                 item.setSensitive(false); | ||||
|  | ||||
|             let nWorkspaces = global.screen.n_workspaces; | ||||
|  | ||||
|             if (!isSticky) { | ||||
|                 let workspace = window.get_workspace(); | ||||
|                 let idx = workspace.index(); | ||||
|                 if (idx > 0) { | ||||
|                     this.addAction(_("Move to Workspace Up"), Lang.bind(this, function(event) { | ||||
|                         window.change_workspace(workspace.get_neighbor(Meta.MotionDirection.UP)); | ||||
|                     })); | ||||
|                 } | ||||
|                 if (idx < nWorkspaces) { | ||||
|                      this.addAction(_("Move to Workspace Down"), Lang.bind(this, function(event) { | ||||
|                         window.change_workspace(workspace.get_neighbor(Meta.MotionDirection.DOWN)); | ||||
|                     })); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); | ||||
|  | ||||
|         item = this.addAction(_("Close"), Lang.bind(this, function(event) { | ||||
|             window.delete(event.get_time()); | ||||
|         })); | ||||
|         if (!window.can_close()) | ||||
|             item.setSensitive(false); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const AppMenu = new Lang.Class({ | ||||
|     Name: 'AppMenu', | ||||
|     Extends: RemoteMenu.RemoteMenu, | ||||
|  | ||||
|     _init: function(window, sourceActor) { | ||||
|         let app = Shell.WindowTracker.get_default().get_window_app(window); | ||||
|  | ||||
|         this.parent(sourceActor, app.menu, app.action_group); | ||||
|  | ||||
|         this.actor.add_style_class_name('fallback-app-menu'); | ||||
|         let variant = window.get_gtk_theme_variant(); | ||||
|         if (variant) | ||||
|             this.actor.add_style_class_name(variant); | ||||
|  | ||||
|         Main.layoutManager.uiGroup.add_actor(this.actor); | ||||
|         this.actor.hide(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const WindowMenuManager = new Lang.Class({ | ||||
|     Name: 'WindowMenuManager', | ||||
|  | ||||
|     _init: function() { | ||||
|         this._manager = new PopupMenu.PopupMenuManager({ actor: Main.layoutManager.dummyCursor }); | ||||
|  | ||||
|         this._sourceActor = new St.Widget({ reactive: true, visible: false }); | ||||
|         this._sourceActor.connect('button-press-event', Lang.bind(this, | ||||
|             function() { | ||||
|                 this._manager.activeMenu.toggle(); | ||||
|             })); | ||||
|         Main.uiGroup.add_actor(this._sourceActor); | ||||
|     }, | ||||
|  | ||||
|     showWindowMenuForWindow: function(window, type, rect) { | ||||
|         let menuType = (type == Meta.WindowMenuType.WM) ? WindowMenu : AppMenu; | ||||
|         let menu = new menuType(window, this._sourceActor); | ||||
|  | ||||
|         this._manager.addMenu(menu); | ||||
|  | ||||
|         menu.connect('activate', function() { | ||||
|             window.check_alive(global.get_current_time()); | ||||
|         }); | ||||
|  | ||||
|         this._sourceActor.set_size(rect.width, rect.height); | ||||
|         this._sourceActor.set_position(rect.x, rect.y); | ||||
|         this._sourceActor.show(); | ||||
|  | ||||
|         menu.open(BoxPointer.PopupAnimation.NONE); | ||||
|         menu.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); | ||||
|         menu.connect('open-state-changed', Lang.bind(this, function(menu_, isOpen) { | ||||
|             if (isOpen) | ||||
|                 return; | ||||
|  | ||||
|             this._sourceActor.hide(); | ||||
|             menu.destroy(); | ||||
|         })); | ||||
|     } | ||||
| }); | ||||
							
								
								
									
										130
									
								
								js/ui/wobbly.js
									
									
									
									
									
								
							
							
						
						
									
										130
									
								
								js/ui/wobbly.js
									
									
									
									
									
								
							| @@ -1,130 +0,0 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
|  | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const Lang = imports.lang; | ||||
| const Meta = imports.gi.Meta; | ||||
| const Shell = imports.gi.Shell; | ||||
|  | ||||
| function clampAbs(v, cap) { | ||||
|     if (v > cap) | ||||
|         v = cap; | ||||
|     if (v < -cap) | ||||
|         v = -cap; | ||||
|     return v; | ||||
| } | ||||
|  | ||||
| const ActorWobbler = new Lang.Class({ | ||||
|     Name: 'ActorWobbler', | ||||
|  | ||||
|     _init: function(actor) { | ||||
|         this._actor = actor; | ||||
|         this._effect = new Shell.WobblyEffect(); | ||||
|         this._actor.add_effect(this._effect); | ||||
|         this._actor._wobbler = this; | ||||
|  | ||||
|         this._currentBend = 0; | ||||
|         this._currentHeightOffset = 0; | ||||
|         this._running = false; | ||||
|  | ||||
|         this._allocationChangedId = this._actor.connect('allocation-changed', Lang.bind(this, this._allocationChanged)); | ||||
|  | ||||
|         this._timeline = new Clutter.Timeline({ duration: 100, repeat_count: -1 }); | ||||
|         this._timeline.connect('new-frame', Lang.bind(this, this._newFrame)); | ||||
|         this._timeline.start(); | ||||
|     }, | ||||
|  | ||||
|     start: function() { | ||||
|         this._running = true; | ||||
|     }, | ||||
|  | ||||
|     stop: function() { | ||||
|         this._running = false; | ||||
|     }, | ||||
|  | ||||
|     _destroy: function() { | ||||
|         this._timeline.run_dispose(); | ||||
|         this._timeline = null; | ||||
|  | ||||
|         this._actor.disconnect(this._allocationChangedId); | ||||
|         this._actor.scale_y = 1.0; | ||||
|         this._actor.remove_effect(this._effect); | ||||
|         this._actor._wobbler = null; | ||||
|     }, | ||||
|  | ||||
|     _newFrame: function() { | ||||
|         this._step(); | ||||
|     }, | ||||
|  | ||||
|     _step: function() { | ||||
|         const DAMPEN = 0.8; | ||||
|         this._currentBend *= DAMPEN; | ||||
|         if (Math.abs(this._currentBend) < 1) | ||||
|             this._currentBend = 0; | ||||
|         this._currentHeightOffset *= DAMPEN; | ||||
|         if (Math.abs(this._currentHeightOffset) < 1) | ||||
|             this._currentHeightOffset = 0; | ||||
|  | ||||
|         // Cap the bend to a 100px shift. | ||||
|         const BEND_CAP = 50; | ||||
|         this._currentBend = clampAbs(this._currentBend, BEND_CAP); | ||||
|         this._effect.set_bend_x(this._currentBend); | ||||
|  | ||||
|         // Cap the height change to 25px in either direction. | ||||
|         const HEIGHT_OFFSET_CAP = 25; | ||||
|         this._currentHeightOffset = clampAbs(this._currentHeightOffset, HEIGHT_OFFSET_CAP); | ||||
|         let [minHeight, natHeight] = this._actor.get_preferred_height(-1); | ||||
|         let scale = (natHeight + this._currentHeightOffset) / natHeight; | ||||
|         this._actor.scale_y = scale; | ||||
|  | ||||
|         if (!this._running && this._currentBend == 0 && this._currentHeightOffset == 0) | ||||
|             this._destroy(); | ||||
|     }, | ||||
|  | ||||
|     _allocationChanged: function(actor, box, flags) { | ||||
|         if (!this._running) | ||||
|             return; | ||||
|  | ||||
|         if (this._oldX) { | ||||
|             let deltaX = box.x1 - this._oldX; | ||||
|             // Every 2px the user moves the window, we bend it by 1px. | ||||
|             this._currentBend -= deltaX / 2; | ||||
|         } | ||||
|  | ||||
|         if (this._oldY) { | ||||
|             let deltaY = box.y1 - this._oldY; | ||||
|             // Every 2px the user moves the window, we scale it by 1px. | ||||
|             this._currentHeightOffset -= deltaY / 2; | ||||
|         } | ||||
|  | ||||
|         this._oldX = box.x1; | ||||
|         this._oldY = box.y1; | ||||
|     }, | ||||
| }); | ||||
|  | ||||
| const WobblyWindowManager = new Lang.Class({ | ||||
|     Name: 'WobblyWindowManager', | ||||
|  | ||||
|     _init: function() { | ||||
|         global.display.connect('grab-op-begin', Lang.bind(this, this._grabOpBegin)); | ||||
|         global.display.connect('grab-op-end', Lang.bind(this, this._grabOpEnd)); | ||||
|     }, | ||||
|  | ||||
|     _grabOpBegin: function(display, screen, window, op) { | ||||
|         if (op != Meta.GrabOp.MOVING) | ||||
|             return; | ||||
|  | ||||
|         let actor = window.get_compositor_private(); | ||||
|         if (!actor._wobbler) | ||||
|             new ActorWobbler(actor); | ||||
|         actor._wobbler.start(); | ||||
|     }, | ||||
|  | ||||
|     _grabOpEnd: function(display, screen, window, op) { | ||||
|         if (!window) | ||||
|             return; | ||||
|  | ||||
|         let actor = window.get_compositor_private(); | ||||
|         if (actor._wobbler) | ||||
|             actor._wobbler.stop(); | ||||
|     }, | ||||
| }); | ||||
| @@ -8,8 +8,6 @@ const Meta = imports.gi.Meta; | ||||
| const Pango = imports.gi.Pango; | ||||
| const Shell = imports.gi.Shell; | ||||
| const St = imports.gi.St; | ||||
| const Atk = imports.gi.Atk; | ||||
|  | ||||
| const Signals = imports.signals; | ||||
|  | ||||
| const DND = imports.ui.dnd; | ||||
| @@ -34,8 +32,6 @@ const DRAGGING_WINDOW_OPACITY = 100; | ||||
| const LAYOUT_SCALE_WEIGHT = 1; | ||||
| const LAYOUT_SPACE_WEIGHT = 0.1; | ||||
|  | ||||
| const WINDOW_ANIMATION_MAX_NUMBER_BLENDING = 3; | ||||
|  | ||||
| function _interpolate(start, end, step) { | ||||
|     return start + (end - start) * step; | ||||
| } | ||||
| @@ -69,7 +65,7 @@ const WindowCloneLayout = new Lang.Class({ | ||||
|         // paradoxically is the smaller rectangle, containing the positions | ||||
|         // of the visible frame. The input rect contains everything, | ||||
|         // including the invisible border padding. | ||||
|         let inputRect = window.get_buffer_rect(); | ||||
|         let inputRect = window.get_input_rect(); | ||||
|  | ||||
|         let box = new Clutter.ActorBox(); | ||||
|  | ||||
| @@ -89,7 +85,7 @@ const WindowCloneLayout = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     vfunc_allocate: function(container, box, flags) { | ||||
|         container.get_children().forEach(Lang.bind(this, function (child) { | ||||
|         let clone = container.get_children().forEach(function (child) { | ||||
|             let realWindow; | ||||
|             if (child == container._delegate._windowClone) | ||||
|                 realWindow = container._delegate.realWindow; | ||||
| @@ -98,8 +94,8 @@ const WindowCloneLayout = new Lang.Class({ | ||||
|  | ||||
|             child.allocate(this._makeBoxForWindow(realWindow.meta_window), | ||||
|                            flags); | ||||
|         })); | ||||
|     } | ||||
|         }, this); | ||||
|     }, | ||||
| }); | ||||
|  | ||||
| const WindowClone = new Lang.Class({ | ||||
| @@ -125,7 +121,6 @@ const WindowClone = new Lang.Class({ | ||||
|         // the hierarchy that is sized to only the visible portion. | ||||
|         this.actor = new St.Widget({ reactive: true, | ||||
|                                      can_focus: true, | ||||
|                                      accessible_role: Atk.Role.PUSH_BUTTON, | ||||
|                                      layout_manager: new WindowCloneLayout() }); | ||||
|  | ||||
|         this.actor.add_child(this._windowClone); | ||||
| @@ -136,7 +131,7 @@ const WindowClone = new Lang.Class({ | ||||
|         this._dragSlot = [0, 0, 0, 0]; | ||||
|         this._stackAbove = null; | ||||
|  | ||||
|         this._windowClone._updateId = this.metaWindow.connect('size-changed', | ||||
|         this._windowClone._updateId = this.realWindow.connect('size-changed', | ||||
|             Lang.bind(this, this._onRealWindowSizeChanged)); | ||||
|         this._windowClone._destroyId = this.realWindow.connect('destroy', Lang.bind(this, function() { | ||||
|             // First destroy the clone and then destroy everything | ||||
| @@ -202,13 +197,9 @@ const WindowClone = new Lang.Class({ | ||||
|         this.emit('size-changed'); | ||||
|     }, | ||||
|  | ||||
|     hasAttachedDialogs: function() { | ||||
|         return this.actor.get_n_children() > 1; | ||||
|     }, | ||||
|  | ||||
|     _doAddAttachedDialog: function(metaWin, realWin) { | ||||
|         let clone = new Clutter.Clone({ source: realWin }); | ||||
|         clone._updateId = metaWin.connect('size-changed', Lang.bind(this, function() { | ||||
|         clone._updateId = realWin.connect('size-changed', Lang.bind(this, function() { | ||||
|             this._computeBoundingBox(); | ||||
|             this.emit('size-changed'); | ||||
|         })); | ||||
| @@ -241,14 +232,6 @@ const WindowClone = new Lang.Class({ | ||||
|         return this._boundingBox; | ||||
|     }, | ||||
|  | ||||
|     get width() { | ||||
|         return this._boundingBox.width; | ||||
|     }, | ||||
|  | ||||
|     get height() { | ||||
|         return this._boundingBox.height; | ||||
|     }, | ||||
|  | ||||
|     getOriginalPosition: function() { | ||||
|         return [this._boundingBox.x, this._boundingBox.y]; | ||||
|     }, | ||||
| @@ -267,8 +250,7 @@ const WindowClone = new Lang.Class({ | ||||
|             rect = rect.union(metaWindow.get_outer_rect()); | ||||
|         }, this); | ||||
|  | ||||
|         // Convert from a MetaRectangle to a native JS object | ||||
|         this._boundingBox = { x: rect.x, y: rect.y, width: rect.width, height: rect.height }; | ||||
|         this._boundingBox = rect; | ||||
|         this.actor.layout_manager.boundingBox = rect; | ||||
|     }, | ||||
|  | ||||
| @@ -313,7 +295,7 @@ const WindowClone = new Lang.Class({ | ||||
|             else | ||||
|                 realWindow = child.source; | ||||
|  | ||||
|             realWindow.meta_window.disconnect(child._updateId); | ||||
|             realWindow.disconnect(child._updateId); | ||||
|             realWindow.disconnect(child._destroyId); | ||||
|         })); | ||||
|     }, | ||||
| @@ -442,7 +424,6 @@ const WindowOverlay = new Lang.Class({ | ||||
|                                    text: metaWindow.title }); | ||||
|         title.clutter_text.ellipsize = Pango.EllipsizeMode.END; | ||||
|         title._spacing = 0; | ||||
|         windowClone.actor.label_actor = title; | ||||
|  | ||||
|         this._updateCaptionId = metaWindow.connect('notify::title', | ||||
|             Lang.bind(this, function(w) { | ||||
| @@ -519,7 +500,6 @@ const WindowOverlay = new Lang.Class({ | ||||
|  | ||||
|         Tweener.removeTweens(button); | ||||
|         Tweener.removeTweens(border); | ||||
|         Tweener.removeTweens(title); | ||||
|  | ||||
|         let [cloneX, cloneY, cloneWidth, cloneHeight] = this._windowClone.slot; | ||||
|  | ||||
| @@ -598,8 +578,7 @@ const WindowOverlay = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _windowCanClose: function() { | ||||
|         return this._windowClone.metaWindow.can_close() && | ||||
|                !this._windowClone.hasAttachedDialogs(); | ||||
|         return this._windowClone.metaWindow.can_close(); | ||||
|     }, | ||||
|  | ||||
|     _onWindowAdded: function(workspace, win) { | ||||
| @@ -611,12 +590,11 @@ const WindowOverlay = new Lang.Class({ | ||||
|  | ||||
|             // use an idle handler to avoid mapping problems - | ||||
|             // see comment in Workspace._windowAdded | ||||
|             let id = Mainloop.idle_add(Lang.bind(this, | ||||
|                                             function() { | ||||
|                                                 this._windowClone.emit('selected'); | ||||
|                                                 return GLib.SOURCE_REMOVE; | ||||
|                                             })); | ||||
|             GLib.Source.set_name_by_id(id, '[gnome-shell] this._windowClone.emit'); | ||||
|             Mainloop.idle_add(Lang.bind(this, | ||||
|                                         function() { | ||||
|                                             this._windowClone.emit('selected'); | ||||
|                                             return GLib.SOURCE_REMOVE; | ||||
|                                         })); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
| @@ -687,10 +665,8 @@ const WindowOverlay = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _onLeave: function() { | ||||
|         if (this._idleToggleCloseId == 0) { | ||||
|         if (this._idleToggleCloseId == 0) | ||||
|             this._idleToggleCloseId = Mainloop.timeout_add(750, Lang.bind(this, this._idleToggleCloseButton)); | ||||
|             GLib.Source.set_name_by_id(this._idleToggleCloseId, '[gnome-shell] this._idleToggleCloseButton'); | ||||
|         } | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     }, | ||||
|  | ||||
| @@ -844,7 +820,7 @@ const LayoutStrategy = new Lang.Class({ | ||||
|         // thumbnails is much more important to preserve than the width of | ||||
|         // them, so two windows with equal height, but maybe differering | ||||
|         // widths line up. | ||||
|         let ratio = window.height / this._monitor.height; | ||||
|         let ratio = window.actor.height / this._monitor.height; | ||||
|  | ||||
|         // The purpose of this manipulation here is to prevent windows | ||||
|         // from getting too small. For something like a calculator window, | ||||
| @@ -946,11 +922,11 @@ const LayoutStrategy = new Lang.Class({ | ||||
|                 let window = row.windows[j]; | ||||
|  | ||||
|                 let s = scale * this._computeWindowScale(window) * row.additionalScale; | ||||
|                 let cellWidth = window.width * s; | ||||
|                 let cellHeight = window.height * s; | ||||
|                 let cellWidth = window.actor.width * s; | ||||
|                 let cellHeight = window.actor.height * s; | ||||
|  | ||||
|                 s = Math.min(s, WINDOW_CLONE_MAXIMUM_SCALE); | ||||
|                 let cloneWidth = window.width * s; | ||||
|                 let cloneWidth = window.actor.width * s; | ||||
|  | ||||
|                 let cloneX = x + (cellWidth - cloneWidth) / 2; | ||||
|                 let cloneY = row.y + row.height - cellHeight; | ||||
| @@ -1004,7 +980,7 @@ const UnalignedLayoutStrategy = new Lang.Class({ | ||||
|         for (let i = 0; i < windows.length; i++) { | ||||
|             let window = windows[i]; | ||||
|             let s = this._computeWindowScale(window); | ||||
|             totalWidth += window.width * s; | ||||
|             totalWidth += window.actor.width * s; | ||||
|         } | ||||
|  | ||||
|         let idealRowWidth = totalWidth / numRows; | ||||
| @@ -1017,8 +993,8 @@ const UnalignedLayoutStrategy = new Lang.Class({ | ||||
|             for (; windowIdx < windows.length; windowIdx++) { | ||||
|                 let window = windows[windowIdx]; | ||||
|                 let s = this._computeWindowScale(window); | ||||
|                 let width = window.width * s; | ||||
|                 let height = window.height * s; | ||||
|                 let width = window.actor.width * s; | ||||
|                 let height = window.actor.height * s; | ||||
|                 row.fullHeight = Math.max(row.fullHeight, height); | ||||
|  | ||||
|                 // either new width is < idealWidth or new width is nearer from idealWidth then oldWidth | ||||
| @@ -1143,11 +1119,6 @@ const Workspace = new Lang.Class({ | ||||
|  | ||||
|         this._positionWindowsFlags = 0; | ||||
|         this._positionWindowsId = 0; | ||||
|  | ||||
|         this.actor.connect('notify::mapped', Lang.bind(this, function() { | ||||
|             if (this.actor.mapped) | ||||
|                 this._syncActualGeometry(); | ||||
|         })); | ||||
|     }, | ||||
|  | ||||
|     setFullGeometry: function(geom) { | ||||
| @@ -1155,9 +1126,7 @@ const Workspace = new Lang.Class({ | ||||
|             return; | ||||
|  | ||||
|         this._fullGeometry = geom; | ||||
|  | ||||
|         if (this.actor.mapped) | ||||
|             this._recalculateWindowPositions(WindowPositionFlags.NONE); | ||||
|         this._recalculateWindowPositions(WindowPositionFlags.NONE); | ||||
|     }, | ||||
|  | ||||
|     setActualGeometry: function(geom) { | ||||
| @@ -1165,29 +1134,18 @@ const Workspace = new Lang.Class({ | ||||
|             return; | ||||
|  | ||||
|         this._actualGeometry = geom; | ||||
|         this._actualGeometryDirty = true; | ||||
|  | ||||
|         if (this.actor.mapped) | ||||
|             this._syncActualGeometry(); | ||||
|     }, | ||||
|  | ||||
|     _syncActualGeometry: function() { | ||||
|         if (this._actualGeometryLater || !this._actualGeometryDirty) | ||||
|             return; | ||||
|         if (!this._actualGeometry) | ||||
|         if (this._actualGeometryLater) | ||||
|             return; | ||||
|  | ||||
|         this._actualGeometryLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { | ||||
|             this._actualGeometryLater = 0; | ||||
|             if (!this.actor.mapped) | ||||
|                 return false; | ||||
|  | ||||
|             let geom = this._actualGeometry; | ||||
|  | ||||
|             this._dropRect.set_position(geom.x, geom.y); | ||||
|             this._dropRect.set_size(geom.width, geom.height); | ||||
|             this._updateWindowPositions(Main.overview.animationInProgress ? WindowPositionFlags.ANIMATE : WindowPositionFlags.NONE); | ||||
|  | ||||
|             this._actualGeometryLater = 0; | ||||
|             return false; | ||||
|         })); | ||||
|     }, | ||||
| @@ -1261,13 +1219,6 @@ const Workspace = new Lang.Class({ | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // We will reposition windows anyway when enter again overview or when ending the windows | ||||
|         // animations whith fade animation. | ||||
|         // In this way we avoid unwanted animations of windows repositioning while | ||||
|         // animating overview. | ||||
|         if (this.leavingOverview || this._animatingWindowsFade) | ||||
|             return; | ||||
|  | ||||
|         let initialPositioning = flags & WindowPositionFlags.INITIAL; | ||||
|         let animate = flags & WindowPositionFlags.ANIMATE; | ||||
|  | ||||
| @@ -1330,7 +1281,7 @@ const Workspace = new Lang.Class({ | ||||
|                                      }); | ||||
|                 } | ||||
|  | ||||
|                 this._animateClone(clone, overlay, x, y, scale); | ||||
|                 this._animateClone(clone, overlay, x, y, scale, initialPositioning); | ||||
|             } else { | ||||
|                 // cancel any active tweens (otherwise they might override our changes) | ||||
|                 Tweener.removeTweens(clone.actor); | ||||
| @@ -1359,7 +1310,7 @@ const Workspace = new Lang.Class({ | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _animateClone: function(clone, overlay, x, y, scale) { | ||||
|     _animateClone: function(clone, overlay, x, y, scale, initialPositioning) { | ||||
|         Tweener.addTween(clone.actor, | ||||
|                          { x: x, | ||||
|                            y: y, | ||||
| @@ -1417,6 +1368,10 @@ const Workspace = new Lang.Class({ | ||||
|         if (index == -1) | ||||
|             return; | ||||
|  | ||||
|         // Check if window still should be here | ||||
|         if (win && this._isMyWindow(win)) | ||||
|             return; | ||||
|  | ||||
|         let clone = this._windows[index]; | ||||
|  | ||||
|         this._windows.splice(index, 1); | ||||
| @@ -1459,7 +1414,6 @@ const Workspace = new Lang.Class({ | ||||
|         this._currentLayout = null; | ||||
|         this._repositionWindowsId = Mainloop.timeout_add(750, | ||||
|             Lang.bind(this, this._delayedWindowRepositioning)); | ||||
|         GLib.Source.set_name_by_id(this._repositionWindowsId, '[gnome-shell] this._delayedWindowRepositioning'); | ||||
|     }, | ||||
|  | ||||
|     _doAddWindow : function(metaWin) { | ||||
| @@ -1471,15 +1425,14 @@ const Workspace = new Lang.Class({ | ||||
|         if (!win) { | ||||
|             // Newly-created windows are added to a workspace before | ||||
|             // the compositor finds out about them... | ||||
|             let id = Mainloop.idle_add(Lang.bind(this, | ||||
|                                             function () { | ||||
|                                                 if (this.actor && | ||||
|                                                     metaWin.get_compositor_private() && | ||||
|                                                     metaWin.get_workspace() == this.metaWorkspace) | ||||
|                                                     this._doAddWindow(metaWin); | ||||
|                                                 return GLib.SOURCE_REMOVE; | ||||
|                                             })); | ||||
|             GLib.Source.set_name_by_id(id, '[gnome-shell] this._doAddWindow'); | ||||
|             Mainloop.idle_add(Lang.bind(this, | ||||
|                                         function () { | ||||
|                                             if (this.actor && | ||||
|                                                 metaWin.get_compositor_private() && | ||||
|                                                 metaWin.get_workspace() == this.metaWorkspace) | ||||
|                                                 this._doAddWindow(metaWin); | ||||
|                                             return GLib.SOURCE_REMOVE; | ||||
|                                         })); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
| @@ -1562,195 +1515,96 @@ const Workspace = new Lang.Class({ | ||||
|         return false; | ||||
|     }, | ||||
|  | ||||
|     fadeToOverview: function() { | ||||
|         // We don't want to reposition windows while animating in this way. | ||||
|         this._animatingWindowsFade = true; | ||||
|         this._overviewShownId = Main.overview.connect('shown', Lang.bind(this, | ||||
|                                                                          this._doneShowingOverview)); | ||||
|         if (this._windows.length == 0) | ||||
|             return; | ||||
|     // Animate the full-screen to Overview transition. | ||||
|     zoomToOverview : function() { | ||||
|         // Position and scale the windows. | ||||
|         this._recalculateWindowPositions(WindowPositionFlags.ANIMATE | WindowPositionFlags.INITIAL); | ||||
|     }, | ||||
|  | ||||
|         if (this.metaWorkspace != null && this.metaWorkspace != global.screen.get_active_workspace()) | ||||
|             return; | ||||
|     _leavingOverview: function() { | ||||
|         let currentWorkspace = global.screen.get_active_workspace(); | ||||
|         if (this.metaWorkspace != null && this.metaWorkspace != currentWorkspace) | ||||
|             return false; | ||||
|  | ||||
|         // Special case maximized windows, since it doesn't make sense | ||||
|         // to animate windows below in the stack | ||||
|         let topMaximizedWindow; | ||||
|         // It is ok to treat the case where there is no maximized | ||||
|         // window as if the bottom-most window was maximized given that | ||||
|         // it won't affect the result of the animation | ||||
|         for (topMaximizedWindow = this._windows.length - 1; topMaximizedWindow > 0; topMaximizedWindow--) { | ||||
|             let metaWindow = this._windows[topMaximizedWindow].metaWindow; | ||||
|             if (metaWindow.maximized_horizontally && metaWindow.maximized_vertically) | ||||
|                 break; | ||||
|         this.leavingOverview = true; | ||||
|         this._overviewHiddenId = Main.overview.connect('hidden', Lang.bind(this, | ||||
|                                                                            this._doneLeavingOverview)); | ||||
|  | ||||
|         for (let i = 0; i < this._windows.length; i++) { | ||||
|             let clone = this._windows[i]; | ||||
|             Tweener.removeTweens(clone.actor); | ||||
|  | ||||
|             let overlay = this._windowOverlays[i]; | ||||
|             if (overlay) | ||||
|                 overlay.hide(); | ||||
|         } | ||||
|  | ||||
|         let nTimeSlots = Math.min(WINDOW_ANIMATION_MAX_NUMBER_BLENDING + 1, this._windows.length - topMaximizedWindow); | ||||
|         let windowBaseTime = Overview.ANIMATION_TIME / nTimeSlots; | ||||
|         if (this._repositionWindowsId > 0) { | ||||
|             Mainloop.source_remove(this._repositionWindowsId); | ||||
|             this._repositionWindowsId = 0; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     // Animates the return from Overview mode | ||||
|     zoomFromOverview : function() { | ||||
|         if (!this._leavingOverview()) | ||||
|             return; | ||||
|  | ||||
|         let topIndex = this._windows.length - 1; | ||||
|         for (let i = 0; i < this._windows.length; i++) { | ||||
|             if (i < topMaximizedWindow) { | ||||
|                 // below top-most maximized window, don't animate | ||||
|                 let overlay = this._windowOverlays[i]; | ||||
|                 if (overlay) | ||||
|                     overlay.hide(); | ||||
|                 this._windows[i].actor.opacity = 0; | ||||
|             } else { | ||||
|                 let fromTop = topIndex - i; | ||||
|                 let time; | ||||
|                 if (fromTop < nTimeSlots) // animate top-most windows gradually | ||||
|                     time = windowBaseTime * (nTimeSlots - fromTop); | ||||
|                 else | ||||
|                     time = windowBaseTime; | ||||
|             let clone = this._windows[i]; | ||||
|  | ||||
|                 this._windows[i].actor.opacity = 255; | ||||
|                 this._fadeWindow(i, time, 0); | ||||
|             if (clone.metaWindow.showing_on_its_workspace()) { | ||||
|                 let [origX, origY] = clone.getOriginalPosition(); | ||||
|  | ||||
|                 Tweener.addTween(clone.actor, | ||||
|                                  { x: origX, | ||||
|                                    y: origY, | ||||
|                                    scale_x: 1.0, | ||||
|                                    scale_y: 1.0, | ||||
|                                    time: Overview.ANIMATION_TIME, | ||||
|                                    opacity: 255, | ||||
|                                    transition: 'easeOutQuad' | ||||
|                                  }); | ||||
|             } else { | ||||
|                 // The window is hidden, make it shrink and fade it out | ||||
|                 Tweener.addTween(clone.actor, | ||||
|                                  { scale_x: 0, | ||||
|                                    scale_y: 0, | ||||
|                                    opacity: 0, | ||||
|                                    time: Overview.ANIMATION_TIME, | ||||
|                                    transition: 'easeOutQuad' | ||||
|                                  }); | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     fadeFromOverview: function() { | ||||
|         this.leavingOverview = true; | ||||
|         this._overviewHiddenId = Main.overview.connect('hidden', Lang.bind(this, | ||||
|                                                                            this._doneLeavingOverview)); | ||||
|         if (this._windows.length == 0) | ||||
|         if (!this._leavingOverview()) | ||||
|             return; | ||||
|  | ||||
|         for (let i = 0; i < this._windows.length; i++) { | ||||
|             let clone = this._windows[i]; | ||||
|             Tweener.removeTweens(clone.actor); | ||||
|         } | ||||
|  | ||||
|         if (this._repositionWindowsId > 0) { | ||||
|             Mainloop.source_remove(this._repositionWindowsId); | ||||
|             this._repositionWindowsId = 0; | ||||
|         } | ||||
|             if (clone.metaWindow.showing_on_its_workspace()) { | ||||
|                 clone.actor.x = clone.origX; | ||||
|                 clone.actor.y = clone.origY; | ||||
|                 clone.actor.scale_x = 1.0; | ||||
|                 clone.actor.scale_y = 1.0; | ||||
|                 clone.actor.opacity = 0; | ||||
|  | ||||
|         if (this.metaWorkspace != null && this.metaWorkspace != global.screen.get_active_workspace()) | ||||
|             return; | ||||
|  | ||||
|         // Special case maximized windows, since it doesn't make sense | ||||
|         // to animate windows below in the stack | ||||
|         let topMaximizedWindow; | ||||
|         // It is ok to treat the case where there is no maximized | ||||
|         // window as if the bottom-most window was maximized given that | ||||
|         // it won't affect the result of the animation | ||||
|         for (topMaximizedWindow = this._windows.length - 1; topMaximizedWindow > 0; topMaximizedWindow--) { | ||||
|             let metaWindow = this._windows[topMaximizedWindow].metaWindow; | ||||
|             if (metaWindow.maximized_horizontally && metaWindow.maximized_vertically) | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         let nTimeSlots = Math.min(WINDOW_ANIMATION_MAX_NUMBER_BLENDING + 1, this._windows.length - topMaximizedWindow); | ||||
|         let windowBaseTime = Overview.ANIMATION_TIME / nTimeSlots; | ||||
|  | ||||
|         let topIndex = this._windows.length - 1; | ||||
|         for (let i = 0; i < this._windows.length; i++) { | ||||
|             if (i < topMaximizedWindow) { | ||||
|                 // below top-most maximized window, don't animate | ||||
|                 let overlay = this._windowOverlays[i]; | ||||
|                 if (overlay) | ||||
|                     overlay.hide(); | ||||
|                 this._windows[i].actor.opacity = 0; | ||||
|                 Tweener.addTween(clone.actor, | ||||
|                                  { opacity: 255, | ||||
|                                    time: Overview.ANIMATION_TIME, | ||||
|                                    transition: 'easeOutQuad' | ||||
|                                  }); | ||||
|             } else { | ||||
|                 let fromTop = topIndex - i; | ||||
|                 let time; | ||||
|                 if (fromTop < nTimeSlots) // animate top-most windows gradually | ||||
|                     time = windowBaseTime * (fromTop + 1); | ||||
|                 else | ||||
|                     time = windowBaseTime * nTimeSlots; | ||||
|  | ||||
|                 this._windows[i].actor.opacity = 0; | ||||
|                 this._fadeWindow(i, time, 255); | ||||
|                 clone.actor.hide(); | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _fadeWindow: function(index, time, opacity) { | ||||
|         let clone = this._windows[index]; | ||||
|         let overlay = this._windowOverlays[index]; | ||||
|  | ||||
|         if (overlay) | ||||
|             overlay.hide(); | ||||
|  | ||||
|         if (clone.metaWindow.showing_on_its_workspace()) { | ||||
|             let [origX, origY] = clone.getOriginalPosition(); | ||||
|             clone.actor.scale_x = 1; | ||||
|             clone.actor.scale_y = 1; | ||||
|             clone.actor.x = origX; | ||||
|             clone.actor.y = origY; | ||||
|             Tweener.addTween(clone.actor, | ||||
|                              { time: time, | ||||
|                                opacity: opacity, | ||||
|                                transition: 'easeOutQuad' | ||||
|                              }); | ||||
|         } else { | ||||
|             // The window is hidden | ||||
|             clone.actor.opacity = 0; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     zoomToOverview: function() { | ||||
|         // Position and scale the windows. | ||||
|         this._recalculateWindowPositions(WindowPositionFlags.ANIMATE | WindowPositionFlags.INITIAL); | ||||
|     }, | ||||
|  | ||||
|     zoomFromOverview: function() { | ||||
|         let currentWorkspace = global.screen.get_active_workspace(); | ||||
|  | ||||
|         this.leavingOverview = true; | ||||
|  | ||||
|         for (let i = 0; i < this._windows.length; i++) { | ||||
|             let clone = this._windows[i]; | ||||
|             Tweener.removeTweens(clone.actor); | ||||
|         } | ||||
|  | ||||
|         if (this._repositionWindowsId > 0) { | ||||
|             Mainloop.source_remove(this._repositionWindowsId); | ||||
|             this._repositionWindowsId = 0; | ||||
|         } | ||||
|         this._overviewHiddenId = Main.overview.connect('hidden', Lang.bind(this, | ||||
|                                                                            this._doneLeavingOverview)); | ||||
|  | ||||
|         if (this.metaWorkspace != null && this.metaWorkspace != currentWorkspace) | ||||
|             return; | ||||
|  | ||||
|         // Position and scale the windows. | ||||
|         for (let i = 0; i < this._windows.length; i++) | ||||
|            this._zoomWindowFromOverview(i); | ||||
|     }, | ||||
|  | ||||
|     _zoomWindowFromOverview: function(index) { | ||||
|         let clone = this._windows[index]; | ||||
|         let overlay = this._windowOverlays[index]; | ||||
|  | ||||
|         if (overlay) | ||||
|             overlay.hide(); | ||||
|  | ||||
|         if (clone.metaWindow.showing_on_its_workspace()) { | ||||
|             let [origX, origY] = clone.getOriginalPosition(); | ||||
|             Tweener.addTween(clone.actor, | ||||
|                              { x: origX, | ||||
|                                y: origY, | ||||
|                                scale_x: 1.0, | ||||
|                                scale_y: 1.0, | ||||
|                                time: Overview.ANIMATION_TIME, | ||||
|                                opacity: 255, | ||||
|                                transition: 'easeOutQuad' | ||||
|                              }); | ||||
|         } else { | ||||
|             // The window is hidden, make it shrink and fade it out | ||||
|             Tweener.addTween(clone.actor, | ||||
|                              { scale_x: 0, | ||||
|                                scale_y: 0, | ||||
|                                opacity: 0, | ||||
|                                time: Overview.ANIMATION_TIME, | ||||
|                                transition: 'easeOutQuad' | ||||
|                              }); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     destroy : function() { | ||||
|         this.actor.destroy(); | ||||
|     }, | ||||
| @@ -1786,11 +1640,6 @@ const Workspace = new Lang.Class({ | ||||
|         this.leavingOverview = false; | ||||
|     }, | ||||
|  | ||||
|     _doneShowingOverview: function() { | ||||
|         this._animatingWindowsFade = false; | ||||
|         this._recalculateWindowPositions(WindowPositionFlags.INITIAL); | ||||
|     }, | ||||
|  | ||||
|     // Tests if @actor belongs to this workspaces and monitor | ||||
|     _isMyWindow : function (actor) { | ||||
|         let win = actor.meta_window; | ||||
|   | ||||
| @@ -25,7 +25,7 @@ const WorkspaceSwitcherPopup = new Lang.Class({ | ||||
|                                      width: global.screen_width, | ||||
|                                      height: global.screen_height, | ||||
|                                      style_class: 'workspace-switcher-group' }); | ||||
|         Main.uiGroup.add_actor(this.actor); | ||||
|         Main.layoutManager.osdGroup.add_child(this.actor); | ||||
|  | ||||
|         this._container = new St.BoxLayout({ style_class: 'workspace-switcher-container' }); | ||||
|         this._list = new Shell.GenericContainer({ style_class: 'workspace-switcher' }); | ||||
| @@ -52,7 +52,6 @@ const WorkspaceSwitcherPopup = new Lang.Class({ | ||||
|         this._globalSignals.push(global.screen.connect('workspace-removed', Lang.bind(this, this._redisplay))); | ||||
|  | ||||
|         this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, Lang.bind(this, this._onTimeout)); | ||||
|         GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] this._onTimeout'); | ||||
|     }, | ||||
|  | ||||
|     _getPreferredHeight : function (actor, forWidth, alloc) { | ||||
| @@ -146,7 +145,6 @@ const WorkspaceSwitcherPopup = new Lang.Class({ | ||||
|         if (this._timeoutId != 0) | ||||
|             Mainloop.source_remove(this._timeoutId); | ||||
|         this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, Lang.bind(this, this._onTimeout)); | ||||
|         GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] this._onTimeout'); | ||||
|         this._show(); | ||||
|     }, | ||||
|  | ||||
|   | ||||
| @@ -68,7 +68,7 @@ const WindowClone = new Lang.Class({ | ||||
|         this.realWindow = realWindow; | ||||
|         this.metaWindow = realWindow.meta_window; | ||||
|  | ||||
|         this.clone._updateId = this.metaWindow.connect('position-changed', | ||||
|         this.clone._updateId = this.realWindow.connect('position-changed', | ||||
|                                                        Lang.bind(this, this._onPositionChanged)); | ||||
|         this.clone._destroyId = this.realWindow.connect('destroy', Lang.bind(this, function() { | ||||
|             // First destroy the clone and then destroy everything | ||||
| @@ -151,7 +151,7 @@ const WindowClone = new Lang.Class({ | ||||
|         let clone = new Clutter.Clone({ source: realDialog }); | ||||
|         this._updateDialogPosition(realDialog, clone); | ||||
|  | ||||
|         clone._updateId = metaDialog.connect('position-changed', | ||||
|         clone._updateId = realDialog.connect('position-changed', | ||||
|                                              Lang.bind(this, this._updateDialogPosition, clone)); | ||||
|         clone._destroyId = realDialog.connect('destroy', Lang.bind(this, function() { | ||||
|             clone.destroy(); | ||||
| @@ -176,7 +176,7 @@ const WindowClone = new Lang.Class({ | ||||
|         this.actor.get_children().forEach(function(child) { | ||||
|             let realWindow = child.source; | ||||
|  | ||||
|             realWindow.meta_window.disconnect(child._updateId); | ||||
|             realWindow.disconnect(child._updateId); | ||||
|             realWindow.disconnect(child._destroyId); | ||||
|         }); | ||||
|     }, | ||||
| @@ -306,7 +306,7 @@ const WorkspaceThumbnail = new Lang.Class({ | ||||
|     _createBackground: function() { | ||||
|         this._bgManager = new Background.BackgroundManager({ monitorIndex: Main.layoutManager.primaryIndex, | ||||
|                                                              container: this._contents, | ||||
|                                                              vignette: false }); | ||||
|                                                              effects: Meta.BackgroundEffects.NONE }); | ||||
|     }, | ||||
|  | ||||
|     setPorthole: function(x, y, width, height) { | ||||
| @@ -332,7 +332,7 @@ const WorkspaceThumbnail = new Lang.Class({ | ||||
|             let clone = this._windows[i]; | ||||
|             let metaWindow = clone.metaWindow; | ||||
|             if (i == 0) { | ||||
|                 clone.setStackAbove(this._bgManager.backgroundActor); | ||||
|                 clone.setStackAbove(this._bgManager.background.actor); | ||||
|             } else { | ||||
|                 let previousClone = this._windows[i - 1]; | ||||
|                 clone.setStackAbove(previousClone.actor); | ||||
| @@ -367,6 +367,10 @@ const WorkspaceThumbnail = new Lang.Class({ | ||||
|         if (index == -1) | ||||
|             return; | ||||
|  | ||||
|         // Check if window still should be here | ||||
|         if (win && this._isMyWindow(win) && this._isOverviewWindow(win)) | ||||
|             return; | ||||
|  | ||||
|         let clone = this._windows[index]; | ||||
|         this._windows.splice(index, 1); | ||||
|  | ||||
| @@ -382,15 +386,14 @@ const WorkspaceThumbnail = new Lang.Class({ | ||||
|         if (!win) { | ||||
|             // Newly-created windows are added to a workspace before | ||||
|             // the compositor finds out about them... | ||||
|             let id = Mainloop.idle_add(Lang.bind(this, | ||||
|                                        function () { | ||||
|             Mainloop.idle_add(Lang.bind(this, | ||||
|                                         function () { | ||||
|                                             if (!this._removed && | ||||
|                                                 metaWin.get_compositor_private() && | ||||
|                                                 metaWin.get_workspace() == this.metaWorkspace) | ||||
|                                                 this._doAddWindow(metaWin); | ||||
|                                             return GLib.SOURCE_REMOVE; | ||||
|                                         })); | ||||
|             GLib.Source.set_name_by_id(id, '[gnome-shell] this._doAddWindow'); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
| @@ -531,7 +534,7 @@ const WorkspaceThumbnail = new Lang.Class({ | ||||
|         this._contents.add_actor(clone.actor); | ||||
|  | ||||
|         if (this._windows.length == 0) | ||||
|             clone.setStackAbove(this._bgManager.backgroundActor); | ||||
|             clone.setStackAbove(this._bgManager.background.actor); | ||||
|         else | ||||
|             clone.setStackAbove(this._windows[this._windows.length - 1].actor); | ||||
|  | ||||
| @@ -661,7 +664,7 @@ const ThumbnailsBox = new Lang.Class({ | ||||
|         Main.overview.connect('window-drag-cancelled', | ||||
|                               Lang.bind(this, this._onDragCancelled)); | ||||
|  | ||||
|         this._settings = new Gio.Settings({ schema_id: OVERRIDE_SCHEMA }); | ||||
|         this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA }); | ||||
|         this._settings.connect('changed::dynamic-workspaces', | ||||
|             Lang.bind(this, this._updateSwitcherVisibility)); | ||||
|     }, | ||||
| @@ -801,35 +804,28 @@ const ThumbnailsBox = new Lang.Class({ | ||||
|             [newWorkspaceIndex, this._dropPlaceholderPos] = [this._dropPlaceholderPos, -1]; | ||||
|  | ||||
|             // Nab all the windows below us. | ||||
|             let windows = global.get_window_actors().filter(function(winActor) { | ||||
|             let windows = global.get_window_actors().filter(function(win) { | ||||
|                 // If the window is attached to an ancestor, we don't need/want to move it | ||||
|                 let window = winActor.meta_window; | ||||
|  | ||||
|                 if (window.get_transient_for() != null) | ||||
|                 if (!!win.meta_window.get_transient_for()) | ||||
|                     return false; | ||||
|  | ||||
|                 if (isWindow) | ||||
|                     return window.get_workspace().index() >= newWorkspaceIndex && winActor != source; | ||||
|                     return win.get_workspace() >= newWorkspaceIndex && win != source; | ||||
|                 else | ||||
|                     return window.get_workspace().index() >= newWorkspaceIndex; | ||||
|                     return win.get_workspace() >= newWorkspaceIndex; | ||||
|             }); | ||||
|  | ||||
|             this._spliceIndex = newWorkspaceIndex; | ||||
|  | ||||
|             // ... move them down one. | ||||
|             windows.forEach(function(winActor) { | ||||
|                 let window = winActor.meta_window; | ||||
|                 window.change_workspace_by_index(window.get_workspace().index() + 1, true); | ||||
|             windows.forEach(function(win) { | ||||
|                 win.meta_window.change_workspace_by_index(win.get_workspace() + 1, true); | ||||
|             }); | ||||
|  | ||||
|             if (isWindow) { | ||||
|             if (isWindow) | ||||
|                 // ... and bam, a workspace, good as new. | ||||
|                 // Move the window to our monitor first if necessary. | ||||
|                 let thumbMonitor = this._thumbnails[newWorkspaceIndex].monitorIndex; | ||||
|                 if (source.metaWindow.get_monitor() != thumbMonitor) | ||||
|                     source.metaWindow.move_to_monitor(thumbMonitor); | ||||
|                 source.metaWindow.change_workspace_by_index(newWorkspaceIndex, true); | ||||
|             } else if (source.shellWorkspaceLaunch) { | ||||
|             else if (source.shellWorkspaceLaunch) { | ||||
|                 source.shellWorkspaceLaunch({ workspace: newWorkspaceIndex, | ||||
|                                               timestamp: time }); | ||||
|                 // This new workspace will be automatically removed if the application fails | ||||
| @@ -874,6 +870,9 @@ const ThumbnailsBox = new Lang.Class({ | ||||
|         for (let key in ThumbnailState) | ||||
|             this._stateCounts[ThumbnailState[key]] = 0; | ||||
|  | ||||
|         // The "porthole" is the portion of the screen that we show in the workspaces | ||||
|         this._porthole = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex); | ||||
|  | ||||
|         this.addThumbnails(0, global.screen.n_workspaces); | ||||
|  | ||||
|         this._updateSwitcherVisibility(); | ||||
| @@ -897,14 +896,10 @@ const ThumbnailsBox = new Lang.Class({ | ||||
|         for (let w = 0; w < this._thumbnails.length; w++) | ||||
|             this._thumbnails[w].destroy(); | ||||
|         this._thumbnails = []; | ||||
|         this._porthole = null; | ||||
|     }, | ||||
|  | ||||
|     _workspacesChanged: function() { | ||||
|         let validThumbnails = this._thumbnails.filter(function(t) { | ||||
|             return t.state <= ThumbnailState.NORMAL; | ||||
|         }); | ||||
|         let oldNumWorkspaces = validThumbnails.length; | ||||
|         let oldNumWorkspaces = this._thumbnails.length; | ||||
|         let newNumWorkspaces = global.screen.n_workspaces; | ||||
|         let active = global.screen.get_active_workspace_index(); | ||||
|  | ||||
| @@ -928,7 +923,6 @@ const ThumbnailsBox = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     addThumbnails: function(start, count) { | ||||
|         this._ensurePorthole(); | ||||
|         for (let k = start; k < start + count; k++) { | ||||
|             let metaWorkspace = global.screen.get_workspace_by_index(k); | ||||
|             let thumbnail = new WorkspaceThumbnail(metaWorkspace); | ||||
| @@ -1116,7 +1110,9 @@ const ThumbnailsBox = new Lang.Class({ | ||||
|         // the size request to our children because we know how big they are and know | ||||
|         // that the actors aren't depending on the virtual functions being called. | ||||
|  | ||||
|         this._ensurePorthole(); | ||||
|         if (this._thumbnails.length == 0) | ||||
|             return; | ||||
|  | ||||
|         let themeNode = this.actor.get_theme_node(); | ||||
|  | ||||
|         let spacing = themeNode.get_length('spacing'); | ||||
| @@ -1128,7 +1124,8 @@ const ThumbnailsBox = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _getPreferredWidth: function(actor, forHeight, alloc) { | ||||
|         this._ensurePorthole(); | ||||
|         if (this._thumbnails.length == 0) | ||||
|             return; | ||||
|  | ||||
|         let themeNode = this.actor.get_theme_node(); | ||||
|  | ||||
| @@ -1146,13 +1143,6 @@ const ThumbnailsBox = new Lang.Class({ | ||||
|         alloc.natural_size = width; | ||||
|     }, | ||||
|  | ||||
|     // The "porthole" is the portion of the screen that we show in the | ||||
|     // workspaces | ||||
|     _ensurePorthole: function() { | ||||
|         if (!this._porthole) | ||||
|             this._porthole = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex); | ||||
|     }, | ||||
|  | ||||
|     _allocate: function(actor, box, flags) { | ||||
|         let rtl = (Clutter.get_default_text_direction () == Clutter.TextDirection.RTL); | ||||
|  | ||||
|   | ||||
| @@ -21,11 +21,6 @@ const WORKSPACE_SWITCH_TIME = 0.25; | ||||
| // Note that mutter has a compile-time limit of 36 | ||||
| const MAX_WORKSPACES = 16; | ||||
|  | ||||
| const AnimationType = { | ||||
|     ZOOM: 0, | ||||
|     FADE: 1 | ||||
| }; | ||||
|  | ||||
| const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides'; | ||||
|  | ||||
| const WorkspacesViewBase = new Lang.Class({ | ||||
| @@ -79,12 +74,12 @@ const WorkspacesViewBase = new Lang.Class({ | ||||
|  | ||||
|     setFullGeometry: function(geom) { | ||||
|         this._fullGeometry = geom; | ||||
|         this._syncFullGeometry(); | ||||
|         this._syncGeometry(); | ||||
|     }, | ||||
|  | ||||
|     setActualGeometry: function(geom) { | ||||
|         this._actualGeometry = geom; | ||||
|         this._syncActualGeometry(); | ||||
|         this._syncGeometry(); | ||||
|     }, | ||||
| }); | ||||
|  | ||||
| @@ -99,7 +94,7 @@ const WorkspacesView = new Lang.Class({ | ||||
|         this._scrolling = false; // swipe-scrolling | ||||
|         this._animatingScroll = false; // programatically updating the adjustment | ||||
|  | ||||
|         this._settings = new Gio.Settings({ schema_id: OVERRIDE_SCHEMA }); | ||||
|         this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA }); | ||||
|  | ||||
|         let activeWorkspaceIndex = global.screen.get_active_workspace_index(); | ||||
|         this.scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex, | ||||
| @@ -132,12 +127,9 @@ const WorkspacesView = new Lang.Class({ | ||||
|             this._workspaces[i].setReservedSlot(clone); | ||||
|     }, | ||||
|  | ||||
|     _syncFullGeometry: function() { | ||||
|     _syncGeometry: function() { | ||||
|         for (let i = 0; i < this._workspaces.length; i++) | ||||
|             this._workspaces[i].setFullGeometry(this._fullGeometry); | ||||
|     }, | ||||
|  | ||||
|     _syncActualGeometry: function() { | ||||
|         for (let i = 0; i < this._workspaces.length; i++) | ||||
|             this._workspaces[i].setActualGeometry(this._actualGeometry); | ||||
|     }, | ||||
| @@ -147,25 +139,28 @@ const WorkspacesView = new Lang.Class({ | ||||
|         return this._workspaces[active]; | ||||
|     }, | ||||
|  | ||||
|     animateToOverview: function(animationType) { | ||||
|         for (let w = 0; w < this._workspaces.length; w++) { | ||||
|             if (animationType == AnimationType.ZOOM) | ||||
|                 this._workspaces[w].zoomToOverview(); | ||||
|             else | ||||
|                 this._workspaces[w].fadeToOverview(); | ||||
|         } | ||||
|     zoomToOverview: function() { | ||||
|         for (let w = 0; w < this._workspaces.length; w++) | ||||
|             this._workspaces[w].zoomToOverview(); | ||||
|         this._updateWorkspaceActors(false); | ||||
|     }, | ||||
|  | ||||
|     animateFromOverview: function(animationType) { | ||||
|     _leaveOverview: function() { | ||||
|         this.actor.remove_clip(); | ||||
|     }, | ||||
|  | ||||
|         for (let w = 0; w < this._workspaces.length; w++) { | ||||
|             if (animationType == AnimationType.ZOOM) | ||||
|                 this._workspaces[w].zoomFromOverview(); | ||||
|             else | ||||
|                 this._workspaces[w].fadeFromOverview(); | ||||
|         } | ||||
|     zoomFromOverview: function() { | ||||
|         this._leaveOverview(); | ||||
|         this._workspaces.forEach(function(w) { | ||||
|             w.zoomFromOverview(); | ||||
|         }); | ||||
|     }, | ||||
|  | ||||
|     fadeFromOverview: function() { | ||||
|         this._leaveOverview(); | ||||
|         this._workspaces.forEach(function(w) { | ||||
|             w.fadeFromOverview(); | ||||
|         }); | ||||
|     }, | ||||
|  | ||||
|     syncStacking: function(stackIndices) { | ||||
| @@ -276,12 +271,10 @@ const WorkspacesView = new Lang.Class({ | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (this._fullGeometry) { | ||||
|         if (this._fullGeometry) | ||||
|             this._updateWorkspaceActors(false); | ||||
|             this._syncFullGeometry(); | ||||
|         } | ||||
|         if (this._actualGeometry) | ||||
|             this._syncActualGeometry(); | ||||
|  | ||||
|         this._syncGeometry(); | ||||
|     }, | ||||
|  | ||||
|     _activeWorkspaceChanged: function(wm, from, to, direction) { | ||||
| @@ -370,26 +363,21 @@ const ExtraWorkspaceView = new Lang.Class({ | ||||
|         this._workspace.setReservedSlot(clone); | ||||
|     }, | ||||
|  | ||||
|     _syncFullGeometry: function() { | ||||
|     _syncGeometry: function() { | ||||
|         this._workspace.setFullGeometry(this._fullGeometry); | ||||
|     }, | ||||
|  | ||||
|     _syncActualGeometry: function() { | ||||
|         this._workspace.setActualGeometry(this._actualGeometry); | ||||
|     }, | ||||
|  | ||||
|     animateToOverview: function(animationType) { | ||||
|         if (animationType == AnimationType.ZOOM) | ||||
|             this._workspace.zoomToOverview(); | ||||
|         else | ||||
|             this._workspace.fadeToOverview(); | ||||
|     zoomToOverview: function() { | ||||
|         this._workspace.zoomToOverview(); | ||||
|     }, | ||||
|  | ||||
|     animateFromOverview: function(animationType) { | ||||
|         if (animationType == AnimationType.ZOOM) | ||||
|             this._workspace.zoomFromOverview(); | ||||
|         else | ||||
|             this._workspace.fadeFromOverview(); | ||||
|     zoomFromOverview: function() { | ||||
|         this._workspace.zoomFromOverview(); | ||||
|     }, | ||||
|  | ||||
|     fadeFromOverview: function() { | ||||
|         this._workspace.fadeFromOverview(); | ||||
|     }, | ||||
|  | ||||
|     syncStacking: function(stackIndices) { | ||||
| @@ -456,7 +444,7 @@ const WorkspacesDisplay = new Lang.Class({ | ||||
|         this._workspacesViews = []; | ||||
|         this._primaryScrollAdjustment = null; | ||||
|  | ||||
|         this._settings = new Gio.Settings({ schema_id: OVERRIDE_SCHEMA }); | ||||
|         this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA }); | ||||
|         this._settings.connect('changed::workspaces-only-on-primary', | ||||
|                                Lang.bind(this, | ||||
|                                          this._workspacesOnlyOnPrimaryChanged)); | ||||
| @@ -481,16 +469,10 @@ const WorkspacesDisplay = new Lang.Class({ | ||||
|         return this._getPrimaryView().actor.navigate_focus(from, direction, false); | ||||
|     }, | ||||
|  | ||||
|     show: function(fadeOnPrimary) { | ||||
|     show: function() { | ||||
|         this._updateWorkspacesViews(); | ||||
|         for (let i = 0; i < this._workspacesViews.length; i++) { | ||||
|             let animationType; | ||||
|             if (fadeOnPrimary && i == this._primaryIndex) | ||||
|                 animationType = AnimationType.FADE; | ||||
|             else | ||||
|                 animationType = AnimationType.ZOOM; | ||||
|             this._workspacesViews[i].animateToOverview(animationType); | ||||
|         } | ||||
|         for (let i = 0; i < this._workspacesViews.length; i++) | ||||
|             this._workspacesViews[i].zoomToOverview(); | ||||
|  | ||||
|         this._restackedNotifyId = | ||||
|             Main.overview.connect('windows-restacked', | ||||
| @@ -499,14 +481,17 @@ const WorkspacesDisplay = new Lang.Class({ | ||||
|             this._scrollEventId = Main.overview.connect('scroll-event', Lang.bind(this, this._onScrollEvent)); | ||||
|     }, | ||||
|  | ||||
|     animateFromOverview: function(fadeOnPrimary) { | ||||
|     leaveOverview: function(zoomPrimary) { | ||||
|         for (let i = 0; i < this._workspacesViews.length; i++) { | ||||
|             let animationType; | ||||
|             if (fadeOnPrimary && i == this._primaryIndex) | ||||
|                 animationType = AnimationType.FADE; | ||||
|             else | ||||
|                 animationType = AnimationType.ZOOM; | ||||
|             this._workspacesViews[i].animateFromOverview(animationType); | ||||
|             let view = this._workspacesViews[i]; | ||||
|             if (i == this._primaryIndex) { | ||||
|                 if (zoomPrimary) | ||||
|                     view.zoomFromOverview(); | ||||
|                 else | ||||
|                     view.fadeFromOverview(); | ||||
|             } else { | ||||
|                 view.zoomFromOverview(); | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|  | ||||
| @@ -637,9 +622,8 @@ const WorkspacesDisplay = new Lang.Class({ | ||||
|             return; | ||||
|  | ||||
|         let [x, y] = this.actor.get_transformed_position(); | ||||
|         let allocation = this.actor.allocation; | ||||
|         let width = allocation.x2 - allocation.x1; | ||||
|         let height = allocation.y2 - allocation.y1; | ||||
|         let width = this.actor.allocation.x2 - this.actor.allocation.x1; | ||||
|         let height = this.actor.allocation.y2 - this.actor.allocation.y1; | ||||
|         let primaryGeometry = { x: x, y: y, width: width, height: height }; | ||||
|  | ||||
|         let monitors = Main.layoutManager.monitors; | ||||
|   | ||||
| @@ -18,7 +18,7 @@ const XdndHandler = new Lang.Class({ | ||||
|  | ||||
|         // Used as a drag actor in case we don't have a cursor window clone | ||||
|         this._dummy = new Clutter.Actor({ width: 1, height: 1, opacity: 0 }); | ||||
|         Main.uiGroup.add_actor(this._dummy); | ||||
|         Main.layoutManager.sessionGroup.add_actor(this._dummy); | ||||
|         this._dummy.hide(); | ||||
|  | ||||
|         if (!Meta.is_wayland_compositor()) | ||||
| @@ -69,7 +69,7 @@ const XdndHandler = new Lang.Class({ | ||||
|                                                                    source: cursorWindow}); | ||||
|  | ||||
|             this._cursorWindowClone = new Clutter.Clone({ source: cursorWindow }); | ||||
|             Main.uiGroup.add_actor(this._cursorWindowClone); | ||||
|             Main.layoutManager.sessionGroup.add_actor(this._cursorWindowClone); | ||||
|  | ||||
|             // Make sure that the clone has the same position as the source | ||||
|             this._cursorWindowClone.add_constraint(constraint_position); | ||||
|   | ||||
| @@ -33,7 +33,6 @@ id | ||||
| it | ||||
| ja | ||||
| kk | ||||
| km | ||||
| kn | ||||
| ko | ||||
| ku | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user