Compare commits
	
		
			50 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					eb695d6c3d | ||
| 
						 | 
					810f35c498 | ||
| 
						 | 
					78dae21171 | ||
| 
						 | 
					257c852908 | ||
| 
						 | 
					e6b218ed0f | ||
| 
						 | 
					6c1793b247 | ||
| 
						 | 
					26df2dfc14 | ||
| 
						 | 
					38829f7405 | ||
| 
						 | 
					485d773fdf | ||
| 
						 | 
					1826108cb5 | ||
| 
						 | 
					71801841e9 | ||
| 
						 | 
					9e8dbe76a9 | ||
| 
						 | 
					2420fd343b | ||
| 
						 | 
					bbd049b073 | ||
| 
						 | 
					6bdd3f6cf6 | ||
| 
						 | 
					e9d518fc3b | ||
| 
						 | 
					73f7991264 | ||
| 
						 | 
					976f26cb26 | ||
| 
						 | 
					1278e31b65 | ||
| 
						 | 
					92f27a3c00 | ||
| 
						 | 
					28667a686d | ||
| 
						 | 
					783683a12c | ||
| 
						 | 
					fc70446050 | ||
| 
						 | 
					70ab08aefd | ||
| 
						 | 
					ca6308ae64 | ||
| 
						 | 
					4dcbb84f06 | ||
| 
						 | 
					f4e6f7074e | ||
| 
						 | 
					0d92f2b0c5 | ||
| 
						 | 
					2afb4cc124 | ||
| 
						 | 
					762b0e45e0 | ||
| 
						 | 
					a7acd3b535 | ||
| 
						 | 
					ccc4b20e83 | ||
| 
						 | 
					8dd45bea1c | ||
| 
						 | 
					0c80f8cec4 | ||
| 
						 | 
					27508864bf | ||
| 
						 | 
					117be3b14d | ||
| 
						 | 
					4bc2f9b5e6 | ||
| 
						 | 
					ba5c45deaf | ||
| 
						 | 
					941246a4f0 | ||
| 
						 | 
					7feef56656 | ||
| 
						 | 
					9a2a07f32a | ||
| 
						 | 
					af9594c902 | ||
| 
						 | 
					569008b084 | ||
| 
						 | 
					0e086563bc | ||
| 
						 | 
					91d4a832ad | ||
| 
						 | 
					832ce362f0 | ||
| 
						 | 
					aa04e453b8 | ||
| 
						 | 
					b0a75aed95 | ||
| 
						 | 
					dba97f36c0 | ||
| 
						 | 
					2560b37819 | 
							
								
								
									
										27
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						@@ -3,7 +3,6 @@
 | 
			
		||||
*.o
 | 
			
		||||
.deps
 | 
			
		||||
.libs
 | 
			
		||||
ABOUT-NLS
 | 
			
		||||
ChangeLog
 | 
			
		||||
INSTALL
 | 
			
		||||
Makefile
 | 
			
		||||
@@ -18,26 +17,9 @@ config
 | 
			
		||||
configure
 | 
			
		||||
data/gnome-shell.desktop
 | 
			
		||||
data/gnome-shell.desktop.in
 | 
			
		||||
data/gnome-shell-extension-prefs.desktop
 | 
			
		||||
data/gnome-shell-extension-prefs.desktop.in
 | 
			
		||||
data/gschemas.compiled
 | 
			
		||||
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
 | 
			
		||||
docs/reference/*/*.args
 | 
			
		||||
docs/reference/*/*.bak
 | 
			
		||||
docs/reference/*/*.hierarchy
 | 
			
		||||
docs/reference/*/*.interfaces
 | 
			
		||||
docs/reference/*/*.prerequisites
 | 
			
		||||
docs/reference/*/*.sgml
 | 
			
		||||
docs/reference/*/*.signals
 | 
			
		||||
docs/reference/*/*.stamp
 | 
			
		||||
docs/reference/*/*.txt
 | 
			
		||||
docs/reference/*/*.types
 | 
			
		||||
docs/reference/*/html/
 | 
			
		||||
docs/reference/*/xml/
 | 
			
		||||
gtk-doc.make
 | 
			
		||||
js/misc/config.js
 | 
			
		||||
intltool-extract.in
 | 
			
		||||
intltool-merge.in
 | 
			
		||||
@@ -47,13 +29,8 @@ m4/
 | 
			
		||||
omf.make
 | 
			
		||||
po/*.gmo
 | 
			
		||||
po/gnome-shell.pot
 | 
			
		||||
po/*.header
 | 
			
		||||
po/*.sed
 | 
			
		||||
po/*.sin
 | 
			
		||||
po/Makefile.in.in
 | 
			
		||||
po/Makevars.template
 | 
			
		||||
po/POTFILES
 | 
			
		||||
po/Rules-quot
 | 
			
		||||
po/stamp-it
 | 
			
		||||
scripts/launcher.pyc
 | 
			
		||||
src/*.gir
 | 
			
		||||
@@ -66,13 +43,9 @@ src/calendar-server/org.gnome.Shell.CalendarServer.service
 | 
			
		||||
src/gnome-shell
 | 
			
		||||
src/gnome-shell-calendar-server
 | 
			
		||||
src/gnome-shell-extension-tool
 | 
			
		||||
src/gnome-shell-extension-prefs
 | 
			
		||||
src/gnome-shell-hotplug-sniffer
 | 
			
		||||
src/gnome-shell-jhbuild
 | 
			
		||||
src/gnome-shell-perf-helper
 | 
			
		||||
src/gnome-shell-perf-tool
 | 
			
		||||
src/gnome-shell-real
 | 
			
		||||
src/hotplug-sniffer/org.gnome.Shell.HotplugSniffer.service
 | 
			
		||||
src/run-js-test
 | 
			
		||||
src/test-recorder
 | 
			
		||||
src/test-recorder.ogg
 | 
			
		||||
 
 | 
			
		||||
@@ -3,5 +3,5 @@ E-mail: otaylor@redhat.com
 | 
			
		||||
Userid: otaylor
 | 
			
		||||
 | 
			
		||||
Colin Walters
 | 
			
		||||
E-mail: walters@verbum.org
 | 
			
		||||
E-mail: walters@redhat.com
 | 
			
		||||
Userid: walters
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
# Point to our macro directory and pick up user flags from the environment
 | 
			
		||||
ACLOCAL_AMFLAGS  = -I m4 ${ACLOCAL_FLAGS}
 | 
			
		||||
 | 
			
		||||
SUBDIRS = data js src browser-plugin tests po man docs
 | 
			
		||||
SUBDIRS = data js src tests po man
 | 
			
		||||
 | 
			
		||||
EXTRA_DIST =		\
 | 
			
		||||
	.project	\
 | 
			
		||||
@@ -19,5 +19,3 @@ DIST_EXCLUDE =					\
 | 
			
		||||
distcheck-hook:
 | 
			
		||||
	@echo "Checking disted files against files in git"
 | 
			
		||||
	@$(srcdir)/tools/check-for-missing.py $(srcdir) $(distdir) $(DIST_EXCLUDE)
 | 
			
		||||
 | 
			
		||||
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										881
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						@@ -1,883 +1,6 @@
 | 
			
		||||
3.5.2
 | 
			
		||||
=====
 | 
			
		||||
* main: Move 'toggle-recording' binding into the shell [Florian; #674377]
 | 
			
		||||
* popupMenu: make sure to break the grab when the slider is not visible
 | 
			
		||||
  [Stefano; #672713]
 | 
			
		||||
* st-theme-node-drawing: Don't use GL types [Neil; #672711]
 | 
			
		||||
* Mirror Evolution calendar settings into our own schema [Owen; #674424]
 | 
			
		||||
* shell-network-agent: don't crash if a request isn't found [Dan; #674961]
 | 
			
		||||
* notificationDaemon: Match app based on WM_CLASS [Jasper; #673761]
 | 
			
		||||
* NetworkMenu: use network-offline while loading [Giovanni; #674426]
 | 
			
		||||
* lookingGlass: Remove the Errors tab [Jasper; #675104]
 | 
			
		||||
* searchDisplay: Reset keyboard focus after displaying async results
 | 
			
		||||
  [Rui; #675078]
 | 
			
		||||
* gdm: don't fail if fprintd is unavailable [Ray; #675006]
 | 
			
		||||
* messageTray: Fix scrolling up [Jasper; #661615]
 | 
			
		||||
* main: Close the recorder instead of pausing it [Rui; #675128]
 | 
			
		||||
* Accessibility [Alejandro]
 | 
			
		||||
  - Use the proper label_actor for date menu on top panel [#675307]
 | 
			
		||||
  - Set the proper role/label_actor for SearchResult.content [#672242]
 | 
			
		||||
  - do not expose a label text if 'hidden' style class is used [#675341]
 | 
			
		||||
* Magnifier: Add brightness and contrast functionality [Joseph; #639851]
 | 
			
		||||
* theme: use a smaller border-radius for top bar [Jakub; #672430]
 | 
			
		||||
* placeDisplay: use new bookmark file location [Matthias; #675443]
 | 
			
		||||
* port all synchronous search providers to the async API [Jasper, Rui; #675328]
 | 
			
		||||
* NetworkAgent: disallow multiple requests for the same connection/setting
 | 
			
		||||
  [Giovanni; #674961]
 | 
			
		||||
* userMenu: Update to latest mockups [Florian; #675802]
 | 
			
		||||
* util: Don't double-fork when spawning from Alt-F2 [Colin; #675789]
 | 
			
		||||
* messageTray: Make Source usable without subclassing [Jasper; #661236]
 | 
			
		||||
* panel: Check for appMenu button's reactivity before opening [Florian; #676316]
 | 
			
		||||
* Fix formatting of bluetooth passkey [Florian; #651251]
 | 
			
		||||
* notificationDaemon: Filter out file-transfer notifications [Jasper; #676175]
 | 
			
		||||
* Don't use global.log() [Jasper; #675790]
 | 
			
		||||
* Fix broken extension loading in some distributions [Owen, Alexandre; #670477]
 | 
			
		||||
* shell-app: Raise windows in reverse order to preserve the stacking
 | 
			
		||||
  [Rui; #676371]
 | 
			
		||||
* Generalize gdm-mode [Florian; #676156]
 | 
			
		||||
* Switch string formatting to the one inside gjs [Jasper; #675479]
 | 
			
		||||
* extensionUtils: Support subdirectories in getCurrentExtension
 | 
			
		||||
  [Jasper; #677001]
 | 
			
		||||
* panel: Refuse to add (legacy) status icons not part of the session mode
 | 
			
		||||
  [Florian; #677058]
 | 
			
		||||
* Add an initial-setup mode [Matthias; #676697]
 | 
			
		||||
* status/keyboard: Port to the new input sources settings [Rui; #641531]
 | 
			
		||||
* NetworkMenu: show notifications for failed VPN connections [Giovanni; #676330]
 | 
			
		||||
* userMenu: Indicate progress on status changes [Florian; #659067]
 | 
			
		||||
* recorder: Honor "disable-save-to-disk" lockdown key [Rūdolfs; #673630]
 | 
			
		||||
* searchDisplay: Use the rowLimit we pass to the IconGrid [Christian; #675527]
 | 
			
		||||
* endSessionDialog: Factor out _updateDescription from _updateContent
 | 
			
		||||
  [Alejandro; #674210]
 | 
			
		||||
* Fix empathy's appMenu freezing the shell [Alban; #676447]
 | 
			
		||||
* Code cleanups [Florian, Giovanni, Jasper; #672807, #672413, #676837, #676850,
 | 
			
		||||
  #672272]
 | 
			
		||||
* Misc bug fixes [Alban, Florian, Giovanni, Guillaume, Jasper, Piotr, Rico,
 | 
			
		||||
  Ron, Rui, Stefano; #659968, #672192, #673177, #673198, #674323, #675301,
 | 
			
		||||
  #675370, #676347, #676806, #677097]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
 Alban Browaeys, Giovanni Campagna, Matthias Clasen, Guillaume Desmottes,
 | 
			
		||||
 Piotr Drąg, Stefano Facchini, Rui Matos, Rūdolfs Mazurs, Florian Müllner,
 | 
			
		||||
 Alejandro Piñeiro, Neil Roberts, Alexandre Rostovtsev, Joseph Scheuhammer,
 | 
			
		||||
 Jakub Steiner, Jasper St. Pierre, Ray Strode, Owen Taylor, Rico Tzschichholz,
 | 
			
		||||
 Colin Walters, Dan Winship, Ron Yorston
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
 OKANO Takayoshi [ja], Daniel Mustieles [es], Changwoo Ryu [ko],
 | 
			
		||||
 Yaron Shahrabani [he], Fran Diéguez [gl], Jonh Wendell [pt_BR],
 | 
			
		||||
 Kjartan Maraas [nb], Luca Ferretti [it], Tom Tryfonidis [el],
 | 
			
		||||
 Sandeep Sheshrao Shedmake [mr], Takanori MATSUURA [ja], Dirgita [id],
 | 
			
		||||
 Mantas Kriaučiūnas [lt], Matej Urbančič [sl], Jiro Matsuzawa [ja]
 | 
			
		||||
 | 
			
		||||
3.4.1
 | 
			
		||||
=====
 | 
			
		||||
* Fix crash that occurred when an icon theme change caused unexpected
 | 
			
		||||
  reentrancy in the icon loading code [Jasper; #673512]
 | 
			
		||||
* Don't show system and other disabled users in the GDM user list
 | 
			
		||||
  [Adel; #673784]
 | 
			
		||||
* Make gnome-shell-calendar-server initialize GTK+ so it can display
 | 
			
		||||
  password prompts if needed [#673608; Owen, Rico]
 | 
			
		||||
* Adapt to Mutter API change for keybinding addition [Florian; #673014]
 | 
			
		||||
* Fix crash when an extension was installed as both a user extension
 | 
			
		||||
  and a system extension [#673613; Jasper]
 | 
			
		||||
* Fix bug where chat entry could end up partially offscreen [Joost, 661944]
 | 
			
		||||
* Fix problem where icons weren't updating when theme was changed
 | 
			
		||||
  [#672941; Florian]
 | 
			
		||||
* Look for Evolution calendar settings in GSettings, not GConf [#673610; Owen]
 | 
			
		||||
* Add <super>F10 for the application menu [#672909; Florian]
 | 
			
		||||
* Fix %Id format characters to work in translations [#673106; Cosimo]
 | 
			
		||||
  (were already used in fa translation)
 | 
			
		||||
* Fix error when NetworkManager restarts [#673043; Giovanni]
 | 
			
		||||
* Improve efficiency of overview redraws by working around Clutter issue
 | 
			
		||||
  [Stefano; #670636]
 | 
			
		||||
* Misc bug fixes [Florian, Giovanni, Jasper, Rui, Stefano;
 | 
			
		||||
  #672592, #672641, #672719, #673187, #673233, #673656]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
 Giovanni Campagna, Cosimo Cecchi, Stefano Facchini, Adel Gadllah, Rui Matos,
 | 
			
		||||
 Florian Müllner, Jasper St. Pierre, Owen Taylor, Rico Tzschichholz,
 | 
			
		||||
 Joost Verdoorn
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
 Khaled Hosny [ar], Ihar Hrachyshka [be], Alexander Shopov [bg], Gil Forcada,
 | 
			
		||||
 Jordi Serratosa [ca], Petr Kovar [cs], Bruce Cowan [en_GB],
 | 
			
		||||
 Carles Ferrando [ca@valencia], Wolfgang Stöggl [de], Daniel Mustieles [es],
 | 
			
		||||
 Arash Mousavi [fa], Bruno Brouard [fr], Fran Diéguez [gl],
 | 
			
		||||
 Sweta Kothari [gu], Yaron Shahrabani [he], Gabor Kelemen [hu],
 | 
			
		||||
 Shankar Prasad [kn], Žygimantas Beručka [lt], Rudolfs Mazurs [lv],
 | 
			
		||||
 Sandeep Sheshrao Shedmake [mr], Kjartan Maraas [nb], Piotr Drąg [pl],
 | 
			
		||||
 Yuri Myasoedov [ru], Daniel Nylander [se], Matej Urbančič [sl],
 | 
			
		||||
 Miroslav Nikolić [sr], Sasi Bhushan, Praveen Illa [te], Yinghua Wang [zh_CN]
 | 
			
		||||
 | 
			
		||||
3.4.0
 | 
			
		||||
=====
 | 
			
		||||
* Don't crash when taking screenshots [Jasper; #672775]
 | 
			
		||||
* Fix dialog-resizing problem [Florian; #672543]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
 Florian Müllner, Jasper St. Pierre
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
 Khaled Hosny, Abderrahim Kitouni [ar], Ihar Hrachyshka [be],
 | 
			
		||||
 Alexander Shopov [bg], Marek Černocký [cs], Jiri Grönroos, Timo Jyrinki [fi],
 | 
			
		||||
 Bruno Brouard [fr], Fran Diéguez [gl], Yaron Shahrabani [he],
 | 
			
		||||
 Gabor Kelemen [hu], Jiro Matsuzawa [ja], Kenneth Nielsen [dk],
 | 
			
		||||
 Mattias Põldaru [et], Changwoo Ryu [ko], Rudolfs Mazurs [lv],
 | 
			
		||||
 Jonh Wendell [pt_BR], Yuri Myasoedov[ru], Daniel Korostil [uk],
 | 
			
		||||
 Nguyễn Thái Ngọc Duy [vi], Chao-Hsiung Liao [zh_HK, zh_TW]
 | 
			
		||||
 | 
			
		||||
3.3.92
 | 
			
		||||
======
 | 
			
		||||
* Add shell-dialogs for GNOME Keyring prompts [Stef; #652459, #652460, #671034]
 | 
			
		||||
* When the user returns from idle, bring up the message tray if there were
 | 
			
		||||
  messages while they were away [Marina; #643014]
 | 
			
		||||
* https://live.gnome.org/EveryDetailMatters
 | 
			
		||||
  - Make the workspace thumbnails clickable all the way to the edge of the
 | 
			
		||||
    screen [Stefano; #643319]
 | 
			
		||||
  - Don't slide out the workspace thumbnails if the mouse is over them when
 | 
			
		||||
    entering the overview [Joost, #651092]
 | 
			
		||||
  - Fix placeholder jumps while dragging a dash item [Joost; #651842]
 | 
			
		||||
  - Don't favorite apps if they are dropped back at the same position
 | 
			
		||||
    [Jean-Philippe; #656333]
 | 
			
		||||
  - To avoid confusion, don't allow removing running apps from favorites
 | 
			
		||||
    [Florian; #644853]
 | 
			
		||||
  - Fix creation of new workspaces by dragging application launchers
 | 
			
		||||
    [Stefano; #664202]
 | 
			
		||||
  - Make it easier to drag dash items without triggering the menu
 | 
			
		||||
    [Florian; #637103]
 | 
			
		||||
* Accessibility [Alejandro]
 | 
			
		||||
  - Add StWidget API for easily adding accessible states and setting roles,
 | 
			
		||||
    names [#668366, #667432, #671378]
 | 
			
		||||
  - Set accessibility information on UI elements
 | 
			
		||||
    [#644255, #667432, #668361, #672047, #670308, #670312, #670719, #671404]
 | 
			
		||||
* Improve key-navigation in the overview [Rui, Florian; #663901]
 | 
			
		||||
* Key navigation bug fixes [Rui, Florian; #662493, #663437, #665215, #671998]
 | 
			
		||||
* Honor a 'org.gnome.shell.overrides.dynamic-workspaces' setting that
 | 
			
		||||
  determines whether the workspace count is dynamic and unsaved in GSettings
 | 
			
		||||
  or static and saved. [Florian; #671568]
 | 
			
		||||
* Avoid saving user presence to GSettings when not necessary
 | 
			
		||||
  [Florian; #665701, #668214]
 | 
			
		||||
* Save screencasts in the users Videos/ directory [Adel; #670749]
 | 
			
		||||
  Use a "human readable" filename [Florian, Adel, Ray; #670753]
 | 
			
		||||
* Allow dragging from the empty part of the top panel to unmaximize a window
 | 
			
		||||
  [Florian; #666359]
 | 
			
		||||
* Fix hangs that could occur when switching away to a VT [Ray; #653833]
 | 
			
		||||
* Fix problems with installing from extensions.gnome.org [Giovanni; #671134]
 | 
			
		||||
* Fix locking the screen when suspending via menu [David, Gert; #670820]
 | 
			
		||||
* Fix browser plugin with Konqueror and Opera [Jasper]
 | 
			
		||||
* Fix shell restart not to bring up failure screen [Giovanni; #648384]
 | 
			
		||||
* Reorganize and clean up CSS theming [Allan; #668209]
 | 
			
		||||
* Improve appearance of modal dialogs [Allan, Florian; #670227, #668209]
 | 
			
		||||
* Update the calendar code to use ECalClient [Giovanni; #671177]
 | 
			
		||||
* Update jhbuild script to use the main moduleset [Owen, Will; #668440]
 | 
			
		||||
* StTextureCache: code cleanup, evict unused icons, merge together
 | 
			
		||||
  simulataneous requests for the same icon [Jasper; #670771, #671656, #672273]
 | 
			
		||||
* Clean up St for recent Clutter changes and fix bugs. StContainer and
 | 
			
		||||
  StGroup are removed [Jasper, Florian; #670034, #670640, #670904]
 | 
			
		||||
* Code cleanup [Adel, Jasper, Rui; #613194, #671086, #671103]
 | 
			
		||||
* Misc bug fixes
 | 
			
		||||
  [Adel, Colin G, Cosimo, Florian, Giovanni, Jasper, Marius, Rui, Stefano;
 | 
			
		||||
  #651130, #658946, #667552, #670076, #671001, #670979, #671410, #671411,
 | 
			
		||||
  #671556, #671656, #671657, #672011, #672024, #672240, #672265, #672270,
 | 
			
		||||
  #672321, #672326, #672413, #672471]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
 Jean-Philippe Braun, Giovanni Campagna, Cosimo Cecchi, Allan Day,
 | 
			
		||||
 Stefano Facchini, David Foerster, Adel Gadllah, Marius Gedminas,
 | 
			
		||||
 Colin Guthrie, Gert Michael Kulyk, William Lachance, Rui Matos,
 | 
			
		||||
 Florian Müllner, Alejandro Piñeiro, Jan Alexander Steffens,
 | 
			
		||||
 Jasper St. Pierre, Ray Strode, Owen Taylor, Joost Verdoorn, Stef Walter,
 | 
			
		||||
 Marina Zhurakhinskaya
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
 Nilamdyuti Goswami [as], Ihar Hrachyshka, Kasia Bondarava [be],
 | 
			
		||||
 Alexander Shopov, Ivaylo Valkov [bg], Gil Forcada [ca], Marek Černocký [cs],
 | 
			
		||||
 Mario Blättermann [de], Kris Thomsen [dk], Bruce Cowan [en_GB],
 | 
			
		||||
 Kristjan Schmidt [eo], Daniel Mustieles [es], Mattias Põldaru [et],
 | 
			
		||||
 Inaki Larranaga Murgoitio [eu], Arash Mousavi [fa], Timo Jyrinki [fi],
 | 
			
		||||
 Bruno Brouard [fr], Fran Diéguez [gl], Sweta Kothari [gu],
 | 
			
		||||
 Yaron Shahrabani [he], Gabor Kelemen [hu], Jiro Matsuzawa [ja],
 | 
			
		||||
 Baurzhan Muftakhidinov [kk], Seong-ho Cho [ko], Žygimantas Beručka [lt],
 | 
			
		||||
 Anita Reitere [lv], Anish A, Praveen Arimbrathodiyil, Mohammed Sadiq [ml],
 | 
			
		||||
 fKjartan Maraas [nb], Wouter Bolsterlee [nl], A S Alam [pa], Piotr Drąg [pl],
 | 
			
		||||
 Duarte Loreto [pt], Jonh Wendell [pt_BR], Yuri Myasoedov [ru],
 | 
			
		||||
 Matej Urbančič [sl], Miroslav Nikolić [sr], Tirumurti Vasudevan [ta],
 | 
			
		||||
 Sasi Bhushan, Krishnababu Krothapalli [te], Daniel Korostil [uk],
 | 
			
		||||
 Nguyễn Thái Ngọc Duy [vi], YunQiang Su, Yinghua Wang [zh_CN],
 | 
			
		||||
 Chao-Hsiung Liao [zh_HK, zh_TW]
 | 
			
		||||
 | 
			
		||||
3.3.90
 | 
			
		||||
======
 | 
			
		||||
 | 
			
		||||
* Allow other applications to implement search providers via D-Bus
 | 
			
		||||
  [Florian; #663125, #670148]
 | 
			
		||||
* Remove "Recent Items" search, as replaced by Documents search
 | 
			
		||||
  [Florian; #663125]
 | 
			
		||||
* Allow NetworkManager VPN plugins to use a shell-themed dialog
 | 
			
		||||
  [Giovanni; #658484]
 | 
			
		||||
* Port away from deprecated Clutter API [Jasper, Florian, Adel; #670034]
 | 
			
		||||
  - StTooltip is removed
 | 
			
		||||
  - StWidget is now a concrete class and can be instantiated
 | 
			
		||||
  - st_container_destroy_children(), st_box_layout_insert_actor(),
 | 
			
		||||
    and other functions removed in favor of new replacements in Clutter.
 | 
			
		||||
* Use systemd for console/session handling when available [Lennart]
 | 
			
		||||
* Visual improvements to contact search, padding, top panel, checkboxes
 | 
			
		||||
  [Allan, Florian, Jakub; #669489, #669811, #669993]
 | 
			
		||||
* Add a include_cursor parameter to Screenshot and ScreenshotWindow
 | 
			
		||||
  D-Bus methods [Adel; #670086]
 | 
			
		||||
* Add a "FlashArea" D-Bus method to do the screenshot flash without a
 | 
			
		||||
  screenshot [Adel; #669660]
 | 
			
		||||
* Build fixes [Adel, Giovanni, Jasper; #658484, #669637]
 | 
			
		||||
* Misc bug fixes [Adel, Florian, Giovanni, Guillaume, Jasper, Jeff,
 | 
			
		||||
  Marc-Antoine, Stef, Stefano, Will; #642135, #658484, #658908, #667694,
 | 
			
		||||
  #669098, #669921, #669662, #669694, #669776, #669887, #669921, #670005,
 | 
			
		||||
  #670006, #670319, #670418, #670489]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
 Giovanni Campagna, Cosimo Cecchi, Allan Day, Guillaume Desmottes, Jeff Epler,
 | 
			
		||||
 Stefano Facchini, Adel Gadllah, Florian Müllner, Marc-Antoine Perennou,
 | 
			
		||||
 Jasper St. Pierre, Lennart Poettering, Jakub Steiner, Jasper St. Pierre,
 | 
			
		||||
 Will Thompson, Stef Walter
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
 Ihar Hrachyshka [be], Marek Černocký, Adam Matoušek [cs],
 | 
			
		||||
 Kenneth Nielsen [dk], Daniel Mustieles [es], Mattias Põldaru [et],
 | 
			
		||||
 Fran Diéguez [gl], Yaron Shahrabani [he], Luca Ferretti [it],
 | 
			
		||||
 Baurzhan Muftakhidinov [kk], Aurimas Černius [lt], Kjartan Maraas [nb],
 | 
			
		||||
 A S Alam [pa], Matej Urbančič [sl], Miroslav Nikolić [sr],
 | 
			
		||||
 Praveen Illa [te], Chao-Hsiung Liao [zh_HK, zh_TW]
 | 
			
		||||
 | 
			
		||||
3.3.5
 | 
			
		||||
=====
 | 
			
		||||
 | 
			
		||||
* Extension system: [Jasper; #668429]
 | 
			
		||||
  http://blog.mecheye.net/2012/02/more-extension-api-breaks/
 | 
			
		||||
 - Add a 'gnome-shell-extension-prefs' application for displaying extension
 | 
			
		||||
   preferences as provided by the extension in a prefs.js file.
 | 
			
		||||
 - Allow launching gnome-shell-extension-prefs from extensions.gnome.org
 | 
			
		||||
   throuhg the browser plugin.
 | 
			
		||||
 - Add ExtensionUtils.getCurrentExtension() for an extension to get a
 | 
			
		||||
   handle to an extension object, to get local imports or paths.
 | 
			
		||||
 - Add an onshellrestart callback to the browser plugin [Jasper; #668517]
 | 
			
		||||
* Screenshots:
 | 
			
		||||
  - Move the screenshot "flash" to the shell [Cosimo; #668618]
 | 
			
		||||
  - Move saving screenshots to a thread [Adel; #652952]
 | 
			
		||||
  - Correctly screenshot rounded decorations [Jasper; #662486]
 | 
			
		||||
* Screen recorder:
 | 
			
		||||
  - Change the default pipeline to favor speed over quality [Owen; #669066]
 | 
			
		||||
  - Drop frames to keep from running the user out of memory [Owen; #669066]
 | 
			
		||||
* Work around a slow implementation of glReadPixels() in the Intel drivers,
 | 
			
		||||
  improving performance for screenshots and the screen recorder.
 | 
			
		||||
  [Owen; #669065]
 | 
			
		||||
* Use Keywords: field in desktop files when search for applications
 | 
			
		||||
  [Florian; #609702]
 | 
			
		||||
* Strip debian- when matching desktop file names [Jasper; #665647]
 | 
			
		||||
* Fix up various problems from CSS background size-addition
 | 
			
		||||
  [Florian, Jasper; #668430, #633462]
 | 
			
		||||
* UI tweaks and behavior fixes
 | 
			
		||||
  [Florian, Giovanni, Stefano; #643867, #666197, #664622]
 | 
			
		||||
* Some improvements to exported accessibility information  [Alejando; #667376]
 | 
			
		||||
* Don't show contacts without IM information as offline [Florian; #662685]
 | 
			
		||||
* Don't change status from hidden to extended_away when going idle
 | 
			
		||||
  [Florian; #642408]
 | 
			
		||||
* Cleanups [Emmanuele, Jasper; #662152, #669239]
 | 
			
		||||
* Misc bug fixes [Cosimo, Dan, Florian, Jasper, Rui, Stefano;
 | 
			
		||||
  #633462, #643867, #662213, #662386, #662747, #665000, #665017, #665322,
 | 
			
		||||
  #667371, #667860, #668020, #668517, #668541, #669236]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
 Emmanuele Bassi, Giovanni Campagna, Cosimo Cecchi, Stefano Facchini,
 | 
			
		||||
 Adel Gadllah, Rui Matos, Florian Müllner, Alejandro Piñeiro,
 | 
			
		||||
 Jasper St. Pierre, Owen Taylor, Dan Winship
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
 Daniel Mustieles [es], Timo Jyrinki [fi], Seán de Búrca [ga],
 | 
			
		||||
 Fran Diéguez [gl], Kjartan Maraas [nb], Wouter Bolsterlee [nl],
 | 
			
		||||
 Danishka Navin [si], Yaron Shahrabani [he], Matej Urbančič [sl],
 | 
			
		||||
 Chao-Hsiung Liao [zh_HK, zh_TW]
 | 
			
		||||
 | 
			
		||||
3.3.4
 | 
			
		||||
=====
 | 
			
		||||
* https://live.gnome.org/EveryDetailMatters
 | 
			
		||||
  - Add "browse" for labels for dash items - once a tooltip is
 | 
			
		||||
    showing, switch to other items without a delay [Seif; #666170]
 | 
			
		||||
  - Always scale down windows in the overview at least to 70% [Vit; #646704]
 | 
			
		||||
  - Fix the new-workspace drop indicator sometimes getting stuck
 | 
			
		||||
    [Stefano; #664201]
 | 
			
		||||
  - Delay rearranging windows in the overview as long as the pointer
 | 
			
		||||
    is over a window [Vit; #645325]
 | 
			
		||||
* Add a GConf => DConf migration file for overriden Mutter settings
 | 
			
		||||
  [Florian; #667636]
 | 
			
		||||
* When a VPN connection is active, show that as the network icon
 | 
			
		||||
  [Giovanni; #665115]
 | 
			
		||||
* Handle the "ExtendedAway" IM status as away, not offline [Guillaume; #667813]
 | 
			
		||||
* Improve the appearance of the labels in "Applications" [Alex; #642392]
 | 
			
		||||
* Adjust for GTK+ and Mutter API changes for application menu [Ryan; #668118]
 | 
			
		||||
* Add section label support to the application menu [Giovanni; #666681]
 | 
			
		||||
* Fix screenshot methods to work again [Cosimo; #667662]
 | 
			
		||||
* Fix several crashers related to updating workspace thumbnails [Owen; #667652]
 | 
			
		||||
* Fix memory management error causing gnome-shell-hotplug-sniffer to crash
 | 
			
		||||
  [Owen; #667378]
 | 
			
		||||
* Build fixes [Emmanuele, Rico; #667864]
 | 
			
		||||
* Code cleanups [Adel; #668087]
 | 
			
		||||
* Misc bug fixes [Colin, Florian, Giovanni, Owen, Xavier; #633028, #658817,
 | 
			
		||||
  #664138, #667881, #668048, #668050]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
 Emmanuele Bassi, Giovanni Campagna, Cosimo Cecchi, Xavier Claessens,
 | 
			
		||||
 Guillaume Desmottes, Stefano Facchini, Adel Gadllah, Alex Hultman,
 | 
			
		||||
 Ryan Lortie, Seif Lotfy, Florian Müllner, Vit Stanislav, Owen Taylor,
 | 
			
		||||
 Rico Tzschichholz, Colin Walters
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
 Ihar Hrachyshka [be], Alexander Shopov [bg], Arash Mousavi [fa],
 | 
			
		||||
 Jiri Grönroos, Timo Jyrinki [fi], Fran Diéguez [gl], Kjartan Maraas [nb],
 | 
			
		||||
 Yuri Myasoedov [ru], Matej Urbančič [sl], Nguyễn Thái Ngọc Duy [vi]
 | 
			
		||||
 | 
			
		||||
3.3.3
 | 
			
		||||
=====
 | 
			
		||||
* https://live.gnome.org/EveryDetailMatters
 | 
			
		||||
  - Stop flashing the window labels on actions in overview [Zan; #644861]
 | 
			
		||||
  - Improve the look of window captions in the overview [Marc; #664487]
 | 
			
		||||
  - Move dash tooltips beside the icon [Seif, Stefano; #666166]
 | 
			
		||||
* Support application menus exported from applications via new GLib API
 | 
			
		||||
   and D-Bus protocol. [Giovanni, Colin, Matthias, Cosimo]
 | 
			
		||||
* For removable device prompts, show "Open with Rhythmbox], rather
 | 
			
		||||
  than "Open with Rhythmbox Music Player' [Florian; #664561]
 | 
			
		||||
* Switch to activating the message tray only with a hot corner rather
 | 
			
		||||
  than a full row of pixels, allowing mouse events to apps [Rui; #663366]
 | 
			
		||||
* Fully handle the case where the workspaces-only-on-primary
 | 
			
		||||
  GSetting is set to false [Florian; #652580]
 | 
			
		||||
* Add support for background-size CSS property to St [Quentin; #633462]
 | 
			
		||||
* Port to new GJS Lang.Class framework [Giovanni; #664436]
 | 
			
		||||
* Finish port to GDBus [Giovanni; #664436]
 | 
			
		||||
* Stop using the deprecated Clutter default stage [Florian, Jasper; #664052]
 | 
			
		||||
* Fix bugs that kept browser plugin from working in WebKit-based browser
 | 
			
		||||
  [Jasper; #666444]
 | 
			
		||||
* Fix typo that made uninstalling extensions not work [Jasper]
 | 
			
		||||
* Fix crash in browser plugin if shell is not run [Jürg]
 | 
			
		||||
* Reintroduce piscine paschal ovum [Giovanni; #666606]
 | 
			
		||||
* Network menu bug fixes
 | 
			
		||||
  Giovanni; #664124, #665194, #665680, #666429, #666614]
 | 
			
		||||
* Misc bug fixes [Florian, Jasper, Jonny, Marina, Ron; #647587, #659272,
 | 
			
		||||
  #664138, #665261, #666020, #666243]
 | 
			
		||||
* Build fixes [Owen]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
 Jürg Billeter, Giovanni Campagna, Stefano Candori, Cosimo Cecchi,
 | 
			
		||||
 Matthias Clasen, Zan Dobersek, Quentin Glidic, Jonny Lamb, Ryan Lortie,
 | 
			
		||||
 Seif Lotfy, Rui Matos, Florian Müllner, Bastien Nocera, Jasper St. Pierre,
 | 
			
		||||
 Marc Plano-Lesay, Owen Taylor, Colin Walters, Ron Yorsten,
 | 
			
		||||
 Marina Zhurakhinskaya
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
 Petr Kovar [cs], Kris Thomsen [dk], Daniel Mustieles [es],
 | 
			
		||||
 Ville-Pekka Vainio [fi], Yaron Shahrabani [he], Luca Ferretti [it],
 | 
			
		||||
 Hideki Yamane [ja], Žygimantas Beručka [lt], Jovan Naumovski [mk],
 | 
			
		||||
 Kjartan Maraas [nb], "Andreas N" [nn], Lucian Adrian Grijincu [ro],
 | 
			
		||||
 Matej Urbančič [sl], Praveen Illa [te], Muhammet Kara [tr],
 | 
			
		||||
 Daniel Korostil [uk], Aron Xu [zh_CN]
 | 
			
		||||
 | 
			
		||||
3.3.2
 | 
			
		||||
=====
 | 
			
		||||
* Port D-Bus usage in the shell to GDBus [Giovanni, Marc-Antoine, Florian,
 | 
			
		||||
  Jasper, Matthias; #648651, #658078, #663902, #663941]
 | 
			
		||||
* Message tray
 | 
			
		||||
  - Add right-click option to chats to mute the conversation [Ana; #659962]
 | 
			
		||||
  - Don't steal the focus when popping up under the pointer [Rui; #661358]
 | 
			
		||||
* Looking Glass
 | 
			
		||||
  - Add alt-Tab completion [Jason; #661054]
 | 
			
		||||
  - Show errors from extensions in the extensions tab [Jasper; #660546]
 | 
			
		||||
  - Allow switching tabs with <Control>PageUp/PageDown
 | 
			
		||||
  - Theme consistently with the rest of the shell [Jason; 650900]
 | 
			
		||||
* Extension system
 | 
			
		||||
  - Don't try to load disabled extensions at all [Jasper; #661815, #662704]
 | 
			
		||||
  - Enable and disable plugins in a consistent order [Jasper; #661815, #662704]
 | 
			
		||||
  - Add options to enable/disable extensions to gnome-shell-extension-tool
 | 
			
		||||
    [Jasper; #661815]
 | 
			
		||||
* Adapt to Mutter change to GSettings [Florian, Matthias; #663429]
 | 
			
		||||
* Allow creating a new workspace by dragging a window or launcher in the
 | 
			
		||||
  middle of two existing ones [Jasper; #646409]
 | 
			
		||||
* Allow using Alt-Tab while during drag-and-drop and other operations
 | 
			
		||||
  that grab the pointer [Adel; #660457]
 | 
			
		||||
* Do a better job of finding the right user to authenticate
 | 
			
		||||
  as when showing a PolKit dialog [Matthias; #651547]
 | 
			
		||||
* Control the D-Bus Eval() method by the developer-tools GSetting which
 | 
			
		||||
  is used for looking glass and screen recorder. [Jasper; #662891]
 | 
			
		||||
* Fix browser plugin to work under WebKit-based browser [Jasper; #663823]
 | 
			
		||||
* Fix certain stacking issues with alt-Tab [Jasper; #660650]
 | 
			
		||||
* Fixes for GLib deprecations [Jasper; #662011]p
 | 
			
		||||
* Fixes for GTK+ deprecations [Florian, Rico; #662245]p
 | 
			
		||||
* Fixes for Clutter deprecations [Jasper; #662627]
 | 
			
		||||
* Visual improvements and UI tweaks [Florian, Jakub, Jasper;
 | 
			
		||||
  #662800, #658096, #662226]
 | 
			
		||||
* Hard-code "Home" as the name for the home dir, rather than looking
 | 
			
		||||
  it up via GSettings; avoids schema dependency [Cosimo; #559895]
 | 
			
		||||
* Don't show "Switch User" on single user machines [Florian; #657011]
 | 
			
		||||
* Generate documentation for St toolkit [Florian]
 | 
			
		||||
* Improve marking of strings for translation [Matthias, Piotr; #658664]
 | 
			
		||||
* Networking menu bug fixes [Giovanni; #650007, #651378, #659277, #663278]
 | 
			
		||||
* Code cleanups and leak fixes to StTextureCache
 | 
			
		||||
  [Jasper, Florian; #660968, #662998]
 | 
			
		||||
* Code cleanups [Adel, Florian, Jasper; #662238, #663584]
 | 
			
		||||
* Build fixes [Adel, Colin, Florian, Ming Han]
 | 
			
		||||
* Misc bug fixes [Adel, Florian, "Fry", Jasper, Giovanni, Ray, Rui, Stefan;
 | 
			
		||||
  #660520, #661029, #661231, #661623, #661921, #662235, #662236, #662502,
 | 
			
		||||
  #662394, #662799, #662969, #663175, #663277, #663815, #663891, #662967]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
 Giovanni Campagna, Cosimo Cecchi, Matthias Clasen, Piotr Drąg, Adel Gadllah,
 | 
			
		||||
 Rui Matos, Florian Müllner, Marc-Antoine Perennou, Ana Risteska,
 | 
			
		||||
 Jason Siefken, Jakub Steiner, Ray Strode, Jasper St. Pierre, Ming Han Teh,
 | 
			
		||||
 Rico Tzschichholz, Colin Walters, Stefan Zwanenburg
 | 
			
		||||
 | 
			
		||||
Translation:
 | 
			
		||||
 Alexander Shopov [bg], Marek Černocký [cs], Mario Blättermann [de],
 | 
			
		||||
 Kostas Papadimas [el], Bruce Cowan [en_GB], Kristjan Schmidt [eo],
 | 
			
		||||
 Jorge González, Daniel Mustieles, Benjamín Valero Espinosa [es],
 | 
			
		||||
 Mattias Põldaru [et], Arash Mousavi [fa], Ville-Pekka Vainio [fi],
 | 
			
		||||
 Fran Diéguez [gl], Yaron Shahrabani [he], Hideki Yamane [ja],
 | 
			
		||||
 Algimantas Margevičius [lt], Kjartan Maraas [nb], Daniel Nylander [se],
 | 
			
		||||
 Matej Urbančič [sl], Praveen Illa [te], Muhammet Kara [tr],
 | 
			
		||||
 Nguyễn Thái Ngọc Duy [vi], Cheng-Chia Tseng [zh_HK, zh_TW]
 | 
			
		||||
 | 
			
		||||
3.2.1
 | 
			
		||||
=====
 | 
			
		||||
* Restore the IM state on startup - if you were available in when you logged
 | 
			
		||||
  out, then you'll be set available again when you log in.
 | 
			
		||||
  [Florian; #65902, #661485]
 | 
			
		||||
* Improve searching for contacts in the overview: search more fields,
 | 
			
		||||
  show a more meaningful name, require that all search terms match.
 | 
			
		||||
  [Florian, Matthias; #660580]
 | 
			
		||||
* Improve search for applications in the overview: take frequency into
 | 
			
		||||
  account and tweak match algorithm [Florian; #623372]
 | 
			
		||||
* Remove the "Show Password" switch from network password prompts, and
 | 
			
		||||
  move the functionality to a right-click menu [Florian; #658948]
 | 
			
		||||
* Add context menus with Cut/Paste options to most entries [Florian; #659275]
 | 
			
		||||
* On screen keyboard:
 | 
			
		||||
 - Show the keyboard immediately when it's turned enabled [Dan; #659743]
 | 
			
		||||
 - Fix problem where keyboard would hide when starting to type
 | 
			
		||||
   in the search entry [Nohemi; #661340]
 | 
			
		||||
 - Fix problem with keyboard hiding when selected accented characters
 | 
			
		||||
   [Nohemi; 661707]
 | 
			
		||||
* Login mode:
 | 
			
		||||
  - Allow hitting Enter to select the first user [Ray; #657996]
 | 
			
		||||
  - Fix flicker of a fingerprint prompt that could show up [Ray; #660492]
 | 
			
		||||
  - Fix password bullets vanishing during login [Ray; #657894]
 | 
			
		||||
  - Misc bug fixes and visual tweaks [Ray; #659763, #660919, #661479]
 | 
			
		||||
* Display a caps-lock warning in password entries [Florian; #660806]
 | 
			
		||||
* Show the state of installed extensions in Looking Glass [Jasper; #660494]
 | 
			
		||||
* Load user extensions after system ones [Jasper; #661815]
 | 
			
		||||
* Fix problem with many applications showing extra-large icons in
 | 
			
		||||
  notifications [Marina; #659158]
 | 
			
		||||
* Fix a problem where alt-Tab had trouble tracking the current
 | 
			
		||||
  application with certain applications such as Emacs. [Dan; #645026]
 | 
			
		||||
* Fix confusion between different users avatar images [Florian; #660585]
 | 
			
		||||
* Remove behavior where you could switch workspaces by bumping
 | 
			
		||||
  a dragged window in the overview against a screen edge; it was
 | 
			
		||||
  leftover and just confusing. [Florian; #660838]
 | 
			
		||||
* Fix long-standing bug where the Dash in the overview could end up mis-sized
 | 
			
		||||
  and run off the screen [Florian; #649248]
 | 
			
		||||
* Fix automatic launching of applications when media is inserted
 | 
			
		||||
  [Cosimo; #660821]
 | 
			
		||||
* Fix handling of vertically stacked monitors with NVIDIA drivers
 | 
			
		||||
  [Florian; #661387]
 | 
			
		||||
* Translation marking fixes [Jasper, Wouter; #660600]
 | 
			
		||||
* Code cleanups and warning fixes [Adel, Dan, Florian, Jasper;
 | 
			
		||||
  #659822, #659940, #660122, #660358, #660968, #661231]
 | 
			
		||||
* Small memory leak fixes [Florian, Jasper; #661231]
 | 
			
		||||
* Misc bug fixes [Adel, Florian, Jasper; #659274, #659861, #660166, #660310,
 | 
			
		||||
  #660397, #660608,  #660606, #660674, #660774. #660848, #661151, #661617]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Wouter Bolsterlee, Cosimo Cecchi, Matthias Clasen, Nohemi Fernandez,
 | 
			
		||||
  Adel Gadllah, Florian Müllner, Jasper St. Pierre, Ray Strode, Dan Winship,
 | 
			
		||||
  Marina Zhurakhinskaya
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
 Tiffany Antopolski [eo], Xandru Armesto [ast], Alexander Shopov,
 | 
			
		||||
 Ivaylo Valkov [bg], Gil Forcada [ca], Carles Ferrando [ca@valencia],
 | 
			
		||||
 Mario Blättermann, Paul Seyfert [de], Bruce Cowan [en_GB],
 | 
			
		||||
 Jorge González, Daniel Mustieles [es], Arash Mousavi [fa], Bruno Brouard [fr],
 | 
			
		||||
 Seán de Búrca [ga], Fran Diéguez [gl], Gabor Kelemen [hu], Luca Ferretti [it],
 | 
			
		||||
 Takayuki Kusano [ja], Changwoo Ryu [ko], Erdal Ronahi [ku],
 | 
			
		||||
 Algimantas Margevičius [lt], Rudolfs Mazurs [lv], Wouter Bolsterlee [nl],
 | 
			
		||||
 Piotr Drąg [pl], Adorilson Bezerra [pt_BR], Yuri Myasoedov [ru],
 | 
			
		||||
 Matej Urbančič [sl], Daniel Nylander [sv], Miroslav Nikolić [sr, sr@latin],
 | 
			
		||||
 Tirumurti Vasudevan [ta], Krishnababu Krothapalli [te], Daniel Korostil [uk],
 | 
			
		||||
 Nguyễn Thái Ngọc Duy [vi], YunQiang Su [zh_CN]
 | 
			
		||||
 | 
			
		||||
3.2.0
 | 
			
		||||
=====
 | 
			
		||||
* Prevent the fallback on-screen keyboard from showing up while
 | 
			
		||||
  GNOME Shell is running [Dan, #659865]
 | 
			
		||||
* Disable code to reposition windows around the on-screen keyboard;
 | 
			
		||||
  it wasn't finished or working properly. [Dan; #659643]
 | 
			
		||||
* Fix interaction between on-screen keyboard and notifications
 | 
			
		||||
  [Dan; #658603]
 | 
			
		||||
* Fix menu-sizing problems in right-to-left locales. [Florian; #659827]
 | 
			
		||||
* Update chat icons in the message tray when an avatar image changes
 | 
			
		||||
  [Marina; #659768]
 | 
			
		||||
* Fix problem with empty notification bubbles being left [Marina; #659862]
 | 
			
		||||
* Fix problem with chat notifications bouncing when new messages come in.
 | 
			
		||||
  [Marina; #659768]
 | 
			
		||||
* Fix bug that was causing SIP calls to automatically be accepted in some
 | 
			
		||||
  circumstances [Guillaume; #660084]
 | 
			
		||||
* Fix string that should have been marked translatable [Frédéric]
 | 
			
		||||
* Fix a crash that could happen during CSS transitions [Florian; #659676]
 | 
			
		||||
* Build fixes [Colin, Florian]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
 Guillaume Desmottes, Florian Müllner, Frédéric Péters, Colin Walters,
 | 
			
		||||
 Dan Winship, Marina Zhurakhinskaya
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
 Friedel Wolff [af], Nilamdyuti Goswami [as], Ihar Hrachyshka [be],
 | 
			
		||||
 Ivaylo Valkov [bg], Gil Forcada [ca], Carles Ferrando [ca@valencia],
 | 
			
		||||
 Petr Kovar [cs], Mario Blättermann [de], Kris Thomsen [dk],
 | 
			
		||||
 Tiffany Antopolski, Kristjan Schmidt [eo], Daniel Mustieles [es],
 | 
			
		||||
 Inaki Larranaga Murgoitio [eu], Tommi Vainikainen [fi], Bruno Brouard [fr],
 | 
			
		||||
 Fran Dieguez [gl], Yaron Shahrabani [he], Gabor Kelemen [hu],
 | 
			
		||||
 Andika Triwidada [id], Jiro Matsuzawa [ja], Changwoo Ryu [ko],
 | 
			
		||||
 Rudolfs Mazurs [lv], Aurimas Černius [lt], Kjartan Maraas [nb],
 | 
			
		||||
 A S Alam [pa], Piotr Drąg [pl], Duarte Loreto [pt], Djavan Fagundes,
 | 
			
		||||
 Rodolfo Ribeiro Gomes, Gabriel F. Vilar [pt_BR], Yuri Myasoedov [ru],
 | 
			
		||||
 Daniel Nylander [se], Martin Srebotnjak [sl], Michal Štrba [sv],
 | 
			
		||||
 Krishnababu Krothapalli, Praveen Illa [te], Cheng-Chia Tseng [zh_KH, zh_TW]
 | 
			
		||||
 | 
			
		||||
3.1.92
 | 
			
		||||
======
 | 
			
		||||
 | 
			
		||||
* Login screen
 | 
			
		||||
  - Add the ability to set a logo at the top of the user list [Ray; #658062]
 | 
			
		||||
  - Add fingerprint reader support [Ray; #657823]
 | 
			
		||||
  - Add a power button offering the choice of Suspend/Restart/Power off
 | 
			
		||||
    [Ray; #657822]
 | 
			
		||||
  - Remove the option to view the current keyboad layout [Matthias; #659164]
 | 
			
		||||
  - Make Control-Alt-Tab work for full keyboard access [Ray; #659177]
 | 
			
		||||
* Frequently initiate a full garbage collection; Spidermonkey isn't very good
 | 
			
		||||
  at tracking the amount of resources we have allocated so this hopefully will
 | 
			
		||||
  improve memory usage without affecting performance too much [Colin; #659254]
 | 
			
		||||
* Stop adding a notification when the network connection is lost
 | 
			
		||||
  [Colin; #658954]
 | 
			
		||||
* When disabling notifications; display a notification
 | 
			
		||||
  "Your chat status will be set to busy" [Florian; #652718]
 | 
			
		||||
* Fix keynav in network dialogs [Florian; #659133]
 | 
			
		||||
* Improve calendar styling [Sean; #641135, #651299]
 | 
			
		||||
* Shrink padding around panel buttons for narrow screens [Dan; #651299]
 | 
			
		||||
* Allow enabling the onscreen keyboard through the accessibility menu
 | 
			
		||||
  [Dan; #612662]
 | 
			
		||||
* Fix problem that was causing VPN secret dialogs to be delayed before showing
 | 
			
		||||
  [Florian; #658484]
 | 
			
		||||
* Make custom-keybindings for the window switcher that don't use alt
 | 
			
		||||
  work correctly [Florian; #645200]
 | 
			
		||||
* Fix duplicate application icons in the Activities Overview [Colin; #659351]
 | 
			
		||||
* Bug fixes for dimming windows with attached modal dialogs
 | 
			
		||||
  [Jasper, Owen; #659302, 659634]
 | 
			
		||||
* Add build-time support for BROWSER_PLUGIN_DIR environment variable
 | 
			
		||||
  [Vincent; #659123]
 | 
			
		||||
* Build fixes [Vincent; #659194]
 | 
			
		||||
* Code cleanups and test cases
 | 
			
		||||
  [Adel, Dan, Florian, Jasper; #651299, #658092, #658939]
 | 
			
		||||
* Misc bug fixes
 | 
			
		||||
  [Adel, Colin, Cosimo, Dan, Florian, Giovanni, Jasper, Ray, Xavier;
 | 
			
		||||
  #651299, #652837, #657249, #658004, #658150, #658239, #658469, #658598,
 | 
			
		||||
  #658605, #659050, #659159, #659210, #659270, #659370, #659633]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
 Giovanni Campagna, Cosimo Cecchi, Xavier Claessens, Matthias Clasen,
 | 
			
		||||
 Rui Matos, Florian Müllner, Jasper St. Pierre, Owen Taylor,
 | 
			
		||||
 Vincent Untz, Colin Walters, Sean Wilson, Dan Winship
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
 Ihar Hrachyshka [be], Alexander Shopov, Ivaylo Valkov [bg],
 | 
			
		||||
 Mario Blättermann [de], Jorge González, Daniel Mustieles [es],
 | 
			
		||||
 Arash Mousavi [fa], Ville-Pekka Vainio [fi], Fran Dieguez [gl],
 | 
			
		||||
 Sweta Kothari [gu], Gabor Kelemen [hu], Jiro Matsuzawa [ja],
 | 
			
		||||
 Luca Ferretti [it], Rudolfs Mazurs [lv], Kjartan Maraas [nb], A S Alam [pa],
 | 
			
		||||
 Piotr Drąg [pl], Duarte Loreto [pt], Yuri Myasoedov [ru],
 | 
			
		||||
 Daniel Nylander [se], Matej Urbančič [sl], Miroslav Nikolić [sr, sr@latin],
 | 
			
		||||
 Michal Štrba [sv], Tirumurti Vasudevan [ta], Phương Lê Hoàng [vi],
 | 
			
		||||
 Aron Xu [zh_CN], Chao-Hsiung Liao [zh_HK, zh_TW]
 | 
			
		||||
 | 
			
		||||
3.1.91.1
 | 
			
		||||
========
 | 
			
		||||
 | 
			
		||||
* Add a browser plugin - this plugin, tied to extensions.gnome.org,
 | 
			
		||||
  allows users to download and install shell extensions, and enable,
 | 
			
		||||
  disable, and uninstall extensions they already have installed.
 | 
			
		||||
  [Jasper; #658070, #658612]
 | 
			
		||||
* Improve adding links to URLs in notifications [Dan; #636252]
 | 
			
		||||
* Remove "connection lost" notifications after reconnecting [Giovanni; #658049]
 | 
			
		||||
* Hide the onscreen keyboard when leaving a text entry [Dan; #658591]
 | 
			
		||||
* Fixes for translated strings [Florian; #639987, #644097, #645037]
 | 
			
		||||
* Bug fixes for network menu [Florian; #658492]
 | 
			
		||||
* Code cleanup [Dan; #646934]
 | 
			
		||||
* Build fixes [Javier, Rico]
 | 
			
		||||
* Misc bug fixes [Emmanuele, Florian, Jasper, Marina, Matthias, Ray;
 | 
			
		||||
  #652837, #658423, #658503, #658525, #658562, #658624, #658640, #658983]
 | 
			
		||||
 | 
			
		||||
Conributors:
 | 
			
		||||
 Emmanuele Bassi, Giovanni Campagna, Matthias Clasen, Javier Jardón,
 | 
			
		||||
 Florian Muellner, Jasper St. Pierre, Ray Strode, Rico Tzschichholz,
 | 
			
		||||
 Dan Winship, Marina Zhurakhinskaya
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
 Ihar Hrachyshka [be], Bruce Cowan [en_GB], Jorge González,
 | 
			
		||||
 Daniel Mustieles [es], Timo Jyrinki [fi], Bruno Brouard, Luc Guillemin,
 | 
			
		||||
 Claude Paroz, Luc Pionchon [fr], Fran Dieguez [gl], Rajesh Ranjan [hi],
 | 
			
		||||
 Andika Triwidada [id], Luca Ferretti [it], Changwoo Ryu [ko],
 | 
			
		||||
 Rudolfs Mazurs [lt], Kjartan Maraas [nb], Manoj Kumar Giri [or],
 | 
			
		||||
 A S Alam [pa], Piotr Drąg [pl], Duarte Loreto [pt], Henrique P. Machado,
 | 
			
		||||
 Gabriel F. Vilar [pt_BR], Daniel Nylander [se], Matej Urbančič [sl],
 | 
			
		||||
 Tirumurti Vasudevan [ta], Yinghua Wang [zh_CN],
 | 
			
		||||
 Chao-Hsiung Liao [zh_HK, zh_TW]
 | 
			
		||||
 | 
			
		||||
3.1.91
 | 
			
		||||
======
 | 
			
		||||
 | 
			
		||||
* Fix problem with applications vanishing from alt-Tab when
 | 
			
		||||
  desktop files change. [Colin; #657990]
 | 
			
		||||
* Fix interaction of on-screen keyboard with run-dialog and
 | 
			
		||||
  Looking Glass console [Dan; #657986]
 | 
			
		||||
* Add public API for adding and removing search providers
 | 
			
		||||
  [Philippe; #657548, #658113]
 | 
			
		||||
* Allow changing IM status with scroll wheel [Florian; #657973]
 | 
			
		||||
* Limit volume slider to 100% [Bastien; #657607]
 | 
			
		||||
* Change "Do Not Disturb" to "Notifications" in user menu [Florian; #652718]
 | 
			
		||||
* Switch browser in default favorites to Epiphany [Colin; #650616]
 | 
			
		||||
* Misc bug fixes [Dan, Florian, Jasper, Marc-Antoine, Rui;
 | 
			
		||||
  #649631, #655069, #656142, #657703, #657759, #658007, #658065, #658176]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
 Rui Matos, Florian Müllner, Philippe Normand, Marc-Antoine Perennou,
 | 
			
		||||
 Jasper St. Pierre, Colin Walters, Dan Winship
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
 Ihar Hrachyshka [be], Mario Blättermann [de], Kris Thomsen [da],
 | 
			
		||||
 Jorge González [es], Arash Mousavi [fa], Fran Dieguez [gl],
 | 
			
		||||
 Takayuki Kusano [ja],Aurimas Černius [lt], Kjartan Maraas [nb], A S Alam [pa],
 | 
			
		||||
 Stas Solovey [ru], Daniel Nylander [se], Tirumurti Vasudevan [ta],
 | 
			
		||||
 Chao-Hsiung Liao [zh_HK, zh_TW]
 | 
			
		||||
 | 
			
		||||
3.1.90.1
 | 
			
		||||
========
 | 
			
		||||
 | 
			
		||||
* Fix typo that was breaking the "Login Screen" mode [Marc-Antoine]
 | 
			
		||||
* Fix build with new gobject-introspection [Dan]
 | 
			
		||||
* Use a better icon for removable devices [Cosimo; #657757]
 | 
			
		||||
* Add support for asynchronous search provides [Philippe, Jasper, Seif; #655220]
 | 
			
		||||
* Misc bug fixes [Alex, Guillaume, Jasper; #657657, #657696]
 | 
			
		||||
* Misc build fixes [Adel; #657697]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
 Cosimo Cecchi, Guillaume Desmottes, Adel Gadllah, Alexander Larsson, Seif Lotfy,
 | 
			
		||||
 Philippe Normand, Marc-Antoine Perennou, Jasper St. Pierre, Dan Winship
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
 Jorge González, Daniel Mustieles [es], Stas Solovey [ru]
 | 
			
		||||
 | 
			
		||||
3.1.90
 | 
			
		||||
======
 | 
			
		||||
* Add an on-screen keyboard that uses Caribou as a backend
 | 
			
		||||
  [Nohemi, Dan; #612662]
 | 
			
		||||
* Allow searching for people in the overview using libfolks
 | 
			
		||||
  as the backend [Morten; #643018]
 | 
			
		||||
* Add a "Login Screen" mode to be used when GDM is running; this
 | 
			
		||||
  mode has a stripped down user interface, and also contains the
 | 
			
		||||
  code to display the user list and authentication. [Ray; #657082]
 | 
			
		||||
* Rework user menu to separate out "Do Not Disturb" from the IM
 | 
			
		||||
  status and to visually match GNOME Contacts. [Florian; #652837]
 | 
			
		||||
* Implement displaying images such as cover-art in notifications
 | 
			
		||||
  [Neha, Marina; #621009]
 | 
			
		||||
* Support default actions for notifications [Florian; #655818]
 | 
			
		||||
* Networking
 | 
			
		||||
  - Stop using nm-applet for dialogs; do them as proper system modal
 | 
			
		||||
    dialogs in the shell code. [Giovanni; #650244]
 | 
			
		||||
  - Fix handling of hidden access points [Giovanni; #646454]
 | 
			
		||||
* Telepathy integration
 | 
			
		||||
  - Support subscription requests [Guillaume, Xavier; #653941]
 | 
			
		||||
  - Notify on account connection errors [Alban, Jasper, Xavier; #654159]
 | 
			
		||||
  - Allow approving file transfers [Guillaume; #653940]
 | 
			
		||||
  - Improve styling of messages [Jasper; #640271]
 | 
			
		||||
* Extension system [Jasper; #654770]
 | 
			
		||||
  - Support live enabling and disabling of extensions
 | 
			
		||||
  - Add the ability to install extensions from HTTP
 | 
			
		||||
  - Enhance D-Bus interface for controlling extensions
 | 
			
		||||
  - Collect errors separately for each extension
 | 
			
		||||
* Add Main.panel.addToStatusArea for extension convenience
 | 
			
		||||
  [Giovanni, Jasper, Marc-Antoine; #653205]
 | 
			
		||||
* Port to the new gnome-menus API. Clean up and speed up
 | 
			
		||||
  application information loading [Colin; #648149, #656546]
 | 
			
		||||
* Use the accountsservice library rather than cut-and-pasted GDM code
 | 
			
		||||
  [Florian; #650893]
 | 
			
		||||
* Add a D-Bus interface to take a screenshot; this will avoid various race
 | 
			
		||||
  conditions with the current gnome-screenshot approach [Adel; #652952]
 | 
			
		||||
* Show numeric indicators to distinguish duplicate keyboard names
 | 
			
		||||
  [Giovanni; #650128]
 | 
			
		||||
* Add GNOME Documents to the favorites list [Adel; #657520]
 | 
			
		||||
* Update the clock immediately on resume from suspend [Colin; #656403]
 | 
			
		||||
* Remove animation support from StAdjustment [Ray; #657082]
 | 
			
		||||
* Support configuration of calendar applications via gsettings
 | 
			
		||||
  [Tassilo; #651190]
 | 
			
		||||
* Don't fade in alt-Tab - wait a bit and show it instantly [Rui; #652346]
 | 
			
		||||
* Darken workspace background on all workspaces [Rui; #656433]
 | 
			
		||||
* Improve detection of the starting day of the week [Florian; #649078]
 | 
			
		||||
* Add StButtonAccessible [Alejandro]
 | 
			
		||||
* Visual tweaks to match mockups
 | 
			
		||||
  [Allan, Dan, Jasper, Marina; #640271, #655627, #655428, #656732]
 | 
			
		||||
* Misc bug fixes [Dan, Florian, Giovanni, Guillaume, Jasper, Jeremy, Rui;
 | 
			
		||||
  #645708, #646761, #653119, #654398, #656125, #654707, #654898, #654638,
 | 
			
		||||
  #656335, #657111]
 | 
			
		||||
* Code cleanups [Colin, Dan, Guillaume, Ray;
 | 
			
		||||
  #652718, #654639, #648651, #655813, #657082]
 | 
			
		||||
* String tweaks [Jasper, Jeremy; #652984, #640271]
 | 
			
		||||
* Build fixes [Jasper, Nohemi; #644275, #655812]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
 Jeremy Bicha, Giovanni Campagna, Xavier Claessens, Alban Crequy,
 | 
			
		||||
 Guillaume Desmottes, Allan Day, Neha Doijode, Nohemi Fernandez,
 | 
			
		||||
 Tassilo Horn, Rui Matos, Morten Mjelva, Florian Müllner, Alejandro Piñeiro,
 | 
			
		||||
 Jasper St. Pierre, Ray Strode, Colin Walters, Dan Winship,
 | 
			
		||||
 Marina Zhurakhinskaya
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
 Ivaylo Valkov [bg], Mario Blättermann [de], Diego Escalante Urrelo,
 | 
			
		||||
 Jorge González, Daniel Mustieles [es], Arash Mousavi [fa], Fran Dieguez [gl],
 | 
			
		||||
 Yaron Shahrabani [he], Andika Triwidada, Wibiharto [id],
 | 
			
		||||
 Aurimas Černius [lt], Umarzuki Bin Mochlis Moktar [ml], Kjartan Maraas [nb],
 | 
			
		||||
 A S Alam [pa], Daniel Nylander [se], Ngô Chin, Nguyễn Thái Ngọc Duy [vi],
 | 
			
		||||
 Aron Xu [zh_CN], Chao-Hsiung Liao [zh_HK, zh_TW]
 | 
			
		||||
 | 
			
		||||
3.1.4
 | 
			
		||||
=====
 | 
			
		||||
* Take over inserted media handling and autorun from gnome-session [Cosimo]
 | 
			
		||||
* Message Tray
 | 
			
		||||
  - Display a count of unread notifications on icons
 | 
			
		||||
    [Jasper, Guillaume; #649356, #654139]
 | 
			
		||||
  - Only remove icons when the sender quits from D-Bus, not when it
 | 
			
		||||
    closes its last window [Neha, Marina; #645764]
 | 
			
		||||
  - Solve problems switching chats between shell and Empathy
 | 
			
		||||
    [Guillaume; #654237]
 | 
			
		||||
  - Fix handling of bad GMarkup in messages [Dan; #650298]
 | 
			
		||||
  - Never show notifications when the screensaver is active [Dan; #654550]
 | 
			
		||||
* Telepathy integrationpp
 | 
			
		||||
  - Implement Telepathy Debug interface to enable empathy-debugger
 | 
			
		||||
    [Guillaume; #652816]
 | 
			
		||||
  - Allow approving room invitations, and audio/video calls
 | 
			
		||||
    [Guillaume; #653740 #653939]
 | 
			
		||||
  - Send typing notifications [Jonny; #650196]
 | 
			
		||||
* Fix selection highlighting for light-on-dark entries [Jasper; #643768]
 | 
			
		||||
* Make control-Return in the overview open a new window [Maxim]
 | 
			
		||||
* Delay showing the alt-Tab switcher to reduce visual noise when
 | 
			
		||||
  flipping betweeen windows [Dan; #652346]
 | 
			
		||||
* When we have vertically stacked monitors, put the message tray
 | 
			
		||||
  on the bottom one [Dan; #636963]
 | 
			
		||||
* Fix various problems with keynav and the Activities button
 | 
			
		||||
  [Dan; #641253 #645759]
 | 
			
		||||
* Ensure screensaver is locked when switching users [Colin; #654565]
 | 
			
		||||
* Improve extension creation tool [Jasper; #653206]
 | 
			
		||||
* Fix compatibility with latest GJS [Giovanni; #654349]
 | 
			
		||||
* Code cleanups [Adel, Dan, Jasper; #645759 #654577 #654791 #654987]
 | 
			
		||||
* Misc bug fixes [Richard, Dan, Florian, Giovanni, Jasper, Marc-Antoine, Rui;
 | 
			
		||||
  #647175 #649513 #650452 #651082 #653700 #653989 #654105 #654791 #654267
 | 
			
		||||
  #654269 #654527 #655446]
 | 
			
		||||
* Build fixes [Florian, Siegfried; #654300]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
 Giovanni Campagna, Cosimo Cecchi, Guillaume Desmottes, Neha Doijode,
 | 
			
		||||
 Maxim Ermilov, Adel Gadllah, Siegfried-Angel Gevatter Pujals, Richard Hughes,
 | 
			
		||||
 Jonny Lamb, Rui Matos, Florian Müllner, Marc-Antoine Perennou, Colin Walters,
 | 
			
		||||
 Dan Winship, Marina Zhurakhinskaya
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
 Mario Blättermann, Paul Seyfert [de], Jorge González, Daniel Mustieles [es],
 | 
			
		||||
 Fran Dieguez [gl], Yaron Shahrabani [he], Luca Ferretti [it],
 | 
			
		||||
 Rudolfs Mazurs [lv], Kjartan Maraas [nb], A S Alam [pa], Yuri Kozlov [ru],
 | 
			
		||||
 Michal Štrba, Matej Urbančič [sl]
 | 
			
		||||
 | 
			
		||||
3.1.3
 | 
			
		||||
=====
 | 
			
		||||
* Fix problem with "user theme extension" breaking the CSS for other
 | 
			
		||||
  extensions [Giovanni; #650971]
 | 
			
		||||
* Telepathy IM framework integration
 | 
			
		||||
  - Switch to using telepathy-glib rather than talking to
 | 
			
		||||
    Telepathy via D-Bus [Guillaume, Jasper; #645585, #649633, #651138, #651227]
 | 
			
		||||
  - Acknowledge messages when the user clicks on them [Guillaume, #647893]
 | 
			
		||||
  - Fix problem with telepathy icon blinking for incoming messages
 | 
			
		||||
    even though the user has been notified of them [Guillaume; #643594]
 | 
			
		||||
* Networking
 | 
			
		||||
  - keep wirelesss networks in predictable order [Giovanni; #646580, #652313]
 | 
			
		||||
  - Show unmanaged devices in the menu [Giovanni; #646946]
 | 
			
		||||
  - Fix overflow when too many VPN connections [Giovanni; #651602]
 | 
			
		||||
* Bluetooth
 | 
			
		||||
  - Show "hardware disabled" when disabled by rfkill [Giovanni; #648048]
 | 
			
		||||
  - Fix bug updating status of devices [Giovanni; #647565]
 | 
			
		||||
* LookingGlass console:
 | 
			
		||||
  - Add a "Memory" tab [Colin; #650692]
 | 
			
		||||
  - Make escape work from any page [Dan Winship; #647303]
 | 
			
		||||
  - Provide a way to refer to panel items as, e.g.,
 | 
			
		||||
    Main.panel._activities [Dan Winship; #646915]
 | 
			
		||||
* User menu
 | 
			
		||||
  - Fix problem with suspend menu option locking the screen even when the user
 | 
			
		||||
    disabled that. [Florian; #652327]
 | 
			
		||||
  - Hide "power off..." option if shutdown is disabled via PolicyKit
 | 
			
		||||
    [Florian; #652038]
 | 
			
		||||
* Track changes to WM_CLASS (fixes problems with LibreOffice tracking)
 | 
			
		||||
  [Colin; #649315]
 | 
			
		||||
* Remove app tracking workarounds for Firefox and LibreOffice [Colin; #651015]
 | 
			
		||||
* Use upstream gettext autoconfigury rather than glib version [Javier; #631576]
 | 
			
		||||
* Show messages in the message tray when an application is fullscreen
 | 
			
		||||
  [Dan Winship; #608667]
 | 
			
		||||
* Don't autohide the workspace pager if there is more than one workspace
 | 
			
		||||
  [Florian; #652714, #653078, #653142]
 | 
			
		||||
* Don't always slide out the workspace pager at drag begin [Florian; #652730]
 | 
			
		||||
* Only offer to remove a favorite app when dragging it's icon [Owen; #642895]
 | 
			
		||||
* Allow dropping an icon anywhere on a workspace [Adel; #652079]
 | 
			
		||||
* st-scroll-view: Make the fade effect and offset themable [Jasper; #651813]
 | 
			
		||||
* Obey the user's preference when running an application in a terminal
 | 
			
		||||
  from the run dialog [Florian; #648422]
 | 
			
		||||
* Consistently exit overview when launching external applications
 | 
			
		||||
  [Colin; #653095]
 | 
			
		||||
* Adapt to changes in GJS for how GObject APIs are bound
 | 
			
		||||
  [Alex, Colin, Florian, Jasper, Marc-Antoine; #649981, #652597]
 | 
			
		||||
* Fix problems with scrolling in overflow for alt-Tab switcher
 | 
			
		||||
  [Dan Winship, Adel; #647807]
 | 
			
		||||
* Mark relationships between labels and actors for accessibility [Alejandro]
 | 
			
		||||
* Add org.gnome.shell.enabled-extensions complementing disabled-extensions
 | 
			
		||||
  GSetting [Tassilo; #651088]
 | 
			
		||||
* Visual tweaks [Jakub, Jasper; #646261, #652715]
 | 
			
		||||
* Switch to building against clutter-1.7 with independent Cogl [Adel; #653397]
 | 
			
		||||
* Code cleanups [Colin, Dan Winship, Florian; #633620, #645031, #648755, #648758,
 | 
			
		||||
  #648760, #649203, #649517, #650317, #652730]
 | 
			
		||||
* Memory leak fixes [Colin, Maxim; #649508, #650934]
 | 
			
		||||
* Build Fixes [Colin, Dan Winship, Florian, Ionut, Morten, Owen, Sean; #647395,
 | 
			
		||||
  #648006, #650869, #653199, #653275
 | 
			
		||||
* Miscellaneous bug fixes [Adam, Adel, Dan Williams, Dan Winship, Florian,
 | 
			
		||||
  Ionut, Jasper, Maxim, Ray; #620105, #639459, #641570, #642793, #643513,
 | 
			
		||||
  #645848, #646919, #647186, #648305, #648410, #648562, #648894, #649001,
 | 
			
		||||
  #645990, #647893, #647907, #651012, #651086, #651606, #651569, #651866,
 | 
			
		||||
  #652388,  #653511]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
 Ionut Biru, Giovanni Campagna, Guillaume Desmottes, Adam Dingle,
 | 
			
		||||
 Maxim Ermilov, Adel Gadllah, Tassilo Horn, Javier Jardón, Jonny Lamb,
 | 
			
		||||
 Alexander Larsson, Rui Matos, Morten Mjelva, Florian Müllner,
 | 
			
		||||
 Marc-Antoine Perennou, Alejandro Piñeiro, Jasper St. Pierre, Jakub Steiner,
 | 
			
		||||
 Ray Strode, Owen Taylor, Colin Walters, Dan Williams, Sean Wilson, Dan Winship
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
 Daniel Martinez Cucalon [ar], Ihar Hrachyshka [be], Carles Ferrando,
 | 
			
		||||
 Gil Forcada, Sílvia Miranda [ca], Kristjan Schmidt [eo], Jorge González,
 | 
			
		||||
 Daniel Mustieles [es], Seán de Búrca [ga], Fran Diéguez [gl],
 | 
			
		||||
 Yaron Shahrabani [he], Kjartan Maraas [nb], Misha Shnurapet,
 | 
			
		||||
 Yuri Myasoedov [ru], Daniel Nylander [se], Peter Mráz [sk],
 | 
			
		||||
 Matej Urbančič [sl], Krishnababu Krothapalli [te], Daniel Korostil [uk],
 | 
			
		||||
 Aron Xu [zh_CN]
 | 
			
		||||
 | 
			
		||||
3.0.2
 | 
			
		||||
=====
 | 
			
		||||
* Network Menu [Dan Williams]
 | 
			
		||||
* Network Menu [Dan Williams
 | 
			
		||||
  - Fix connecting to WPA2 Enterprise access points
 | 
			
		||||
    Fixes https://bugzilla.gnome.org/show_bug.cgi?id=648171
 | 
			
		||||
  - Show the mobile broadband wizard when selecting 3G network
 | 
			
		||||
@@ -900,7 +23,7 @@ Translations:
 | 
			
		||||
* Memory leak fixes [Colin, Maxim]
 | 
			
		||||
  642652, 649508, 649497
 | 
			
		||||
* Miscellaneous minor bug fixes [Adel, Christopher, Jasper]
 | 
			
		||||
  649596, 648765, 648983, 649632
 | 
			
		||||
  649596,648765, 648983, 649632
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
 Christopher Aillon, Giovanni Campagna, Maxim Ermilov,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,21 +0,0 @@
 | 
			
		||||
 | 
			
		||||
mozillalibdir = $(BROWSER_PLUGIN_DIR)
 | 
			
		||||
 | 
			
		||||
mozillalib_LTLIBRARIES = libgnome-shell-browser-plugin.la
 | 
			
		||||
 | 
			
		||||
libgnome_shell_browser_plugin_la_LDFLAGS = -module -avoid-version -no-undefined
 | 
			
		||||
 | 
			
		||||
libgnome_shell_browser_plugin_la_LIBADD = 	\
 | 
			
		||||
	$(BROWSER_PLUGIN_LIBS)
 | 
			
		||||
 | 
			
		||||
libgnome_shell_browser_plugin_la_SOURCES = 	\
 | 
			
		||||
	browser-plugin.c \
 | 
			
		||||
	npapi/npapi.h \
 | 
			
		||||
	npapi/npfunctions.h \
 | 
			
		||||
	npapi/npruntime.h \
 | 
			
		||||
	npapi/nptypes.h
 | 
			
		||||
 | 
			
		||||
libgnome_shell_browser_plugin_la_CFLAGS = 	\
 | 
			
		||||
	$(BROWSER_PLUGIN_CFLAGS)		\
 | 
			
		||||
	-DG_DISABLE_DEPRECATED			\
 | 
			
		||||
	-DG_LOG_DOMAIN=\"GnomeShellBrowserPlugin\"
 | 
			
		||||
@@ -1,17 +0,0 @@
 | 
			
		||||
The GNOME Shell Browser Plugin provides integration with gnome-shell and the
 | 
			
		||||
corresponding extensions repository, codenamed "SweetTooth". The plugin allows
 | 
			
		||||
the extensions repository to provide good integration, letting the website
 | 
			
		||||
know which extensions are enabled and disabled, and allowing the website to
 | 
			
		||||
enable, disable and install them.
 | 
			
		||||
 | 
			
		||||
Bugs should be reported at http://bugzilla.gnome.org against the 'gnome-shell'
 | 
			
		||||
product.
 | 
			
		||||
 | 
			
		||||
License
 | 
			
		||||
=======
 | 
			
		||||
The GNOME Shell Browser Plugin, like GNOME Shell itself is distributed under
 | 
			
		||||
the GNU General Public License, version 2 or later. The plugin also contains
 | 
			
		||||
header files from the "NPAPI SDK" project, tri-licensed under MPL 1.1, GPL 2.0
 | 
			
		||||
and LGPL 2.1. These headers are third-party sources and can be retrieved from:
 | 
			
		||||
 | 
			
		||||
  http://code.google.com/p/npapi-sdk/
 | 
			
		||||
@@ -1,981 +0,0 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2011 Red Hat
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
 * published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 | 
			
		||||
 * 02111-1307, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * Authors:
 | 
			
		||||
 *      Jasper St. Pierre <jstpierre@mecheye.net>
 | 
			
		||||
 *      Giovanni Campagna <scampa.giovanni@gmail.com>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#define XP_UNIX 1
 | 
			
		||||
 | 
			
		||||
#include "npapi/npapi.h"
 | 
			
		||||
#include "npapi/npruntime.h"
 | 
			
		||||
#include "npapi/npfunctions.h"
 | 
			
		||||
 | 
			
		||||
#include <glib.h>
 | 
			
		||||
#include <gio/gio.h>
 | 
			
		||||
#include <json-glib/json-glib.h>
 | 
			
		||||
 | 
			
		||||
#define ORIGIN "extensions.gnome.org"
 | 
			
		||||
#define PLUGIN_NAME "Gnome Shell Integration"
 | 
			
		||||
#define PLUGIN_DESCRIPTION "This plugin provides integration with Gnome Shell " \
 | 
			
		||||
      "for live extension enabling and disabling. " \
 | 
			
		||||
      "It can be used only by extensions.gnome.org"
 | 
			
		||||
#define PLUGIN_MIME_STRING "application/x-gnome-shell-integration::Gnome Shell Integration Dummy Content-Type";
 | 
			
		||||
 | 
			
		||||
#define PLUGIN_API_VERSION 4
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  GDBusProxy *proxy;
 | 
			
		||||
} PluginData;
 | 
			
		||||
 | 
			
		||||
static NPNetscapeFuncs funcs;
 | 
			
		||||
 | 
			
		||||
static inline gchar *
 | 
			
		||||
get_string_property (NPP         instance,
 | 
			
		||||
                     NPObject   *obj,
 | 
			
		||||
                     const char *name)
 | 
			
		||||
{
 | 
			
		||||
  NPVariant result = { NPVariantType_Void };
 | 
			
		||||
  NPString result_str;
 | 
			
		||||
  gchar *result_copy;
 | 
			
		||||
 | 
			
		||||
  result_copy = NULL;
 | 
			
		||||
 | 
			
		||||
  if (!funcs.getproperty (instance, obj,
 | 
			
		||||
                          funcs.getstringidentifier (name),
 | 
			
		||||
                          &result))
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  if (!NPVARIANT_IS_STRING (result))
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  result_str = NPVARIANT_TO_STRING (result);
 | 
			
		||||
  result_copy = g_strndup (result_str.UTF8Characters, result_str.UTF8Length);
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  funcs.releasevariantvalue (&result);
 | 
			
		||||
  return result_copy;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
check_origin_and_protocol (NPP instance)
 | 
			
		||||
{
 | 
			
		||||
  gboolean ret = FALSE;
 | 
			
		||||
  NPError error;
 | 
			
		||||
  NPObject *window = NULL;
 | 
			
		||||
  NPVariant document = { NPVariantType_Void };
 | 
			
		||||
  NPVariant location = { NPVariantType_Void };
 | 
			
		||||
  gchar *hostname = NULL;
 | 
			
		||||
  gchar *protocol = NULL;
 | 
			
		||||
 | 
			
		||||
  error = funcs.getvalue (instance, NPNVWindowNPObject, &window);
 | 
			
		||||
  if (error != NPERR_NO_ERROR)
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  if (!funcs.getproperty (instance, window,
 | 
			
		||||
                          funcs.getstringidentifier ("document"),
 | 
			
		||||
                          &document))
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  if (!NPVARIANT_IS_OBJECT (document))
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  if (!funcs.getproperty (instance, NPVARIANT_TO_OBJECT (document),
 | 
			
		||||
                          funcs.getstringidentifier ("location"),
 | 
			
		||||
                          &location))
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  if (!NPVARIANT_IS_OBJECT (location))
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  hostname = get_string_property (instance,
 | 
			
		||||
                                  NPVARIANT_TO_OBJECT (location),
 | 
			
		||||
                                  "hostname");
 | 
			
		||||
 | 
			
		||||
  if (g_strcmp0 (hostname, ORIGIN))
 | 
			
		||||
    {
 | 
			
		||||
      g_debug ("origin does not match, is %s",
 | 
			
		||||
               hostname);
 | 
			
		||||
 | 
			
		||||
      goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  protocol = get_string_property (instance,
 | 
			
		||||
                                  NPVARIANT_TO_OBJECT (location),
 | 
			
		||||
                                  "protocol");
 | 
			
		||||
 | 
			
		||||
  if (g_strcmp0 (protocol, "https:") != 0)
 | 
			
		||||
    {
 | 
			
		||||
      g_debug ("protocol does not match, is %s",
 | 
			
		||||
               protocol);
 | 
			
		||||
 | 
			
		||||
      goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  ret = TRUE;
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  g_free (protocol);
 | 
			
		||||
  g_free (hostname);
 | 
			
		||||
 | 
			
		||||
  funcs.releasevariantvalue (&location);
 | 
			
		||||
  funcs.releasevariantvalue (&document);
 | 
			
		||||
 | 
			
		||||
  if (window != NULL)
 | 
			
		||||
    funcs.releaseobject (window);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* =============== public entry points =================== */
 | 
			
		||||
 | 
			
		||||
NPError
 | 
			
		||||
NP_Initialize(NPNetscapeFuncs *pfuncs, NPPluginFuncs *plugin)
 | 
			
		||||
{
 | 
			
		||||
  /* global initialization routine, called once when plugin
 | 
			
		||||
     is loaded */
 | 
			
		||||
 | 
			
		||||
  g_type_init ();
 | 
			
		||||
 | 
			
		||||
  g_debug ("plugin loaded");
 | 
			
		||||
 | 
			
		||||
  memcpy (&funcs, pfuncs, sizeof (funcs));
 | 
			
		||||
 | 
			
		||||
  plugin->size = sizeof(NPPluginFuncs);
 | 
			
		||||
  plugin->newp = NPP_New;
 | 
			
		||||
  plugin->destroy = NPP_Destroy;
 | 
			
		||||
  plugin->getvalue = NPP_GetValue;
 | 
			
		||||
  plugin->setwindow = NPP_SetWindow;
 | 
			
		||||
 | 
			
		||||
  return NPERR_NO_ERROR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NPError
 | 
			
		||||
NP_Shutdown(void)
 | 
			
		||||
{
 | 
			
		||||
  return NPERR_NO_ERROR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char*
 | 
			
		||||
NP_GetMIMEDescription(void)
 | 
			
		||||
{
 | 
			
		||||
  return PLUGIN_MIME_STRING;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NPError
 | 
			
		||||
NP_GetValue(void         *instance,
 | 
			
		||||
            NPPVariable   variable,
 | 
			
		||||
            void         *value)
 | 
			
		||||
{
 | 
			
		||||
  switch (variable) {
 | 
			
		||||
  case NPPVpluginNameString:
 | 
			
		||||
    *(char**)value = PLUGIN_NAME;
 | 
			
		||||
    break;
 | 
			
		||||
  case NPPVpluginDescriptionString:
 | 
			
		||||
    *(char**)value = PLUGIN_DESCRIPTION;
 | 
			
		||||
    break;
 | 
			
		||||
  default:
 | 
			
		||||
    ;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return NPERR_NO_ERROR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NPError
 | 
			
		||||
NPP_New(NPMIMEType    mimetype,
 | 
			
		||||
        NPP           instance,
 | 
			
		||||
        uint16_t      mode,
 | 
			
		||||
        int16_t       argc,
 | 
			
		||||
        char        **argn,
 | 
			
		||||
        char        **argv,
 | 
			
		||||
        NPSavedData  *saved)
 | 
			
		||||
{
 | 
			
		||||
  /* instance initialization function */
 | 
			
		||||
  PluginData *data;
 | 
			
		||||
  GError *error = NULL;
 | 
			
		||||
 | 
			
		||||
  g_debug ("plugin created");
 | 
			
		||||
 | 
			
		||||
  if (!check_origin_and_protocol (instance))
 | 
			
		||||
    return NPERR_GENERIC_ERROR;
 | 
			
		||||
 | 
			
		||||
  data = g_slice_new (PluginData);
 | 
			
		||||
  instance->pdata = data;
 | 
			
		||||
 | 
			
		||||
  data->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
 | 
			
		||||
                                               G_DBUS_PROXY_FLAGS_NONE,
 | 
			
		||||
                                               NULL, /* interface info */
 | 
			
		||||
                                               "org.gnome.Shell",
 | 
			
		||||
                                               "/org/gnome/Shell",
 | 
			
		||||
                                               "org.gnome.Shell",
 | 
			
		||||
                                               NULL, /* GCancellable */
 | 
			
		||||
                                               &error);
 | 
			
		||||
  if (!data->proxy)
 | 
			
		||||
    {
 | 
			
		||||
      /* ignore error if the shell is not running, otherwise warn */
 | 
			
		||||
      if (error->domain != G_DBUS_ERROR ||
 | 
			
		||||
          error->code != G_DBUS_ERROR_NAME_HAS_NO_OWNER)
 | 
			
		||||
        {
 | 
			
		||||
          g_warning ("Failed to set up Shell proxy: %s", error->message);
 | 
			
		||||
        }
 | 
			
		||||
      g_clear_error (&error);
 | 
			
		||||
      return NPERR_GENERIC_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_debug ("plugin created successfully");
 | 
			
		||||
 | 
			
		||||
  return NPERR_NO_ERROR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NPError
 | 
			
		||||
NPP_Destroy(NPP           instance,
 | 
			
		||||
	    NPSavedData **saved)
 | 
			
		||||
{
 | 
			
		||||
  /* instance finalization function */
 | 
			
		||||
 | 
			
		||||
  PluginData *data = instance->pdata;
 | 
			
		||||
 | 
			
		||||
  g_debug ("plugin destroyed");
 | 
			
		||||
 | 
			
		||||
  g_object_unref (data->proxy);
 | 
			
		||||
 | 
			
		||||
  g_slice_free (PluginData, data);
 | 
			
		||||
 | 
			
		||||
  return NPERR_NO_ERROR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* =================== scripting interface =================== */
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  NPObject     parent;
 | 
			
		||||
  NPP          instance;
 | 
			
		||||
  GDBusProxy  *proxy;
 | 
			
		||||
  GSettings   *settings;
 | 
			
		||||
  NPObject    *listener;
 | 
			
		||||
  NPObject    *restart_listener;
 | 
			
		||||
  gint         signal_id;
 | 
			
		||||
  guint        watch_name_id;
 | 
			
		||||
} PluginObject;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_shell_signal (GDBusProxy *proxy,
 | 
			
		||||
                 gchar      *sender_name,
 | 
			
		||||
                 gchar      *signal_name,
 | 
			
		||||
                 GVariant   *parameters,
 | 
			
		||||
                 gpointer    user_data)
 | 
			
		||||
{
 | 
			
		||||
  PluginObject *obj = user_data;
 | 
			
		||||
 | 
			
		||||
  if (strcmp (signal_name, "ExtensionStatusChanged") == 0)
 | 
			
		||||
    {
 | 
			
		||||
      gchar *uuid;
 | 
			
		||||
      gint32 status;
 | 
			
		||||
      gchar *error;
 | 
			
		||||
      NPVariant args[3];
 | 
			
		||||
      NPVariant result = { NPVariantType_Void };
 | 
			
		||||
 | 
			
		||||
      g_variant_get (parameters, "(sis)", &uuid, &status, &error);
 | 
			
		||||
      STRINGZ_TO_NPVARIANT (uuid, args[0]);
 | 
			
		||||
      INT32_TO_NPVARIANT (status, args[1]);
 | 
			
		||||
      STRINGZ_TO_NPVARIANT (error, args[2]);
 | 
			
		||||
 | 
			
		||||
      funcs.invokeDefault (obj->instance, obj->listener,
 | 
			
		||||
			   args, 3, &result);
 | 
			
		||||
 | 
			
		||||
      funcs.releasevariantvalue (&result);
 | 
			
		||||
      g_free (uuid);
 | 
			
		||||
      g_free (error);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_shell_appeared (GDBusConnection *connection,
 | 
			
		||||
                   const gchar     *name,
 | 
			
		||||
                   const gchar     *name_owner,
 | 
			
		||||
                   gpointer         user_data)
 | 
			
		||||
{
 | 
			
		||||
  PluginObject *obj = (PluginObject*) user_data;
 | 
			
		||||
 | 
			
		||||
  if (obj->restart_listener)
 | 
			
		||||
    {
 | 
			
		||||
      NPVariant result = { NPVariantType_Void };
 | 
			
		||||
 | 
			
		||||
      funcs.invokeDefault (obj->instance, obj->restart_listener,
 | 
			
		||||
                           NULL, 0, &result);
 | 
			
		||||
 | 
			
		||||
      funcs.releasevariantvalue (&result);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define SHELL_SCHEMA "org.gnome.shell"
 | 
			
		||||
#define ENABLED_EXTENSIONS_KEY "enabled-extensions"
 | 
			
		||||
 | 
			
		||||
static NPObject *
 | 
			
		||||
plugin_object_allocate (NPP      instance,
 | 
			
		||||
                        NPClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  PluginData *data = instance->pdata;
 | 
			
		||||
  PluginObject *obj = g_slice_new0 (PluginObject);
 | 
			
		||||
 | 
			
		||||
  obj->instance = instance;
 | 
			
		||||
  obj->proxy = g_object_ref (data->proxy);
 | 
			
		||||
  obj->settings = g_settings_new (SHELL_SCHEMA);
 | 
			
		||||
  obj->signal_id = g_signal_connect (obj->proxy, "g-signal",
 | 
			
		||||
                                     G_CALLBACK (on_shell_signal), obj);
 | 
			
		||||
 | 
			
		||||
  obj->watch_name_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
 | 
			
		||||
                                         "org.gnome.Shell",
 | 
			
		||||
                                         G_BUS_NAME_WATCHER_FLAGS_NONE,
 | 
			
		||||
                                         on_shell_appeared,
 | 
			
		||||
                                         NULL,
 | 
			
		||||
                                         obj,
 | 
			
		||||
                                         NULL);
 | 
			
		||||
 | 
			
		||||
  g_debug ("plugin object created");
 | 
			
		||||
 | 
			
		||||
  return (NPObject*)obj;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
plugin_object_deallocate (NPObject *npobj)
 | 
			
		||||
{
 | 
			
		||||
  PluginObject *obj = (PluginObject*)npobj;
 | 
			
		||||
 | 
			
		||||
  g_signal_handler_disconnect (obj->proxy, obj->signal_id);
 | 
			
		||||
  g_object_unref (obj->proxy);
 | 
			
		||||
 | 
			
		||||
  if (obj->listener)
 | 
			
		||||
    funcs.releaseobject (obj->listener);
 | 
			
		||||
 | 
			
		||||
  if (obj->watch_name_id)
 | 
			
		||||
    g_bus_unwatch_name (obj->watch_name_id);
 | 
			
		||||
 | 
			
		||||
  g_debug ("plugin object destroyed");
 | 
			
		||||
 | 
			
		||||
  g_slice_free (PluginObject, obj);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static NPIdentifier api_version_id;
 | 
			
		||||
static NPIdentifier shell_version_id;
 | 
			
		||||
static NPIdentifier get_info_id;
 | 
			
		||||
static NPIdentifier list_extensions_id;
 | 
			
		||||
static NPIdentifier enable_extension_id;
 | 
			
		||||
static NPIdentifier install_extension_id;
 | 
			
		||||
static NPIdentifier uninstall_extension_id;
 | 
			
		||||
static NPIdentifier onextension_changed_id;
 | 
			
		||||
static NPIdentifier onrestart_id;
 | 
			
		||||
static NPIdentifier get_errors_id;
 | 
			
		||||
static NPIdentifier launch_extension_prefs_id;
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
plugin_object_has_method (NPObject     *npobj,
 | 
			
		||||
                          NPIdentifier  name)
 | 
			
		||||
{
 | 
			
		||||
  return (name == get_info_id ||
 | 
			
		||||
          name == list_extensions_id ||
 | 
			
		||||
          name == enable_extension_id ||
 | 
			
		||||
          name == install_extension_id ||
 | 
			
		||||
          name == uninstall_extension_id ||
 | 
			
		||||
          name == get_errors_id ||
 | 
			
		||||
          name == launch_extension_prefs_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline gboolean
 | 
			
		||||
uuid_is_valid (const gchar *uuid)
 | 
			
		||||
{
 | 
			
		||||
  gsize i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; uuid[i]; i ++)
 | 
			
		||||
    {
 | 
			
		||||
      gchar c = uuid[i];
 | 
			
		||||
      if (c < 32 || c >= 127)
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
      switch (c)
 | 
			
		||||
        {
 | 
			
		||||
        case '&':
 | 
			
		||||
        case '<':
 | 
			
		||||
        case '>':
 | 
			
		||||
        case '/':
 | 
			
		||||
        case '\\':
 | 
			
		||||
          return FALSE;
 | 
			
		||||
        default:
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
jsonify_variant (GVariant  *variant,
 | 
			
		||||
                 NPVariant *result)
 | 
			
		||||
{
 | 
			
		||||
  gboolean ret;
 | 
			
		||||
  GVariant *real_value;
 | 
			
		||||
  JsonNode *root;
 | 
			
		||||
  JsonGenerator *generator;
 | 
			
		||||
  gsize json_length;
 | 
			
		||||
  gchar *json;
 | 
			
		||||
  gchar *buffer;
 | 
			
		||||
 | 
			
		||||
  ret = TRUE;
 | 
			
		||||
 | 
			
		||||
  /* DBus methods can return multiple values,
 | 
			
		||||
   * but we're only interested in the first. */
 | 
			
		||||
  g_variant_get (variant, "(@*)", &real_value);
 | 
			
		||||
 | 
			
		||||
  root = json_gvariant_serialize (real_value);
 | 
			
		||||
 | 
			
		||||
  generator = json_generator_new ();
 | 
			
		||||
  json_generator_set_root (generator, root);
 | 
			
		||||
  json = json_generator_to_data (generator, &json_length);
 | 
			
		||||
 | 
			
		||||
  buffer = funcs.memalloc (json_length + 1);
 | 
			
		||||
  if (!buffer)
 | 
			
		||||
    {
 | 
			
		||||
      ret = FALSE;
 | 
			
		||||
      goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  strcpy (buffer, json);
 | 
			
		||||
 | 
			
		||||
  STRINGN_TO_NPVARIANT (buffer, json_length, *result);
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  g_variant_unref (variant);
 | 
			
		||||
  g_variant_unref (real_value);
 | 
			
		||||
  json_node_free (root);
 | 
			
		||||
  g_free (json);
 | 
			
		||||
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
plugin_list_extensions (PluginObject  *obj,
 | 
			
		||||
                        NPVariant     *result)
 | 
			
		||||
{
 | 
			
		||||
  GError *error = NULL;
 | 
			
		||||
  GVariant *res;
 | 
			
		||||
 | 
			
		||||
  res = g_dbus_proxy_call_sync (obj->proxy,
 | 
			
		||||
                                "ListExtensions",
 | 
			
		||||
                                NULL, /* parameters */
 | 
			
		||||
                                G_DBUS_CALL_FLAGS_NONE,
 | 
			
		||||
                                -1, /* timeout */
 | 
			
		||||
                                NULL, /* cancellable */
 | 
			
		||||
                                &error);
 | 
			
		||||
 | 
			
		||||
  if (!res)
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("Failed to retrieve extension list: %s", error->message);
 | 
			
		||||
      g_error_free (error);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return jsonify_variant (res, result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
plugin_enable_extension (PluginObject *obj,
 | 
			
		||||
                         NPString      uuid,
 | 
			
		||||
                         gboolean      enabled)
 | 
			
		||||
{
 | 
			
		||||
  gboolean ret;
 | 
			
		||||
  gchar *uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
 | 
			
		||||
  gsize length;
 | 
			
		||||
  gchar **uuids;
 | 
			
		||||
  const gchar **new_uuids;
 | 
			
		||||
 | 
			
		||||
  if (!uuid_is_valid (uuid_str))
 | 
			
		||||
    {
 | 
			
		||||
      g_free (uuid_str);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  uuids = g_settings_get_strv (obj->settings, ENABLED_EXTENSIONS_KEY);
 | 
			
		||||
  length = g_strv_length (uuids);
 | 
			
		||||
 | 
			
		||||
  if (enabled)
 | 
			
		||||
    {
 | 
			
		||||
      new_uuids = g_new (const gchar *, length + 2); /* New key, NULL */
 | 
			
		||||
      memcpy (new_uuids, uuids, length * sizeof (*new_uuids));
 | 
			
		||||
      new_uuids[length] = uuid_str;
 | 
			
		||||
      new_uuids[length + 1] = NULL;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      gsize i = 0, j = 0;
 | 
			
		||||
      new_uuids = g_new (const gchar *, length);
 | 
			
		||||
      for (i = 0; i < length; i ++)
 | 
			
		||||
        {
 | 
			
		||||
          if (g_str_equal (uuids[i], uuid_str))
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
          new_uuids[j] = uuids[i];
 | 
			
		||||
          j++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      new_uuids[j] = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  ret = g_settings_set_strv (obj->settings,
 | 
			
		||||
                             ENABLED_EXTENSIONS_KEY,
 | 
			
		||||
                             new_uuids);
 | 
			
		||||
 | 
			
		||||
  g_strfreev (uuids);
 | 
			
		||||
  g_free (new_uuids);
 | 
			
		||||
  g_free (uuid_str);
 | 
			
		||||
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
plugin_install_extension (PluginObject *obj,
 | 
			
		||||
                          NPString      uuid)
 | 
			
		||||
{
 | 
			
		||||
  gchar *uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
 | 
			
		||||
 | 
			
		||||
  if (!uuid_is_valid (uuid_str))
 | 
			
		||||
    {
 | 
			
		||||
      g_free (uuid_str);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_dbus_proxy_call (obj->proxy,
 | 
			
		||||
                     "InstallRemoteExtension",
 | 
			
		||||
                     g_variant_new ("(s)", uuid_str),
 | 
			
		||||
                     G_DBUS_CALL_FLAGS_NONE,
 | 
			
		||||
                     -1, /* timeout */
 | 
			
		||||
                     NULL, /* cancellable */
 | 
			
		||||
                     NULL, /* callback */
 | 
			
		||||
                     NULL /* user_data */);
 | 
			
		||||
 | 
			
		||||
  g_free (uuid_str);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
plugin_uninstall_extension (PluginObject *obj,
 | 
			
		||||
                            NPString      uuid,
 | 
			
		||||
                            NPVariant    *result)
 | 
			
		||||
{
 | 
			
		||||
  GError *error = NULL;
 | 
			
		||||
  GVariant *res;
 | 
			
		||||
  gchar *uuid_str;
 | 
			
		||||
 | 
			
		||||
  uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
 | 
			
		||||
  if (!uuid_is_valid (uuid_str))
 | 
			
		||||
    {
 | 
			
		||||
      g_free (uuid_str);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  res = g_dbus_proxy_call_sync (obj->proxy,
 | 
			
		||||
                                "UninstallExtension",
 | 
			
		||||
                                g_variant_new ("(s)",
 | 
			
		||||
                                               uuid_str),
 | 
			
		||||
                                G_DBUS_CALL_FLAGS_NONE,
 | 
			
		||||
                                -1, /* timeout */
 | 
			
		||||
                                NULL, /* cancellable */
 | 
			
		||||
                                &error);
 | 
			
		||||
 | 
			
		||||
  g_free (uuid_str);
 | 
			
		||||
 | 
			
		||||
  if (!res)
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("Failed to uninstall extension: %s", error->message);
 | 
			
		||||
      g_error_free (error);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return jsonify_variant (res, result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
plugin_get_info (PluginObject *obj,
 | 
			
		||||
                 NPString      uuid,
 | 
			
		||||
                 NPVariant    *result)
 | 
			
		||||
{
 | 
			
		||||
  GError *error = NULL;
 | 
			
		||||
  GVariant *res;
 | 
			
		||||
  gchar *uuid_str;
 | 
			
		||||
 | 
			
		||||
  uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
 | 
			
		||||
  if (!uuid_is_valid (uuid_str))
 | 
			
		||||
    {
 | 
			
		||||
      g_free (uuid_str);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  res = g_dbus_proxy_call_sync (obj->proxy,
 | 
			
		||||
                                "GetExtensionInfo",
 | 
			
		||||
                                g_variant_new ("(s)", uuid_str),
 | 
			
		||||
                                G_DBUS_CALL_FLAGS_NONE,
 | 
			
		||||
                                -1, /* timeout */
 | 
			
		||||
                                NULL, /* cancellable */
 | 
			
		||||
                                &error);
 | 
			
		||||
 | 
			
		||||
  g_free (uuid_str);
 | 
			
		||||
 | 
			
		||||
  if (!res)
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("Failed to retrieve extension metadata: %s", error->message);
 | 
			
		||||
      g_error_free (error);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return jsonify_variant (res, result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
plugin_get_errors (PluginObject *obj,
 | 
			
		||||
                   NPString      uuid,
 | 
			
		||||
                   NPVariant    *result)
 | 
			
		||||
{
 | 
			
		||||
  GError *error = NULL;
 | 
			
		||||
  GVariant *res;
 | 
			
		||||
  gchar *uuid_str;
 | 
			
		||||
 | 
			
		||||
  uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
 | 
			
		||||
  if (!uuid_is_valid (uuid_str))
 | 
			
		||||
    {
 | 
			
		||||
      g_free (uuid_str);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  res = g_dbus_proxy_call_sync (obj->proxy,
 | 
			
		||||
                                "GetExtensionErrors",
 | 
			
		||||
                                g_variant_new ("(s)", uuid_str),
 | 
			
		||||
                                G_DBUS_CALL_FLAGS_NONE,
 | 
			
		||||
                                -1, /* timeout */
 | 
			
		||||
                                NULL, /* cancellable */
 | 
			
		||||
                                &error);
 | 
			
		||||
 | 
			
		||||
  g_free (uuid_str);
 | 
			
		||||
 | 
			
		||||
  if (!res)
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("Failed to retrieve errors: %s", error->message);
 | 
			
		||||
      g_error_free (error);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return jsonify_variant (res, result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
plugin_launch_extension_prefs (PluginObject *obj,
 | 
			
		||||
                               NPString      uuid,
 | 
			
		||||
                               NPVariant    *result)
 | 
			
		||||
{
 | 
			
		||||
  gchar *uuid_str;
 | 
			
		||||
 | 
			
		||||
  uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
 | 
			
		||||
  if (!uuid_is_valid (uuid_str))
 | 
			
		||||
    {
 | 
			
		||||
      g_free (uuid_str);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_dbus_proxy_call (obj->proxy,
 | 
			
		||||
                     "LaunchExtensionPrefs",
 | 
			
		||||
                     g_variant_new ("(s)", uuid_str),
 | 
			
		||||
                     G_DBUS_CALL_FLAGS_NONE,
 | 
			
		||||
                     -1, /* timeout */
 | 
			
		||||
                     NULL, /* cancellable */
 | 
			
		||||
                     NULL, /* callback */
 | 
			
		||||
                     NULL /* user_data */);
 | 
			
		||||
 | 
			
		||||
  g_free (uuid_str);
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
plugin_get_api_version (PluginObject  *obj,
 | 
			
		||||
                        NPVariant     *result)
 | 
			
		||||
{
 | 
			
		||||
  INT32_TO_NPVARIANT (PLUGIN_API_VERSION, *result);
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
plugin_get_shell_version (PluginObject  *obj,
 | 
			
		||||
                          NPVariant     *result)
 | 
			
		||||
{
 | 
			
		||||
  GVariant *res;
 | 
			
		||||
  const gchar *version;
 | 
			
		||||
  gsize length;
 | 
			
		||||
  gchar *buffer;
 | 
			
		||||
  gboolean ret;
 | 
			
		||||
 | 
			
		||||
  ret = TRUE;
 | 
			
		||||
 | 
			
		||||
  res = g_dbus_proxy_get_cached_property (obj->proxy,
 | 
			
		||||
                                          "ShellVersion");
 | 
			
		||||
 | 
			
		||||
  if (res == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("Failed to grab shell version.");
 | 
			
		||||
      version = "-1";
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      g_variant_get (res, "&s", &version);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  length = strlen (version);
 | 
			
		||||
  buffer = funcs.memalloc (length + 1);
 | 
			
		||||
  if (!buffer)
 | 
			
		||||
    {
 | 
			
		||||
      ret = FALSE;
 | 
			
		||||
      goto out;
 | 
			
		||||
    }
 | 
			
		||||
  strcpy (buffer, version);
 | 
			
		||||
 | 
			
		||||
  STRINGN_TO_NPVARIANT (buffer, length, *result);
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  if (res)
 | 
			
		||||
    g_variant_unref (res);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
plugin_object_invoke (NPObject        *npobj,
 | 
			
		||||
                      NPIdentifier     name,
 | 
			
		||||
                      const NPVariant *args,
 | 
			
		||||
                      uint32_t         argc,
 | 
			
		||||
                      NPVariant       *result)
 | 
			
		||||
{
 | 
			
		||||
  PluginObject *obj;
 | 
			
		||||
 | 
			
		||||
  g_debug ("invoking plugin object method");
 | 
			
		||||
 | 
			
		||||
  obj = (PluginObject*) npobj;
 | 
			
		||||
 | 
			
		||||
  VOID_TO_NPVARIANT (*result);
 | 
			
		||||
 | 
			
		||||
  if (!plugin_object_has_method (npobj, name))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (name == list_extensions_id)
 | 
			
		||||
    return plugin_list_extensions (obj, result);
 | 
			
		||||
  else if (name == get_info_id)
 | 
			
		||||
    {
 | 
			
		||||
      if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
 | 
			
		||||
 | 
			
		||||
      return plugin_get_info (obj, NPVARIANT_TO_STRING(args[0]), result);
 | 
			
		||||
    }
 | 
			
		||||
  else if (name == enable_extension_id)
 | 
			
		||||
    {
 | 
			
		||||
      if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
 | 
			
		||||
      if (!NPVARIANT_IS_BOOLEAN(args[1])) return FALSE;
 | 
			
		||||
 | 
			
		||||
      return plugin_enable_extension (obj,
 | 
			
		||||
                                      NPVARIANT_TO_STRING(args[0]),
 | 
			
		||||
                                      NPVARIANT_TO_BOOLEAN(args[1]));
 | 
			
		||||
    }
 | 
			
		||||
  else if (name == install_extension_id)
 | 
			
		||||
    {
 | 
			
		||||
      if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
 | 
			
		||||
 | 
			
		||||
      return plugin_install_extension (obj,
 | 
			
		||||
                                       NPVARIANT_TO_STRING(args[0]));
 | 
			
		||||
    }
 | 
			
		||||
  else if (name == uninstall_extension_id)
 | 
			
		||||
    {
 | 
			
		||||
      if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
 | 
			
		||||
 | 
			
		||||
      return plugin_uninstall_extension (obj,
 | 
			
		||||
                                         NPVARIANT_TO_STRING(args[0]),
 | 
			
		||||
                                         result);
 | 
			
		||||
    }
 | 
			
		||||
  else if (name == get_errors_id)
 | 
			
		||||
    {
 | 
			
		||||
      if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
 | 
			
		||||
 | 
			
		||||
      return plugin_get_errors (obj,
 | 
			
		||||
                                NPVARIANT_TO_STRING(args[0]),
 | 
			
		||||
                                result);
 | 
			
		||||
    }
 | 
			
		||||
  else if (name == launch_extension_prefs_id)
 | 
			
		||||
    {
 | 
			
		||||
      if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
 | 
			
		||||
 | 
			
		||||
      return plugin_launch_extension_prefs (obj,
 | 
			
		||||
                                            NPVARIANT_TO_STRING(args[0]),
 | 
			
		||||
                                            result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
plugin_object_has_property (NPObject     *npobj,
 | 
			
		||||
                            NPIdentifier  name)
 | 
			
		||||
{
 | 
			
		||||
  return (name == onextension_changed_id ||
 | 
			
		||||
          name == onrestart_id ||
 | 
			
		||||
          name == api_version_id ||
 | 
			
		||||
          name == shell_version_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
plugin_object_get_property (NPObject     *npobj,
 | 
			
		||||
                            NPIdentifier  name,
 | 
			
		||||
                            NPVariant    *result)
 | 
			
		||||
{
 | 
			
		||||
  PluginObject *obj;
 | 
			
		||||
 | 
			
		||||
  if (!plugin_object_has_property (npobj, name))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  obj = (PluginObject*) npobj;
 | 
			
		||||
  if (name == api_version_id)
 | 
			
		||||
    return plugin_get_api_version (obj, result);
 | 
			
		||||
  else if (name == shell_version_id)
 | 
			
		||||
    return plugin_get_shell_version (obj, result);
 | 
			
		||||
  else if (name == onextension_changed_id)
 | 
			
		||||
    {
 | 
			
		||||
      if (obj->listener)
 | 
			
		||||
        OBJECT_TO_NPVARIANT (obj->listener, *result);
 | 
			
		||||
      else
 | 
			
		||||
        NULL_TO_NPVARIANT (*result);
 | 
			
		||||
    }
 | 
			
		||||
  else if (name == onrestart_id)
 | 
			
		||||
    {
 | 
			
		||||
      if (obj->restart_listener)
 | 
			
		||||
        OBJECT_TO_NPVARIANT (obj->restart_listener, *result);
 | 
			
		||||
      else
 | 
			
		||||
        NULL_TO_NPVARIANT (*result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
plugin_object_set_callback (NPObject        **listener,
 | 
			
		||||
                            const NPVariant  *value)
 | 
			
		||||
{
 | 
			
		||||
  if (!NPVARIANT_IS_OBJECT (*value) && !NPVARIANT_IS_NULL (*value))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (*listener)
 | 
			
		||||
    funcs.releaseobject (*listener);
 | 
			
		||||
  *listener = NULL;
 | 
			
		||||
 | 
			
		||||
  if (NPVARIANT_IS_OBJECT (*value))
 | 
			
		||||
    {
 | 
			
		||||
      *listener = NPVARIANT_TO_OBJECT (*value);
 | 
			
		||||
      funcs.retainobject (*listener);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
plugin_object_set_property (NPObject        *npobj,
 | 
			
		||||
                            NPIdentifier     name,
 | 
			
		||||
                            const NPVariant *value)
 | 
			
		||||
{
 | 
			
		||||
  PluginObject *obj;
 | 
			
		||||
 | 
			
		||||
  obj = (PluginObject *)npobj;
 | 
			
		||||
 | 
			
		||||
  if (name == onextension_changed_id)
 | 
			
		||||
    return plugin_object_set_callback (&obj->listener, value);
 | 
			
		||||
 | 
			
		||||
  if (name == onrestart_id)
 | 
			
		||||
    return plugin_object_set_callback (&obj->restart_listener, value);
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static NPClass plugin_class = {
 | 
			
		||||
  NP_CLASS_STRUCT_VERSION,
 | 
			
		||||
  plugin_object_allocate,
 | 
			
		||||
  plugin_object_deallocate,
 | 
			
		||||
  NULL, /* invalidate */
 | 
			
		||||
  plugin_object_has_method,
 | 
			
		||||
  plugin_object_invoke,
 | 
			
		||||
  NULL, /* invoke default */
 | 
			
		||||
  plugin_object_has_property,
 | 
			
		||||
  plugin_object_get_property,
 | 
			
		||||
  plugin_object_set_property,
 | 
			
		||||
  NULL, /* remove property */
 | 
			
		||||
  NULL, /* enumerate */
 | 
			
		||||
  NULL, /* construct */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
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");
 | 
			
		||||
 | 
			
		||||
  get_info_id = funcs.getstringidentifier ("getExtensionInfo");
 | 
			
		||||
  list_extensions_id = funcs.getstringidentifier ("listExtensions");
 | 
			
		||||
  enable_extension_id = funcs.getstringidentifier ("setExtensionEnabled");
 | 
			
		||||
  install_extension_id = funcs.getstringidentifier ("installExtension");
 | 
			
		||||
  uninstall_extension_id = funcs.getstringidentifier ("uninstallExtension");
 | 
			
		||||
  get_errors_id = funcs.getstringidentifier ("getExtensionErrors");
 | 
			
		||||
  launch_extension_prefs_id = funcs.getstringidentifier ("launchExtensionPrefs");
 | 
			
		||||
 | 
			
		||||
  onrestart_id = funcs.getstringidentifier ("onshellrestart");
 | 
			
		||||
  onextension_changed_id = funcs.getstringidentifier ("onchange");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NPError
 | 
			
		||||
NPP_GetValue(NPP          instance,
 | 
			
		||||
	     NPPVariable  variable,
 | 
			
		||||
	     void        *value)
 | 
			
		||||
{
 | 
			
		||||
  g_debug ("NPP_GetValue called");
 | 
			
		||||
 | 
			
		||||
  switch (variable) {
 | 
			
		||||
  case NPPVpluginScriptableNPObject:
 | 
			
		||||
    g_debug ("creating scriptable object");
 | 
			
		||||
    init_methods_and_properties ();
 | 
			
		||||
 | 
			
		||||
    *(NPObject**)value = funcs.createobject (instance, &plugin_class);
 | 
			
		||||
    break;
 | 
			
		||||
 | 
			
		||||
  case NPPVpluginNeedsXEmbed:
 | 
			
		||||
    *(bool *)value = TRUE;
 | 
			
		||||
    break;
 | 
			
		||||
 | 
			
		||||
  default:
 | 
			
		||||
    ;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return NPERR_NO_ERROR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Opera tries to call NPP_SetWindow without checking the
 | 
			
		||||
 * NULL pointer beforehand. */
 | 
			
		||||
NPError
 | 
			
		||||
NPP_SetWindow(NPP          instance,
 | 
			
		||||
              NPWindow    *window)
 | 
			
		||||
{
 | 
			
		||||
  return NPERR_NO_ERROR;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,893 +0,0 @@
 | 
			
		||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | 
			
		||||
/* ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 | 
			
		||||
 *
 | 
			
		||||
 * The contents of this file are subject to the Mozilla Public License Version
 | 
			
		||||
 * 1.1 (the "License"); you may not use this file except in compliance with
 | 
			
		||||
 * the License. You may obtain a copy of the License at
 | 
			
		||||
 * http://www.mozilla.org/MPL/
 | 
			
		||||
 *
 | 
			
		||||
 * Software distributed under the License is distributed on an "AS IS" basis,
 | 
			
		||||
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 | 
			
		||||
 * for the specific language governing rights and limitations under the
 | 
			
		||||
 * License.
 | 
			
		||||
 *
 | 
			
		||||
 * The Original Code is mozilla.org code.
 | 
			
		||||
 *
 | 
			
		||||
 * The Initial Developer of the Original Code is
 | 
			
		||||
 * Netscape Communications Corporation.
 | 
			
		||||
 * Portions created by the Initial Developer are Copyright (C) 1998
 | 
			
		||||
 * the Initial Developer. All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributor(s):
 | 
			
		||||
 *
 | 
			
		||||
 * Alternatively, the contents of this file may be used under the terms of
 | 
			
		||||
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 | 
			
		||||
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 | 
			
		||||
 * in which case the provisions of the GPL or the LGPL are applicable instead
 | 
			
		||||
 * of those above. If you wish to allow use of your version of this file only
 | 
			
		||||
 * under the terms of either the GPL or the LGPL, and not to allow others to
 | 
			
		||||
 * use your version of this file under the terms of the MPL, indicate your
 | 
			
		||||
 * decision by deleting the provisions above and replace them with the notice
 | 
			
		||||
 * and other provisions required by the GPL or the LGPL. If you do not delete
 | 
			
		||||
 * the provisions above, a recipient may use your version of this file under
 | 
			
		||||
 * the terms of any one of the MPL, the GPL or the LGPL.
 | 
			
		||||
 *
 | 
			
		||||
 * ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
#ifndef npapi_h_
 | 
			
		||||
#define npapi_h_
 | 
			
		||||
 | 
			
		||||
#if defined(__OS2__)
 | 
			
		||||
#pragma pack(1)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "nptypes.h"
 | 
			
		||||
 | 
			
		||||
#if defined(__OS2__) || defined(OS2)
 | 
			
		||||
#ifndef XP_OS2
 | 
			
		||||
#define XP_OS2 1
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(_WIN32) && !defined(__SYMBIAN32__)
 | 
			
		||||
#include <windef.h>
 | 
			
		||||
#ifndef XP_WIN
 | 
			
		||||
#define XP_WIN 1
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__SYMBIAN32__)
 | 
			
		||||
#ifndef XP_SYMBIAN
 | 
			
		||||
#define XP_SYMBIAN 1
 | 
			
		||||
#undef XP_WIN
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__APPLE_CC__) && !defined(XP_UNIX)
 | 
			
		||||
#ifndef XP_MACOSX
 | 
			
		||||
#define XP_MACOSX 1
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(XP_MACOSX) && defined(__LP64__)
 | 
			
		||||
#define NP_NO_QUICKDRAW
 | 
			
		||||
#define NP_NO_CARBON
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(XP_MACOSX)
 | 
			
		||||
#include <ApplicationServices/ApplicationServices.h>
 | 
			
		||||
#include <OpenGL/OpenGL.h>
 | 
			
		||||
#ifndef NP_NO_CARBON
 | 
			
		||||
#include <Carbon/Carbon.h>
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(XP_UNIX)
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#if defined(MOZ_X11)
 | 
			
		||||
#include <X11/Xlib.h>
 | 
			
		||||
#include <X11/Xutil.h>
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(XP_SYMBIAN)
 | 
			
		||||
#include <QEvent>
 | 
			
		||||
#include <QRegion>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*----------------------------------------------------------------------*/
 | 
			
		||||
/*                        Plugin Version Constants                      */
 | 
			
		||||
/*----------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#define NP_VERSION_MAJOR 0
 | 
			
		||||
#define NP_VERSION_MINOR 27
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* The OS/2 version of Netscape uses RC_DATA to define the
 | 
			
		||||
   mime types, file extensions, etc that are required.
 | 
			
		||||
   Use a vertical bar to separate types, end types with \0.
 | 
			
		||||
   FileVersion and ProductVersion are 32bit ints, all other
 | 
			
		||||
   entries are strings that MUST be terminated with a \0.
 | 
			
		||||
 | 
			
		||||
AN EXAMPLE:
 | 
			
		||||
 | 
			
		||||
RCDATA NP_INFO_ProductVersion { 1,0,0,1,}
 | 
			
		||||
 | 
			
		||||
RCDATA NP_INFO_MIMEType    { "video/x-video|",
 | 
			
		||||
                             "video/x-flick\0" }
 | 
			
		||||
RCDATA NP_INFO_FileExtents { "avi|",
 | 
			
		||||
                             "flc\0" }
 | 
			
		||||
RCDATA NP_INFO_FileOpenName{ "MMOS2 video player(*.avi)|",
 | 
			
		||||
                             "MMOS2 Flc/Fli player(*.flc)\0" }
 | 
			
		||||
 | 
			
		||||
RCDATA NP_INFO_FileVersion       { 1,0,0,1 }
 | 
			
		||||
RCDATA NP_INFO_CompanyName       { "Netscape Communications\0" }
 | 
			
		||||
RCDATA NP_INFO_FileDescription   { "NPAVI32 Extension DLL\0"
 | 
			
		||||
RCDATA NP_INFO_InternalName      { "NPAVI32\0" )
 | 
			
		||||
RCDATA NP_INFO_LegalCopyright    { "Copyright Netscape Communications \251 1996\0"
 | 
			
		||||
RCDATA NP_INFO_OriginalFilename  { "NVAPI32.DLL" }
 | 
			
		||||
RCDATA NP_INFO_ProductName       { "NPAVI32 Dynamic Link Library\0" }
 | 
			
		||||
*/
 | 
			
		||||
/* RC_DATA types for version info - required */
 | 
			
		||||
#define NP_INFO_ProductVersion      1
 | 
			
		||||
#define NP_INFO_MIMEType            2
 | 
			
		||||
#define NP_INFO_FileOpenName        3
 | 
			
		||||
#define NP_INFO_FileExtents         4
 | 
			
		||||
/* RC_DATA types for version info - used if found */
 | 
			
		||||
#define NP_INFO_FileDescription     5
 | 
			
		||||
#define NP_INFO_ProductName         6
 | 
			
		||||
/* RC_DATA types for version info - optional */
 | 
			
		||||
#define NP_INFO_CompanyName         7
 | 
			
		||||
#define NP_INFO_FileVersion         8
 | 
			
		||||
#define NP_INFO_InternalName        9
 | 
			
		||||
#define NP_INFO_LegalCopyright      10
 | 
			
		||||
#define NP_INFO_OriginalFilename    11
 | 
			
		||||
 | 
			
		||||
#ifndef RC_INVOKED
 | 
			
		||||
 | 
			
		||||
/*----------------------------------------------------------------------*/
 | 
			
		||||
/*                       Definition of Basic Types                      */
 | 
			
		||||
/*----------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
typedef unsigned char NPBool;
 | 
			
		||||
typedef int16_t       NPError;
 | 
			
		||||
typedef int16_t       NPReason;
 | 
			
		||||
typedef char*         NPMIMEType;
 | 
			
		||||
 | 
			
		||||
/*----------------------------------------------------------------------*/
 | 
			
		||||
/*                       Structures and definitions                     */
 | 
			
		||||
/*----------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#if !defined(__LP64__)
 | 
			
		||||
#if defined(XP_MACOSX)
 | 
			
		||||
#pragma options align=mac68k
 | 
			
		||||
#endif
 | 
			
		||||
#endif /* __LP64__ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *  NPP is a plug-in's opaque instance handle
 | 
			
		||||
 */
 | 
			
		||||
typedef struct _NPP
 | 
			
		||||
{
 | 
			
		||||
  void* pdata;      /* plug-in private data */
 | 
			
		||||
  void* ndata;      /* netscape private data */
 | 
			
		||||
} NPP_t;
 | 
			
		||||
 | 
			
		||||
typedef NPP_t*  NPP;
 | 
			
		||||
 | 
			
		||||
typedef struct _NPStream
 | 
			
		||||
{
 | 
			
		||||
  void*    pdata; /* plug-in private data */
 | 
			
		||||
  void*    ndata; /* netscape private data */
 | 
			
		||||
  const    char* url;
 | 
			
		||||
  uint32_t end;
 | 
			
		||||
  uint32_t lastmodified;
 | 
			
		||||
  void*    notifyData;
 | 
			
		||||
  const    char* headers; /* Response headers from host.
 | 
			
		||||
                           * Exists only for >= NPVERS_HAS_RESPONSE_HEADERS.
 | 
			
		||||
                           * Used for HTTP only; NULL for non-HTTP.
 | 
			
		||||
                           * Available from NPP_NewStream onwards.
 | 
			
		||||
                           * Plugin should copy this data before storing it.
 | 
			
		||||
                           * Includes HTTP status line and all headers,
 | 
			
		||||
                           * preferably verbatim as received from server,
 | 
			
		||||
                           * headers formatted as in HTTP ("Header: Value"),
 | 
			
		||||
                           * and newlines (\n, NOT \r\n) separating lines.
 | 
			
		||||
                           * Terminated by \n\0 (NOT \n\n\0). */
 | 
			
		||||
} NPStream;
 | 
			
		||||
 | 
			
		||||
typedef struct _NPByteRange
 | 
			
		||||
{
 | 
			
		||||
  int32_t  offset; /* negative offset means from the end */
 | 
			
		||||
  uint32_t length;
 | 
			
		||||
  struct _NPByteRange* next;
 | 
			
		||||
} NPByteRange;
 | 
			
		||||
 | 
			
		||||
typedef struct _NPSavedData
 | 
			
		||||
{
 | 
			
		||||
  int32_t len;
 | 
			
		||||
  void*   buf;
 | 
			
		||||
} NPSavedData;
 | 
			
		||||
 | 
			
		||||
typedef struct _NPRect
 | 
			
		||||
{
 | 
			
		||||
  uint16_t top;
 | 
			
		||||
  uint16_t left;
 | 
			
		||||
  uint16_t bottom;
 | 
			
		||||
  uint16_t right;
 | 
			
		||||
} NPRect;
 | 
			
		||||
 | 
			
		||||
typedef struct _NPSize
 | 
			
		||||
{
 | 
			
		||||
  int32_t width;
 | 
			
		||||
  int32_t height;
 | 
			
		||||
} NPSize;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  NPFocusNext = 0,
 | 
			
		||||
  NPFocusPrevious = 1
 | 
			
		||||
} NPFocusDirection;
 | 
			
		||||
 | 
			
		||||
/* Return values for NPP_HandleEvent */
 | 
			
		||||
#define kNPEventNotHandled 0
 | 
			
		||||
#define kNPEventHandled 1
 | 
			
		||||
/* Exact meaning must be spec'd in event model. */
 | 
			
		||||
#define kNPEventStartIME 2
 | 
			
		||||
 | 
			
		||||
#if defined(XP_UNIX)
 | 
			
		||||
/*
 | 
			
		||||
 * Unix specific structures and definitions
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Callback Structures.
 | 
			
		||||
 *
 | 
			
		||||
 * These are used to pass additional platform specific information.
 | 
			
		||||
 */
 | 
			
		||||
enum {
 | 
			
		||||
  NP_SETWINDOW = 1,
 | 
			
		||||
  NP_PRINT
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  int32_t type;
 | 
			
		||||
} NPAnyCallbackStruct;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  int32_t      type;
 | 
			
		||||
#if defined(MOZ_X11)
 | 
			
		||||
  Display*     display;
 | 
			
		||||
  Visual*      visual;
 | 
			
		||||
  Colormap     colormap;
 | 
			
		||||
  unsigned int depth;
 | 
			
		||||
#endif
 | 
			
		||||
} NPSetWindowCallbackStruct;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  int32_t type;
 | 
			
		||||
  FILE* fp;
 | 
			
		||||
} NPPrintCallbackStruct;
 | 
			
		||||
 | 
			
		||||
#endif /* XP_UNIX */
 | 
			
		||||
 | 
			
		||||
#if defined(XP_MACOSX)
 | 
			
		||||
typedef enum {
 | 
			
		||||
#ifndef NP_NO_QUICKDRAW
 | 
			
		||||
  NPDrawingModelQuickDraw = 0,
 | 
			
		||||
#endif
 | 
			
		||||
  NPDrawingModelCoreGraphics = 1,
 | 
			
		||||
  NPDrawingModelOpenGL = 2,
 | 
			
		||||
  NPDrawingModelCoreAnimation = 3,
 | 
			
		||||
  NPDrawingModelInvalidatingCoreAnimation = 4
 | 
			
		||||
} NPDrawingModel;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
#ifndef NP_NO_CARBON
 | 
			
		||||
  NPEventModelCarbon = 0,
 | 
			
		||||
#endif
 | 
			
		||||
  NPEventModelCocoa = 1
 | 
			
		||||
} NPEventModel;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *   The following masks are applied on certain platforms to NPNV and
 | 
			
		||||
 *   NPPV selectors that pass around pointers to COM interfaces. Newer
 | 
			
		||||
 *   compilers on some platforms may generate vtables that are not
 | 
			
		||||
 *   compatible with older compilers. To prevent older plugins from
 | 
			
		||||
 *   not understanding a new browser's ABI, these masks change the
 | 
			
		||||
 *   values of those selectors on those platforms. To remain backwards
 | 
			
		||||
 *   compatible with different versions of the browser, plugins can
 | 
			
		||||
 *   use these masks to dynamically determine and use the correct C++
 | 
			
		||||
 *   ABI that the browser is expecting. This does not apply to Windows
 | 
			
		||||
 *   as Microsoft's COM ABI will likely not change.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define NP_ABI_GCC3_MASK  0x10000000
 | 
			
		||||
/*
 | 
			
		||||
 *   gcc 3.x generated vtables on UNIX and OSX are incompatible with
 | 
			
		||||
 *   previous compilers.
 | 
			
		||||
 */
 | 
			
		||||
#if (defined(XP_UNIX) && defined(__GNUC__) && (__GNUC__ >= 3))
 | 
			
		||||
#define _NP_ABI_MIXIN_FOR_GCC3 NP_ABI_GCC3_MASK
 | 
			
		||||
#else
 | 
			
		||||
#define _NP_ABI_MIXIN_FOR_GCC3 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(XP_MACOSX)
 | 
			
		||||
#define NP_ABI_MACHO_MASK 0x01000000
 | 
			
		||||
#define _NP_ABI_MIXIN_FOR_MACHO NP_ABI_MACHO_MASK
 | 
			
		||||
#else
 | 
			
		||||
#define _NP_ABI_MIXIN_FOR_MACHO 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define NP_ABI_MASK (_NP_ABI_MIXIN_FOR_GCC3 | _NP_ABI_MIXIN_FOR_MACHO)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * List of variable names for which NPP_GetValue shall be implemented
 | 
			
		||||
 */
 | 
			
		||||
typedef enum {
 | 
			
		||||
  NPPVpluginNameString = 1,
 | 
			
		||||
  NPPVpluginDescriptionString,
 | 
			
		||||
  NPPVpluginWindowBool,
 | 
			
		||||
  NPPVpluginTransparentBool,
 | 
			
		||||
  NPPVjavaClass,
 | 
			
		||||
  NPPVpluginWindowSize,
 | 
			
		||||
  NPPVpluginTimerInterval,
 | 
			
		||||
  NPPVpluginScriptableInstance = (10 | NP_ABI_MASK),
 | 
			
		||||
  NPPVpluginScriptableIID = 11,
 | 
			
		||||
  NPPVjavascriptPushCallerBool = 12,
 | 
			
		||||
  NPPVpluginKeepLibraryInMemory = 13,
 | 
			
		||||
  NPPVpluginNeedsXEmbed         = 14,
 | 
			
		||||
 | 
			
		||||
  /* Get the NPObject for scripting the plugin. Introduced in NPAPI minor version 14.
 | 
			
		||||
   */
 | 
			
		||||
  NPPVpluginScriptableNPObject  = 15,
 | 
			
		||||
 | 
			
		||||
  /* Get the plugin value (as \0-terminated UTF-8 string data) for
 | 
			
		||||
   * form submission if the plugin is part of a form. Use
 | 
			
		||||
   * NPN_MemAlloc() to allocate memory for the string data. Introduced
 | 
			
		||||
   * in NPAPI minor version 15.
 | 
			
		||||
   */
 | 
			
		||||
  NPPVformValue = 16,
 | 
			
		||||
 | 
			
		||||
  NPPVpluginUrlRequestsDisplayedBool = 17,
 | 
			
		||||
 | 
			
		||||
  /* Checks if the plugin is interested in receiving the http body of
 | 
			
		||||
   * all http requests (including failed ones, http status != 200).
 | 
			
		||||
   */
 | 
			
		||||
  NPPVpluginWantsAllNetworkStreams = 18,
 | 
			
		||||
 | 
			
		||||
  /* Browsers can retrieve a native ATK accessibility plug ID via this variable. */
 | 
			
		||||
  NPPVpluginNativeAccessibleAtkPlugId = 19,
 | 
			
		||||
 | 
			
		||||
  /* Checks to see if the plug-in would like the browser to load the "src" attribute. */
 | 
			
		||||
  NPPVpluginCancelSrcStream = 20,
 | 
			
		||||
 | 
			
		||||
  NPPVsupportsAdvancedKeyHandling = 21,
 | 
			
		||||
 | 
			
		||||
  NPPVpluginUsesDOMForCursorBool = 22
 | 
			
		||||
 | 
			
		||||
#if defined(XP_MACOSX)
 | 
			
		||||
  /* Used for negotiating drawing models */
 | 
			
		||||
  , NPPVpluginDrawingModel = 1000
 | 
			
		||||
  /* Used for negotiating event models */
 | 
			
		||||
  , NPPVpluginEventModel = 1001
 | 
			
		||||
  /* In the NPDrawingModelCoreAnimation drawing model, the browser asks the plug-in for a Core Animation layer. */
 | 
			
		||||
  , NPPVpluginCoreAnimationLayer = 1003
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
 | 
			
		||||
  , NPPVpluginWindowlessLocalBool = 2002
 | 
			
		||||
#endif
 | 
			
		||||
} NPPVariable;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * List of variable names for which NPN_GetValue should be implemented.
 | 
			
		||||
 */
 | 
			
		||||
typedef enum {
 | 
			
		||||
  NPNVxDisplay = 1,
 | 
			
		||||
  NPNVxtAppContext,
 | 
			
		||||
  NPNVnetscapeWindow,
 | 
			
		||||
  NPNVjavascriptEnabledBool,
 | 
			
		||||
  NPNVasdEnabledBool,
 | 
			
		||||
  NPNVisOfflineBool,
 | 
			
		||||
 | 
			
		||||
  NPNVserviceManager = (10 | NP_ABI_MASK),
 | 
			
		||||
  NPNVDOMElement     = (11 | NP_ABI_MASK),
 | 
			
		||||
  NPNVDOMWindow      = (12 | NP_ABI_MASK),
 | 
			
		||||
  NPNVToolkit        = (13 | NP_ABI_MASK),
 | 
			
		||||
  NPNVSupportsXEmbedBool = 14,
 | 
			
		||||
 | 
			
		||||
  /* Get the NPObject wrapper for the browser window. */
 | 
			
		||||
  NPNVWindowNPObject = 15,
 | 
			
		||||
 | 
			
		||||
  /* Get the NPObject wrapper for the plugins DOM element. */
 | 
			
		||||
  NPNVPluginElementNPObject = 16,
 | 
			
		||||
 | 
			
		||||
  NPNVSupportsWindowless = 17,
 | 
			
		||||
 | 
			
		||||
  NPNVprivateModeBool = 18,
 | 
			
		||||
 | 
			
		||||
  NPNVsupportsAdvancedKeyHandling = 21
 | 
			
		||||
 | 
			
		||||
#if defined(XP_MACOSX)
 | 
			
		||||
  /* Used for negotiating drawing models */
 | 
			
		||||
  , NPNVpluginDrawingModel = 1000
 | 
			
		||||
#ifndef NP_NO_QUICKDRAW
 | 
			
		||||
  , NPNVsupportsQuickDrawBool = 2000
 | 
			
		||||
#endif
 | 
			
		||||
  , NPNVsupportsCoreGraphicsBool = 2001
 | 
			
		||||
  , NPNVsupportsOpenGLBool = 2002
 | 
			
		||||
  , NPNVsupportsCoreAnimationBool = 2003
 | 
			
		||||
  , NPNVsupportsInvalidatingCoreAnimationBool = 2004
 | 
			
		||||
#ifndef NP_NO_CARBON
 | 
			
		||||
  , NPNVsupportsCarbonBool = 3000 /* TRUE if the browser supports the Carbon event model */
 | 
			
		||||
#endif
 | 
			
		||||
  , NPNVsupportsCocoaBool = 3001 /* TRUE if the browser supports the Cocoa event model */
 | 
			
		||||
  , NPNVsupportsUpdatedCocoaTextInputBool = 3002 /* TRUE if the browser supports the updated
 | 
			
		||||
                                                    Cocoa text input specification. */
 | 
			
		||||
  , NPNVsupportsCompositingCoreAnimationPluginsBool = 74656 /* TRUE if the browser supports
 | 
			
		||||
                                                               CA model compositing */
 | 
			
		||||
#endif
 | 
			
		||||
#if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
 | 
			
		||||
  , NPNVSupportsWindowlessLocal = 2002
 | 
			
		||||
#endif
 | 
			
		||||
} NPNVariable;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  NPNURLVCookie = 501,
 | 
			
		||||
  NPNURLVProxy
 | 
			
		||||
} NPNURLVariable;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The type of Toolkit the widgets use
 | 
			
		||||
 */
 | 
			
		||||
typedef enum {
 | 
			
		||||
  NPNVGtk12 = 1,
 | 
			
		||||
  NPNVGtk2
 | 
			
		||||
} NPNToolkitType;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The type of a NPWindow - it specifies the type of the data structure
 | 
			
		||||
 * returned in the window field.
 | 
			
		||||
 */
 | 
			
		||||
typedef enum {
 | 
			
		||||
  NPWindowTypeWindow = 1,
 | 
			
		||||
  NPWindowTypeDrawable
 | 
			
		||||
} NPWindowType;
 | 
			
		||||
 | 
			
		||||
typedef struct _NPWindow
 | 
			
		||||
{
 | 
			
		||||
  void* window;  /* Platform specific window handle */
 | 
			
		||||
                 /* OS/2: x - Position of bottom left corner */
 | 
			
		||||
                 /* OS/2: y - relative to visible netscape window */
 | 
			
		||||
  int32_t  x;      /* Position of top left corner relative */
 | 
			
		||||
  int32_t  y;      /* to a netscape page. */
 | 
			
		||||
  uint32_t width;  /* Maximum window size */
 | 
			
		||||
  uint32_t height;
 | 
			
		||||
  NPRect   clipRect; /* Clipping rectangle in port coordinates */
 | 
			
		||||
#if (defined(XP_UNIX) || defined(XP_SYMBIAN)) && !defined(XP_MACOSX)
 | 
			
		||||
  void * ws_info; /* Platform-dependent additional data */
 | 
			
		||||
#endif /* XP_UNIX */
 | 
			
		||||
  NPWindowType type; /* Is this a window or a drawable? */
 | 
			
		||||
} NPWindow;
 | 
			
		||||
 | 
			
		||||
typedef struct _NPImageExpose
 | 
			
		||||
{
 | 
			
		||||
  char*    data;       /* image pointer */
 | 
			
		||||
  int32_t  stride;     /* Stride of data image pointer */
 | 
			
		||||
  int32_t  depth;      /* Depth of image pointer */
 | 
			
		||||
  int32_t  x;          /* Expose x */
 | 
			
		||||
  int32_t  y;          /* Expose y */
 | 
			
		||||
  uint32_t width;      /* Expose width */
 | 
			
		||||
  uint32_t height;     /* Expose height */
 | 
			
		||||
  NPSize   dataSize;   /* Data buffer size */
 | 
			
		||||
  float    translateX; /* translate X matrix value */
 | 
			
		||||
  float    translateY; /* translate Y matrix value */
 | 
			
		||||
  float    scaleX;     /* scale X matrix value */
 | 
			
		||||
  float    scaleY;     /* scale Y matrix value */
 | 
			
		||||
} NPImageExpose;
 | 
			
		||||
 | 
			
		||||
typedef struct _NPFullPrint
 | 
			
		||||
{
 | 
			
		||||
  NPBool pluginPrinted;/* Set TRUE if plugin handled fullscreen printing */
 | 
			
		||||
  NPBool printOne;     /* TRUE if plugin should print one copy to default
 | 
			
		||||
                          printer */
 | 
			
		||||
  void* platformPrint; /* Platform-specific printing info */
 | 
			
		||||
} NPFullPrint;
 | 
			
		||||
 | 
			
		||||
typedef struct _NPEmbedPrint
 | 
			
		||||
{
 | 
			
		||||
  NPWindow window;
 | 
			
		||||
  void* platformPrint; /* Platform-specific printing info */
 | 
			
		||||
} NPEmbedPrint;
 | 
			
		||||
 | 
			
		||||
typedef struct _NPPrint
 | 
			
		||||
{
 | 
			
		||||
  uint16_t mode;               /* NP_FULL or NP_EMBED */
 | 
			
		||||
  union
 | 
			
		||||
  {
 | 
			
		||||
    NPFullPrint fullPrint;   /* if mode is NP_FULL */
 | 
			
		||||
    NPEmbedPrint embedPrint; /* if mode is NP_EMBED */
 | 
			
		||||
  } print;
 | 
			
		||||
} NPPrint;
 | 
			
		||||
 | 
			
		||||
#if defined(XP_MACOSX)
 | 
			
		||||
#ifndef NP_NO_CARBON
 | 
			
		||||
typedef EventRecord NPEvent;
 | 
			
		||||
#endif
 | 
			
		||||
#elif defined(XP_SYMBIAN)
 | 
			
		||||
typedef QEvent NPEvent;
 | 
			
		||||
#elif defined(XP_WIN)
 | 
			
		||||
typedef struct _NPEvent
 | 
			
		||||
{
 | 
			
		||||
  uint16_t event;
 | 
			
		||||
  uintptr_t wParam;
 | 
			
		||||
  uintptr_t lParam;
 | 
			
		||||
} NPEvent;
 | 
			
		||||
#elif defined(XP_OS2)
 | 
			
		||||
typedef struct _NPEvent
 | 
			
		||||
{
 | 
			
		||||
  uint32_t event;
 | 
			
		||||
  uint32_t wParam;
 | 
			
		||||
  uint32_t lParam;
 | 
			
		||||
} NPEvent;
 | 
			
		||||
#elif defined(XP_UNIX) && defined(MOZ_X11)
 | 
			
		||||
typedef XEvent NPEvent;
 | 
			
		||||
#else
 | 
			
		||||
typedef void*  NPEvent;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(XP_MACOSX)
 | 
			
		||||
typedef void* NPRegion;
 | 
			
		||||
#ifndef NP_NO_QUICKDRAW
 | 
			
		||||
typedef RgnHandle NPQDRegion;
 | 
			
		||||
#endif
 | 
			
		||||
typedef CGPathRef NPCGRegion;
 | 
			
		||||
#elif defined(XP_WIN)
 | 
			
		||||
typedef HRGN NPRegion;
 | 
			
		||||
#elif defined(XP_UNIX) && defined(MOZ_X11)
 | 
			
		||||
typedef Region NPRegion;
 | 
			
		||||
#elif defined(XP_SYMBIAN)
 | 
			
		||||
typedef QRegion* NPRegion;
 | 
			
		||||
#else
 | 
			
		||||
typedef void *NPRegion;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef struct _NPNSString NPNSString;
 | 
			
		||||
typedef struct _NPNSWindow NPNSWindow;
 | 
			
		||||
typedef struct _NPNSMenu   NPNSMenu;
 | 
			
		||||
 | 
			
		||||
#if defined(XP_MACOSX)
 | 
			
		||||
typedef NPNSMenu NPMenu;
 | 
			
		||||
#else
 | 
			
		||||
typedef void *NPMenu;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  NPCoordinateSpacePlugin = 1,
 | 
			
		||||
  NPCoordinateSpaceWindow,
 | 
			
		||||
  NPCoordinateSpaceFlippedWindow,
 | 
			
		||||
  NPCoordinateSpaceScreen,
 | 
			
		||||
  NPCoordinateSpaceFlippedScreen
 | 
			
		||||
} NPCoordinateSpace;
 | 
			
		||||
 | 
			
		||||
#if defined(XP_MACOSX)
 | 
			
		||||
 | 
			
		||||
#ifndef NP_NO_QUICKDRAW
 | 
			
		||||
typedef struct NP_Port
 | 
			
		||||
{
 | 
			
		||||
  CGrafPtr port;
 | 
			
		||||
  int32_t portx; /* position inside the topmost window */
 | 
			
		||||
  int32_t porty;
 | 
			
		||||
} NP_Port;
 | 
			
		||||
#endif /* NP_NO_QUICKDRAW */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * NP_CGContext is the type of the NPWindow's 'window' when the plugin specifies NPDrawingModelCoreGraphics
 | 
			
		||||
 * as its drawing model.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
typedef struct NP_CGContext
 | 
			
		||||
{
 | 
			
		||||
  CGContextRef context;
 | 
			
		||||
  void *window; /* A WindowRef under the Carbon event model. */
 | 
			
		||||
} NP_CGContext;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * NP_GLContext is the type of the NPWindow's 'window' when the plugin specifies NPDrawingModelOpenGL as its
 | 
			
		||||
 * drawing model.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
typedef struct NP_GLContext
 | 
			
		||||
{
 | 
			
		||||
  CGLContextObj context;
 | 
			
		||||
#ifdef NP_NO_CARBON
 | 
			
		||||
  NPNSWindow *window;
 | 
			
		||||
#else
 | 
			
		||||
  void *window; /* Can be either an NSWindow or a WindowRef depending on the event model */
 | 
			
		||||
#endif
 | 
			
		||||
} NP_GLContext;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  NPCocoaEventDrawRect = 1,
 | 
			
		||||
  NPCocoaEventMouseDown,
 | 
			
		||||
  NPCocoaEventMouseUp,
 | 
			
		||||
  NPCocoaEventMouseMoved,
 | 
			
		||||
  NPCocoaEventMouseEntered,
 | 
			
		||||
  NPCocoaEventMouseExited,
 | 
			
		||||
  NPCocoaEventMouseDragged,
 | 
			
		||||
  NPCocoaEventKeyDown,
 | 
			
		||||
  NPCocoaEventKeyUp,
 | 
			
		||||
  NPCocoaEventFlagsChanged,
 | 
			
		||||
  NPCocoaEventFocusChanged,
 | 
			
		||||
  NPCocoaEventWindowFocusChanged,
 | 
			
		||||
  NPCocoaEventScrollWheel,
 | 
			
		||||
  NPCocoaEventTextInput
 | 
			
		||||
} NPCocoaEventType;
 | 
			
		||||
 | 
			
		||||
typedef struct _NPCocoaEvent {
 | 
			
		||||
  NPCocoaEventType type;
 | 
			
		||||
  uint32_t version;
 | 
			
		||||
  union {
 | 
			
		||||
    struct {
 | 
			
		||||
      uint32_t modifierFlags;
 | 
			
		||||
      double   pluginX;
 | 
			
		||||
      double   pluginY;
 | 
			
		||||
      int32_t  buttonNumber;
 | 
			
		||||
      int32_t  clickCount;
 | 
			
		||||
      double   deltaX;
 | 
			
		||||
      double   deltaY;
 | 
			
		||||
      double   deltaZ;
 | 
			
		||||
    } mouse;
 | 
			
		||||
    struct {
 | 
			
		||||
      uint32_t    modifierFlags;
 | 
			
		||||
      NPNSString *characters;
 | 
			
		||||
      NPNSString *charactersIgnoringModifiers;
 | 
			
		||||
      NPBool      isARepeat;
 | 
			
		||||
      uint16_t    keyCode;
 | 
			
		||||
    } key;
 | 
			
		||||
    struct {
 | 
			
		||||
      CGContextRef context;
 | 
			
		||||
      double x;
 | 
			
		||||
      double y;
 | 
			
		||||
      double width;
 | 
			
		||||
      double height;
 | 
			
		||||
    } draw;
 | 
			
		||||
    struct {
 | 
			
		||||
      NPBool hasFocus;
 | 
			
		||||
    } focus;
 | 
			
		||||
    struct {
 | 
			
		||||
      NPNSString *text;
 | 
			
		||||
    } text;
 | 
			
		||||
  } data;
 | 
			
		||||
} NPCocoaEvent;
 | 
			
		||||
 | 
			
		||||
#ifndef NP_NO_CARBON
 | 
			
		||||
/* Non-standard event types that can be passed to HandleEvent */
 | 
			
		||||
enum NPEventType {
 | 
			
		||||
  NPEventType_GetFocusEvent = (osEvt + 16),
 | 
			
		||||
  NPEventType_LoseFocusEvent,
 | 
			
		||||
  NPEventType_AdjustCursorEvent,
 | 
			
		||||
  NPEventType_MenuCommandEvent,
 | 
			
		||||
  NPEventType_ClippingChangedEvent,
 | 
			
		||||
  NPEventType_ScrollingBeginsEvent = 1000,
 | 
			
		||||
  NPEventType_ScrollingEndsEvent
 | 
			
		||||
};
 | 
			
		||||
#endif /* NP_NO_CARBON */
 | 
			
		||||
 | 
			
		||||
#endif /* XP_MACOSX */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Values for mode passed to NPP_New:
 | 
			
		||||
 */
 | 
			
		||||
#define NP_EMBED 1
 | 
			
		||||
#define NP_FULL  2
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Values for stream type passed to NPP_NewStream:
 | 
			
		||||
 */
 | 
			
		||||
#define NP_NORMAL     1
 | 
			
		||||
#define NP_SEEK       2
 | 
			
		||||
#define NP_ASFILE     3
 | 
			
		||||
#define NP_ASFILEONLY 4
 | 
			
		||||
 | 
			
		||||
#define NP_MAXREADY (((unsigned)(~0)<<1)>>1)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Flags for NPP_ClearSiteData.
 | 
			
		||||
 */
 | 
			
		||||
#define NP_CLEAR_ALL   0
 | 
			
		||||
#define NP_CLEAR_CACHE (1 << 0)
 | 
			
		||||
 | 
			
		||||
#if !defined(__LP64__)
 | 
			
		||||
#if defined(XP_MACOSX)
 | 
			
		||||
#pragma options align=reset
 | 
			
		||||
#endif
 | 
			
		||||
#endif /* __LP64__ */
 | 
			
		||||
 | 
			
		||||
/*----------------------------------------------------------------------*/
 | 
			
		||||
/*       Error and Reason Code definitions                              */
 | 
			
		||||
/*----------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Values of type NPError:
 | 
			
		||||
 */
 | 
			
		||||
#define NPERR_BASE                         0
 | 
			
		||||
#define NPERR_NO_ERROR                    (NPERR_BASE + 0)
 | 
			
		||||
#define NPERR_GENERIC_ERROR               (NPERR_BASE + 1)
 | 
			
		||||
#define NPERR_INVALID_INSTANCE_ERROR      (NPERR_BASE + 2)
 | 
			
		||||
#define NPERR_INVALID_FUNCTABLE_ERROR     (NPERR_BASE + 3)
 | 
			
		||||
#define NPERR_MODULE_LOAD_FAILED_ERROR    (NPERR_BASE + 4)
 | 
			
		||||
#define NPERR_OUT_OF_MEMORY_ERROR         (NPERR_BASE + 5)
 | 
			
		||||
#define NPERR_INVALID_PLUGIN_ERROR        (NPERR_BASE + 6)
 | 
			
		||||
#define NPERR_INVALID_PLUGIN_DIR_ERROR    (NPERR_BASE + 7)
 | 
			
		||||
#define NPERR_INCOMPATIBLE_VERSION_ERROR  (NPERR_BASE + 8)
 | 
			
		||||
#define NPERR_INVALID_PARAM               (NPERR_BASE + 9)
 | 
			
		||||
#define NPERR_INVALID_URL                 (NPERR_BASE + 10)
 | 
			
		||||
#define NPERR_FILE_NOT_FOUND              (NPERR_BASE + 11)
 | 
			
		||||
#define NPERR_NO_DATA                     (NPERR_BASE + 12)
 | 
			
		||||
#define NPERR_STREAM_NOT_SEEKABLE         (NPERR_BASE + 13)
 | 
			
		||||
#define NPERR_TIME_RANGE_NOT_SUPPORTED    (NPERR_BASE + 14)
 | 
			
		||||
#define NPERR_MALFORMED_SITE              (NPERR_BASE + 15)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Values of type NPReason:
 | 
			
		||||
 */
 | 
			
		||||
#define NPRES_BASE          0
 | 
			
		||||
#define NPRES_DONE         (NPRES_BASE + 0)
 | 
			
		||||
#define NPRES_NETWORK_ERR  (NPRES_BASE + 1)
 | 
			
		||||
#define NPRES_USER_BREAK   (NPRES_BASE + 2)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Don't use these obsolete error codes any more.
 | 
			
		||||
 */
 | 
			
		||||
#define NP_NOERR  NP_NOERR_is_obsolete_use_NPERR_NO_ERROR
 | 
			
		||||
#define NP_EINVAL NP_EINVAL_is_obsolete_use_NPERR_GENERIC_ERROR
 | 
			
		||||
#define NP_EABORT NP_EABORT_is_obsolete_use_NPRES_USER_BREAK
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Version feature information
 | 
			
		||||
 */
 | 
			
		||||
#define NPVERS_HAS_STREAMOUTPUT             8
 | 
			
		||||
#define NPVERS_HAS_NOTIFICATION             9
 | 
			
		||||
#define NPVERS_HAS_LIVECONNECT              9
 | 
			
		||||
#define NPVERS_68K_HAS_LIVECONNECT          11
 | 
			
		||||
#define NPVERS_HAS_WINDOWLESS               11
 | 
			
		||||
#define NPVERS_HAS_XPCONNECT_SCRIPTING      13
 | 
			
		||||
#define NPVERS_HAS_NPRUNTIME_SCRIPTING      14
 | 
			
		||||
#define NPVERS_HAS_FORM_VALUES              15
 | 
			
		||||
#define NPVERS_HAS_POPUPS_ENABLED_STATE     16
 | 
			
		||||
#define NPVERS_HAS_RESPONSE_HEADERS         17
 | 
			
		||||
#define NPVERS_HAS_NPOBJECT_ENUM            18
 | 
			
		||||
#define NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL 19
 | 
			
		||||
#define NPVERS_HAS_ALL_NETWORK_STREAMS      20
 | 
			
		||||
#define NPVERS_HAS_URL_AND_AUTH_INFO        21
 | 
			
		||||
#define NPVERS_HAS_PRIVATE_MODE             22
 | 
			
		||||
#define NPVERS_MACOSX_HAS_COCOA_EVENTS      23
 | 
			
		||||
#define NPVERS_HAS_ADVANCED_KEY_HANDLING    25
 | 
			
		||||
#define NPVERS_HAS_URL_REDIRECT_HANDLING    26
 | 
			
		||||
#define NPVERS_HAS_CLEAR_SITE_DATA          27
 | 
			
		||||
 | 
			
		||||
/*----------------------------------------------------------------------*/
 | 
			
		||||
/*                        Function Prototypes                           */
 | 
			
		||||
/*----------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#if defined(__OS2__)
 | 
			
		||||
#define NP_LOADDS _System
 | 
			
		||||
#else
 | 
			
		||||
#define NP_LOADDS
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* NPP_* functions are provided by the plugin and called by the navigator. */
 | 
			
		||||
 | 
			
		||||
#if defined(XP_UNIX)
 | 
			
		||||
const char* NPP_GetMIMEDescription(void);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
NPError NP_LOADDS NPP_New(NPMIMEType pluginType, NPP instance,
 | 
			
		||||
                          uint16_t mode, int16_t argc, char* argn[],
 | 
			
		||||
                          char* argv[], NPSavedData* saved);
 | 
			
		||||
NPError NP_LOADDS NPP_Destroy(NPP instance, NPSavedData** save);
 | 
			
		||||
NPError NP_LOADDS NPP_SetWindow(NPP instance, NPWindow* window);
 | 
			
		||||
NPError NP_LOADDS NPP_NewStream(NPP instance, NPMIMEType type,
 | 
			
		||||
                                NPStream* stream, NPBool seekable,
 | 
			
		||||
                                uint16_t* stype);
 | 
			
		||||
NPError NP_LOADDS NPP_DestroyStream(NPP instance, NPStream* stream,
 | 
			
		||||
                                    NPReason reason);
 | 
			
		||||
int32_t NP_LOADDS NPP_WriteReady(NPP instance, NPStream* stream);
 | 
			
		||||
int32_t NP_LOADDS NPP_Write(NPP instance, NPStream* stream, int32_t offset,
 | 
			
		||||
                            int32_t len, void* buffer);
 | 
			
		||||
void    NP_LOADDS NPP_StreamAsFile(NPP instance, NPStream* stream,
 | 
			
		||||
                                   const char* fname);
 | 
			
		||||
void    NP_LOADDS NPP_Print(NPP instance, NPPrint* platformPrint);
 | 
			
		||||
int16_t NP_LOADDS NPP_HandleEvent(NPP instance, void* event);
 | 
			
		||||
void    NP_LOADDS NPP_URLNotify(NPP instance, const char* url,
 | 
			
		||||
                                NPReason reason, void* notifyData);
 | 
			
		||||
NPError NP_LOADDS NPP_GetValue(NPP instance, NPPVariable variable, void *value);
 | 
			
		||||
NPError NP_LOADDS NPP_SetValue(NPP instance, NPNVariable variable, void *value);
 | 
			
		||||
NPBool  NP_LOADDS NPP_GotFocus(NPP instance, NPFocusDirection direction);
 | 
			
		||||
void    NP_LOADDS NPP_LostFocus(NPP instance);
 | 
			
		||||
void    NP_LOADDS NPP_URLRedirectNotify(NPP instance, const char* url, int32_t status, void* notifyData);
 | 
			
		||||
NPError NP_LOADDS NPP_ClearSiteData(const char* site, uint64_t flags, uint64_t maxAge);
 | 
			
		||||
char**  NP_LOADDS NPP_GetSitesWithData(void);
 | 
			
		||||
 | 
			
		||||
/* NPN_* functions are provided by the navigator and called by the plugin. */
 | 
			
		||||
void        NP_LOADDS NPN_Version(int* plugin_major, int* plugin_minor,
 | 
			
		||||
                                  int* netscape_major, int* netscape_minor);
 | 
			
		||||
NPError     NP_LOADDS NPN_GetURLNotify(NPP instance, const char* url,
 | 
			
		||||
                                       const char* target, void* notifyData);
 | 
			
		||||
NPError     NP_LOADDS NPN_GetURL(NPP instance, const char* url,
 | 
			
		||||
                                 const char* target);
 | 
			
		||||
NPError     NP_LOADDS NPN_PostURLNotify(NPP instance, const char* url,
 | 
			
		||||
                                        const char* target, uint32_t len,
 | 
			
		||||
                                        const char* buf, NPBool file,
 | 
			
		||||
                                        void* notifyData);
 | 
			
		||||
NPError     NP_LOADDS NPN_PostURL(NPP instance, const char* url,
 | 
			
		||||
                                  const char* target, uint32_t len,
 | 
			
		||||
                                  const char* buf, NPBool file);
 | 
			
		||||
NPError     NP_LOADDS NPN_RequestRead(NPStream* stream, NPByteRange* rangeList);
 | 
			
		||||
NPError     NP_LOADDS NPN_NewStream(NPP instance, NPMIMEType type,
 | 
			
		||||
                                    const char* target, NPStream** stream);
 | 
			
		||||
int32_t     NP_LOADDS NPN_Write(NPP instance, NPStream* stream, int32_t len,
 | 
			
		||||
                                void* buffer);
 | 
			
		||||
NPError     NP_LOADDS NPN_DestroyStream(NPP instance, NPStream* stream,
 | 
			
		||||
                                        NPReason reason);
 | 
			
		||||
void        NP_LOADDS NPN_Status(NPP instance, const char* message);
 | 
			
		||||
const char* NP_LOADDS NPN_UserAgent(NPP instance);
 | 
			
		||||
void*       NP_LOADDS NPN_MemAlloc(uint32_t size);
 | 
			
		||||
void        NP_LOADDS NPN_MemFree(void* ptr);
 | 
			
		||||
uint32_t    NP_LOADDS NPN_MemFlush(uint32_t size);
 | 
			
		||||
void        NP_LOADDS NPN_ReloadPlugins(NPBool reloadPages);
 | 
			
		||||
NPError     NP_LOADDS NPN_GetValue(NPP instance, NPNVariable variable,
 | 
			
		||||
                                   void *value);
 | 
			
		||||
NPError     NP_LOADDS NPN_SetValue(NPP instance, NPPVariable variable,
 | 
			
		||||
                                   void *value);
 | 
			
		||||
void        NP_LOADDS NPN_InvalidateRect(NPP instance, NPRect *invalidRect);
 | 
			
		||||
void        NP_LOADDS NPN_InvalidateRegion(NPP instance,
 | 
			
		||||
                                           NPRegion invalidRegion);
 | 
			
		||||
void        NP_LOADDS NPN_ForceRedraw(NPP instance);
 | 
			
		||||
void        NP_LOADDS NPN_PushPopupsEnabledState(NPP instance, NPBool enabled);
 | 
			
		||||
void        NP_LOADDS NPN_PopPopupsEnabledState(NPP instance);
 | 
			
		||||
void        NP_LOADDS NPN_PluginThreadAsyncCall(NPP instance,
 | 
			
		||||
                                                void (*func) (void *),
 | 
			
		||||
                                                void *userData);
 | 
			
		||||
NPError     NP_LOADDS NPN_GetValueForURL(NPP instance, NPNURLVariable variable,
 | 
			
		||||
                                         const char *url, char **value,
 | 
			
		||||
                                         uint32_t *len);
 | 
			
		||||
NPError     NP_LOADDS NPN_SetValueForURL(NPP instance, NPNURLVariable variable,
 | 
			
		||||
                                         const char *url, const char *value,
 | 
			
		||||
                                         uint32_t len);
 | 
			
		||||
NPError     NP_LOADDS NPN_GetAuthenticationInfo(NPP instance,
 | 
			
		||||
                                                const char *protocol,
 | 
			
		||||
                                                const char *host, int32_t port,
 | 
			
		||||
                                                const char *scheme,
 | 
			
		||||
                                                const char *realm,
 | 
			
		||||
                                                char **username, uint32_t *ulen,
 | 
			
		||||
                                                char **password,
 | 
			
		||||
                                                uint32_t *plen);
 | 
			
		||||
uint32_t    NP_LOADDS NPN_ScheduleTimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID));
 | 
			
		||||
void        NP_LOADDS NPN_UnscheduleTimer(NPP instance, uint32_t timerID);
 | 
			
		||||
NPError     NP_LOADDS NPN_PopUpContextMenu(NPP instance, NPMenu* menu);
 | 
			
		||||
NPBool      NP_LOADDS NPN_ConvertPoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace);
 | 
			
		||||
NPBool      NP_LOADDS NPN_HandleEvent(NPP instance, void *event, NPBool handled);
 | 
			
		||||
NPBool      NP_LOADDS NPN_UnfocusInstance(NPP instance, NPFocusDirection direction);
 | 
			
		||||
void        NP_LOADDS NPN_URLRedirectResponse(NPP instance, void* notifyData, NPBool allow);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}  /* end extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* RC_INVOKED */
 | 
			
		||||
#if defined(__OS2__)
 | 
			
		||||
#pragma pack()
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* npapi_h_ */
 | 
			
		||||
@@ -1,322 +0,0 @@
 | 
			
		||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/* ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 | 
			
		||||
 *
 | 
			
		||||
 * The contents of this file are subject to the Mozilla Public License Version
 | 
			
		||||
 * 1.1 (the "License"); you may not use this file except in compliance with
 | 
			
		||||
 * the License. You may obtain a copy of the License at
 | 
			
		||||
 * http://www.mozilla.org/MPL/
 | 
			
		||||
 *
 | 
			
		||||
 * Software distributed under the License is distributed on an "AS IS" basis,
 | 
			
		||||
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 | 
			
		||||
 * for the specific language governing rights and limitations under the
 | 
			
		||||
 * License.
 | 
			
		||||
 *
 | 
			
		||||
 * The Original Code is mozilla.org code.
 | 
			
		||||
 *
 | 
			
		||||
 * The Initial Developer of the Original Code is
 | 
			
		||||
 * Netscape Communications Corporation.
 | 
			
		||||
 * Portions created by the Initial Developer are Copyright (C) 1998
 | 
			
		||||
 * the Initial Developer. All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributor(s):
 | 
			
		||||
 *
 | 
			
		||||
 * Alternatively, the contents of this file may be used under the terms of
 | 
			
		||||
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 | 
			
		||||
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 | 
			
		||||
 * in which case the provisions of the GPL or the LGPL are applicable instead
 | 
			
		||||
 * of those above. If you wish to allow use of your version of this file only
 | 
			
		||||
 * under the terms of either the GPL or the LGPL, and not to allow others to
 | 
			
		||||
 * use your version of this file under the terms of the MPL, indicate your
 | 
			
		||||
 * decision by deleting the provisions above and replace them with the notice
 | 
			
		||||
 * and other provisions required by the GPL or the LGPL. If you do not delete
 | 
			
		||||
 * the provisions above, a recipient may use your version of this file under
 | 
			
		||||
 * the terms of any one of the MPL, the GPL or the LGPL.
 | 
			
		||||
 *
 | 
			
		||||
 * ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
#ifndef npfunctions_h_
 | 
			
		||||
#define npfunctions_h_
 | 
			
		||||
 | 
			
		||||
#ifdef __OS2__
 | 
			
		||||
#pragma pack(1)
 | 
			
		||||
#define NP_LOADDS _System
 | 
			
		||||
#else
 | 
			
		||||
#define NP_LOADDS
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "npapi.h"
 | 
			
		||||
#include "npruntime.h"
 | 
			
		||||
 | 
			
		||||
typedef NPError      (* NP_LOADDS NPP_NewProcPtr)(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved);
 | 
			
		||||
typedef NPError      (* NP_LOADDS NPP_DestroyProcPtr)(NPP instance, NPSavedData** save);
 | 
			
		||||
typedef NPError      (* NP_LOADDS NPP_SetWindowProcPtr)(NPP instance, NPWindow* window);
 | 
			
		||||
typedef NPError      (* NP_LOADDS NPP_NewStreamProcPtr)(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype);
 | 
			
		||||
typedef NPError      (* NP_LOADDS NPP_DestroyStreamProcPtr)(NPP instance, NPStream* stream, NPReason reason);
 | 
			
		||||
typedef int32_t      (* NP_LOADDS NPP_WriteReadyProcPtr)(NPP instance, NPStream* stream);
 | 
			
		||||
typedef int32_t      (* NP_LOADDS NPP_WriteProcPtr)(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer);
 | 
			
		||||
typedef void         (* NP_LOADDS NPP_StreamAsFileProcPtr)(NPP instance, NPStream* stream, const char* fname);
 | 
			
		||||
typedef void         (* NP_LOADDS NPP_PrintProcPtr)(NPP instance, NPPrint* platformPrint);
 | 
			
		||||
typedef int16_t      (* NP_LOADDS NPP_HandleEventProcPtr)(NPP instance, void* event);
 | 
			
		||||
typedef void         (* NP_LOADDS NPP_URLNotifyProcPtr)(NPP instance, const char* url, NPReason reason, void* notifyData);
 | 
			
		||||
/* Any NPObjects returned to the browser via NPP_GetValue should be retained
 | 
			
		||||
   by the plugin on the way out. The browser is responsible for releasing. */
 | 
			
		||||
typedef NPError      (* NP_LOADDS NPP_GetValueProcPtr)(NPP instance, NPPVariable variable, void *ret_value);
 | 
			
		||||
typedef NPError      (* NP_LOADDS NPP_SetValueProcPtr)(NPP instance, NPNVariable variable, void *value);
 | 
			
		||||
typedef NPBool       (* NP_LOADDS NPP_GotFocusPtr)(NPP instance, NPFocusDirection direction);
 | 
			
		||||
typedef void         (* NP_LOADDS NPP_LostFocusPtr)(NPP instance);
 | 
			
		||||
typedef void         (* NP_LOADDS NPP_URLRedirectNotifyPtr)(NPP instance, const char* url, int32_t status, void* notifyData);
 | 
			
		||||
typedef NPError      (* NP_LOADDS NPP_ClearSiteDataPtr)(const char* site, uint64_t flags, uint64_t maxAge);
 | 
			
		||||
typedef char**       (* NP_LOADDS NPP_GetSitesWithDataPtr)(void);
 | 
			
		||||
 | 
			
		||||
typedef NPError      (*NPN_GetValueProcPtr)(NPP instance, NPNVariable variable, void *ret_value);
 | 
			
		||||
typedef NPError      (*NPN_SetValueProcPtr)(NPP instance, NPPVariable variable, void *value);
 | 
			
		||||
typedef NPError      (*NPN_GetURLNotifyProcPtr)(NPP instance, const char* url, const char* window, void* notifyData);
 | 
			
		||||
typedef NPError      (*NPN_PostURLNotifyProcPtr)(NPP instance, const char* url, const char* window, uint32_t len, const char* buf, NPBool file, void* notifyData);
 | 
			
		||||
typedef NPError      (*NPN_GetURLProcPtr)(NPP instance, const char* url, const char* window);
 | 
			
		||||
typedef NPError      (*NPN_PostURLProcPtr)(NPP instance, const char* url, const char* window, uint32_t len, const char* buf, NPBool file);
 | 
			
		||||
typedef NPError      (*NPN_RequestReadProcPtr)(NPStream* stream, NPByteRange* rangeList);
 | 
			
		||||
typedef NPError      (*NPN_NewStreamProcPtr)(NPP instance, NPMIMEType type, const char* window, NPStream** stream);
 | 
			
		||||
typedef int32_t      (*NPN_WriteProcPtr)(NPP instance, NPStream* stream, int32_t len, void* buffer);
 | 
			
		||||
typedef NPError      (*NPN_DestroyStreamProcPtr)(NPP instance, NPStream* stream, NPReason reason);
 | 
			
		||||
typedef void         (*NPN_StatusProcPtr)(NPP instance, const char* message);
 | 
			
		||||
/* Browser manages the lifetime of the buffer returned by NPN_UserAgent, don't
 | 
			
		||||
   depend on it sticking around and don't free it. */
 | 
			
		||||
typedef const char*  (*NPN_UserAgentProcPtr)(NPP instance);
 | 
			
		||||
typedef void*        (*NPN_MemAllocProcPtr)(uint32_t size);
 | 
			
		||||
typedef void         (*NPN_MemFreeProcPtr)(void* ptr);
 | 
			
		||||
typedef uint32_t     (*NPN_MemFlushProcPtr)(uint32_t size);
 | 
			
		||||
typedef void         (*NPN_ReloadPluginsProcPtr)(NPBool reloadPages);
 | 
			
		||||
typedef void*        (*NPN_GetJavaEnvProcPtr)(void);
 | 
			
		||||
typedef void*        (*NPN_GetJavaPeerProcPtr)(NPP instance);
 | 
			
		||||
typedef void         (*NPN_InvalidateRectProcPtr)(NPP instance, NPRect *rect);
 | 
			
		||||
typedef void         (*NPN_InvalidateRegionProcPtr)(NPP instance, NPRegion region);
 | 
			
		||||
typedef void         (*NPN_ForceRedrawProcPtr)(NPP instance);
 | 
			
		||||
typedef NPIdentifier (*NPN_GetStringIdentifierProcPtr)(const NPUTF8* name);
 | 
			
		||||
typedef void         (*NPN_GetStringIdentifiersProcPtr)(const NPUTF8** names, int32_t nameCount, NPIdentifier* identifiers);
 | 
			
		||||
typedef NPIdentifier (*NPN_GetIntIdentifierProcPtr)(int32_t intid);
 | 
			
		||||
typedef bool         (*NPN_IdentifierIsStringProcPtr)(NPIdentifier identifier);
 | 
			
		||||
typedef NPUTF8*      (*NPN_UTF8FromIdentifierProcPtr)(NPIdentifier identifier);
 | 
			
		||||
typedef int32_t      (*NPN_IntFromIdentifierProcPtr)(NPIdentifier identifier);
 | 
			
		||||
typedef NPObject*    (*NPN_CreateObjectProcPtr)(NPP npp, NPClass *aClass);
 | 
			
		||||
typedef NPObject*    (*NPN_RetainObjectProcPtr)(NPObject *obj);
 | 
			
		||||
typedef void         (*NPN_ReleaseObjectProcPtr)(NPObject *obj);
 | 
			
		||||
typedef bool         (*NPN_InvokeProcPtr)(NPP npp, NPObject* obj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result);
 | 
			
		||||
typedef bool         (*NPN_InvokeDefaultProcPtr)(NPP npp, NPObject* obj, const NPVariant *args, uint32_t argCount, NPVariant *result);
 | 
			
		||||
typedef bool         (*NPN_EvaluateProcPtr)(NPP npp, NPObject *obj, NPString *script, NPVariant *result);
 | 
			
		||||
typedef bool         (*NPN_GetPropertyProcPtr)(NPP npp, NPObject *obj, NPIdentifier propertyName, NPVariant *result);
 | 
			
		||||
typedef bool         (*NPN_SetPropertyProcPtr)(NPP npp, NPObject *obj, NPIdentifier propertyName, const NPVariant *value);
 | 
			
		||||
typedef bool         (*NPN_RemovePropertyProcPtr)(NPP npp, NPObject *obj, NPIdentifier propertyName);
 | 
			
		||||
typedef bool         (*NPN_HasPropertyProcPtr)(NPP npp, NPObject *obj, NPIdentifier propertyName);
 | 
			
		||||
typedef bool         (*NPN_HasMethodProcPtr)(NPP npp, NPObject *obj, NPIdentifier propertyName);
 | 
			
		||||
typedef void         (*NPN_ReleaseVariantValueProcPtr)(NPVariant *variant);
 | 
			
		||||
typedef void         (*NPN_SetExceptionProcPtr)(NPObject *obj, const NPUTF8 *message);
 | 
			
		||||
typedef void         (*NPN_PushPopupsEnabledStateProcPtr)(NPP npp, NPBool enabled);
 | 
			
		||||
typedef void         (*NPN_PopPopupsEnabledStateProcPtr)(NPP npp);
 | 
			
		||||
typedef bool         (*NPN_EnumerateProcPtr)(NPP npp, NPObject *obj, NPIdentifier **identifier, uint32_t *count);
 | 
			
		||||
typedef void         (*NPN_PluginThreadAsyncCallProcPtr)(NPP instance, void (*func)(void *), void *userData);
 | 
			
		||||
typedef bool         (*NPN_ConstructProcPtr)(NPP npp, NPObject* obj, const NPVariant *args, uint32_t argCount, NPVariant *result);
 | 
			
		||||
typedef NPError      (*NPN_GetValueForURLPtr)(NPP npp, NPNURLVariable variable, const char *url, char **value, uint32_t *len);
 | 
			
		||||
typedef NPError      (*NPN_SetValueForURLPtr)(NPP npp, NPNURLVariable variable, const char *url, const char *value, uint32_t len);
 | 
			
		||||
typedef NPError      (*NPN_GetAuthenticationInfoPtr)(NPP npp, const char *protocol, const char *host, int32_t port, const char *scheme, const char *realm, char **username, uint32_t *ulen, char **password, uint32_t *plen);
 | 
			
		||||
typedef uint32_t     (*NPN_ScheduleTimerPtr)(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID));
 | 
			
		||||
typedef void         (*NPN_UnscheduleTimerPtr)(NPP instance, uint32_t timerID);
 | 
			
		||||
typedef NPError      (*NPN_PopUpContextMenuPtr)(NPP instance, NPMenu* menu);
 | 
			
		||||
typedef NPBool       (*NPN_ConvertPointPtr)(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace);
 | 
			
		||||
typedef NPBool       (*NPN_HandleEventPtr)(NPP instance, void *event, NPBool handled);
 | 
			
		||||
typedef NPBool       (*NPN_UnfocusInstancePtr)(NPP instance, NPFocusDirection direction);
 | 
			
		||||
typedef void         (*NPN_URLRedirectResponsePtr)(NPP instance, void* notifyData, NPBool allow);
 | 
			
		||||
 | 
			
		||||
typedef struct _NPPluginFuncs {
 | 
			
		||||
  uint16_t size;
 | 
			
		||||
  uint16_t version;
 | 
			
		||||
  NPP_NewProcPtr newp;
 | 
			
		||||
  NPP_DestroyProcPtr destroy;
 | 
			
		||||
  NPP_SetWindowProcPtr setwindow;
 | 
			
		||||
  NPP_NewStreamProcPtr newstream;
 | 
			
		||||
  NPP_DestroyStreamProcPtr destroystream;
 | 
			
		||||
  NPP_StreamAsFileProcPtr asfile;
 | 
			
		||||
  NPP_WriteReadyProcPtr writeready;
 | 
			
		||||
  NPP_WriteProcPtr write;
 | 
			
		||||
  NPP_PrintProcPtr print;
 | 
			
		||||
  NPP_HandleEventProcPtr event;
 | 
			
		||||
  NPP_URLNotifyProcPtr urlnotify;
 | 
			
		||||
  void* javaClass;
 | 
			
		||||
  NPP_GetValueProcPtr getvalue;
 | 
			
		||||
  NPP_SetValueProcPtr setvalue;
 | 
			
		||||
  NPP_GotFocusPtr gotfocus;
 | 
			
		||||
  NPP_LostFocusPtr lostfocus;
 | 
			
		||||
  NPP_URLRedirectNotifyPtr urlredirectnotify;
 | 
			
		||||
  NPP_ClearSiteDataPtr clearsitedata;
 | 
			
		||||
  NPP_GetSitesWithDataPtr getsiteswithdata;
 | 
			
		||||
} NPPluginFuncs;
 | 
			
		||||
 | 
			
		||||
typedef struct _NPNetscapeFuncs {
 | 
			
		||||
  uint16_t size;
 | 
			
		||||
  uint16_t version;
 | 
			
		||||
  NPN_GetURLProcPtr geturl;
 | 
			
		||||
  NPN_PostURLProcPtr posturl;
 | 
			
		||||
  NPN_RequestReadProcPtr requestread;
 | 
			
		||||
  NPN_NewStreamProcPtr newstream;
 | 
			
		||||
  NPN_WriteProcPtr write;
 | 
			
		||||
  NPN_DestroyStreamProcPtr destroystream;
 | 
			
		||||
  NPN_StatusProcPtr status;
 | 
			
		||||
  NPN_UserAgentProcPtr uagent;
 | 
			
		||||
  NPN_MemAllocProcPtr memalloc;
 | 
			
		||||
  NPN_MemFreeProcPtr memfree;
 | 
			
		||||
  NPN_MemFlushProcPtr memflush;
 | 
			
		||||
  NPN_ReloadPluginsProcPtr reloadplugins;
 | 
			
		||||
  NPN_GetJavaEnvProcPtr getJavaEnv;
 | 
			
		||||
  NPN_GetJavaPeerProcPtr getJavaPeer;
 | 
			
		||||
  NPN_GetURLNotifyProcPtr geturlnotify;
 | 
			
		||||
  NPN_PostURLNotifyProcPtr posturlnotify;
 | 
			
		||||
  NPN_GetValueProcPtr getvalue;
 | 
			
		||||
  NPN_SetValueProcPtr setvalue;
 | 
			
		||||
  NPN_InvalidateRectProcPtr invalidaterect;
 | 
			
		||||
  NPN_InvalidateRegionProcPtr invalidateregion;
 | 
			
		||||
  NPN_ForceRedrawProcPtr forceredraw;
 | 
			
		||||
  NPN_GetStringIdentifierProcPtr getstringidentifier;
 | 
			
		||||
  NPN_GetStringIdentifiersProcPtr getstringidentifiers;
 | 
			
		||||
  NPN_GetIntIdentifierProcPtr getintidentifier;
 | 
			
		||||
  NPN_IdentifierIsStringProcPtr identifierisstring;
 | 
			
		||||
  NPN_UTF8FromIdentifierProcPtr utf8fromidentifier;
 | 
			
		||||
  NPN_IntFromIdentifierProcPtr intfromidentifier;
 | 
			
		||||
  NPN_CreateObjectProcPtr createobject;
 | 
			
		||||
  NPN_RetainObjectProcPtr retainobject;
 | 
			
		||||
  NPN_ReleaseObjectProcPtr releaseobject;
 | 
			
		||||
  NPN_InvokeProcPtr invoke;
 | 
			
		||||
  NPN_InvokeDefaultProcPtr invokeDefault;
 | 
			
		||||
  NPN_EvaluateProcPtr evaluate;
 | 
			
		||||
  NPN_GetPropertyProcPtr getproperty;
 | 
			
		||||
  NPN_SetPropertyProcPtr setproperty;
 | 
			
		||||
  NPN_RemovePropertyProcPtr removeproperty;
 | 
			
		||||
  NPN_HasPropertyProcPtr hasproperty;
 | 
			
		||||
  NPN_HasMethodProcPtr hasmethod;
 | 
			
		||||
  NPN_ReleaseVariantValueProcPtr releasevariantvalue;
 | 
			
		||||
  NPN_SetExceptionProcPtr setexception;
 | 
			
		||||
  NPN_PushPopupsEnabledStateProcPtr pushpopupsenabledstate;
 | 
			
		||||
  NPN_PopPopupsEnabledStateProcPtr poppopupsenabledstate;
 | 
			
		||||
  NPN_EnumerateProcPtr enumerate;
 | 
			
		||||
  NPN_PluginThreadAsyncCallProcPtr pluginthreadasynccall;
 | 
			
		||||
  NPN_ConstructProcPtr construct;
 | 
			
		||||
  NPN_GetValueForURLPtr getvalueforurl;
 | 
			
		||||
  NPN_SetValueForURLPtr setvalueforurl;
 | 
			
		||||
  NPN_GetAuthenticationInfoPtr getauthenticationinfo;
 | 
			
		||||
  NPN_ScheduleTimerPtr scheduletimer;
 | 
			
		||||
  NPN_UnscheduleTimerPtr unscheduletimer;
 | 
			
		||||
  NPN_PopUpContextMenuPtr popupcontextmenu;
 | 
			
		||||
  NPN_ConvertPointPtr convertpoint;
 | 
			
		||||
  NPN_HandleEventPtr handleevent;
 | 
			
		||||
  NPN_UnfocusInstancePtr unfocusinstance;
 | 
			
		||||
  NPN_URLRedirectResponsePtr urlredirectresponse;
 | 
			
		||||
} NPNetscapeFuncs;
 | 
			
		||||
 | 
			
		||||
#ifdef XP_MACOSX
 | 
			
		||||
/*
 | 
			
		||||
 * Mac OS X version(s) of NP_GetMIMEDescription(const char *)
 | 
			
		||||
 * These can be called to retreive MIME information from the plugin dynamically
 | 
			
		||||
 *
 | 
			
		||||
 * Note: For compatibility with Quicktime, BPSupportedMIMEtypes is another way
 | 
			
		||||
 *       to get mime info from the plugin only on OSX and may not be supported
 | 
			
		||||
 *       in furture version -- use NP_GetMIMEDescription instead
 | 
			
		||||
 */
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
 kBPSupportedMIMETypesStructVers_1    = 1
 | 
			
		||||
};
 | 
			
		||||
typedef struct _BPSupportedMIMETypes
 | 
			
		||||
{
 | 
			
		||||
 SInt32    structVersion;      /* struct version */
 | 
			
		||||
 Handle    typeStrings;        /* STR# formated handle, allocated by plug-in */
 | 
			
		||||
 Handle    infoStrings;        /* STR# formated handle, allocated by plug-in */
 | 
			
		||||
} BPSupportedMIMETypes;
 | 
			
		||||
OSErr BP_GetSupportedMIMETypes(BPSupportedMIMETypes *mimeInfo, UInt32 flags);
 | 
			
		||||
#define NP_GETMIMEDESCRIPTION_NAME "NP_GetMIMEDescription"
 | 
			
		||||
typedef const char* (*NP_GetMIMEDescriptionProcPtr)(void);
 | 
			
		||||
typedef OSErr (*BP_GetSupportedMIMETypesProcPtr)(BPSupportedMIMETypes*, UInt32);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(_WIN32)
 | 
			
		||||
#define OSCALL WINAPI
 | 
			
		||||
#else
 | 
			
		||||
#if defined(__OS2__)
 | 
			
		||||
#define OSCALL _System
 | 
			
		||||
#else
 | 
			
		||||
#define OSCALL
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(XP_UNIX)
 | 
			
		||||
/* GCC 3.3 and later support the visibility attribute. */
 | 
			
		||||
#if defined(__GNUC__) && ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3))
 | 
			
		||||
#define NP_VISIBILITY_DEFAULT __attribute__((visibility("default")))
 | 
			
		||||
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
 | 
			
		||||
#define NP_VISIBILITY_DEFAULT __global
 | 
			
		||||
#else
 | 
			
		||||
#define NP_VISIBILITY_DEFAULT
 | 
			
		||||
#endif
 | 
			
		||||
#define NP_EXPORT(__type) NP_VISIBILITY_DEFAULT __type
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(_WIN32) || defined (__OS2__)
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
/* plugin meta member functions */
 | 
			
		||||
#if defined(__OS2__)
 | 
			
		||||
typedef struct _NPPluginData {   /* Alternate OS2 Plugin interface */
 | 
			
		||||
  char *pMimeTypes;
 | 
			
		||||
  char *pFileExtents;
 | 
			
		||||
  char *pFileOpenTemplate;
 | 
			
		||||
  char *pProductName;
 | 
			
		||||
  char *pProductDescription;
 | 
			
		||||
  unsigned long dwProductVersionMS;
 | 
			
		||||
  unsigned long dwProductVersionLS;
 | 
			
		||||
} NPPluginData;
 | 
			
		||||
typedef NPError     (*NP_GetPluginDataFunc)(NPPluginData*);
 | 
			
		||||
NPError OSCALL      NP_GetPluginData(NPPluginData * pPluginData);
 | 
			
		||||
#endif
 | 
			
		||||
typedef NPError     (*NP_GetEntryPointsFunc)(NPPluginFuncs*);
 | 
			
		||||
NPError OSCALL      NP_GetEntryPoints(NPPluginFuncs* pFuncs);
 | 
			
		||||
typedef NPError     (*NP_InitializeFunc)(NPNetscapeFuncs*);
 | 
			
		||||
NPError OSCALL      NP_Initialize(NPNetscapeFuncs* bFuncs);
 | 
			
		||||
typedef NPError     (*NP_ShutdownFunc)(void);
 | 
			
		||||
NPError OSCALL      NP_Shutdown(void);
 | 
			
		||||
typedef const char* (*NP_GetMIMEDescriptionFunc)(void);
 | 
			
		||||
const char*         NP_GetMIMEDescription(void);
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__OS2__)
 | 
			
		||||
#pragma pack()
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef XP_UNIX
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
typedef char*          (*NP_GetPluginVersionFunc)(void);
 | 
			
		||||
NP_EXPORT(char*)       NP_GetPluginVersion(void);
 | 
			
		||||
typedef const char*    (*NP_GetMIMEDescriptionFunc)(void);
 | 
			
		||||
NP_EXPORT(const char*) NP_GetMIMEDescription(void);
 | 
			
		||||
#ifdef XP_MACOSX
 | 
			
		||||
typedef NPError        (*NP_InitializeFunc)(NPNetscapeFuncs*);
 | 
			
		||||
NP_EXPORT(NPError)     NP_Initialize(NPNetscapeFuncs* bFuncs);
 | 
			
		||||
typedef NPError        (*NP_GetEntryPointsFunc)(NPPluginFuncs*);
 | 
			
		||||
NP_EXPORT(NPError)     NP_GetEntryPoints(NPPluginFuncs* pFuncs);
 | 
			
		||||
#else
 | 
			
		||||
typedef NPError        (*NP_InitializeFunc)(NPNetscapeFuncs*, NPPluginFuncs*);
 | 
			
		||||
NP_EXPORT(NPError)     NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs);
 | 
			
		||||
#endif
 | 
			
		||||
typedef NPError        (*NP_ShutdownFunc)(void);
 | 
			
		||||
NP_EXPORT(NPError)     NP_Shutdown(void);
 | 
			
		||||
typedef NPError        (*NP_GetValueFunc)(void *, NPPVariable, void *);
 | 
			
		||||
NP_EXPORT(NPError)     NP_GetValue(void *future, NPPVariable aVariable, void *aValue);
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* npfunctions_h_ */
 | 
			
		||||
@@ -1,393 +0,0 @@
 | 
			
		||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2004, Apple Computer, Inc. and The Mozilla Foundation.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions are
 | 
			
		||||
 * met:
 | 
			
		||||
 *
 | 
			
		||||
 * 1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 * notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 * 2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 * notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 * documentation and/or other materials provided with the distribution.
 | 
			
		||||
 * 3. Neither the names of Apple Computer, Inc. ("Apple") or The Mozilla
 | 
			
		||||
 * Foundation ("Mozilla") nor the names of their contributors may be used
 | 
			
		||||
 * to endorse or promote products derived from this software without
 | 
			
		||||
 * specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY APPLE, MOZILLA AND THEIR CONTRIBUTORS "AS
 | 
			
		||||
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 | 
			
		||||
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 | 
			
		||||
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE, MOZILLA OR
 | 
			
		||||
 * THEIR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 | 
			
		||||
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 | 
			
		||||
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 | 
			
		||||
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 | 
			
		||||
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#ifndef _NP_RUNTIME_H_
 | 
			
		||||
#define _NP_RUNTIME_H_
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "nptypes.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    This API is used to facilitate binding code written in C to script
 | 
			
		||||
    objects.  The API in this header does not assume the presence of a
 | 
			
		||||
    user agent.  That is, it can be used to bind C code to scripting
 | 
			
		||||
    environments outside of the context of a user agent.
 | 
			
		||||
 | 
			
		||||
    However, the normal use of the this API is in the context of a
 | 
			
		||||
    scripting environment running in a browser or other user agent.
 | 
			
		||||
    In particular it is used to support the extended Netscape
 | 
			
		||||
    script-ability API for plugins (NP-SAP).  NP-SAP is an extension
 | 
			
		||||
    of the Netscape plugin API.  As such we have adopted the use of
 | 
			
		||||
    the "NP" prefix for this API.
 | 
			
		||||
 | 
			
		||||
    The following NP{N|P}Variables were added to the Netscape plugin
 | 
			
		||||
    API (in npapi.h):
 | 
			
		||||
 | 
			
		||||
    NPNVWindowNPObject
 | 
			
		||||
    NPNVPluginElementNPObject
 | 
			
		||||
    NPPVpluginScriptableNPObject
 | 
			
		||||
 | 
			
		||||
    These variables are exposed through NPN_GetValue() and
 | 
			
		||||
    NPP_GetValue() (respectively) and are used to establish the
 | 
			
		||||
    initial binding between the user agent and native code.  The DOM
 | 
			
		||||
    objects in the user agent can be examined and manipulated using
 | 
			
		||||
    the NPN_ functions that operate on NPObjects described in this
 | 
			
		||||
    header.
 | 
			
		||||
 | 
			
		||||
    To the extent possible the assumptions about the scripting
 | 
			
		||||
    language used by the scripting environment have been minimized.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#define NP_BEGIN_MACRO  do {
 | 
			
		||||
#define NP_END_MACRO    } while (0)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    Objects (non-primitive data) passed between 'C' and script is
 | 
			
		||||
    always wrapped in an NPObject.  The 'interface' of an NPObject is
 | 
			
		||||
    described by an NPClass.
 | 
			
		||||
*/
 | 
			
		||||
typedef struct NPObject NPObject;
 | 
			
		||||
typedef struct NPClass NPClass;
 | 
			
		||||
 | 
			
		||||
typedef char NPUTF8;
 | 
			
		||||
typedef struct _NPString {
 | 
			
		||||
    const NPUTF8 *UTF8Characters;
 | 
			
		||||
    uint32_t UTF8Length;
 | 
			
		||||
} NPString;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    NPVariantType_Void,
 | 
			
		||||
    NPVariantType_Null,
 | 
			
		||||
    NPVariantType_Bool,
 | 
			
		||||
    NPVariantType_Int32,
 | 
			
		||||
    NPVariantType_Double,
 | 
			
		||||
    NPVariantType_String,
 | 
			
		||||
    NPVariantType_Object
 | 
			
		||||
} NPVariantType;
 | 
			
		||||
 | 
			
		||||
typedef struct _NPVariant {
 | 
			
		||||
    NPVariantType type;
 | 
			
		||||
    union {
 | 
			
		||||
        bool boolValue;
 | 
			
		||||
        int32_t intValue;
 | 
			
		||||
        double doubleValue;
 | 
			
		||||
        NPString stringValue;
 | 
			
		||||
        NPObject *objectValue;
 | 
			
		||||
    } value;
 | 
			
		||||
} NPVariant;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    NPN_ReleaseVariantValue is called on all 'out' parameters
 | 
			
		||||
    references.  Specifically it is to be called on variants that own
 | 
			
		||||
    their value, as is the case with all non-const NPVariant*
 | 
			
		||||
    arguments after a successful call to any methods (except this one)
 | 
			
		||||
    in this API.
 | 
			
		||||
 | 
			
		||||
    After calling NPN_ReleaseVariantValue, the type of the variant
 | 
			
		||||
    will be NPVariantType_Void.
 | 
			
		||||
*/
 | 
			
		||||
void NPN_ReleaseVariantValue(NPVariant *variant);
 | 
			
		||||
 | 
			
		||||
#define NPVARIANT_IS_VOID(_v)    ((_v).type == NPVariantType_Void)
 | 
			
		||||
#define NPVARIANT_IS_NULL(_v)    ((_v).type == NPVariantType_Null)
 | 
			
		||||
#define NPVARIANT_IS_BOOLEAN(_v) ((_v).type == NPVariantType_Bool)
 | 
			
		||||
#define NPVARIANT_IS_INT32(_v)   ((_v).type == NPVariantType_Int32)
 | 
			
		||||
#define NPVARIANT_IS_DOUBLE(_v)  ((_v).type == NPVariantType_Double)
 | 
			
		||||
#define NPVARIANT_IS_STRING(_v)  ((_v).type == NPVariantType_String)
 | 
			
		||||
#define NPVARIANT_IS_OBJECT(_v)  ((_v).type == NPVariantType_Object)
 | 
			
		||||
 | 
			
		||||
#define NPVARIANT_TO_BOOLEAN(_v) ((_v).value.boolValue)
 | 
			
		||||
#define NPVARIANT_TO_INT32(_v)   ((_v).value.intValue)
 | 
			
		||||
#define NPVARIANT_TO_DOUBLE(_v)  ((_v).value.doubleValue)
 | 
			
		||||
#define NPVARIANT_TO_STRING(_v)  ((_v).value.stringValue)
 | 
			
		||||
#define NPVARIANT_TO_OBJECT(_v)  ((_v).value.objectValue)
 | 
			
		||||
 | 
			
		||||
#define VOID_TO_NPVARIANT(_v)                                                 \
 | 
			
		||||
NP_BEGIN_MACRO                                                                \
 | 
			
		||||
    (_v).type = NPVariantType_Void;                                           \
 | 
			
		||||
    (_v).value.objectValue = NULL;                                            \
 | 
			
		||||
NP_END_MACRO
 | 
			
		||||
 | 
			
		||||
#define NULL_TO_NPVARIANT(_v)                                                 \
 | 
			
		||||
NP_BEGIN_MACRO                                                                \
 | 
			
		||||
    (_v).type = NPVariantType_Null;                                           \
 | 
			
		||||
    (_v).value.objectValue = NULL;                                            \
 | 
			
		||||
NP_END_MACRO
 | 
			
		||||
 | 
			
		||||
#define BOOLEAN_TO_NPVARIANT(_val, _v)                                        \
 | 
			
		||||
NP_BEGIN_MACRO                                                                \
 | 
			
		||||
    (_v).type = NPVariantType_Bool;                                           \
 | 
			
		||||
    (_v).value.boolValue = !!(_val);                                          \
 | 
			
		||||
NP_END_MACRO
 | 
			
		||||
 | 
			
		||||
#define INT32_TO_NPVARIANT(_val, _v)                                          \
 | 
			
		||||
NP_BEGIN_MACRO                                                                \
 | 
			
		||||
    (_v).type = NPVariantType_Int32;                                          \
 | 
			
		||||
    (_v).value.intValue = _val;                                               \
 | 
			
		||||
NP_END_MACRO
 | 
			
		||||
 | 
			
		||||
#define DOUBLE_TO_NPVARIANT(_val, _v)                                         \
 | 
			
		||||
NP_BEGIN_MACRO                                                                \
 | 
			
		||||
    (_v).type = NPVariantType_Double;                                         \
 | 
			
		||||
    (_v).value.doubleValue = _val;                                            \
 | 
			
		||||
NP_END_MACRO
 | 
			
		||||
 | 
			
		||||
#define STRINGZ_TO_NPVARIANT(_val, _v)                                        \
 | 
			
		||||
NP_BEGIN_MACRO                                                                \
 | 
			
		||||
    (_v).type = NPVariantType_String;                                         \
 | 
			
		||||
    NPString str = { _val, (uint32_t)(strlen(_val)) };                        \
 | 
			
		||||
    (_v).value.stringValue = str;                                             \
 | 
			
		||||
NP_END_MACRO
 | 
			
		||||
 | 
			
		||||
#define STRINGN_TO_NPVARIANT(_val, _len, _v)                                  \
 | 
			
		||||
NP_BEGIN_MACRO                                                                \
 | 
			
		||||
    (_v).type = NPVariantType_String;                                         \
 | 
			
		||||
    NPString str = { _val, (uint32_t)(_len) };                                \
 | 
			
		||||
    (_v).value.stringValue = str;                                             \
 | 
			
		||||
NP_END_MACRO
 | 
			
		||||
 | 
			
		||||
#define OBJECT_TO_NPVARIANT(_val, _v)                                         \
 | 
			
		||||
NP_BEGIN_MACRO                                                                \
 | 
			
		||||
    (_v).type = NPVariantType_Object;                                         \
 | 
			
		||||
    (_v).value.objectValue = _val;                                            \
 | 
			
		||||
NP_END_MACRO
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  Type mappings (JavaScript types have been used for illustration
 | 
			
		||||
    purposes):
 | 
			
		||||
 | 
			
		||||
  JavaScript       to             C (NPVariant with type:)
 | 
			
		||||
  undefined                       NPVariantType_Void
 | 
			
		||||
  null                            NPVariantType_Null
 | 
			
		||||
  Boolean                         NPVariantType_Bool
 | 
			
		||||
  Number                          NPVariantType_Double or NPVariantType_Int32
 | 
			
		||||
  String                          NPVariantType_String
 | 
			
		||||
  Object                          NPVariantType_Object
 | 
			
		||||
 | 
			
		||||
  C (NPVariant with type:)   to   JavaScript
 | 
			
		||||
  NPVariantType_Void              undefined
 | 
			
		||||
  NPVariantType_Null              null
 | 
			
		||||
  NPVariantType_Bool              Boolean
 | 
			
		||||
  NPVariantType_Int32             Number
 | 
			
		||||
  NPVariantType_Double            Number
 | 
			
		||||
  NPVariantType_String            String
 | 
			
		||||
  NPVariantType_Object            Object
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
typedef void *NPIdentifier;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    NPObjects have methods and properties.  Methods and properties are
 | 
			
		||||
    identified with NPIdentifiers.  These identifiers may be reflected
 | 
			
		||||
    in script.  NPIdentifiers can be either strings or integers, IOW,
 | 
			
		||||
    methods and properties can be identified by either strings or
 | 
			
		||||
    integers (i.e. foo["bar"] vs foo[1]). NPIdentifiers can be
 | 
			
		||||
    compared using ==.  In case of any errors, the requested
 | 
			
		||||
    NPIdentifier(s) will be NULL. NPIdentifier lifetime is controlled
 | 
			
		||||
    by the browser. Plugins do not need to worry about memory management
 | 
			
		||||
    with regards to NPIdentifiers.
 | 
			
		||||
*/
 | 
			
		||||
NPIdentifier NPN_GetStringIdentifier(const NPUTF8 *name);
 | 
			
		||||
void NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount,
 | 
			
		||||
                              NPIdentifier *identifiers);
 | 
			
		||||
NPIdentifier NPN_GetIntIdentifier(int32_t intid);
 | 
			
		||||
bool NPN_IdentifierIsString(NPIdentifier identifier);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    The NPUTF8 returned from NPN_UTF8FromIdentifier SHOULD be freed.
 | 
			
		||||
*/
 | 
			
		||||
NPUTF8 *NPN_UTF8FromIdentifier(NPIdentifier identifier);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    Get the integer represented by identifier. If identifier is not an
 | 
			
		||||
    integer identifier, the behaviour is undefined.
 | 
			
		||||
*/
 | 
			
		||||
int32_t NPN_IntFromIdentifier(NPIdentifier identifier);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    NPObject behavior is implemented using the following set of
 | 
			
		||||
    callback functions.
 | 
			
		||||
 | 
			
		||||
    The NPVariant *result argument of these functions (where
 | 
			
		||||
    applicable) should be released using NPN_ReleaseVariantValue().
 | 
			
		||||
*/
 | 
			
		||||
typedef NPObject *(*NPAllocateFunctionPtr)(NPP npp, NPClass *aClass);
 | 
			
		||||
typedef void (*NPDeallocateFunctionPtr)(NPObject *npobj);
 | 
			
		||||
typedef void (*NPInvalidateFunctionPtr)(NPObject *npobj);
 | 
			
		||||
typedef bool (*NPHasMethodFunctionPtr)(NPObject *npobj, NPIdentifier name);
 | 
			
		||||
typedef bool (*NPInvokeFunctionPtr)(NPObject *npobj, NPIdentifier name,
 | 
			
		||||
                                    const NPVariant *args, uint32_t argCount,
 | 
			
		||||
                                    NPVariant *result);
 | 
			
		||||
typedef bool (*NPInvokeDefaultFunctionPtr)(NPObject *npobj,
 | 
			
		||||
                                           const NPVariant *args,
 | 
			
		||||
                                           uint32_t argCount,
 | 
			
		||||
                                           NPVariant *result);
 | 
			
		||||
typedef bool (*NPHasPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name);
 | 
			
		||||
typedef bool (*NPGetPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name,
 | 
			
		||||
                                         NPVariant *result);
 | 
			
		||||
typedef bool (*NPSetPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name,
 | 
			
		||||
                                         const NPVariant *value);
 | 
			
		||||
typedef bool (*NPRemovePropertyFunctionPtr)(NPObject *npobj,
 | 
			
		||||
                                            NPIdentifier name);
 | 
			
		||||
typedef bool (*NPEnumerationFunctionPtr)(NPObject *npobj, NPIdentifier **value,
 | 
			
		||||
                                         uint32_t *count);
 | 
			
		||||
typedef bool (*NPConstructFunctionPtr)(NPObject *npobj,
 | 
			
		||||
                                       const NPVariant *args,
 | 
			
		||||
                                       uint32_t argCount,
 | 
			
		||||
                                       NPVariant *result);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    NPObjects returned by create, retain, invoke, and getProperty pass
 | 
			
		||||
    a reference count to the caller.  That is, the callee adds a
 | 
			
		||||
    reference count which passes to the caller.  It is the caller's
 | 
			
		||||
    responsibility to release the returned object.
 | 
			
		||||
 | 
			
		||||
    NPInvokeFunctionPtr function may return 0 to indicate a void
 | 
			
		||||
    result.
 | 
			
		||||
 | 
			
		||||
    NPInvalidateFunctionPtr is called by the scripting environment
 | 
			
		||||
    when the native code is shutdown.  Any attempt to message a
 | 
			
		||||
    NPObject instance after the invalidate callback has been
 | 
			
		||||
    called will result in undefined behavior, even if the native code
 | 
			
		||||
    is still retaining those NPObject instances.  (The runtime
 | 
			
		||||
    will typically return immediately, with 0 or NULL, from an attempt
 | 
			
		||||
    to dispatch to a NPObject, but this behavior should not be
 | 
			
		||||
    depended upon.)
 | 
			
		||||
 | 
			
		||||
    The NPEnumerationFunctionPtr function may pass an array of
 | 
			
		||||
    NPIdentifiers back to the caller. The callee allocs the memory of
 | 
			
		||||
    the array using NPN_MemAlloc(), and it's the caller's responsibility
 | 
			
		||||
    to release it using NPN_MemFree().
 | 
			
		||||
*/
 | 
			
		||||
struct NPClass
 | 
			
		||||
{
 | 
			
		||||
    uint32_t structVersion;
 | 
			
		||||
    NPAllocateFunctionPtr allocate;
 | 
			
		||||
    NPDeallocateFunctionPtr deallocate;
 | 
			
		||||
    NPInvalidateFunctionPtr invalidate;
 | 
			
		||||
    NPHasMethodFunctionPtr hasMethod;
 | 
			
		||||
    NPInvokeFunctionPtr invoke;
 | 
			
		||||
    NPInvokeDefaultFunctionPtr invokeDefault;
 | 
			
		||||
    NPHasPropertyFunctionPtr hasProperty;
 | 
			
		||||
    NPGetPropertyFunctionPtr getProperty;
 | 
			
		||||
    NPSetPropertyFunctionPtr setProperty;
 | 
			
		||||
    NPRemovePropertyFunctionPtr removeProperty;
 | 
			
		||||
    NPEnumerationFunctionPtr enumerate;
 | 
			
		||||
    NPConstructFunctionPtr construct;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define NP_CLASS_STRUCT_VERSION      3
 | 
			
		||||
 | 
			
		||||
#define NP_CLASS_STRUCT_VERSION_ENUM 2
 | 
			
		||||
#define NP_CLASS_STRUCT_VERSION_CTOR 3
 | 
			
		||||
 | 
			
		||||
#define NP_CLASS_STRUCT_VERSION_HAS_ENUM(npclass)   \
 | 
			
		||||
        ((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_ENUM)
 | 
			
		||||
 | 
			
		||||
#define NP_CLASS_STRUCT_VERSION_HAS_CTOR(npclass)   \
 | 
			
		||||
        ((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_CTOR)
 | 
			
		||||
 | 
			
		||||
struct NPObject {
 | 
			
		||||
    NPClass *_class;
 | 
			
		||||
    uint32_t referenceCount;
 | 
			
		||||
    /*
 | 
			
		||||
     * Additional space may be allocated here by types of NPObjects
 | 
			
		||||
     */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    If the class has an allocate function, NPN_CreateObject invokes
 | 
			
		||||
    that function, otherwise a NPObject is allocated and
 | 
			
		||||
    returned. This method will initialize the referenceCount member of
 | 
			
		||||
    the NPObject to 1.
 | 
			
		||||
*/
 | 
			
		||||
NPObject *NPN_CreateObject(NPP npp, NPClass *aClass);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    Increment the NPObject's reference count.
 | 
			
		||||
*/
 | 
			
		||||
NPObject *NPN_RetainObject(NPObject *npobj);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    Decremented the NPObject's reference count.  If the reference
 | 
			
		||||
    count goes to zero, the class's destroy function is invoke if
 | 
			
		||||
    specified, otherwise the object is freed directly.
 | 
			
		||||
*/
 | 
			
		||||
void NPN_ReleaseObject(NPObject *npobj);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    Functions to access script objects represented by NPObject.
 | 
			
		||||
 | 
			
		||||
    Calls to script objects are synchronous.  If a function returns a
 | 
			
		||||
    value, it will be supplied via the result NPVariant
 | 
			
		||||
    argument. Successful calls will return true, false will be
 | 
			
		||||
    returned in case of an error.
 | 
			
		||||
 | 
			
		||||
    Calls made from plugin code to script must be made from the thread
 | 
			
		||||
    on which the plugin was initialized.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
bool NPN_Invoke(NPP npp, NPObject *npobj, NPIdentifier methodName,
 | 
			
		||||
                const NPVariant *args, uint32_t argCount, NPVariant *result);
 | 
			
		||||
bool NPN_InvokeDefault(NPP npp, NPObject *npobj, const NPVariant *args,
 | 
			
		||||
                       uint32_t argCount, NPVariant *result);
 | 
			
		||||
bool NPN_Evaluate(NPP npp, NPObject *npobj, NPString *script,
 | 
			
		||||
                  NPVariant *result);
 | 
			
		||||
bool NPN_GetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName,
 | 
			
		||||
                     NPVariant *result);
 | 
			
		||||
bool NPN_SetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName,
 | 
			
		||||
                     const NPVariant *value);
 | 
			
		||||
bool NPN_RemoveProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
 | 
			
		||||
bool NPN_HasProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
 | 
			
		||||
bool NPN_HasMethod(NPP npp, NPObject *npobj, NPIdentifier methodName);
 | 
			
		||||
bool NPN_Enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier,
 | 
			
		||||
                   uint32_t *count);
 | 
			
		||||
bool NPN_Construct(NPP npp, NPObject *npobj, const NPVariant *args,
 | 
			
		||||
                   uint32_t argCount, NPVariant *result);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    NPN_SetException may be called to trigger a script exception upon
 | 
			
		||||
    return from entry points into NPObjects.  Typical usage:
 | 
			
		||||
 | 
			
		||||
    NPN_SetException (npobj, message);
 | 
			
		||||
*/
 | 
			
		||||
void NPN_SetException(NPObject *npobj, const NPUTF8 *message);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,121 +0,0 @@
 | 
			
		||||
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | 
			
		||||
/* ***** BEGIN LICENSE BLOCK *****
 | 
			
		||||
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 | 
			
		||||
 *
 | 
			
		||||
 * The contents of this file are subject to the Mozilla Public License Version
 | 
			
		||||
 * 1.1 (the "License"); you may not use this file except in compliance with
 | 
			
		||||
 * the License. You may obtain a copy of the License at
 | 
			
		||||
 * http://www.mozilla.org/MPL/
 | 
			
		||||
 *
 | 
			
		||||
 * Software distributed under the License is distributed on an "AS IS" basis,
 | 
			
		||||
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 | 
			
		||||
 * for the specific language governing rights and limitations under the
 | 
			
		||||
 * License.
 | 
			
		||||
 *
 | 
			
		||||
 * The Original Code is mozilla.org code.
 | 
			
		||||
 *
 | 
			
		||||
 * The Initial Developer of the Original Code is
 | 
			
		||||
 * mozilla.org.
 | 
			
		||||
 * Portions created by the Initial Developer are Copyright (C) 2004
 | 
			
		||||
 * the Initial Developer. All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributor(s):
 | 
			
		||||
 *   Johnny Stenback <jst@mozilla.org> (Original author)
 | 
			
		||||
 *
 | 
			
		||||
 * Alternatively, the contents of this file may be used under the terms of
 | 
			
		||||
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 | 
			
		||||
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 | 
			
		||||
 * in which case the provisions of the GPL or the LGPL are applicable instead
 | 
			
		||||
 * of those above. If you wish to allow use of your version of this file only
 | 
			
		||||
 * under the terms of either the GPL or the LGPL, and not to allow others to
 | 
			
		||||
 * use your version of this file under the terms of the MPL, indicate your
 | 
			
		||||
 * decision by deleting the provisions above and replace them with the notice
 | 
			
		||||
 * and other provisions required by the GPL or the LGPL. If you do not delete
 | 
			
		||||
 * the provisions above, a recipient may use your version of this file under
 | 
			
		||||
 * the terms of any one of the MPL, the GPL or the LGPL.
 | 
			
		||||
 *
 | 
			
		||||
 * ***** END LICENSE BLOCK ***** */
 | 
			
		||||
 | 
			
		||||
#ifndef nptypes_h_
 | 
			
		||||
#define nptypes_h_
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Header file for ensuring that C99 types ([u]int32_t, [u]int64_t and bool) and
 | 
			
		||||
 * true/false macros are available.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(WIN32) || defined(OS2)
 | 
			
		||||
  /*
 | 
			
		||||
   * Win32 and OS/2 don't know C99, so define [u]int_16/32/64 here. The bool
 | 
			
		||||
   * is predefined tho, both in C and C++.
 | 
			
		||||
   */
 | 
			
		||||
  typedef short int16_t;
 | 
			
		||||
  typedef unsigned short uint16_t;
 | 
			
		||||
  typedef int int32_t;
 | 
			
		||||
  typedef unsigned int uint32_t;
 | 
			
		||||
  typedef long long int64_t;
 | 
			
		||||
  typedef unsigned long long uint64_t;
 | 
			
		||||
#elif defined(_AIX) || defined(__sun) || defined(__osf__) || defined(IRIX) || defined(HPUX)
 | 
			
		||||
  /*
 | 
			
		||||
   * AIX and SunOS ship a inttypes.h header that defines [u]int32_t,
 | 
			
		||||
   * but not bool for C.
 | 
			
		||||
   */
 | 
			
		||||
  #include <inttypes.h>
 | 
			
		||||
 | 
			
		||||
  #ifndef __cplusplus
 | 
			
		||||
    typedef int bool;
 | 
			
		||||
    #define true   1
 | 
			
		||||
    #define false  0
 | 
			
		||||
  #endif
 | 
			
		||||
#elif defined(bsdi) || defined(FREEBSD) || defined(OPENBSD)
 | 
			
		||||
  /*
 | 
			
		||||
   * BSD/OS, FreeBSD, and OpenBSD ship sys/types.h that define int32_t and
 | 
			
		||||
   * u_int32_t.
 | 
			
		||||
   */
 | 
			
		||||
  #include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * BSD/OS ships no header that defines uint32_t, nor bool (for C)
 | 
			
		||||
   */
 | 
			
		||||
  #if defined(bsdi)
 | 
			
		||||
  typedef u_int32_t uint32_t;
 | 
			
		||||
  typedef u_int64_t uint64_t;
 | 
			
		||||
 | 
			
		||||
  #if !defined(__cplusplus)
 | 
			
		||||
    typedef int bool;
 | 
			
		||||
    #define true   1
 | 
			
		||||
    #define false  0
 | 
			
		||||
  #endif
 | 
			
		||||
  #else
 | 
			
		||||
  /*
 | 
			
		||||
   * FreeBSD and OpenBSD define uint32_t and bool.
 | 
			
		||||
   */
 | 
			
		||||
    #include <inttypes.h>
 | 
			
		||||
    #include <stdbool.h>
 | 
			
		||||
  #endif
 | 
			
		||||
#elif defined(BEOS)
 | 
			
		||||
  #include <inttypes.h>
 | 
			
		||||
#else
 | 
			
		||||
  /*
 | 
			
		||||
   * For those that ship a standard C99 stdint.h header file, include
 | 
			
		||||
   * it. Can't do the same for stdbool.h tho, since some systems ship
 | 
			
		||||
   * with a stdbool.h file that doesn't compile!
 | 
			
		||||
   */
 | 
			
		||||
  #include <stdint.h>
 | 
			
		||||
 | 
			
		||||
  #ifndef __cplusplus
 | 
			
		||||
    #if !defined(__GNUC__) || (__GNUC__ > 2 || __GNUC_MINOR__ > 95)
 | 
			
		||||
      #include <stdbool.h>
 | 
			
		||||
    #else
 | 
			
		||||
      /*
 | 
			
		||||
       * GCC 2.91 can't deal with a typedef for bool, but a #define
 | 
			
		||||
       * works.
 | 
			
		||||
       */
 | 
			
		||||
      #define bool int
 | 
			
		||||
      #define true   1
 | 
			
		||||
      #define false  0
 | 
			
		||||
    #endif
 | 
			
		||||
  #endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* nptypes_h_ */
 | 
			
		||||
							
								
								
									
										148
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						@@ -1,5 +1,5 @@
 | 
			
		||||
AC_PREREQ(2.63)
 | 
			
		||||
AC_INIT([gnome-shell],[3.5.2],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
 | 
			
		||||
AC_INIT([gnome-shell],[3.0.2],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
 | 
			
		||||
 | 
			
		||||
AC_CONFIG_HEADERS([config.h])
 | 
			
		||||
AC_CONFIG_SRCDIR([src/shell-global.c])
 | 
			
		||||
@@ -9,8 +9,8 @@ AC_CONFIG_AUX_DIR([config])
 | 
			
		||||
AC_SUBST([PACKAGE_NAME], ["$PACKAGE_NAME"])
 | 
			
		||||
AC_SUBST([PACKAGE_VERSION], ["$PACKAGE_VERSION"])
 | 
			
		||||
 | 
			
		||||
AM_INIT_AUTOMAKE([1.11 no-dist-gzip dist-xz tar-ustar foreign])
 | 
			
		||||
AM_MAINTAINER_MODE([enable])
 | 
			
		||||
AM_INIT_AUTOMAKE([1.10 dist-bzip2 no-dist-gzip foreign])
 | 
			
		||||
AM_MAINTAINER_MODE
 | 
			
		||||
 | 
			
		||||
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
 | 
			
		||||
 | 
			
		||||
@@ -23,19 +23,19 @@ AM_PROG_CC_C_O
 | 
			
		||||
LT_PREREQ([2.2.6])
 | 
			
		||||
LT_INIT([disable-static])
 | 
			
		||||
 | 
			
		||||
# i18n
 | 
			
		||||
IT_PROG_INTLTOOL([0.40])
 | 
			
		||||
 | 
			
		||||
AM_GNU_GETTEXT([external])
 | 
			
		||||
AM_GNU_GETTEXT_VERSION([0.17])
 | 
			
		||||
 | 
			
		||||
GETTEXT_PACKAGE=gnome-shell
 | 
			
		||||
AC_SUBST(GETTEXT_PACKAGE)
 | 
			
		||||
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
 | 
			
		||||
                   [The prefix for our gettext translation domains.])
 | 
			
		||||
IT_PROG_INTLTOOL(0.26)
 | 
			
		||||
AM_GLIB_GNU_GETTEXT
 | 
			
		||||
 | 
			
		||||
PKG_PROG_PKG_CONFIG([0.22])
 | 
			
		||||
 | 
			
		||||
# GConf stuff
 | 
			
		||||
AC_PATH_PROG(GCONFTOOL, gconftool-2, no)
 | 
			
		||||
AM_GCONF_SOURCE_2
 | 
			
		||||
 | 
			
		||||
GLIB_GSETTINGS
 | 
			
		||||
 | 
			
		||||
# Get a value to substitute into gnome-shell.in
 | 
			
		||||
@@ -53,84 +53,81 @@ if $PKG_CONFIG --exists gstreamer-0.10 '>=' $GSTREAMER_MIN_VERSION ; then
 | 
			
		||||
   AC_MSG_RESULT(yes)
 | 
			
		||||
   build_recorder=true
 | 
			
		||||
   recorder_modules="gstreamer-0.10 gstreamer-base-0.10 x11"
 | 
			
		||||
   PKG_CHECK_MODULES(TEST_SHELL_RECORDER, $recorder_modules clutter-1.0 xfixes gl)
 | 
			
		||||
   PKG_CHECK_MODULES(TEST_SHELL_RECORDER, $recorder_modules clutter-1.0 xfixes)
 | 
			
		||||
else
 | 
			
		||||
   AC_MSG_RESULT(no)
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
 | 
			
		||||
 | 
			
		||||
CLUTTER_MIN_VERSION=1.9.16
 | 
			
		||||
CLUTTER_MIN_VERSION=1.5.15
 | 
			
		||||
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
 | 
			
		||||
GJS_MIN_VERSION=1.29.18
 | 
			
		||||
MUTTER_MIN_VERSION=3.5.2
 | 
			
		||||
FOLKS_MIN_VERSION=0.5.2
 | 
			
		||||
GTK_MIN_VERSION=3.3.9
 | 
			
		||||
GIO_MIN_VERSION=2.31.6
 | 
			
		||||
GJS_MIN_VERSION=0.7.11
 | 
			
		||||
MUTTER_MIN_VERSION=3.0.0
 | 
			
		||||
GTK_MIN_VERSION=3.0.0
 | 
			
		||||
GIO_MIN_VERSION=2.25.9
 | 
			
		||||
LIBECAL_MIN_VERSION=2.32.0
 | 
			
		||||
LIBEDATASERVER_MIN_VERSION=1.2.0
 | 
			
		||||
LIBEDATASERVERUI_MIN_VERSION=2.91.6
 | 
			
		||||
TELEPATHY_GLIB_MIN_VERSION=0.17.5
 | 
			
		||||
LIBEDATASERVERUI2_MIN_VERSION=1.2.0
 | 
			
		||||
LIBEDATASERVERUI3_MIN_VERSION=2.91.6
 | 
			
		||||
TELEPATHY_GLIB_MIN_VERSION=0.13.12
 | 
			
		||||
TELEPATHY_LOGGER_MIN_VERSION=0.2.4
 | 
			
		||||
POLKIT_MIN_VERSION=0.100
 | 
			
		||||
STARTUP_NOTIFICATION_MIN_VERSION=0.11
 | 
			
		||||
GCR_MIN_VERSION=3.3.90
 | 
			
		||||
GNOME_DESKTOP_REQUIRED_VERSION=3.5.1
 | 
			
		||||
 | 
			
		||||
# Collect more than 20 libraries for a prize!
 | 
			
		||||
PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION
 | 
			
		||||
			       libxml-2.0
 | 
			
		||||
PKG_CHECK_MODULES(GNOME_SHELL, gio-2.0 >= $GIO_MIN_VERSION
 | 
			
		||||
                               gio-unix-2.0 dbus-glib-1 libxml-2.0
 | 
			
		||||
                               gtk+-3.0 >= $GTK_MIN_VERSION
 | 
			
		||||
                               folks >= $FOLKS_MIN_VERSION
 | 
			
		||||
                               libmutter >= $MUTTER_MIN_VERSION
 | 
			
		||||
                               gjs-internals-1.0 >= $GJS_MIN_VERSION
 | 
			
		||||
			       libgnome-menu-3.0 $recorder_modules
 | 
			
		||||
                               gdk-x11-3.0 libsoup-2.4
 | 
			
		||||
                               gl
 | 
			
		||||
			       libgnome-menu $recorder_modules gconf-2.0
 | 
			
		||||
                               gdk-x11-3.0
 | 
			
		||||
			       clutter-x11-1.0 >= $CLUTTER_MIN_VERSION
 | 
			
		||||
			       clutter-glx-1.0 >= $CLUTTER_MIN_VERSION
 | 
			
		||||
                               libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_MIN_VERSION
 | 
			
		||||
                               libstartup-notification-1.0
 | 
			
		||||
                               gobject-introspection-1.0 >= $GOBJECT_INTROSPECTION_MIN_VERSION
 | 
			
		||||
			       libcanberra
 | 
			
		||||
                               telepathy-glib >= $TELEPATHY_GLIB_MIN_VERSION
 | 
			
		||||
                               telepathy-logger-0.2 >= $TELEPATHY_LOGGER_MIN_VERSION
 | 
			
		||||
                               polkit-agent-1 >= $POLKIT_MIN_VERSION xfixes
 | 
			
		||||
                               libnm-glib libnm-util gnome-keyring-1
 | 
			
		||||
                               gcr-3 >= $GCR_MIN_VERSION
 | 
			
		||||
                               gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION)
 | 
			
		||||
                               polkit-agent-1 >= $POLKIT_MIN_VERSION xfixes)
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(SHELL_PERF_HELPER, gtk+-3.0 gio-2.0)
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(SHELL_HOTPLUG_SNIFFER, gio-2.0 gdk-pixbuf-2.0)
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(BROWSER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION json-glib-1.0 >= 0.13.2)
 | 
			
		||||
 | 
			
		||||
GJS_VERSION=`$PKG_CONFIG --modversion gjs-internals-1.0`
 | 
			
		||||
AC_DEFINE_UNQUOTED([GJS_VERSION], ["$GJS_VERSION"], [The version of GJS we're linking to])
 | 
			
		||||
AC_SUBST([GJS_VERSION], ["$GJS_VERSION"])
 | 
			
		||||
 | 
			
		||||
GOBJECT_INTROSPECTION_CHECK([$GOBJECT_INTROSPECTION_MIN_VERSION])
 | 
			
		||||
JHBUILD_TYPELIBDIR="$INTROSPECTION_TYPELIBDIR"
 | 
			
		||||
# NM is the only typelib we use that we don't jhbuild
 | 
			
		||||
PKG_CHECK_EXISTS([libnm-glib >= 0.8.999],
 | 
			
		||||
        [NM_TYPELIBDIR=`$PKG_CONFIG --variable=libdir libnm-glib`/girepository-1.0
 | 
			
		||||
	 if test "$INTROSPECTION_TYPELIBDIR" != "$NM_TYPELIBDIR"; then
 | 
			
		||||
	     JHBUILD_TYPELIBDIR="$JHBUILD_TYPELIBDIR:$NM_TYPELIBDIR"
 | 
			
		||||
	 fi])
 | 
			
		||||
AC_SUBST(JHBUILD_TYPELIBDIR)
 | 
			
		||||
 | 
			
		||||
saved_CFLAGS=$CFLAGS
 | 
			
		||||
saved_LIBS=$LIBS
 | 
			
		||||
CFLAGS=$GNOME_SHELL_CFLAGS
 | 
			
		||||
LIBS=$GNOME_SHELL_LIBS
 | 
			
		||||
AC_CHECK_FUNCS(JS_NewGlobalObject XFixesCreatePointerBarrier)
 | 
			
		||||
# sn_startup_sequence_get_application_id, we can replace with a version check later
 | 
			
		||||
AC_CHECK_FUNCS(JS_NewGlobalObject sn_startup_sequence_get_application_id XFixesCreatePointerBarrier)
 | 
			
		||||
CFLAGS=$saved_CFLAGS
 | 
			
		||||
LIBS=$saved_LIBS
 | 
			
		||||
 | 
			
		||||
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.2 x11)
 | 
			
		||||
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 gnome-desktop-3.0 >= 2.90.0 x11)
 | 
			
		||||
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-3.0)
 | 
			
		||||
PKG_CHECK_MODULES(TRAY, gtk+-3.0)
 | 
			
		||||
PKG_CHECK_MODULES(GVC, libpulse libpulse-mainloop-glib gobject-2.0)
 | 
			
		||||
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.5.1)
 | 
			
		||||
PKG_CHECK_MODULES(JS_TEST, clutter-x11-1.0 gjs-1.0 gobject-introspection-1.0 gtk+-3.0)
 | 
			
		||||
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 0.1.7)
 | 
			
		||||
 | 
			
		||||
AC_MSG_CHECKING([for bluetooth support])
 | 
			
		||||
PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.1.0],
 | 
			
		||||
        [BLUETOOTH_DIR=`$PKG_CONFIG --variable=applet_libdir gnome-bluetooth-1.0`
 | 
			
		||||
	 BLUETOOTH_LIBS=`$PKG_CONFIG --variable=applet_libs gnome-bluetooth-1.0`
 | 
			
		||||
PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 2.90.0],
 | 
			
		||||
        [BLUETOOTH_DIR=`$PKG_CONFIG --variable=libdir gnome-bluetooth-1.0`/gnome-bluetooth
 | 
			
		||||
	 BLUETOOTH_LIBS="-L'$BLUETOOTH_DIR' -lgnome-bluetooth-applet"
 | 
			
		||||
	 AC_SUBST([BLUETOOTH_LIBS],["$BLUETOOTH_LIBS"])
 | 
			
		||||
	 AC_SUBST([BLUETOOTH_DIR],["$BLUETOOTH_DIR"])
 | 
			
		||||
	 AC_DEFINE_UNQUOTED([BLUETOOTH_DIR],["$BLUETOOTH_DIR"],[Path to installed GnomeBluetooth typelib and library])
 | 
			
		||||
	 AC_DEFINE([HAVE_BLUETOOTH],[1],[Define if you have libgnome-bluetooth-applet])
 | 
			
		||||
	 AC_SUBST([HAVE_BLUETOOTH],[1])
 | 
			
		||||
@@ -139,37 +136,16 @@ PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.1.0],
 | 
			
		||||
	 AC_SUBST([HAVE_BLUETOOTH],[0])
 | 
			
		||||
	 AC_MSG_RESULT([no])])
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(CALENDAR_SERVER, libecal-1.2 >= $LIBECAL_MIN_VERSION libedataserver-1.2 >= $LIBEDATASERVER_MIN_VERSION libedataserverui-3.0 >= $LIBEDATASERVERUI_MIN_VERSION gio-2.0)
 | 
			
		||||
# Default to libedataserverui-3.0, but allow falling back to 1.2
 | 
			
		||||
PKG_CHECK_EXISTS(libedataserverui-3.0,
 | 
			
		||||
                 [EDS_API=3.0
 | 
			
		||||
                  LIBEDATASERVERUI_MIN_VERSION=$LIBEDATASERVERUI3_MIN_VERSION],
 | 
			
		||||
                 [EDS_API=1.2
 | 
			
		||||
                  LIBEDATASERVERUI_MIN_VERSION=$LIBEDATASERVERUI2_MIN_VERSION])
 | 
			
		||||
PKG_CHECK_MODULES(CALENDAR_SERVER, libecal-1.2 >= $LIBECAL_MIN_VERSION libedataserver-1.2 >= $LIBEDATASERVER_MIN_VERSION libedataserverui-$EDS_API >= $LIBEDATASERVERUI_MIN_VERSION gio-2.0)
 | 
			
		||||
AC_SUBST(CALENDAR_SERVER_CFLAGS)
 | 
			
		||||
AC_SUBST(CALENDAR_SERVER_LIBS)
 | 
			
		||||
 | 
			
		||||
AC_ARG_WITH(systemd,
 | 
			
		||||
            AS_HELP_STRING([--with-systemd],
 | 
			
		||||
                           [Add systemd support]),
 | 
			
		||||
            [with_systemd=$withval], [with_systemd=auto])
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(SYSTEMD,
 | 
			
		||||
                  [libsystemd-login libsystemd-daemon],
 | 
			
		||||
                  [have_systemd=yes], [have_systemd=no])
 | 
			
		||||
 | 
			
		||||
if test "x$with_systemd" = "xauto" ; then
 | 
			
		||||
        if test x$have_systemd = xno ; then
 | 
			
		||||
                use_systemd=no
 | 
			
		||||
        else
 | 
			
		||||
                use_systemd=yes
 | 
			
		||||
        fi
 | 
			
		||||
else
 | 
			
		||||
        use_systemd=$with_systemd
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test "x$use_systemd" = "xyes"; then
 | 
			
		||||
        if test "x$have_systemd" = "xno"; then
 | 
			
		||||
                AC_MSG_ERROR([Systemd support explicitly required, but systemd not found])
 | 
			
		||||
        fi
 | 
			
		||||
 | 
			
		||||
        AC_DEFINE(WITH_SYSTEMD, 1, [systemd support])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
MUTTER_GIR_DIR=`$PKG_CONFIG --variable=girdir libmutter`
 | 
			
		||||
MUTTER_TYPELIB_DIR=`$PKG_CONFIG --variable=typelibdir libmutter`
 | 
			
		||||
AC_SUBST(MUTTER_GIR_DIR)
 | 
			
		||||
@@ -182,17 +158,6 @@ AC_CHECK_FUNCS(fdwalk)
 | 
			
		||||
AC_CHECK_FUNCS(mallinfo)
 | 
			
		||||
AC_CHECK_HEADERS([sys/resource.h])
 | 
			
		||||
 | 
			
		||||
# _NL_TIME_FIRST_WEEKDAY is an enum and not a define
 | 
			
		||||
AC_MSG_CHECKING([for _NL_TIME_FIRST_WEEKDAY])
 | 
			
		||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <langinfo.h>]],
 | 
			
		||||
                                   [[nl_langinfo(_NL_TIME_FIRST_WEEKDAY);]])],
 | 
			
		||||
               [langinfo_ok=yes], [langinfo_ok=no])
 | 
			
		||||
AC_MSG_RESULT($langinfo_ok)
 | 
			
		||||
if test "$langinfo_ok" = "yes"; then
 | 
			
		||||
  AC_DEFINE([HAVE__NL_TIME_FIRST_WEEKDAY], [1],
 | 
			
		||||
            [Define if _NL_TIME_FIRST_WEEKDAY is available])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Sets GLIB_GENMARSHAL and GLIB_MKENUMS
 | 
			
		||||
AM_PATH_GLIB_2_0()
 | 
			
		||||
G_IR_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
 | 
			
		||||
@@ -206,8 +171,6 @@ AC_SUBST(GIRDIR)
 | 
			
		||||
TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
 | 
			
		||||
AC_SUBST(TYPELIBDIR)
 | 
			
		||||
 | 
			
		||||
GTK_DOC_CHECK([1.15], [--flavour no-tmpl])
 | 
			
		||||
 | 
			
		||||
# Stay command-line compatible with the gnome-common configure option. Here
 | 
			
		||||
# minimum/yes/maximum are the same, however.
 | 
			
		||||
AC_ARG_ENABLE(compile_warnings,
 | 
			
		||||
@@ -228,7 +191,7 @@ if test "$enable_compile_warnings" != no ; then
 | 
			
		||||
    if test "$enable_compile_warnings" = error ; then
 | 
			
		||||
      case " $CFLAGS " in
 | 
			
		||||
      *[\ \	]-Werror[\ \	]*) ;;
 | 
			
		||||
      *) CFLAGS="$CFLAGS -Werror -Wno-error=deprecated-declarations" ;;
 | 
			
		||||
      *) CFLAGS="$CFLAGS -Werror" ;;
 | 
			
		||||
      esac
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
@@ -236,24 +199,15 @@ fi
 | 
			
		||||
changequote([,])dnl
 | 
			
		||||
 | 
			
		||||
AC_ARG_ENABLE(jhbuild-wrapper-script,
 | 
			
		||||
  AS_HELP_STRING([--enable-jhbuild-wrapper-script],[Make "gnome-shell" script work for jhbuild]),,enable_jhbuild_wrapper_script=no)
 | 
			
		||||
  AS_HELP_STRING([--jhbuild-wrapper-script=yes],[Make "gnome-shell" script work for jhbuild]),,enable_jhbuild_wrapper_script=no)
 | 
			
		||||
AM_CONDITIONAL(USE_JHBUILD_WRAPPER_SCRIPT, test "x$enable_jhbuild_wrapper_script" = xyes)
 | 
			
		||||
 | 
			
		||||
BROWSER_PLUGIN_DIR="${BROWSER_PLUGIN_DIR:-"\${libdir}/mozilla/plugins"}"
 | 
			
		||||
AC_ARG_VAR([BROWSER_PLUGIN_DIR],[Where to install the plugin to])
 | 
			
		||||
 | 
			
		||||
AC_CONFIG_FILES([
 | 
			
		||||
  Makefile
 | 
			
		||||
  data/Makefile
 | 
			
		||||
  docs/Makefile
 | 
			
		||||
  docs/reference/Makefile
 | 
			
		||||
  docs/reference/shell/Makefile
 | 
			
		||||
  docs/reference/shell/shell-docs.sgml
 | 
			
		||||
  docs/reference/st/Makefile
 | 
			
		||||
  docs/reference/st/st-docs.sgml
 | 
			
		||||
  js/Makefile
 | 
			
		||||
  js/misc/config.js
 | 
			
		||||
  src/Makefile
 | 
			
		||||
  browser-plugin/Makefile
 | 
			
		||||
  tests/Makefile
 | 
			
		||||
  po/Makefile.in
 | 
			
		||||
  man/Makefile
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
desktopdir=$(datadir)/applications
 | 
			
		||||
desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop
 | 
			
		||||
desktop_DATA = gnome-shell.desktop
 | 
			
		||||
 | 
			
		||||
# We substitute in bindir so it works as an autostart
 | 
			
		||||
# file when built in a non-system prefix
 | 
			
		||||
@@ -12,23 +12,16 @@ desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop
 | 
			
		||||
%.desktop:%.desktop.in
 | 
			
		||||
	$(AM_V_GEN) sed s/^_// < $< > $@ || rm $@
 | 
			
		||||
 | 
			
		||||
searchprovidersdir = $(pkgdatadir)/open-search-providers
 | 
			
		||||
searchprovidersdir = $(pkgdatadir)/search_providers
 | 
			
		||||
dist_searchproviders_DATA =				\
 | 
			
		||||
	open-search-providers/google.xml		\
 | 
			
		||||
	open-search-providers/wikipedia.xml
 | 
			
		||||
 | 
			
		||||
introspectiondir = $(datadir)/dbus-1/interfaces
 | 
			
		||||
introspection_DATA = org.gnome.ShellSearchProvider.xml
 | 
			
		||||
	search_providers/google.xml				\
 | 
			
		||||
	search_providers/wikipedia.xml
 | 
			
		||||
 | 
			
		||||
themedir = $(pkgdatadir)/theme
 | 
			
		||||
dist_theme_DATA =				\
 | 
			
		||||
	theme/calendar-arrow-left.svg		\
 | 
			
		||||
	theme/calendar-arrow-right.svg		\
 | 
			
		||||
	theme/calendar-today.svg		\
 | 
			
		||||
	theme/checkbox-focused.svg		\
 | 
			
		||||
	theme/checkbox-off-focused.svg		\
 | 
			
		||||
	theme/checkbox-off.svg			\
 | 
			
		||||
	theme/checkbox.svg			\
 | 
			
		||||
	theme/close-window.svg			\
 | 
			
		||||
	theme/close.svg				\
 | 
			
		||||
	theme/corner-ripple-ltr.png		\
 | 
			
		||||
@@ -36,15 +29,27 @@ dist_theme_DATA =				\
 | 
			
		||||
	theme/dash-placeholder.svg		\
 | 
			
		||||
	theme/filter-selected-ltr.svg		\
 | 
			
		||||
	theme/filter-selected-rtl.svg		\
 | 
			
		||||
	theme/gdm.css				\
 | 
			
		||||
	theme/gnome-shell.css			\
 | 
			
		||||
	theme/mosaic-view-active.svg		\
 | 
			
		||||
	theme/mosaic-view.svg			\
 | 
			
		||||
	theme/move-window-on-new.svg		\
 | 
			
		||||
	theme/panel-border.svg			\
 | 
			
		||||
	theme/panel-button-border.svg		\
 | 
			
		||||
	theme/panel-button-highlight-narrow.svg	\
 | 
			
		||||
	theme/panel-button-highlight-wide.svg	\
 | 
			
		||||
	theme/process-working.svg		\
 | 
			
		||||
	theme/running-indicator.svg		\
 | 
			
		||||
	theme/scroll-button-down-hover.png	\
 | 
			
		||||
	theme/scroll-button-down.png		\
 | 
			
		||||
	theme/scroll-button-up-hover.png	\
 | 
			
		||||
	theme/scroll-button-up.png		\
 | 
			
		||||
	theme/scroll-hhandle.svg		\
 | 
			
		||||
	theme/scroll-vhandle.svg		\
 | 
			
		||||
	theme/section-more.svg			\
 | 
			
		||||
	theme/section-more-open.svg		\
 | 
			
		||||
	theme/separator-white.png		\
 | 
			
		||||
	theme/single-view-active.svg		\
 | 
			
		||||
	theme/single-view.svg			\
 | 
			
		||||
	theme/source-button-border.svg		\
 | 
			
		||||
	theme/toggle-off-us.svg			\
 | 
			
		||||
	theme/toggle-off-intl.svg		\
 | 
			
		||||
@@ -53,7 +58,7 @@ dist_theme_DATA =				\
 | 
			
		||||
	theme/ws-switch-arrow-up.svg		\
 | 
			
		||||
	theme/ws-switch-arrow-down.svg
 | 
			
		||||
 | 
			
		||||
gsettings_SCHEMAS = org.gnome.shell.gschema.xml org.gnome.shell.evolution.calendar.gschema.xml
 | 
			
		||||
gsettings_SCHEMAS = org.gnome.shell.gschema.xml
 | 
			
		||||
 | 
			
		||||
@INTLTOOL_XML_NOMERGE_RULE@
 | 
			
		||||
@GSETTINGS_RULES@
 | 
			
		||||
@@ -65,27 +70,29 @@ gschemas.compiled: $(gsettings_SCHEMAS:.xml=.valid)
 | 
			
		||||
 | 
			
		||||
all-local: gschemas.compiled
 | 
			
		||||
 | 
			
		||||
convertdir = $(datadir)/GConf/gsettings
 | 
			
		||||
convert_DATA = gnome-shell-overrides.convert
 | 
			
		||||
 | 
			
		||||
# GConf schemas: provide defaults for keys from Metacity we are overriding
 | 
			
		||||
gconfschemadir  = @GCONF_SCHEMA_FILE_DIR@
 | 
			
		||||
gconfschema_DATA = gnome-shell.schemas
 | 
			
		||||
 | 
			
		||||
shadersdir = $(pkgdatadir)/shaders
 | 
			
		||||
shaders_DATA = \
 | 
			
		||||
	shaders/dim-window.glsl
 | 
			
		||||
 | 
			
		||||
install-data-local:
 | 
			
		||||
	GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(srcdir)/$(gconfschema_DATA)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
EXTRA_DIST =						\
 | 
			
		||||
	gnome-shell.desktop.in.in			\
 | 
			
		||||
	gnome-shell-extension-prefs.desktop.in.in	\
 | 
			
		||||
	$(introspection_DATA)				\
 | 
			
		||||
	$(menu_DATA)					\
 | 
			
		||||
	$(gconfschema_DATA)				\
 | 
			
		||||
	$(shaders_DATA)					\
 | 
			
		||||
	$(convert_DATA)					\
 | 
			
		||||
	org.gnome.shell.evolution.calendar.gschema.xml.in	\
 | 
			
		||||
	org.gnome.shell.gschema.xml.in
 | 
			
		||||
 | 
			
		||||
CLEANFILES =						\
 | 
			
		||||
	gnome-shell.desktop.in				\
 | 
			
		||||
	gnome-shell-extension-prefs.in			\
 | 
			
		||||
	$(desktop_DATA)					\
 | 
			
		||||
	$(gsettings_SCHEMAS)				\
 | 
			
		||||
	gschemas.compiled
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +0,0 @@
 | 
			
		||||
[Desktop Entry]
 | 
			
		||||
Type=Application
 | 
			
		||||
_Name=GNOME Shell Extension Preferences
 | 
			
		||||
_Comment=Configure GNOME Shell Extensions
 | 
			
		||||
Exec=@bindir@/gnome-shell-extension-prefs %u
 | 
			
		||||
X-GNOME-Bugzilla-Bugzilla=GNOME
 | 
			
		||||
X-GNOME-Bugzilla-Product=gnome-shell
 | 
			
		||||
X-GNOME-Bugzilla-Component=extensions
 | 
			
		||||
X-GNOME-Bugzilla-Version=@VERSION@
 | 
			
		||||
Categories=GNOME;GTK;
 | 
			
		||||
OnlyShowIn=GNOME;
 | 
			
		||||
NoDisplay=true
 | 
			
		||||
@@ -1,5 +0,0 @@
 | 
			
		||||
[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
 | 
			
		||||
@@ -13,4 +13,4 @@ NoDisplay=true
 | 
			
		||||
X-GNOME-Autostart-Phase=WindowManager
 | 
			
		||||
X-GNOME-Provides=panel;windowmanager;
 | 
			
		||||
X-GNOME-Autostart-Notify=true
 | 
			
		||||
X-GNOME-AutoRestart=false
 | 
			
		||||
X-GNOME-AutoRestart=true
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										100
									
								
								data/gnome-shell.schemas
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,100 @@
 | 
			
		||||
<gconfschemafile>
 | 
			
		||||
    <schemalist>
 | 
			
		||||
 | 
			
		||||
      <!-- Metacity overrides -->
 | 
			
		||||
      <schema>
 | 
			
		||||
        <key>/schemas/desktop/gnome/shell/windows/attach_modal_dialogs</key>
 | 
			
		||||
        <applyto>/desktop/gnome/shell/windows/attach_modal_dialogs</applyto>
 | 
			
		||||
        <owner>gnome-shell</owner>
 | 
			
		||||
        <type>bool</type>
 | 
			
		||||
        <default>true</default>
 | 
			
		||||
        <locale name="C">
 | 
			
		||||
          <short>Attach modal dialog to the parent window</short>
 | 
			
		||||
          <long>
 | 
			
		||||
             This key overrides /apps/mutter/general/attach_modal_dialogs when
 | 
			
		||||
             running GNOME Shell.
 | 
			
		||||
          </long>
 | 
			
		||||
        </locale>
 | 
			
		||||
      </schema>
 | 
			
		||||
 | 
			
		||||
      <schema>
 | 
			
		||||
        <key>/schemas/desktop/gnome/shell/windows/button_layout</key>
 | 
			
		||||
        <applyto>/desktop/gnome/shell/windows/button_layout</applyto>
 | 
			
		||||
        <owner>gnome-shell</owner>
 | 
			
		||||
        <type>string</type>
 | 
			
		||||
        <default>:close</default>
 | 
			
		||||
        <locale name="C">
 | 
			
		||||
           <short>Arrangement of buttons on the titlebar</short>
 | 
			
		||||
           <long>
 | 
			
		||||
             Arrangement of buttons on the titlebar. The
 | 
			
		||||
             value should be a string, such as
 | 
			
		||||
             "menu:minimize,maximize,spacer,close"; the colon separates the
 | 
			
		||||
             left corner of the window from the right corner, and
 | 
			
		||||
             the button names are comma-separated. Duplicate buttons
 | 
			
		||||
             are not allowed. Unknown button names are silently ignored
 | 
			
		||||
             so that buttons can be added in future gnome-shell versions
 | 
			
		||||
             without breaking older versions.
 | 
			
		||||
             A special spacer tag can be used to insert some space between
 | 
			
		||||
             two adjacent buttons.
 | 
			
		||||
 | 
			
		||||
             This key overrides /apps/metacity/general/button_layout when
 | 
			
		||||
             running GNOME Shell.
 | 
			
		||||
           </long>
 | 
			
		||||
        </locale>
 | 
			
		||||
      </schema>
 | 
			
		||||
 | 
			
		||||
      <schema>
 | 
			
		||||
        <key>/schemas/desktop/gnome/shell/windows/edge_tiling</key>
 | 
			
		||||
        <applyto>/desktop/gnome/shell/windows/edge_tiling</applyto>
 | 
			
		||||
        <owner>gnome-shell</owner>
 | 
			
		||||
        <type>bool</type>
 | 
			
		||||
        <default>true</default>
 | 
			
		||||
        <locale name="C">
 | 
			
		||||
          <short>enable edge tiling when dropping windows on screen edges</short>
 | 
			
		||||
          <long>
 | 
			
		||||
             If enabled, dropping windows on vertical screen edges maximizes them
 | 
			
		||||
             vertically and resizes them horizontally to cover half of the
 | 
			
		||||
             available area. Dropping windows on the top screen edge maximizes them
 | 
			
		||||
             completely.
 | 
			
		||||
 | 
			
		||||
             This key overrides /apps/metacity/general/edge_tiling when
 | 
			
		||||
             running GNOME Shell.
 | 
			
		||||
          </long>
 | 
			
		||||
        </locale>
 | 
			
		||||
      </schema>
 | 
			
		||||
 | 
			
		||||
      <schema>
 | 
			
		||||
        <key>/schemas/desktop/gnome/shell/windows/theme</key>
 | 
			
		||||
        <applyto>/desktop/gnome/shell/windows/theme</applyto>
 | 
			
		||||
        <owner>gnome-shell</owner>
 | 
			
		||||
        <type>string</type>
 | 
			
		||||
        <default>Adwaita</default>
 | 
			
		||||
        <locale name="C">
 | 
			
		||||
          <short>Current theme</short>
 | 
			
		||||
          <long>
 | 
			
		||||
            The theme determines the appearance of window borders,
 | 
			
		||||
            titlebar, and so forth.
 | 
			
		||||
 | 
			
		||||
            This key overrides /apps/metacity/general/theme when
 | 
			
		||||
            running GNOME Shell.
 | 
			
		||||
          </long>
 | 
			
		||||
        </locale>
 | 
			
		||||
      </schema>
 | 
			
		||||
 | 
			
		||||
      <schema>
 | 
			
		||||
        <key>/schemas/desktop/gnome/shell/windows/workspaces_only_on_primary</key>
 | 
			
		||||
        <applyto>/desktop/gnome/shell/windows/workspaces_only_on_primary</applyto>
 | 
			
		||||
        <owner>gnome-shell</owner>
 | 
			
		||||
        <type>bool</type>
 | 
			
		||||
        <default>true</default>
 | 
			
		||||
        <locale name="C">
 | 
			
		||||
          <short>Workspaces only on primary monitor</short>
 | 
			
		||||
          <long>
 | 
			
		||||
             This key overrides /apps/mutter/general/workspaces_only_on_primary when
 | 
			
		||||
             running GNOME Shell.
 | 
			
		||||
          </long>
 | 
			
		||||
        </locale>
 | 
			
		||||
      </schema>
 | 
			
		||||
 | 
			
		||||
  </schemalist>
 | 
			
		||||
</gconfschemafile>
 | 
			
		||||
@@ -1,147 +0,0 @@
 | 
			
		||||
<!DOCTYPE node PUBLIC
 | 
			
		||||
'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
 | 
			
		||||
'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
 | 
			
		||||
<node>
 | 
			
		||||
  <interface name="org.gnome.Shell.SearchProvider">
 | 
			
		||||
    <doc:doc>
 | 
			
		||||
      <doc:description>
 | 
			
		||||
        <doc:para>
 | 
			
		||||
          The interface used for integrating into GNOME Shell's search
 | 
			
		||||
          interface.
 | 
			
		||||
        </doc:para>
 | 
			
		||||
      </doc:description>
 | 
			
		||||
    </doc:doc>
 | 
			
		||||
 | 
			
		||||
    <method name="GetInitialResultSet">
 | 
			
		||||
      <doc:doc>
 | 
			
		||||
        <doc:description>
 | 
			
		||||
          <doc:para>
 | 
			
		||||
            Called when the user first begins a search.
 | 
			
		||||
          </doc:para>
 | 
			
		||||
        </doc:description>
 | 
			
		||||
      </doc:doc>
 | 
			
		||||
      <arg type="as" direction="in">
 | 
			
		||||
        <doc:doc>
 | 
			
		||||
          <doc:summary>
 | 
			
		||||
            <doc:para>
 | 
			
		||||
              Array of search terms, which the provider should treat as
 | 
			
		||||
              logical AND.
 | 
			
		||||
            </doc:para>
 | 
			
		||||
          </doc:summary>
 | 
			
		||||
        </doc:doc>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg type="as" direction="out">
 | 
			
		||||
        <doc:doc>
 | 
			
		||||
          <doc:summary>
 | 
			
		||||
            <doc:para>
 | 
			
		||||
              An array of result identifier strings representing items which
 | 
			
		||||
              match the given search terms. Identifiers must be unique within
 | 
			
		||||
              the provider's domain, but other than that may be chosen freely
 | 
			
		||||
              by the provider.
 | 
			
		||||
            </doc:para>
 | 
			
		||||
          </doc:summary>
 | 
			
		||||
        </doc:doc>
 | 
			
		||||
      </arg>
 | 
			
		||||
    </method>
 | 
			
		||||
 | 
			
		||||
    <method name="GetSubsearchResultSet">
 | 
			
		||||
      <doc:doc>
 | 
			
		||||
        <doc:description>
 | 
			
		||||
          <doc:para>
 | 
			
		||||
            Called when a search is performed which is a "subsearch" of
 | 
			
		||||
            the previous search, e.g. the method may return less results, but
 | 
			
		||||
            not more or different results.
 | 
			
		||||
 | 
			
		||||
            This allows search providers to only search through the previous
 | 
			
		||||
            result set, rather than possibly performing a full re-query.
 | 
			
		||||
          </doc:para>
 | 
			
		||||
        </doc:description>
 | 
			
		||||
      </doc:doc>
 | 
			
		||||
      <arg type="as" direction="in">
 | 
			
		||||
        <doc:doc>
 | 
			
		||||
          <doc:summary>
 | 
			
		||||
            <doc:para>
 | 
			
		||||
              Array of item identifiers
 | 
			
		||||
            </doc:para>
 | 
			
		||||
          </doc:summary>
 | 
			
		||||
        </doc:doc>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg type="as" direction="in">
 | 
			
		||||
        <doc:doc>
 | 
			
		||||
          <doc:summary>
 | 
			
		||||
            <doc:para>
 | 
			
		||||
              Array of updated search terms, which the provider should treat as
 | 
			
		||||
              logical AND.
 | 
			
		||||
            </doc:para>
 | 
			
		||||
          </doc:summary>
 | 
			
		||||
        </doc:doc>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg type="as" direction="out">
 | 
			
		||||
        <doc:doc>
 | 
			
		||||
          <doc:summary>
 | 
			
		||||
            <doc:para>
 | 
			
		||||
              An array of result identifier strings representing items which
 | 
			
		||||
              match the given search terms. Identifiers must be unique within
 | 
			
		||||
              the provider's domain, but other than that may be chosen freely
 | 
			
		||||
              by the provider.
 | 
			
		||||
            </doc:para>
 | 
			
		||||
          </doc:summary>
 | 
			
		||||
        </doc:doc>
 | 
			
		||||
      </arg>
 | 
			
		||||
    </method>
 | 
			
		||||
 | 
			
		||||
    <method name="GetResultMetas">
 | 
			
		||||
      <doc:doc>
 | 
			
		||||
        <doc:description>
 | 
			
		||||
          <doc:para>
 | 
			
		||||
            Return an array of meta data used to display each given result
 | 
			
		||||
          </doc:para>
 | 
			
		||||
        </doc:description>
 | 
			
		||||
      </doc:doc>
 | 
			
		||||
      <arg type="as" direction="in">
 | 
			
		||||
        <doc:doc>
 | 
			
		||||
          <doc:summary>
 | 
			
		||||
            <doc:para>
 | 
			
		||||
              An array of result identifiers as returned by
 | 
			
		||||
              GetInitialResultSet() or GetSubsearchResultSet()
 | 
			
		||||
            </doc:para>
 | 
			
		||||
          </doc:summary>
 | 
			
		||||
        </doc:doc>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg type="a{sv}" direction="out">
 | 
			
		||||
        <doc:doc>
 | 
			
		||||
          <doc:summary>
 | 
			
		||||
            <doc:para>
 | 
			
		||||
              A dictionary describing the given search result, containing
 | 
			
		||||
              'id', 'name' (both strings) and either 'icon' (a serialized
 | 
			
		||||
              GIcon) or 'icon-data' (raw image data as (iiibiiay) - width,
 | 
			
		||||
              height, rowstride, has-alpha, bits per sample, channels, data)
 | 
			
		||||
            </doc:para>
 | 
			
		||||
          </doc:summary>
 | 
			
		||||
        </doc:doc>
 | 
			
		||||
      </arg>
 | 
			
		||||
    </method>
 | 
			
		||||
 | 
			
		||||
    <method name="ActivateResult">
 | 
			
		||||
      <doc:doc>
 | 
			
		||||
        <doc:description>
 | 
			
		||||
          <doc:para>
 | 
			
		||||
            Called when the users chooses a given result. The result should
 | 
			
		||||
            be displayed in the application associated with the corresponding
 | 
			
		||||
            provider.
 | 
			
		||||
          </doc:para>
 | 
			
		||||
        </doc:description>
 | 
			
		||||
      </doc:doc>
 | 
			
		||||
      <arg type="s" direction="in">
 | 
			
		||||
        <doc:doc>
 | 
			
		||||
          <doc:summary>
 | 
			
		||||
            <doc:para>
 | 
			
		||||
              A result identifier as returned by GetInitialResultSet() or
 | 
			
		||||
              GetSubsearchResultSet()
 | 
			
		||||
            </doc:para>
 | 
			
		||||
          </doc:summary>
 | 
			
		||||
        </doc:doc>
 | 
			
		||||
      </arg>
 | 
			
		||||
    </method>
 | 
			
		||||
  </interface>
 | 
			
		||||
</node>
 | 
			
		||||
@@ -1,21 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- NOTE: This schema is a GNOME 3.4 workaround - it uses the same path
 | 
			
		||||
     as org.gnome.evolution.calendar, but avoids us requiring Evolution
 | 
			
		||||
     be installed. In GNOME 3.6 the selected state will become a flag
 | 
			
		||||
     on the calendar. Because the translations are in Evolution,
 | 
			
		||||
     this is untranslated and in POTFILES.skip.
 | 
			
		||||
  -->
 | 
			
		||||
<schemalist>
 | 
			
		||||
  <schema path="/org/gnome/evolution/calendar/" id="org.gnome.shell.evolution.calendar" gettext-domain="evolution">
 | 
			
		||||
    <key type="as" name="selected-calendars">
 | 
			
		||||
      <default>[]</default>
 | 
			
		||||
      <summary>List of selected calendars</summary>
 | 
			
		||||
      <description>List of calendars to load</description>
 | 
			
		||||
    </key>
 | 
			
		||||
    <key type="as" name="selected-tasks">
 | 
			
		||||
      <default>[]</default>
 | 
			
		||||
      <summary>List of selected task lists</summary>
 | 
			
		||||
      <description>List of task lists to load</description>
 | 
			
		||||
    </key>
 | 
			
		||||
  </schema>
 | 
			
		||||
</schemalist>
 | 
			
		||||
@@ -11,14 +11,12 @@
 | 
			
		||||
        using the Alt-F2 dialog.
 | 
			
		||||
      </_description>
 | 
			
		||||
    </key>
 | 
			
		||||
    <key name="enabled-extensions" type="as">
 | 
			
		||||
    <key name="disabled-extensions" type="as">
 | 
			
		||||
      <default>[]</default>
 | 
			
		||||
      <_summary>Uuids of extensions to enable</_summary>
 | 
			
		||||
      <_summary>Uuids of extensions to disable</_summary>
 | 
			
		||||
      <_description>
 | 
			
		||||
        GNOME Shell extensions have a uuid property; this key lists extensions
 | 
			
		||||
        which should be loaded. Any extension that wants to be loaded needs
 | 
			
		||||
        to be in this list. You can also manipulate this list with the
 | 
			
		||||
        EnableExtension and DisableExtension DBus methods on org.gnome.Shell.
 | 
			
		||||
        GNOME Shell extensions have a uuid property;
 | 
			
		||||
        this key lists extensions which should not be loaded.
 | 
			
		||||
      </_description>
 | 
			
		||||
    </key>
 | 
			
		||||
    <key name="enable-app-monitoring" type="b">
 | 
			
		||||
@@ -32,7 +30,7 @@
 | 
			
		||||
      </_description>
 | 
			
		||||
    </key>
 | 
			
		||||
    <key name="favorite-apps" type="as">
 | 
			
		||||
      <default>[ 'epiphany.desktop', 'evolution.desktop', 'empathy.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'libreoffice-writer.desktop', 'nautilus.desktop', 'gnome-documents.desktop' ]</default>
 | 
			
		||||
      <default>[ 'mozilla-firefox.desktop', 'evolution.desktop', 'empathy.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'openoffice.org-writer.desktop', 'nautilus.desktop' ]</default>
 | 
			
		||||
      <_summary>List of desktop file IDs for favorite applications</_summary>
 | 
			
		||||
      <_description>
 | 
			
		||||
        The applications corresponding to these identifiers
 | 
			
		||||
@@ -51,21 +49,9 @@
 | 
			
		||||
      <default>[]</default>
 | 
			
		||||
      <_summary>History for the looking glass dialog</_summary>
 | 
			
		||||
    </key>
 | 
			
		||||
    <key name="saved-im-presence" type="i">
 | 
			
		||||
      <default>1</default>
 | 
			
		||||
      <_summary>Internally used to store the last IM presence explicitly set by the user. The
 | 
			
		||||
value here is from the TpConnectionPresenceType enumeration.</_summary>
 | 
			
		||||
    </key>
 | 
			
		||||
    <key name="saved-session-presence" type="i">
 | 
			
		||||
      <default>0</default>
 | 
			
		||||
      <_summary>Internally used to store the last session presence status for the user. The
 | 
			
		||||
value here is from the GsmPresenceStatus enumeration.</_summary>
 | 
			
		||||
    </key>
 | 
			
		||||
    <child name="clock" schema="org.gnome.shell.clock"/>
 | 
			
		||||
    <child name="calendar" schema="org.gnome.shell.calendar"/>
 | 
			
		||||
    <child name="recorder" schema="org.gnome.shell.recorder"/>
 | 
			
		||||
    <child name="keybindings" schema="org.gnome.shell.keybindings"/>
 | 
			
		||||
    <child name="keyboard" schema="org.gnome.shell.keyboard"/>
 | 
			
		||||
  </schema>
 | 
			
		||||
 | 
			
		||||
  <schema id="org.gnome.shell.calendar" path="/org/gnome/shell/calendar/"
 | 
			
		||||
@@ -79,35 +65,6 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
 | 
			
		||||
      </key>
 | 
			
		||||
  </schema>
 | 
			
		||||
 | 
			
		||||
  <schema id="org.gnome.shell.keybindings" path="/org/gnome/shell/keybindings/"
 | 
			
		||||
          gettext-domain="@GETTEXT_PACKAGE@">
 | 
			
		||||
    <key name="open-application-menu" type="as">
 | 
			
		||||
      <default>["<Super>F10"]</default>
 | 
			
		||||
      <_summary>Keybinding to open the application menu</_summary>
 | 
			
		||||
      <_description>
 | 
			
		||||
        Keybinding to open the application menu.
 | 
			
		||||
      </_description>
 | 
			
		||||
    </key>
 | 
			
		||||
    <key name="toggle-recording" type="as">
 | 
			
		||||
      <default><![CDATA[['<Control><Shift><Alt>r']]]></default>
 | 
			
		||||
      <_summary>Keybinding to toggle the screen recorder</_summary>
 | 
			
		||||
      <_description>
 | 
			
		||||
        Keybinding to start/stop the builtin screen recorder.
 | 
			
		||||
      </_description>
 | 
			
		||||
    </key>
 | 
			
		||||
  </schema>
 | 
			
		||||
 | 
			
		||||
  <schema id="org.gnome.shell.keyboard" path="/org/gnome/shell/keyboard/"
 | 
			
		||||
          gettext-domain="@GETTEXT_PACKAGE@">
 | 
			
		||||
    <key name="keyboard-type" type="s">
 | 
			
		||||
      <default>'touch'</default>
 | 
			
		||||
      <_summary>Which keyboard to use</_summary>
 | 
			
		||||
      <_description>
 | 
			
		||||
        The type of keyboard to use.
 | 
			
		||||
      </_description>
 | 
			
		||||
    </key>
 | 
			
		||||
  </schema>
 | 
			
		||||
 | 
			
		||||
  <schema id="org.gnome.shell.clock" path="/org/gnome/shell/clock/"
 | 
			
		||||
          gettext-domain="@GETTEXT_PACKAGE@">
 | 
			
		||||
    <key name="show-seconds" type="b">
 | 
			
		||||
@@ -129,7 +86,7 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
 | 
			
		||||
  <schema id="org.gnome.shell.recorder" path="/org/gnome/shell/recorder/"
 | 
			
		||||
          gettext-domain="@GETTEXT_PACKAGE@">
 | 
			
		||||
    <key name="framerate" type="i">
 | 
			
		||||
      <default>30</default>
 | 
			
		||||
      <default>15</default>
 | 
			
		||||
      <_summary>Framerate used for recording screencasts.</_summary>
 | 
			
		||||
      <_description>
 | 
			
		||||
        The framerate of the resulting screencast recordered
 | 
			
		||||
@@ -148,7 +105,7 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
 | 
			
		||||
        take care of its own output - this might be used to send the output
 | 
			
		||||
        to an icecast server via shout2send or similar. When unset or set
 | 
			
		||||
        to an empty value, the default pipeline will be used. This is currently
 | 
			
		||||
        'vp8enc quality=8 speed=6 threads=%T ! queue ! webmmux'
 | 
			
		||||
        'videorate ! vp8enc quality=10 speed=2 threads=%T ! queue ! webmmux'
 | 
			
		||||
        and records to WEBM using the VP8 codec. %T is used as a placeholder
 | 
			
		||||
        for a guess at the optimal thread count on the system.
 | 
			
		||||
      </_description>
 | 
			
		||||
@@ -163,48 +120,4 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
 | 
			
		||||
      </_description>
 | 
			
		||||
    </key>
 | 
			
		||||
  </schema>
 | 
			
		||||
 | 
			
		||||
  <schema id="org.gnome.shell.overrides" path="/org/gnome/shell/overrides/">
 | 
			
		||||
    <key name="attach-modal-dialogs" type="b">
 | 
			
		||||
      <default>true</default>
 | 
			
		||||
      <summary>Attach modal dialog to the parent window</summary>
 | 
			
		||||
      <description>
 | 
			
		||||
        This key overrides the key in org.gnome.mutter when running
 | 
			
		||||
        GNOME Shell.
 | 
			
		||||
      </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>
 | 
			
		||||
      <description>
 | 
			
		||||
        This key overrides the key in org.gnome.mutter when running GNOME Shell.
 | 
			
		||||
      </description>
 | 
			
		||||
    </key>
 | 
			
		||||
 | 
			
		||||
    <key name="dynamic-workspaces" type="b">
 | 
			
		||||
      <default>true</default>
 | 
			
		||||
      <summary>Workspaces are managed dynamically</summary>
 | 
			
		||||
      <description>
 | 
			
		||||
        This key overrides the key in org.gnome.mutter when running GNOME Shell.
 | 
			
		||||
      </description>
 | 
			
		||||
    </key>
 | 
			
		||||
 | 
			
		||||
    <key name="workspaces-only-on-primary" type="b">
 | 
			
		||||
      <default>true</default>
 | 
			
		||||
      <summary>Workspaces only on primary monitor</summary>
 | 
			
		||||
      <description>
 | 
			
		||||
        This key overrides the key in org.gnome.mutter when running GNOME Shell.
 | 
			
		||||
      </description>
 | 
			
		||||
    </key>
 | 
			
		||||
  </schema>
 | 
			
		||||
</schemalist>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
#version 110
 | 
			
		||||
uniform sampler2D tex;
 | 
			
		||||
uniform sampler2D sampler0;
 | 
			
		||||
uniform float fraction;
 | 
			
		||||
uniform float height;
 | 
			
		||||
const float c = -0.2;
 | 
			
		||||
@@ -12,16 +12,15 @@ mat4 contrast = mat4 (1.0 + c, 0.0, 0.0, 0.0,
 | 
			
		||||
vec4 off = vec4(0.633, 0.633, 0.633, 0);
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
  vec4 color = texture2D(tex, cogl_tex_coord_in[0].xy);
 | 
			
		||||
  float y = height * cogl_tex_coord_in[0].y;
 | 
			
		||||
  vec4 color = texture2D(sampler0, gl_TexCoord[0].st);
 | 
			
		||||
  float y = height * gl_TexCoord[0][1];
 | 
			
		||||
 | 
			
		||||
  // To reduce contrast, blend with a mid gray
 | 
			
		||||
  cogl_color_out = color * contrast - off * c * color.a;
 | 
			
		||||
  gl_FragColor = color * contrast - off * c;
 | 
			
		||||
 | 
			
		||||
  // We only fully dim at a distance of BORDER_MAX_HEIGHT from the top and
 | 
			
		||||
  // We only fully dim at a distance of BORDER_MAX_HEIGHT from the edge and
 | 
			
		||||
  // when the fraction is 1.0. For other locations and fractions we linearly
 | 
			
		||||
  // interpolate back to the original undimmed color, so the top of the window
 | 
			
		||||
  // is at full color.
 | 
			
		||||
  cogl_color_out = color + (cogl_color_out - color) * max(min(y / border_max_height, 1.0), 0.0);
 | 
			
		||||
  cogl_color_out = color + (cogl_color_out - color) * fraction;
 | 
			
		||||
  // interpolate back to the original undimmed color.
 | 
			
		||||
  gl_FragColor = color + (gl_FragColor - color) * min(y / border_max_height, 1.0);
 | 
			
		||||
  gl_FragColor = color + (gl_FragColor - color) * fraction;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,289 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
   xmlns:dc="http://purl.org/dc/elements/1.1/"
 | 
			
		||||
   xmlns:cc="http://creativecommons.org/ns#"
 | 
			
		||||
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 | 
			
		||||
   xmlns:svg="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:xlink="http://www.w3.org/1999/xlink"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   width="24"
 | 
			
		||||
   height="22"
 | 
			
		||||
   id="svg3199"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
   inkscape:version="0.48.1 r9760"
 | 
			
		||||
   sodipodi:docname="checkbox.svg">
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs3201">
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       id="linearGradient15404"
 | 
			
		||||
       inkscape:collect="always">
 | 
			
		||||
      <stop
 | 
			
		||||
         id="stop15406"
 | 
			
		||||
         offset="0"
 | 
			
		||||
         style="stop-color:#515151;stop-opacity:1" />
 | 
			
		||||
      <stop
 | 
			
		||||
         id="stop15408"
 | 
			
		||||
         offset="1"
 | 
			
		||||
         style="stop-color:#292929;stop-opacity:1" />
 | 
			
		||||
    </linearGradient>
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       sodipodi:type="inkscape:persp3d"
 | 
			
		||||
       inkscape:vp_x="0 : 526.18109 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_z="744.09448 : 526.18109 : 1"
 | 
			
		||||
       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
 | 
			
		||||
       id="perspective3207" />
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       id="perspective3187"
 | 
			
		||||
       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
 | 
			
		||||
       inkscape:vp_z="1 : 0.5 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_x="0 : 0.5 : 1"
 | 
			
		||||
       sodipodi:type="inkscape:persp3d" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       inkscape:collect="always"
 | 
			
		||||
       xlink:href="#linearGradient5872-5-1"
 | 
			
		||||
       id="linearGradient5891-0-4"
 | 
			
		||||
       gradientUnits="userSpaceOnUse"
 | 
			
		||||
       x1="205.84143"
 | 
			
		||||
       y1="246.7094"
 | 
			
		||||
       x2="206.74803"
 | 
			
		||||
       y2="231.24142" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       inkscape:collect="always"
 | 
			
		||||
       id="linearGradient5872-5-1">
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#0b2e52;stop-opacity:1"
 | 
			
		||||
         offset="0"
 | 
			
		||||
         id="stop5874-4-4" />
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#1862af;stop-opacity:1"
 | 
			
		||||
         offset="1"
 | 
			
		||||
         id="stop5876-0-5" />
 | 
			
		||||
    </linearGradient>
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="spiro"
 | 
			
		||||
       id="path-effect5837-4-6"
 | 
			
		||||
       is_visible="true" />
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="spiro"
 | 
			
		||||
       id="path-effect14768"
 | 
			
		||||
       is_visible="true" />
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="spiro"
 | 
			
		||||
       id="path-effect5884-4-7"
 | 
			
		||||
       is_visible="true" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       y2="-388.72955"
 | 
			
		||||
       x2="-93.031357"
 | 
			
		||||
       y1="-396.34738"
 | 
			
		||||
       x1="-93.031357"
 | 
			
		||||
       gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.685418)"
 | 
			
		||||
       gradientUnits="userSpaceOnUse"
 | 
			
		||||
       id="linearGradient14219"
 | 
			
		||||
       xlink:href="#linearGradient15404"
 | 
			
		||||
       inkscape:collect="always" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       inkscape:collect="always"
 | 
			
		||||
       id="linearGradient10013-4-63-6">
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#333333;stop-opacity:1;"
 | 
			
		||||
         offset="0"
 | 
			
		||||
         id="stop10015-2-76-1" />
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#292929;stop-opacity:1"
 | 
			
		||||
         offset="1"
 | 
			
		||||
         id="stop10017-46-15-8" />
 | 
			
		||||
    </linearGradient>
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       inkscape:collect="always"
 | 
			
		||||
       id="linearGradient10597-5">
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#16191a;stop-opacity:1;"
 | 
			
		||||
         offset="0"
 | 
			
		||||
         id="stop10599-2" />
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#2b3133;stop-opacity:1"
 | 
			
		||||
         offset="1"
 | 
			
		||||
         id="stop10601-5" />
 | 
			
		||||
    </linearGradient>
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       y2="-322.16354"
 | 
			
		||||
       x2="921.22498"
 | 
			
		||||
       y1="-330.05121"
 | 
			
		||||
       x1="921.32812"
 | 
			
		||||
       gradientTransform="matrix(1.5918367,0,0,0.85714285,-1456.5464,275.45191)"
 | 
			
		||||
       gradientUnits="userSpaceOnUse"
 | 
			
		||||
       id="linearGradient15374"
 | 
			
		||||
       xlink:href="#linearGradient10013-4-63-6"
 | 
			
		||||
       inkscape:collect="always" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       gradientTransform="translate(-1199.9852,216.38048)"
 | 
			
		||||
       y2="-227.07961"
 | 
			
		||||
       x2="1203.9177"
 | 
			
		||||
       y1="-217.56708"
 | 
			
		||||
       x1="1203.9177"
 | 
			
		||||
       gradientUnits="userSpaceOnUse"
 | 
			
		||||
       id="linearGradient15376"
 | 
			
		||||
       xlink:href="#linearGradient10597-5"
 | 
			
		||||
       inkscape:collect="always" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       y2="-388.72955"
 | 
			
		||||
       x2="-93.031357"
 | 
			
		||||
       y1="-396.34738"
 | 
			
		||||
       x1="-93.031357"
 | 
			
		||||
       gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.685418)"
 | 
			
		||||
       gradientUnits="userSpaceOnUse"
 | 
			
		||||
       id="linearGradient14219-6"
 | 
			
		||||
       xlink:href="#linearGradient15404-9"
 | 
			
		||||
       inkscape:collect="always" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       id="linearGradient15404-9"
 | 
			
		||||
       inkscape:collect="always">
 | 
			
		||||
      <stop
 | 
			
		||||
         id="stop15406-6"
 | 
			
		||||
         offset="0"
 | 
			
		||||
         style="stop-color:#515151;stop-opacity:1" />
 | 
			
		||||
      <stop
 | 
			
		||||
         id="stop15408-7"
 | 
			
		||||
         offset="1"
 | 
			
		||||
         style="stop-color:#292929;stop-opacity:1" />
 | 
			
		||||
    </linearGradient>
 | 
			
		||||
  </defs>
 | 
			
		||||
  <sodipodi:namedview
 | 
			
		||||
     id="base"
 | 
			
		||||
     pagecolor="#000000"
 | 
			
		||||
     bordercolor="#2d2d2d"
 | 
			
		||||
     borderopacity="1"
 | 
			
		||||
     inkscape:pageopacity="1"
 | 
			
		||||
     inkscape:pageshadow="2"
 | 
			
		||||
     inkscape:zoom="1"
 | 
			
		||||
     inkscape:cx="71.516955"
 | 
			
		||||
     inkscape:cy="5.8710559"
 | 
			
		||||
     inkscape:document-units="px"
 | 
			
		||||
     inkscape:current-layer="layer1"
 | 
			
		||||
     showgrid="false"
 | 
			
		||||
     inkscape:window-width="1412"
 | 
			
		||||
     inkscape:window-height="1067"
 | 
			
		||||
     inkscape:window-x="2635"
 | 
			
		||||
     inkscape:window-y="226"
 | 
			
		||||
     inkscape:window-maximized="0"
 | 
			
		||||
     borderlayer="true"
 | 
			
		||||
     inkscape:showpageshadow="false"
 | 
			
		||||
     inkscape:snap-nodes="false"
 | 
			
		||||
     inkscape:snap-bbox="true"
 | 
			
		||||
     showborder="false">
 | 
			
		||||
    <inkscape:grid
 | 
			
		||||
       type="xygrid"
 | 
			
		||||
       id="grid14843"
 | 
			
		||||
       empspacing="5"
 | 
			
		||||
       visible="true"
 | 
			
		||||
       enabled="true"
 | 
			
		||||
       snapvisiblegridlinesonly="true" />
 | 
			
		||||
  </sodipodi:namedview>
 | 
			
		||||
  <metadata
 | 
			
		||||
     id="metadata3204">
 | 
			
		||||
    <rdf:RDF>
 | 
			
		||||
      <cc:Work
 | 
			
		||||
         rdf:about="">
 | 
			
		||||
        <dc:format>image/svg+xml</dc:format>
 | 
			
		||||
        <dc:type
 | 
			
		||||
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 | 
			
		||||
        <dc:title></dc:title>
 | 
			
		||||
      </cc:Work>
 | 
			
		||||
    </rdf:RDF>
 | 
			
		||||
  </metadata>
 | 
			
		||||
  <g
 | 
			
		||||
     inkscape:label="Layer 1"
 | 
			
		||||
     inkscape:groupmode="layer"
 | 
			
		||||
     id="layer1"
 | 
			
		||||
     transform="translate(-342.5,-521.36218)">
 | 
			
		||||
    <g
 | 
			
		||||
       transform="matrix(0.80230061,0,0,0.80230061,-87.624044,-453.10297)"
 | 
			
		||||
       id="g14586-0"
 | 
			
		||||
       style="stroke-width:2.3714385;stroke-miterlimit:4;stroke-dasharray:none">
 | 
			
		||||
      <g
 | 
			
		||||
         inkscape:export-ydpi="90"
 | 
			
		||||
         inkscape:export-xdpi="90"
 | 
			
		||||
         inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
 | 
			
		||||
         transform="matrix(1.9969286,0,0,1.9969286,-397.05491,877.00482)"
 | 
			
		||||
         id="g15291-9-6"
 | 
			
		||||
         style="stroke-width:1.18754292;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new">
 | 
			
		||||
        <g
 | 
			
		||||
           transform="translate(877.50354,-102.83507)"
 | 
			
		||||
           id="g16853-4-9"
 | 
			
		||||
           style="stroke-width:1.18754292;stroke-miterlimit:4;stroke-dasharray:none;enable-background:new">
 | 
			
		||||
          <rect
 | 
			
		||||
             transform="scale(1,-1)"
 | 
			
		||||
             style="color:#000000;fill:url(#linearGradient14219-6);fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:1.24833274;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
 | 
			
		||||
             id="rect6506-6"
 | 
			
		||||
             width="11.281681"
 | 
			
		||||
             height="11.26221"
 | 
			
		||||
             x="-409.59354"
 | 
			
		||||
             y="-284.40115"
 | 
			
		||||
             rx="1.0052766"
 | 
			
		||||
             ry="1.0052764" />
 | 
			
		||||
        </g>
 | 
			
		||||
      </g>
 | 
			
		||||
      <g
 | 
			
		||||
         inkscape:export-ydpi="90"
 | 
			
		||||
         inkscape:export-xdpi="90"
 | 
			
		||||
         inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
 | 
			
		||||
         transform="translate(343.99999,987.99997)"
 | 
			
		||||
         id="g5886-5"
 | 
			
		||||
         style="stroke-width:2.3714385;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new" />
 | 
			
		||||
    </g>
 | 
			
		||||
    <g
 | 
			
		||||
       transform="matrix(0.84337,0,0,0.84337,-110.16632,-503.56182)"
 | 
			
		||||
       id="g14586">
 | 
			
		||||
      <g
 | 
			
		||||
         inkscape:export-ydpi="90"
 | 
			
		||||
         inkscape:export-xdpi="90"
 | 
			
		||||
         inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
 | 
			
		||||
         transform="matrix(1.9969286,0,0,1.9969286,-397.05491,877.00482)"
 | 
			
		||||
         id="g15291-9"
 | 
			
		||||
         style="display:inline;enable-background:new">
 | 
			
		||||
        <g
 | 
			
		||||
           transform="translate(877.50354,-102.83507)"
 | 
			
		||||
           id="g16853-4"
 | 
			
		||||
           style="enable-background:new" />
 | 
			
		||||
      </g>
 | 
			
		||||
      <g
 | 
			
		||||
         inkscape:export-ydpi="90"
 | 
			
		||||
         inkscape:export-xdpi="90"
 | 
			
		||||
         inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
 | 
			
		||||
         transform="translate(343.99999,987.99997)"
 | 
			
		||||
         id="g5886"
 | 
			
		||||
         style="display:inline;enable-background:new">
 | 
			
		||||
        <path
 | 
			
		||||
           style="fill:none;stroke:url(#linearGradient5891-0-4);stroke-width:7.11431503;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
 | 
			
		||||
           d="m 198.5,240 5.25,5.25 13.98616,-14.43081"
 | 
			
		||||
           id="path5835"
 | 
			
		||||
           inkscape:path-effect="#path-effect5837-4-6"
 | 
			
		||||
           inkscape:original-d="m 198.5,240 5.25,5.25 13.98616,-14.43081"
 | 
			
		||||
           inkscape:connector-curvature="0"
 | 
			
		||||
           sodipodi:nodetypes="ccc" />
 | 
			
		||||
        <path
 | 
			
		||||
           inkscape:connector-curvature="0"
 | 
			
		||||
           inkscape:original-d="m 198.5,240 5.25,5.25 13.91205,-14.31964"
 | 
			
		||||
           inkscape:path-effect="#path-effect5837-4-6"
 | 
			
		||||
           id="path5880"
 | 
			
		||||
           d="m 198.5,240 5.25,5.25 13.91205,-14.31964"
 | 
			
		||||
           style="fill:none;stroke:#4787c8;stroke-width:3.55715752;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
 | 
			
		||||
           sodipodi:nodetypes="ccc" />
 | 
			
		||||
        <path
 | 
			
		||||
           style="fill:none;stroke:#7ea7d3;stroke-width:1.18571913px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
 | 
			
		||||
           d="m 197.45937,240.47455 c -0.17828,-0.29362 -0.20087,-0.67548 -0.0603,-0.98892 0.14055,-0.31344 0.43739,-0.54812 0.77144,-0.62817 0.33405,-0.08 0.69314,-0.01 0.99635,0.15175 0.30321,0.16144 0.55146,0.40727 0.79165,0.65284 l 3.66429,3.74643 12.87946,-12.98973 c 0.20796,-0.20974 0.42306,-0.41969 0.68548,-0.55522 0.26242,-0.13553 0.57293,-0.19052 0.85827,-0.11426 0.14267,0.0381 0.27708,0.10787 0.38874,0.20452 0.11167,0.0966 0.20021,0.22004 0.25479,0.35726 0.0546,0.13722 0.075,0.28793 0.0585,0.43468 -0.0165,0.14674 -0.07,0.28919 -0.15422,0.41052"
 | 
			
		||||
           id="path5882"
 | 
			
		||||
           inkscape:path-effect="#path-effect5884-4-7"
 | 
			
		||||
           inkscape:original-d="m 197.45937,240.47455 c 0.65604,-0.56057 2.02485,-1.34847 2.49911,-0.8125 l 3.66429,3.74643 12.87946,-12.98973 c 0.6875,-0.6875 2.09152,0.7375 2.09152,0.7375"
 | 
			
		||||
           inkscape:connector-curvature="0"
 | 
			
		||||
           sodipodi:nodetypes="csccc" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 11 KiB  | 
@@ -1,198 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
   xmlns:dc="http://purl.org/dc/elements/1.1/"
 | 
			
		||||
   xmlns:cc="http://creativecommons.org/ns#"
 | 
			
		||||
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 | 
			
		||||
   xmlns:svg="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:xlink="http://www.w3.org/1999/xlink"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   width="24"
 | 
			
		||||
   height="22"
 | 
			
		||||
   id="svg3199"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
   inkscape:version="0.48.1 r9760"
 | 
			
		||||
   sodipodi:docname="checkbox-off.svg">
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs3201">
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       id="linearGradient15404"
 | 
			
		||||
       inkscape:collect="always">
 | 
			
		||||
      <stop
 | 
			
		||||
         id="stop15406"
 | 
			
		||||
         offset="0"
 | 
			
		||||
         style="stop-color:#515151;stop-opacity:1" />
 | 
			
		||||
      <stop
 | 
			
		||||
         id="stop15408"
 | 
			
		||||
         offset="1"
 | 
			
		||||
         style="stop-color:#292929;stop-opacity:1" />
 | 
			
		||||
    </linearGradient>
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       sodipodi:type="inkscape:persp3d"
 | 
			
		||||
       inkscape:vp_x="0 : 526.18109 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_z="744.09448 : 526.18109 : 1"
 | 
			
		||||
       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
 | 
			
		||||
       id="perspective3207" />
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       id="perspective3187"
 | 
			
		||||
       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
 | 
			
		||||
       inkscape:vp_z="1 : 0.5 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_x="0 : 0.5 : 1"
 | 
			
		||||
       sodipodi:type="inkscape:persp3d" />
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="spiro"
 | 
			
		||||
       id="path-effect5837-4-6"
 | 
			
		||||
       is_visible="true" />
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="spiro"
 | 
			
		||||
       id="path-effect14768"
 | 
			
		||||
       is_visible="true" />
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="spiro"
 | 
			
		||||
       id="path-effect5884-4-7"
 | 
			
		||||
       is_visible="true" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       y2="-388.72955"
 | 
			
		||||
       x2="-93.031357"
 | 
			
		||||
       y1="-396.34738"
 | 
			
		||||
       x1="-93.031357"
 | 
			
		||||
       gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.685418)"
 | 
			
		||||
       gradientUnits="userSpaceOnUse"
 | 
			
		||||
       id="linearGradient14219"
 | 
			
		||||
       xlink:href="#linearGradient15404"
 | 
			
		||||
       inkscape:collect="always" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       inkscape:collect="always"
 | 
			
		||||
       id="linearGradient10013-4-63-6">
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#333333;stop-opacity:1;"
 | 
			
		||||
         offset="0"
 | 
			
		||||
         id="stop10015-2-76-1" />
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#292929;stop-opacity:1"
 | 
			
		||||
         offset="1"
 | 
			
		||||
         id="stop10017-46-15-8" />
 | 
			
		||||
    </linearGradient>
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       inkscape:collect="always"
 | 
			
		||||
       id="linearGradient10597-5">
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#16191a;stop-opacity:1;"
 | 
			
		||||
         offset="0"
 | 
			
		||||
         id="stop10599-2" />
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#2b3133;stop-opacity:1"
 | 
			
		||||
         offset="1"
 | 
			
		||||
         id="stop10601-5" />
 | 
			
		||||
    </linearGradient>
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       y2="-322.16354"
 | 
			
		||||
       x2="921.22498"
 | 
			
		||||
       y1="-330.05121"
 | 
			
		||||
       x1="921.32812"
 | 
			
		||||
       gradientTransform="matrix(1.5918367,0,0,0.85714285,-1456.5464,275.45191)"
 | 
			
		||||
       gradientUnits="userSpaceOnUse"
 | 
			
		||||
       id="linearGradient15374"
 | 
			
		||||
       xlink:href="#linearGradient10013-4-63-6"
 | 
			
		||||
       inkscape:collect="always" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       gradientTransform="translate(-1199.9852,216.38048)"
 | 
			
		||||
       y2="-227.07961"
 | 
			
		||||
       x2="1203.9177"
 | 
			
		||||
       y1="-217.56708"
 | 
			
		||||
       x1="1203.9177"
 | 
			
		||||
       gradientUnits="userSpaceOnUse"
 | 
			
		||||
       id="linearGradient15376"
 | 
			
		||||
       xlink:href="#linearGradient10597-5"
 | 
			
		||||
       inkscape:collect="always" />
 | 
			
		||||
  </defs>
 | 
			
		||||
  <sodipodi:namedview
 | 
			
		||||
     id="base"
 | 
			
		||||
     pagecolor="#000000"
 | 
			
		||||
     bordercolor="#2d2d2d"
 | 
			
		||||
     borderopacity="1"
 | 
			
		||||
     inkscape:pageopacity="1"
 | 
			
		||||
     inkscape:pageshadow="2"
 | 
			
		||||
     inkscape:zoom="1"
 | 
			
		||||
     inkscape:cx="6.1225392"
 | 
			
		||||
     inkscape:cy="3.6003241"
 | 
			
		||||
     inkscape:document-units="px"
 | 
			
		||||
     inkscape:current-layer="layer1"
 | 
			
		||||
     showgrid="false"
 | 
			
		||||
     inkscape:window-width="1412"
 | 
			
		||||
     inkscape:window-height="1067"
 | 
			
		||||
     inkscape:window-x="2116"
 | 
			
		||||
     inkscape:window-y="261"
 | 
			
		||||
     inkscape:window-maximized="0"
 | 
			
		||||
     borderlayer="true"
 | 
			
		||||
     inkscape:showpageshadow="false"
 | 
			
		||||
     inkscape:snap-nodes="false"
 | 
			
		||||
     inkscape:snap-bbox="true"
 | 
			
		||||
     showborder="false">
 | 
			
		||||
    <inkscape:grid
 | 
			
		||||
       type="xygrid"
 | 
			
		||||
       id="grid14843"
 | 
			
		||||
       empspacing="5"
 | 
			
		||||
       visible="true"
 | 
			
		||||
       enabled="true"
 | 
			
		||||
       snapvisiblegridlinesonly="true" />
 | 
			
		||||
  </sodipodi:namedview>
 | 
			
		||||
  <metadata
 | 
			
		||||
     id="metadata3204">
 | 
			
		||||
    <rdf:RDF>
 | 
			
		||||
      <cc:Work
 | 
			
		||||
         rdf:about="">
 | 
			
		||||
        <dc:format>image/svg+xml</dc:format>
 | 
			
		||||
        <dc:type
 | 
			
		||||
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 | 
			
		||||
        <dc:title></dc:title>
 | 
			
		||||
      </cc:Work>
 | 
			
		||||
    </rdf:RDF>
 | 
			
		||||
  </metadata>
 | 
			
		||||
  <g
 | 
			
		||||
     inkscape:label="Layer 1"
 | 
			
		||||
     inkscape:groupmode="layer"
 | 
			
		||||
     id="layer1"
 | 
			
		||||
     transform="translate(-342.5,-521.36218)">
 | 
			
		||||
    <g
 | 
			
		||||
       transform="matrix(0.80230061,0,0,0.80230061,-87.624044,-453.10297)"
 | 
			
		||||
       id="g14586"
 | 
			
		||||
       style="stroke-width:2.3714385;stroke-miterlimit:4;stroke-dasharray:none">
 | 
			
		||||
      <g
 | 
			
		||||
         inkscape:export-ydpi="90"
 | 
			
		||||
         inkscape:export-xdpi="90"
 | 
			
		||||
         inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
 | 
			
		||||
         transform="matrix(1.9969286,0,0,1.9969286,-397.05491,877.00482)"
 | 
			
		||||
         id="g15291-9"
 | 
			
		||||
         style="stroke-width:1.18754292;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new">
 | 
			
		||||
        <g
 | 
			
		||||
           transform="translate(877.50354,-102.83507)"
 | 
			
		||||
           id="g16853-4"
 | 
			
		||||
           style="stroke-width:1.18754292;stroke-miterlimit:4;stroke-dasharray:none;enable-background:new">
 | 
			
		||||
          <rect
 | 
			
		||||
             transform="scale(1,-1)"
 | 
			
		||||
             style="color:#000000;fill:url(#linearGradient14219);fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:1.24833274;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
 | 
			
		||||
             id="rect6506-6"
 | 
			
		||||
             width="11.281681"
 | 
			
		||||
             height="11.26221"
 | 
			
		||||
             x="-409.59354"
 | 
			
		||||
             y="-284.40115"
 | 
			
		||||
             rx="1.0052766"
 | 
			
		||||
             ry="1.0052764" />
 | 
			
		||||
        </g>
 | 
			
		||||
      </g>
 | 
			
		||||
      <g
 | 
			
		||||
         inkscape:export-ydpi="90"
 | 
			
		||||
         inkscape:export-xdpi="90"
 | 
			
		||||
         inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
 | 
			
		||||
         transform="translate(343.99999,987.99997)"
 | 
			
		||||
         id="g5886"
 | 
			
		||||
         style="stroke-width:2.3714385;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new" />
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 6.5 KiB  | 
@@ -1,218 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
   xmlns:dc="http://purl.org/dc/elements/1.1/"
 | 
			
		||||
   xmlns:cc="http://creativecommons.org/ns#"
 | 
			
		||||
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 | 
			
		||||
   xmlns:svg="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:xlink="http://www.w3.org/1999/xlink"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   width="24"
 | 
			
		||||
   height="22"
 | 
			
		||||
   id="svg3199"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
   inkscape:version="0.48.1 r9760"
 | 
			
		||||
   sodipodi:docname="checkbox.svg">
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs3201">
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       id="linearGradient15404"
 | 
			
		||||
       inkscape:collect="always">
 | 
			
		||||
      <stop
 | 
			
		||||
         id="stop15406"
 | 
			
		||||
         offset="0"
 | 
			
		||||
         style="stop-color:#515151;stop-opacity:1" />
 | 
			
		||||
      <stop
 | 
			
		||||
         id="stop15408"
 | 
			
		||||
         offset="1"
 | 
			
		||||
         style="stop-color:#292929;stop-opacity:1" />
 | 
			
		||||
    </linearGradient>
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       sodipodi:type="inkscape:persp3d"
 | 
			
		||||
       inkscape:vp_x="0 : 526.18109 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_z="744.09448 : 526.18109 : 1"
 | 
			
		||||
       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
 | 
			
		||||
       id="perspective3207" />
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       id="perspective3187"
 | 
			
		||||
       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
 | 
			
		||||
       inkscape:vp_z="1 : 0.5 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_x="0 : 0.5 : 1"
 | 
			
		||||
       sodipodi:type="inkscape:persp3d" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       inkscape:collect="always"
 | 
			
		||||
       xlink:href="#linearGradient5872-5-1"
 | 
			
		||||
       id="linearGradient5891-0-4"
 | 
			
		||||
       gradientUnits="userSpaceOnUse"
 | 
			
		||||
       x1="205.84143"
 | 
			
		||||
       y1="246.7094"
 | 
			
		||||
       x2="206.74803"
 | 
			
		||||
       y2="231.24142" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       inkscape:collect="always"
 | 
			
		||||
       id="linearGradient5872-5-1">
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#0b2e52;stop-opacity:1"
 | 
			
		||||
         offset="0"
 | 
			
		||||
         id="stop5874-4-4" />
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#1862af;stop-opacity:1"
 | 
			
		||||
         offset="1"
 | 
			
		||||
         id="stop5876-0-5" />
 | 
			
		||||
    </linearGradient>
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="spiro"
 | 
			
		||||
       id="path-effect5837-4-6"
 | 
			
		||||
       is_visible="true" />
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="spiro"
 | 
			
		||||
       id="path-effect14768"
 | 
			
		||||
       is_visible="true" />
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="spiro"
 | 
			
		||||
       id="path-effect5884-4-7"
 | 
			
		||||
       is_visible="true" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       y2="-388.72955"
 | 
			
		||||
       x2="-93.031357"
 | 
			
		||||
       y1="-396.34738"
 | 
			
		||||
       x1="-93.031357"
 | 
			
		||||
       gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.685418)"
 | 
			
		||||
       gradientUnits="userSpaceOnUse"
 | 
			
		||||
       id="linearGradient14219"
 | 
			
		||||
       xlink:href="#linearGradient15404"
 | 
			
		||||
       inkscape:collect="always" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       inkscape:collect="always"
 | 
			
		||||
       id="linearGradient10013-4-63-6">
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#333333;stop-opacity:1;"
 | 
			
		||||
         offset="0"
 | 
			
		||||
         id="stop10015-2-76-1" />
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#292929;stop-opacity:1"
 | 
			
		||||
         offset="1"
 | 
			
		||||
         id="stop10017-46-15-8" />
 | 
			
		||||
    </linearGradient>
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       inkscape:collect="always"
 | 
			
		||||
       id="linearGradient10597-5">
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#16191a;stop-opacity:1;"
 | 
			
		||||
         offset="0"
 | 
			
		||||
         id="stop10599-2" />
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#2b3133;stop-opacity:1"
 | 
			
		||||
         offset="1"
 | 
			
		||||
         id="stop10601-5" />
 | 
			
		||||
    </linearGradient>
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       y2="-322.16354"
 | 
			
		||||
       x2="921.22498"
 | 
			
		||||
       y1="-330.05121"
 | 
			
		||||
       x1="921.32812"
 | 
			
		||||
       gradientTransform="matrix(1.5918367,0,0,0.85714285,-1456.5464,275.45191)"
 | 
			
		||||
       gradientUnits="userSpaceOnUse"
 | 
			
		||||
       id="linearGradient15374"
 | 
			
		||||
       xlink:href="#linearGradient10013-4-63-6"
 | 
			
		||||
       inkscape:collect="always" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       gradientTransform="translate(-1199.9852,216.38048)"
 | 
			
		||||
       y2="-227.07961"
 | 
			
		||||
       x2="1203.9177"
 | 
			
		||||
       y1="-217.56708"
 | 
			
		||||
       x1="1203.9177"
 | 
			
		||||
       gradientUnits="userSpaceOnUse"
 | 
			
		||||
       id="linearGradient15376"
 | 
			
		||||
       xlink:href="#linearGradient10597-5"
 | 
			
		||||
       inkscape:collect="always" />
 | 
			
		||||
  </defs>
 | 
			
		||||
  <sodipodi:namedview
 | 
			
		||||
     id="base"
 | 
			
		||||
     pagecolor="#000000"
 | 
			
		||||
     bordercolor="#2d2d2d"
 | 
			
		||||
     borderopacity="1"
 | 
			
		||||
     inkscape:pageopacity="1"
 | 
			
		||||
     inkscape:pageshadow="2"
 | 
			
		||||
     inkscape:zoom="4"
 | 
			
		||||
     inkscape:cx="71.247925"
 | 
			
		||||
     inkscape:cy="33.339093"
 | 
			
		||||
     inkscape:document-units="px"
 | 
			
		||||
     inkscape:current-layer="layer1"
 | 
			
		||||
     showgrid="false"
 | 
			
		||||
     inkscape:window-width="1412"
 | 
			
		||||
     inkscape:window-height="1067"
 | 
			
		||||
     inkscape:window-x="2116"
 | 
			
		||||
     inkscape:window-y="261"
 | 
			
		||||
     inkscape:window-maximized="0"
 | 
			
		||||
     borderlayer="true"
 | 
			
		||||
     inkscape:showpageshadow="false"
 | 
			
		||||
     inkscape:snap-nodes="false"
 | 
			
		||||
     inkscape:snap-bbox="true"
 | 
			
		||||
     showborder="false">
 | 
			
		||||
    <inkscape:grid
 | 
			
		||||
       type="xygrid"
 | 
			
		||||
       id="grid14843"
 | 
			
		||||
       empspacing="5"
 | 
			
		||||
       visible="true"
 | 
			
		||||
       enabled="true"
 | 
			
		||||
       snapvisiblegridlinesonly="true" />
 | 
			
		||||
  </sodipodi:namedview>
 | 
			
		||||
  <metadata
 | 
			
		||||
     id="metadata3204">
 | 
			
		||||
    <rdf:RDF>
 | 
			
		||||
      <cc:Work
 | 
			
		||||
         rdf:about="">
 | 
			
		||||
        <dc:format>image/svg+xml</dc:format>
 | 
			
		||||
        <dc:type
 | 
			
		||||
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 | 
			
		||||
        <dc:title></dc:title>
 | 
			
		||||
      </cc:Work>
 | 
			
		||||
    </rdf:RDF>
 | 
			
		||||
  </metadata>
 | 
			
		||||
  <g
 | 
			
		||||
     inkscape:label="Layer 1"
 | 
			
		||||
     inkscape:groupmode="layer"
 | 
			
		||||
     id="layer1"
 | 
			
		||||
     transform="translate(-342.5,-521.36218)">
 | 
			
		||||
    <g
 | 
			
		||||
       transform="matrix(0.84337,0,0,0.84337,-110.16632,-503.56182)"
 | 
			
		||||
       id="g14586">
 | 
			
		||||
      <g
 | 
			
		||||
         inkscape:export-ydpi="90"
 | 
			
		||||
         inkscape:export-xdpi="90"
 | 
			
		||||
         inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
 | 
			
		||||
         transform="matrix(1.9969286,0,0,1.9969286,-397.05491,877.00482)"
 | 
			
		||||
         id="g15291-9"
 | 
			
		||||
         style="display:inline;enable-background:new">
 | 
			
		||||
        <g
 | 
			
		||||
           transform="translate(877.50354,-102.83507)"
 | 
			
		||||
           id="g16853-4"
 | 
			
		||||
           style="enable-background:new">
 | 
			
		||||
          <rect
 | 
			
		||||
             transform="scale(1,-1)"
 | 
			
		||||
             style="color:#000000;fill:url(#linearGradient14219);fill-opacity:1;fill-rule:nonzero;stroke:#868686;stroke-width:0.59377144999999998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
 | 
			
		||||
             id="rect6506-6"
 | 
			
		||||
             width="11.281681"
 | 
			
		||||
             height="11.26221"
 | 
			
		||||
             x="-409.59354"
 | 
			
		||||
             y="-284.40115"
 | 
			
		||||
             rx="0.95632279"
 | 
			
		||||
             ry="0.95632273" />
 | 
			
		||||
        </g>
 | 
			
		||||
      </g>
 | 
			
		||||
      <g
 | 
			
		||||
         inkscape:export-ydpi="90"
 | 
			
		||||
         inkscape:export-xdpi="90"
 | 
			
		||||
         inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
 | 
			
		||||
         transform="translate(343.99999,987.99997)"
 | 
			
		||||
         id="g5886"
 | 
			
		||||
         style="display:inline;enable-background:new" />
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 6.8 KiB  | 
@@ -1,243 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
   xmlns:dc="http://purl.org/dc/elements/1.1/"
 | 
			
		||||
   xmlns:cc="http://creativecommons.org/ns#"
 | 
			
		||||
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 | 
			
		||||
   xmlns:svg="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:xlink="http://www.w3.org/1999/xlink"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   width="24"
 | 
			
		||||
   height="22"
 | 
			
		||||
   id="svg3199"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
   inkscape:version="0.48.1 r9760"
 | 
			
		||||
   sodipodi:docname="checkbox-focused.svg">
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs3201">
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       id="linearGradient15404"
 | 
			
		||||
       inkscape:collect="always">
 | 
			
		||||
      <stop
 | 
			
		||||
         id="stop15406"
 | 
			
		||||
         offset="0"
 | 
			
		||||
         style="stop-color:#515151;stop-opacity:1" />
 | 
			
		||||
      <stop
 | 
			
		||||
         id="stop15408"
 | 
			
		||||
         offset="1"
 | 
			
		||||
         style="stop-color:#292929;stop-opacity:1" />
 | 
			
		||||
    </linearGradient>
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       sodipodi:type="inkscape:persp3d"
 | 
			
		||||
       inkscape:vp_x="0 : 526.18109 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_z="744.09448 : 526.18109 : 1"
 | 
			
		||||
       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
 | 
			
		||||
       id="perspective3207" />
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       id="perspective3187"
 | 
			
		||||
       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
 | 
			
		||||
       inkscape:vp_z="1 : 0.5 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_x="0 : 0.5 : 1"
 | 
			
		||||
       sodipodi:type="inkscape:persp3d" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       inkscape:collect="always"
 | 
			
		||||
       xlink:href="#linearGradient5872-5-1"
 | 
			
		||||
       id="linearGradient5891-0-4"
 | 
			
		||||
       gradientUnits="userSpaceOnUse"
 | 
			
		||||
       x1="205.84143"
 | 
			
		||||
       y1="246.7094"
 | 
			
		||||
       x2="206.74803"
 | 
			
		||||
       y2="231.24142" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       inkscape:collect="always"
 | 
			
		||||
       id="linearGradient5872-5-1">
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#0b2e52;stop-opacity:1"
 | 
			
		||||
         offset="0"
 | 
			
		||||
         id="stop5874-4-4" />
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#1862af;stop-opacity:1"
 | 
			
		||||
         offset="1"
 | 
			
		||||
         id="stop5876-0-5" />
 | 
			
		||||
    </linearGradient>
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="spiro"
 | 
			
		||||
       id="path-effect5837-4-6"
 | 
			
		||||
       is_visible="true" />
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="spiro"
 | 
			
		||||
       id="path-effect14768"
 | 
			
		||||
       is_visible="true" />
 | 
			
		||||
    <inkscape:path-effect
 | 
			
		||||
       effect="spiro"
 | 
			
		||||
       id="path-effect5884-4-7"
 | 
			
		||||
       is_visible="true" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       y2="-388.72955"
 | 
			
		||||
       x2="-93.031357"
 | 
			
		||||
       y1="-396.34738"
 | 
			
		||||
       x1="-93.031357"
 | 
			
		||||
       gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.685418)"
 | 
			
		||||
       gradientUnits="userSpaceOnUse"
 | 
			
		||||
       id="linearGradient14219"
 | 
			
		||||
       xlink:href="#linearGradient15404"
 | 
			
		||||
       inkscape:collect="always" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       inkscape:collect="always"
 | 
			
		||||
       id="linearGradient10013-4-63-6">
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#333333;stop-opacity:1;"
 | 
			
		||||
         offset="0"
 | 
			
		||||
         id="stop10015-2-76-1" />
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#292929;stop-opacity:1"
 | 
			
		||||
         offset="1"
 | 
			
		||||
         id="stop10017-46-15-8" />
 | 
			
		||||
    </linearGradient>
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       inkscape:collect="always"
 | 
			
		||||
       id="linearGradient10597-5">
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#16191a;stop-opacity:1;"
 | 
			
		||||
         offset="0"
 | 
			
		||||
         id="stop10599-2" />
 | 
			
		||||
      <stop
 | 
			
		||||
         style="stop-color:#2b3133;stop-opacity:1"
 | 
			
		||||
         offset="1"
 | 
			
		||||
         id="stop10601-5" />
 | 
			
		||||
    </linearGradient>
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       y2="-322.16354"
 | 
			
		||||
       x2="921.22498"
 | 
			
		||||
       y1="-330.05121"
 | 
			
		||||
       x1="921.32812"
 | 
			
		||||
       gradientTransform="matrix(1.5918367,0,0,0.85714285,-1456.5464,275.45191)"
 | 
			
		||||
       gradientUnits="userSpaceOnUse"
 | 
			
		||||
       id="linearGradient15374"
 | 
			
		||||
       xlink:href="#linearGradient10013-4-63-6"
 | 
			
		||||
       inkscape:collect="always" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       gradientTransform="translate(-1199.9852,216.38048)"
 | 
			
		||||
       y2="-227.07961"
 | 
			
		||||
       x2="1203.9177"
 | 
			
		||||
       y1="-217.56708"
 | 
			
		||||
       x1="1203.9177"
 | 
			
		||||
       gradientUnits="userSpaceOnUse"
 | 
			
		||||
       id="linearGradient15376"
 | 
			
		||||
       xlink:href="#linearGradient10597-5"
 | 
			
		||||
       inkscape:collect="always" />
 | 
			
		||||
  </defs>
 | 
			
		||||
  <sodipodi:namedview
 | 
			
		||||
     id="base"
 | 
			
		||||
     pagecolor="#000000"
 | 
			
		||||
     bordercolor="#2d2d2d"
 | 
			
		||||
     borderopacity="1"
 | 
			
		||||
     inkscape:pageopacity="1"
 | 
			
		||||
     inkscape:pageshadow="2"
 | 
			
		||||
     inkscape:zoom="1"
 | 
			
		||||
     inkscape:cx="64.516955"
 | 
			
		||||
     inkscape:cy="13.871056"
 | 
			
		||||
     inkscape:document-units="px"
 | 
			
		||||
     inkscape:current-layer="layer1"
 | 
			
		||||
     showgrid="false"
 | 
			
		||||
     inkscape:window-width="1412"
 | 
			
		||||
     inkscape:window-height="1067"
 | 
			
		||||
     inkscape:window-x="2635"
 | 
			
		||||
     inkscape:window-y="226"
 | 
			
		||||
     inkscape:window-maximized="0"
 | 
			
		||||
     borderlayer="true"
 | 
			
		||||
     inkscape:showpageshadow="false"
 | 
			
		||||
     inkscape:snap-nodes="false"
 | 
			
		||||
     inkscape:snap-bbox="true"
 | 
			
		||||
     showborder="false">
 | 
			
		||||
    <inkscape:grid
 | 
			
		||||
       type="xygrid"
 | 
			
		||||
       id="grid14843"
 | 
			
		||||
       empspacing="5"
 | 
			
		||||
       visible="true"
 | 
			
		||||
       enabled="true"
 | 
			
		||||
       snapvisiblegridlinesonly="true" />
 | 
			
		||||
  </sodipodi:namedview>
 | 
			
		||||
  <metadata
 | 
			
		||||
     id="metadata3204">
 | 
			
		||||
    <rdf:RDF>
 | 
			
		||||
      <cc:Work
 | 
			
		||||
         rdf:about="">
 | 
			
		||||
        <dc:format>image/svg+xml</dc:format>
 | 
			
		||||
        <dc:type
 | 
			
		||||
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 | 
			
		||||
        <dc:title></dc:title>
 | 
			
		||||
      </cc:Work>
 | 
			
		||||
    </rdf:RDF>
 | 
			
		||||
  </metadata>
 | 
			
		||||
  <g
 | 
			
		||||
     inkscape:label="Layer 1"
 | 
			
		||||
     inkscape:groupmode="layer"
 | 
			
		||||
     id="layer1"
 | 
			
		||||
     transform="translate(-342.5,-521.36218)">
 | 
			
		||||
    <g
 | 
			
		||||
       transform="matrix(0.84337,0,0,0.84337,-110.16632,-503.56182)"
 | 
			
		||||
       id="g14586">
 | 
			
		||||
      <g
 | 
			
		||||
         inkscape:export-ydpi="90"
 | 
			
		||||
         inkscape:export-xdpi="90"
 | 
			
		||||
         inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
 | 
			
		||||
         transform="matrix(1.9969286,0,0,1.9969286,-397.05491,877.00482)"
 | 
			
		||||
         id="g15291-9"
 | 
			
		||||
         style="display:inline;enable-background:new">
 | 
			
		||||
        <g
 | 
			
		||||
           transform="translate(877.50354,-102.83507)"
 | 
			
		||||
           id="g16853-4"
 | 
			
		||||
           style="enable-background:new">
 | 
			
		||||
          <rect
 | 
			
		||||
             transform="scale(1,-1)"
 | 
			
		||||
             style="color:#000000;fill:url(#linearGradient14219);fill-opacity:1;fill-rule:nonzero;stroke:#868686;stroke-width:0.59377144999999998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
 | 
			
		||||
             id="rect6506-6"
 | 
			
		||||
             width="11.281681"
 | 
			
		||||
             height="11.26221"
 | 
			
		||||
             x="-409.59354"
 | 
			
		||||
             y="-284.40115"
 | 
			
		||||
             rx="0.95632279"
 | 
			
		||||
             ry="0.95632273" />
 | 
			
		||||
        </g>
 | 
			
		||||
      </g>
 | 
			
		||||
      <g
 | 
			
		||||
         inkscape:export-ydpi="90"
 | 
			
		||||
         inkscape:export-xdpi="90"
 | 
			
		||||
         inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
 | 
			
		||||
         transform="translate(343.99999,987.99997)"
 | 
			
		||||
         id="g5886"
 | 
			
		||||
         style="display:inline;enable-background:new">
 | 
			
		||||
        <path
 | 
			
		||||
           style="fill:none;stroke:url(#linearGradient5891-0-4);stroke-width:7.11431503;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
 | 
			
		||||
           d="m 198.5,240 5.25,5.25 13.98616,-14.43081"
 | 
			
		||||
           id="path5835"
 | 
			
		||||
           inkscape:path-effect="#path-effect5837-4-6"
 | 
			
		||||
           inkscape:original-d="m 198.5,240 5.25,5.25 13.98616,-14.43081"
 | 
			
		||||
           inkscape:connector-curvature="0"
 | 
			
		||||
           sodipodi:nodetypes="ccc" />
 | 
			
		||||
        <path
 | 
			
		||||
           inkscape:connector-curvature="0"
 | 
			
		||||
           inkscape:original-d="m 198.5,240 5.25,5.25 13.91205,-14.31964"
 | 
			
		||||
           inkscape:path-effect="#path-effect5837-4-6"
 | 
			
		||||
           id="path5880"
 | 
			
		||||
           d="m 198.5,240 5.25,5.25 13.91205,-14.31964"
 | 
			
		||||
           style="fill:none;stroke:#4787c8;stroke-width:3.55715752;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
 | 
			
		||||
           sodipodi:nodetypes="ccc" />
 | 
			
		||||
        <path
 | 
			
		||||
           style="fill:none;stroke:#7ea7d3;stroke-width:1.18571913px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
 | 
			
		||||
           d="m 197.45937,240.47455 c -0.17828,-0.29362 -0.20087,-0.67548 -0.0603,-0.98892 0.14055,-0.31344 0.43739,-0.54812 0.77144,-0.62817 0.33405,-0.08 0.69314,-0.01 0.99635,0.15175 0.30321,0.16144 0.55146,0.40727 0.79165,0.65284 l 3.66429,3.74643 12.87946,-12.98973 c 0.20796,-0.20974 0.42306,-0.41969 0.68548,-0.55522 0.26242,-0.13553 0.57293,-0.19052 0.85827,-0.11426 0.14267,0.0381 0.27708,0.10787 0.38874,0.20452 0.11167,0.0966 0.20021,0.22004 0.25479,0.35726 0.0546,0.13722 0.075,0.28793 0.0585,0.43468 -0.0165,0.14674 -0.07,0.28919 -0.15422,0.41052"
 | 
			
		||||
           id="path5882"
 | 
			
		||||
           inkscape:path-effect="#path-effect5884-4-7"
 | 
			
		||||
           inkscape:original-d="m 197.45937,240.47455 c 0.65604,-0.56057 2.02485,-1.34847 2.49911,-0.8125 l 3.66429,3.74643 12.87946,-12.98973 c 0.6875,-0.6875 2.09152,0.7375 2.09152,0.7375"
 | 
			
		||||
           inkscape:connector-curvature="0"
 | 
			
		||||
           sodipodi:nodetypes="csccc" />
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 8.8 KiB  | 
@@ -1,180 +0,0 @@
 | 
			
		||||
/* Copyright 2011, Red Hat, Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify it
 | 
			
		||||
 * under the terms and conditions of the GNU Lesser General Public License,
 | 
			
		||||
 * version 2.1, as published by the Free Software Foundation.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope it will be useful, but WITHOUT ANY
 | 
			
		||||
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 | 
			
		||||
 * more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software Foundation,
 | 
			
		||||
 * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Login Dialog */
 | 
			
		||||
 | 
			
		||||
.login-dialog-title {
 | 
			
		||||
    font-size: 14pt;
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    color: #666666;
 | 
			
		||||
    padding-bottom: 2em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog {
 | 
			
		||||
    border-radius: 16px;
 | 
			
		||||
    min-height: 150px;
 | 
			
		||||
    max-height: 700px;
 | 
			
		||||
    min-width: 350px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-prompt-fingerprint-message {
 | 
			
		||||
    font-size: 10.5pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-user-list-view {
 | 
			
		||||
    -st-vfade-offset: 1em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-user-list {
 | 
			
		||||
    spacing: 12px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-user-list-item {
 | 
			
		||||
    color: #666666;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-user-list-item:ltr {
 | 
			
		||||
    padding-right: 1em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-user-list-item:rtl {
 | 
			
		||||
    padding-left: 1em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-user-list-item .login-dialog-user-list-item-name {
 | 
			
		||||
    font-size: 20pt;
 | 
			
		||||
    padding-left: 1em;
 | 
			
		||||
    color: #666666;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-user-list-item:hover .login-dialog-user-list-item-name {
 | 
			
		||||
    color: white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-user-list-item:focus .login-dialog-user-list-item-name {
 | 
			
		||||
    color: white;
 | 
			
		||||
    text-shadow: black 0px 2px 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-user-list-item-vertical-layout {
 | 
			
		||||
    spacing: 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-user-list-item .login-dialog-user-list-item-focus-bin {
 | 
			
		||||
    background-color: rgba(0,0,0,0.0);
 | 
			
		||||
    height: 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-user-list-item:focus .login-dialog-user-list-item-focus-bin {
 | 
			
		||||
    background-color: #666666;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-user-list-item-icon {
 | 
			
		||||
    border: 2px solid #8b8b8b;
 | 
			
		||||
    border-radius: 8px;
 | 
			
		||||
    width: 64px;
 | 
			
		||||
    height: 64px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-not-listed-button {
 | 
			
		||||
    padding-top: 2em;
 | 
			
		||||
}
 | 
			
		||||
.login-dialog-not-listed-label {
 | 
			
		||||
    font-size: 14pt;
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    color: #666666;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-not-listed-button:hover .login-dialog-not-listed-label {
 | 
			
		||||
    color: white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-prompt-layout {
 | 
			
		||||
    padding-bottom: 32px;
 | 
			
		||||
}
 | 
			
		||||
.login-dialog-prompt-label {
 | 
			
		||||
    color: white;
 | 
			
		||||
    font-size: 20pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-prompt-entry {
 | 
			
		||||
    padding: 4px;
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
    border: 2px solid #5656cc;
 | 
			
		||||
    color: black;
 | 
			
		||||
    background-color: white;
 | 
			
		||||
    caret-color: black;
 | 
			
		||||
    caret-size: 1px;
 | 
			
		||||
    width: 15em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-prompt-entry .capslock-warning {
 | 
			
		||||
    icon-size: 16px;
 | 
			
		||||
    warning-color: #999;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-prompt-entry:insensitive {
 | 
			
		||||
    color: rgba(0,0,0,0.7);
 | 
			
		||||
    border: 2px solid #565656;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-session-list {
 | 
			
		||||
    color: #ffffff;
 | 
			
		||||
    font-size: 10.5pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-session-list-button {
 | 
			
		||||
    padding: 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-session-list-button:focus {
 | 
			
		||||
    background-color: #4c4c4c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-session-list-button:active {
 | 
			
		||||
    background-color: #4c4c4c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-session-list-button:hover {
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-session-list-scroll-view {
 | 
			
		||||
    background-gradient-start: rgba(80,80,80,0.3);
 | 
			
		||||
    background-gradient-end: rgba(80,80,80,0.7);
 | 
			
		||||
    background-gradient-direction: vertical;
 | 
			
		||||
    box-shadow: inset 0px 2px 4px rgba(0,0,0,0.9);
 | 
			
		||||
    border-radius: 8px;
 | 
			
		||||
    border: 1px solid rgba(80,80,80,1.0);
 | 
			
		||||
    padding: .5em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-session-list-item:focus {
 | 
			
		||||
    background-color: #666666;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-session-list-triangle {
 | 
			
		||||
    padding-right: .5em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-session-list-item-box {
 | 
			
		||||
    spacing: .25em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-session-list-item-dot {
 | 
			
		||||
    width: .75em;
 | 
			
		||||
    height: .75em;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										113
									
								
								data/theme/mosaic-view-active.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,113 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
   xmlns:dc="http://purl.org/dc/elements/1.1/"
 | 
			
		||||
   xmlns:cc="http://creativecommons.org/ns#"
 | 
			
		||||
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 | 
			
		||||
   xmlns:svg="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   width="24"
 | 
			
		||||
   height="16"
 | 
			
		||||
   id="svg6503"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
   inkscape:version="0.47pre4 r22446"
 | 
			
		||||
   sodipodi:docname="mosaic-view-active.svg">
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs6505">
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       sodipodi:type="inkscape:persp3d"
 | 
			
		||||
       inkscape:vp_x="0 : 16 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_z="32 : 16 : 1"
 | 
			
		||||
       inkscape:persp3d-origin="16 : 10.666667 : 1"
 | 
			
		||||
       id="perspective6511" />
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       id="perspective6494"
 | 
			
		||||
       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
 | 
			
		||||
       inkscape:vp_z="1 : 0.5 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_x="0 : 0.5 : 1"
 | 
			
		||||
       sodipodi:type="inkscape:persp3d" />
 | 
			
		||||
  </defs>
 | 
			
		||||
  <sodipodi:namedview
 | 
			
		||||
     id="base"
 | 
			
		||||
     pagecolor="#ffffff"
 | 
			
		||||
     bordercolor="#666666"
 | 
			
		||||
     borderopacity="1.0"
 | 
			
		||||
     inkscape:pageopacity="0.0"
 | 
			
		||||
     inkscape:pageshadow="2"
 | 
			
		||||
     inkscape:zoom="11.197802"
 | 
			
		||||
     inkscape:cx="-15.97056"
 | 
			
		||||
     inkscape:cy="16"
 | 
			
		||||
     inkscape:current-layer="layer1"
 | 
			
		||||
     showgrid="true"
 | 
			
		||||
     inkscape:grid-bbox="true"
 | 
			
		||||
     inkscape:document-units="px"
 | 
			
		||||
     inkscape:window-width="1680"
 | 
			
		||||
     inkscape:window-height="997"
 | 
			
		||||
     inkscape:window-x="0"
 | 
			
		||||
     inkscape:window-y="26"
 | 
			
		||||
     inkscape:window-maximized="1" />
 | 
			
		||||
  <metadata
 | 
			
		||||
     id="metadata6508">
 | 
			
		||||
    <rdf:RDF>
 | 
			
		||||
      <cc:Work
 | 
			
		||||
         rdf:about="">
 | 
			
		||||
        <dc:format>image/svg+xml</dc:format>
 | 
			
		||||
        <dc:type
 | 
			
		||||
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 | 
			
		||||
        <dc:title />
 | 
			
		||||
      </cc:Work>
 | 
			
		||||
    </rdf:RDF>
 | 
			
		||||
  </metadata>
 | 
			
		||||
  <g
 | 
			
		||||
     id="layer1"
 | 
			
		||||
     inkscape:label="Layer 1"
 | 
			
		||||
     inkscape:groupmode="layer"
 | 
			
		||||
     transform="translate(0,-16)">
 | 
			
		||||
    <g
 | 
			
		||||
       style="display:inline;fill:#cbcbcb;fill-opacity:1"
 | 
			
		||||
       transform="translate(-449.85476,-685.85869)"
 | 
			
		||||
       id="g5306">
 | 
			
		||||
      <rect
 | 
			
		||||
         style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999970000000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none"
 | 
			
		||||
         id="rect5308"
 | 
			
		||||
         width="11"
 | 
			
		||||
         height="7"
 | 
			
		||||
         x="450.5"
 | 
			
		||||
         y="710.5"
 | 
			
		||||
         rx="0.99999958"
 | 
			
		||||
         ry="1" />
 | 
			
		||||
      <rect
 | 
			
		||||
         style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999970000000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none;display:inline"
 | 
			
		||||
         id="rect5310"
 | 
			
		||||
         width="11"
 | 
			
		||||
         height="7"
 | 
			
		||||
         x="462.5"
 | 
			
		||||
         y="702.5"
 | 
			
		||||
         rx="0.99999958"
 | 
			
		||||
         ry="1" />
 | 
			
		||||
      <rect
 | 
			
		||||
         style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999976000000002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none;display:inline"
 | 
			
		||||
         id="rect5312"
 | 
			
		||||
         width="11"
 | 
			
		||||
         height="7"
 | 
			
		||||
         x="450.5"
 | 
			
		||||
         y="702.5"
 | 
			
		||||
         rx="0.99999958"
 | 
			
		||||
         ry="1" />
 | 
			
		||||
      <rect
 | 
			
		||||
         style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999970000000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none;display:inline"
 | 
			
		||||
         id="rect5314"
 | 
			
		||||
         width="11"
 | 
			
		||||
         height="7"
 | 
			
		||||
         x="462.5"
 | 
			
		||||
         y="710.5"
 | 
			
		||||
         rx="0.99999958"
 | 
			
		||||
         ry="1" />
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 3.7 KiB  | 
							
								
								
									
										113
									
								
								data/theme/mosaic-view.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,113 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
   xmlns:dc="http://purl.org/dc/elements/1.1/"
 | 
			
		||||
   xmlns:cc="http://creativecommons.org/ns#"
 | 
			
		||||
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 | 
			
		||||
   xmlns:svg="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   width="24"
 | 
			
		||||
   height="16"
 | 
			
		||||
   id="svg6503"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
   inkscape:version="0.47pre4 r22446"
 | 
			
		||||
   sodipodi:docname="New document 19">
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs6505">
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       sodipodi:type="inkscape:persp3d"
 | 
			
		||||
       inkscape:vp_x="0 : 16 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_z="32 : 16 : 1"
 | 
			
		||||
       inkscape:persp3d-origin="16 : 10.666667 : 1"
 | 
			
		||||
       id="perspective6511" />
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       id="perspective6494"
 | 
			
		||||
       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
 | 
			
		||||
       inkscape:vp_z="1 : 0.5 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_x="0 : 0.5 : 1"
 | 
			
		||||
       sodipodi:type="inkscape:persp3d" />
 | 
			
		||||
  </defs>
 | 
			
		||||
  <sodipodi:namedview
 | 
			
		||||
     id="base"
 | 
			
		||||
     pagecolor="#ffffff"
 | 
			
		||||
     bordercolor="#666666"
 | 
			
		||||
     borderopacity="1.0"
 | 
			
		||||
     inkscape:pageopacity="0.0"
 | 
			
		||||
     inkscape:pageshadow="2"
 | 
			
		||||
     inkscape:zoom="11.197802"
 | 
			
		||||
     inkscape:cx="16"
 | 
			
		||||
     inkscape:cy="16"
 | 
			
		||||
     inkscape:current-layer="layer1"
 | 
			
		||||
     showgrid="true"
 | 
			
		||||
     inkscape:grid-bbox="true"
 | 
			
		||||
     inkscape:document-units="px"
 | 
			
		||||
     inkscape:window-width="1680"
 | 
			
		||||
     inkscape:window-height="997"
 | 
			
		||||
     inkscape:window-x="0"
 | 
			
		||||
     inkscape:window-y="26"
 | 
			
		||||
     inkscape:window-maximized="1" />
 | 
			
		||||
  <metadata
 | 
			
		||||
     id="metadata6508">
 | 
			
		||||
    <rdf:RDF>
 | 
			
		||||
      <cc:Work
 | 
			
		||||
         rdf:about="">
 | 
			
		||||
        <dc:format>image/svg+xml</dc:format>
 | 
			
		||||
        <dc:type
 | 
			
		||||
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 | 
			
		||||
        <dc:title></dc:title>
 | 
			
		||||
      </cc:Work>
 | 
			
		||||
    </rdf:RDF>
 | 
			
		||||
  </metadata>
 | 
			
		||||
  <g
 | 
			
		||||
     id="layer1"
 | 
			
		||||
     inkscape:label="Layer 1"
 | 
			
		||||
     inkscape:groupmode="layer"
 | 
			
		||||
     transform="translate(0,-16)">
 | 
			
		||||
    <g
 | 
			
		||||
       style="display:inline"
 | 
			
		||||
       transform="translate(-449.85476,-685.85869)"
 | 
			
		||||
       id="g5306">
 | 
			
		||||
      <rect
 | 
			
		||||
         style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.9999997;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none"
 | 
			
		||||
         id="rect5308"
 | 
			
		||||
         width="11"
 | 
			
		||||
         height="7"
 | 
			
		||||
         x="450.5"
 | 
			
		||||
         y="710.5"
 | 
			
		||||
         rx="0.99999958"
 | 
			
		||||
         ry="1" />
 | 
			
		||||
      <rect
 | 
			
		||||
         style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.9999997;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none;display:inline"
 | 
			
		||||
         id="rect5310"
 | 
			
		||||
         width="11"
 | 
			
		||||
         height="7"
 | 
			
		||||
         x="462.5"
 | 
			
		||||
         y="702.5"
 | 
			
		||||
         rx="0.99999958"
 | 
			
		||||
         ry="1" />
 | 
			
		||||
      <rect
 | 
			
		||||
         style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.99999976;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none;display:inline"
 | 
			
		||||
         id="rect5312"
 | 
			
		||||
         width="11"
 | 
			
		||||
         height="7"
 | 
			
		||||
         x="450.5"
 | 
			
		||||
         y="702.5"
 | 
			
		||||
         rx="0.99999958"
 | 
			
		||||
         ry="1" />
 | 
			
		||||
      <rect
 | 
			
		||||
         style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.9999997;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none;display:inline"
 | 
			
		||||
         id="rect5314"
 | 
			
		||||
         width="11"
 | 
			
		||||
         height="7"
 | 
			
		||||
         x="462.5"
 | 
			
		||||
         y="710.5"
 | 
			
		||||
         rx="0.99999958"
 | 
			
		||||
         ry="1" />
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 3.6 KiB  | 
							
								
								
									
										89
									
								
								data/theme/move-window-on-new.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,89 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
   xmlns:dc="http://purl.org/dc/elements/1.1/"
 | 
			
		||||
   xmlns:cc="http://creativecommons.org/ns#"
 | 
			
		||||
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 | 
			
		||||
   xmlns:svg="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   width="98"
 | 
			
		||||
   height="98"
 | 
			
		||||
   id="svg6375"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
   inkscape:version="0.47 r22583"
 | 
			
		||||
   sodipodi:docname="add-workspace.svg">
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs6377">
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       sodipodi:type="inkscape:persp3d"
 | 
			
		||||
       inkscape:vp_x="0 : 16 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_z="32 : 16 : 1"
 | 
			
		||||
       inkscape:persp3d-origin="16 : 10.666667 : 1"
 | 
			
		||||
       id="perspective6383" />
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       id="perspective6366"
 | 
			
		||||
       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
 | 
			
		||||
       inkscape:vp_z="1 : 0.5 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_x="0 : 0.5 : 1"
 | 
			
		||||
       sodipodi:type="inkscape:persp3d" />
 | 
			
		||||
  </defs>
 | 
			
		||||
  <sodipodi:namedview
 | 
			
		||||
     id="base"
 | 
			
		||||
     pagecolor="#ffffff"
 | 
			
		||||
     bordercolor="#666666"
 | 
			
		||||
     borderopacity="1.0"
 | 
			
		||||
     inkscape:pageopacity="0.0"
 | 
			
		||||
     inkscape:pageshadow="2"
 | 
			
		||||
     inkscape:zoom="3.9590209"
 | 
			
		||||
     inkscape:cx="56.650687"
 | 
			
		||||
     inkscape:cy="20.635343"
 | 
			
		||||
     inkscape:current-layer="layer1"
 | 
			
		||||
     showgrid="true"
 | 
			
		||||
     inkscape:grid-bbox="true"
 | 
			
		||||
     inkscape:document-units="px"
 | 
			
		||||
     inkscape:window-width="1680"
 | 
			
		||||
     inkscape:window-height="997"
 | 
			
		||||
     inkscape:window-x="0"
 | 
			
		||||
     inkscape:window-y="26"
 | 
			
		||||
     inkscape:window-maximized="1" />
 | 
			
		||||
  <metadata
 | 
			
		||||
     id="metadata6380">
 | 
			
		||||
    <rdf:RDF>
 | 
			
		||||
      <cc:Work
 | 
			
		||||
         rdf:about="">
 | 
			
		||||
        <dc:format>image/svg+xml</dc:format>
 | 
			
		||||
        <dc:type
 | 
			
		||||
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 | 
			
		||||
        <dc:title></dc:title>
 | 
			
		||||
      </cc:Work>
 | 
			
		||||
    </rdf:RDF>
 | 
			
		||||
  </metadata>
 | 
			
		||||
  <g
 | 
			
		||||
     id="layer1"
 | 
			
		||||
     inkscape:label="Layer 1"
 | 
			
		||||
     inkscape:groupmode="layer"
 | 
			
		||||
     transform="translate(0,66)">
 | 
			
		||||
    <g
 | 
			
		||||
       id="g2824"
 | 
			
		||||
       transform="matrix(11.568551,0,0,11.698271,-78.828159,-304.81518)">
 | 
			
		||||
      <path
 | 
			
		||||
         style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
 | 
			
		||||
         d="m 11.07363,21.36834 0,6.43903"
 | 
			
		||||
         id="path5322" />
 | 
			
		||||
      <path
 | 
			
		||||
         style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
 | 
			
		||||
         d="m 14.29314,24.58786 -6.43902,0"
 | 
			
		||||
         id="path5324" />
 | 
			
		||||
    </g>
 | 
			
		||||
    <path
 | 
			
		||||
       style="fill:#000000;fill-opacity:0.98823529"
 | 
			
		||||
       d="m 48.239516,97.908047 c -0.41677,-0.05102 -1.269253,-0.222408 -1.894408,-0.380859 -4.088493,-1.036262 -7.520781,-4.753234 -8.330163,-9.021094 -0.154947,-0.817026 -0.257819,-6.68112 -0.257819,-14.696556 l 0,-13.337088 -13.829177,-0.08909 C 10.802042,60.298796 10.026884,60.268266 8.6851548,59.783022 3.6288503,57.954375 0.62673331,53.828648 0.62673331,48.708554 c 0,-5.625522 4.25936019,-10.425065 9.97721469,-11.242548 0.987903,-0.141242 7.368912,-0.254994 14.460646,-0.257791 l 12.692532,-0.005 0,-13.586668 c 0,-14.6441583 0.03287,-15.0698926 1.364686,-17.6753047 2.185477,-4.2754229 6.938193,-6.75739913 11.687647,-6.10355607 3.382776,0.46569661 6.737962,2.72496967 8.414081,5.66577137 1.480816,2.5981315 1.519067,3.0522448 1.519067,18.0333334 l 0,13.666424 12.692533,0.005 c 7.091733,0.0028 13.472742,0.116549 14.460646,0.257791 6.395303,0.914337 10.804785,6.623716 9.941157,12.871766 -0.698243,5.051565 -4.792685,9.104635 -9.941157,9.840713 -0.987904,0.141242 -7.368913,0.254995 -14.460646,0.257791 l -12.692533,0.005 0,13.801945 c 0,13.031417 -0.02798,13.895893 -0.501177,15.484801 -1.526902,5.127058 -6.919246,8.802262 -12.001914,8.18002 z"
 | 
			
		||||
       id="path2828"
 | 
			
		||||
       transform="translate(0,-66)" />
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 4.0 KiB  | 
							
								
								
									
										33
									
								
								data/theme/panel-border.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,33 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
   xmlns:svg="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   width="3"
 | 
			
		||||
   height="10"
 | 
			
		||||
   id="svg2"
 | 
			
		||||
   version="1.1">
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs4" />
 | 
			
		||||
  <metadata
 | 
			
		||||
     id="metadata7">
 | 
			
		||||
  </metadata>
 | 
			
		||||
  <g
 | 
			
		||||
     id="layer1">
 | 
			
		||||
    <rect
 | 
			
		||||
       style="fill:#000000;fill-opacity:1;stroke-width:0.43599999000000000;stroke-miterlimit:4;stroke-dasharray:none"
 | 
			
		||||
       id="rect3779"
 | 
			
		||||
       width="3"
 | 
			
		||||
       height="10"
 | 
			
		||||
       x="0"
 | 
			
		||||
       y="0" />
 | 
			
		||||
    <rect
 | 
			
		||||
       style="fill:#536272;fill-opacity:1;stroke-width:0.43599999;stroke-miterlimit:4;stroke-dasharray:none"
 | 
			
		||||
       id="rect3796"
 | 
			
		||||
       width="3"
 | 
			
		||||
       height="1"
 | 
			
		||||
       x="0"
 | 
			
		||||
       y="9" />
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 787 B  | 
@@ -9,7 +9,7 @@
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   width="17"
 | 
			
		||||
   width="21"
 | 
			
		||||
   height="10"
 | 
			
		||||
   id="svg2"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
@@ -66,9 +66,9 @@
 | 
			
		||||
    <rect
 | 
			
		||||
       style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke-width:0.43599999;stroke-miterlimit:4;stroke-dasharray:none"
 | 
			
		||||
       id="rect3796"
 | 
			
		||||
       width="7"
 | 
			
		||||
       width="3"
 | 
			
		||||
       height="2"
 | 
			
		||||
       x="5"
 | 
			
		||||
       x="9"
 | 
			
		||||
       y="8" />
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
 
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB  | 
@@ -2,62 +2,24 @@
 | 
			
		||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
   xmlns:dc="http://purl.org/dc/elements/1.1/"
 | 
			
		||||
   xmlns:cc="http://creativecommons.org/ns#"
 | 
			
		||||
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 | 
			
		||||
   xmlns:svg="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:xlink="http://www.w3.org/1999/xlink"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   width="119.97824"
 | 
			
		||||
   height="119.97824"
 | 
			
		||||
   id="svg7355"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
   inkscape:version="0.48.1 r9760"
 | 
			
		||||
   sodipodi:docname="running-indicator.svg">
 | 
			
		||||
  <metadata
 | 
			
		||||
     id="metadata4175">
 | 
			
		||||
    <rdf:RDF>
 | 
			
		||||
      <cc:Work
 | 
			
		||||
         rdf:about="">
 | 
			
		||||
        <dc:format>image/svg+xml</dc:format>
 | 
			
		||||
        <dc:type
 | 
			
		||||
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 | 
			
		||||
      </cc:Work>
 | 
			
		||||
    </rdf:RDF>
 | 
			
		||||
  </metadata>
 | 
			
		||||
  <sodipodi:namedview
 | 
			
		||||
     pagecolor="#2c1cff"
 | 
			
		||||
     bordercolor="#666666"
 | 
			
		||||
     borderopacity="1"
 | 
			
		||||
     objecttolerance="10"
 | 
			
		||||
     gridtolerance="10"
 | 
			
		||||
     guidetolerance="10"
 | 
			
		||||
     inkscape:pageopacity="1"
 | 
			
		||||
     inkscape:pageshadow="2"
 | 
			
		||||
     inkscape:window-width="1920"
 | 
			
		||||
     inkscape:window-height="1141"
 | 
			
		||||
     id="namedview4173"
 | 
			
		||||
     showgrid="false"
 | 
			
		||||
     inkscape:zoom="8.1348081"
 | 
			
		||||
     inkscape:cx="81.120662"
 | 
			
		||||
     inkscape:cy="58.117986"
 | 
			
		||||
     inkscape:window-x="0"
 | 
			
		||||
     inkscape:window-y="26"
 | 
			
		||||
     inkscape:window-maximized="1"
 | 
			
		||||
     inkscape:current-layer="g30864" />
 | 
			
		||||
   version="1.1">
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs7357">
 | 
			
		||||
    <radialGradient
 | 
			
		||||
       xlink:href="#linearGradient36429"
 | 
			
		||||
       id="radialGradient7461"
 | 
			
		||||
       gradientUnits="userSpaceOnUse"
 | 
			
		||||
       gradientTransform="matrix(1.011539,0,0,0.57582113,-0.39262194,71.83807)"
 | 
			
		||||
       cx="47.428951"
 | 
			
		||||
       cy="167.16817"
 | 
			
		||||
       fx="47.428951"
 | 
			
		||||
       fy="167.16817"
 | 
			
		||||
       gradientTransform="matrix(1.0525552,0,0,1.0525552,-2.5162753,-9.0000838)"
 | 
			
		||||
       cx="47.878681"
 | 
			
		||||
       cy="171.25"
 | 
			
		||||
       fx="47.878681"
 | 
			
		||||
       fy="171.25"
 | 
			
		||||
       r="37" />
 | 
			
		||||
    <linearGradient
 | 
			
		||||
       id="linearGradient36429">
 | 
			
		||||
@@ -97,7 +59,7 @@
 | 
			
		||||
       fx="49.067139"
 | 
			
		||||
       cy="242.50381"
 | 
			
		||||
       cx="49.067139"
 | 
			
		||||
       gradientTransform="matrix(1.1891549,0,0,0.15252127,-9.281289,132.52772)"
 | 
			
		||||
       gradientTransform="matrix(1.1891549,0,0,0.55513246,-9.281289,36.12653)"
 | 
			
		||||
       gradientUnits="userSpaceOnUse"
 | 
			
		||||
       id="radialGradient7488"
 | 
			
		||||
       xlink:href="#linearGradient36471" />
 | 
			
		||||
@@ -110,21 +72,19 @@
 | 
			
		||||
       id="g30864"
 | 
			
		||||
       transform="translate(255.223,70.118091)">
 | 
			
		||||
      <rect
 | 
			
		||||
         ry="3.4593496"
 | 
			
		||||
         rx="3.4593496"
 | 
			
		||||
         y="99.596962"
 | 
			
		||||
         x="12.596948"
 | 
			
		||||
         height="71.116341"
 | 
			
		||||
         width="71.116341"
 | 
			
		||||
         ry="3.5996203"
 | 
			
		||||
         rx="3.5996203"
 | 
			
		||||
         y="98"
 | 
			
		||||
         x="11"
 | 
			
		||||
         height="74"
 | 
			
		||||
         width="74"
 | 
			
		||||
         id="rect14000"
 | 
			
		||||
         style="opacity:0.37187500000000001;fill:url(#radialGradient7461);fill-opacity:1;stroke:none" />
 | 
			
		||||
         style="opacity:0.371875;fill:url(#radialGradient7461);fill-opacity:1;stroke:none" />
 | 
			
		||||
      <path
 | 
			
		||||
         id="rect34520"
 | 
			
		||||
         d="m 83.273151,166.72152 c 0,1.96759 -1.584022,3.55163 -3.551629,3.55163 l -63.443032,0 c -1.967608,0 -3.551648,-1.58402 -3.551643,-3.55164 0,-5.85318 0,-5.85318 0,0"
 | 
			
		||||
         style="opacity:0.35;fill:none;stroke:url(#radialGradient7488);stroke-width:1;stroke-opacity:1"
 | 
			
		||||
         connector-curvature="0"
 | 
			
		||||
         inkscape:connector-curvature="0"
 | 
			
		||||
         sodipodi:nodetypes="ccscc" />
 | 
			
		||||
         d="m 84.506708,167.95508 c 6e-6,1.96759 -1.584022,3.55162 -3.551629,3.55163 l -65.910146,0 c -1.967608,-1e-5 -3.551648,-1.58402 -3.551643,-3.55164"
 | 
			
		||||
         style="opacity:0.2;fill:none;stroke:url(#radialGradient7488);stroke-width:1;stroke-opacity:1"
 | 
			
		||||
         inkscape:connector-curvature="0" />
 | 
			
		||||
    </g>
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
 
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 2.7 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								data/theme/scroll-button-down-hover.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 225 B  | 
							
								
								
									
										
											BIN
										
									
								
								data/theme/scroll-button-down.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 225 B  | 
							
								
								
									
										
											BIN
										
									
								
								data/theme/scroll-button-up-hover.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 211 B  | 
							
								
								
									
										
											BIN
										
									
								
								data/theme/scroll-button-up.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 211 B  | 
							
								
								
									
										87
									
								
								data/theme/section-more-open.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,87 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
   xmlns:dc="http://purl.org/dc/elements/1.1/"
 | 
			
		||||
   xmlns:cc="http://creativecommons.org/ns#"
 | 
			
		||||
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 | 
			
		||||
   xmlns:svg="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   width="5.8600588"
 | 
			
		||||
   height="9"
 | 
			
		||||
   id="svg3647"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
   inkscape:version="0.47 r22583"
 | 
			
		||||
   sodipodi:docname="section-more.svg">
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs3649">
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       sodipodi:type="inkscape:persp3d"
 | 
			
		||||
       inkscape:vp_x="0 : 526.18109 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_z="744.09448 : 526.18109 : 1"
 | 
			
		||||
       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
 | 
			
		||||
       id="perspective3655" />
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       id="perspective3603"
 | 
			
		||||
       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
 | 
			
		||||
       inkscape:vp_z="1 : 0.5 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_x="0 : 0.5 : 1"
 | 
			
		||||
       sodipodi:type="inkscape:persp3d" />
 | 
			
		||||
  </defs>
 | 
			
		||||
  <sodipodi:namedview
 | 
			
		||||
     id="base"
 | 
			
		||||
     pagecolor="#ffffff"
 | 
			
		||||
     bordercolor="#666666"
 | 
			
		||||
     borderopacity="1.0"
 | 
			
		||||
     inkscape:pageopacity="0.0"
 | 
			
		||||
     inkscape:pageshadow="2"
 | 
			
		||||
     inkscape:zoom="82.777778"
 | 
			
		||||
     inkscape:cx="2.9300294"
 | 
			
		||||
     inkscape:cy="5.466443"
 | 
			
		||||
     inkscape:document-units="px"
 | 
			
		||||
     inkscape:current-layer="layer1"
 | 
			
		||||
     showgrid="false"
 | 
			
		||||
     inkscape:window-width="1680"
 | 
			
		||||
     inkscape:window-height="997"
 | 
			
		||||
     inkscape:window-x="0"
 | 
			
		||||
     inkscape:window-y="26"
 | 
			
		||||
     inkscape:window-maximized="1" />
 | 
			
		||||
  <metadata
 | 
			
		||||
     id="metadata3652">
 | 
			
		||||
    <rdf:RDF>
 | 
			
		||||
      <cc:Work
 | 
			
		||||
         rdf:about="">
 | 
			
		||||
        <dc:format>image/svg+xml</dc:format>
 | 
			
		||||
        <dc:type
 | 
			
		||||
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 | 
			
		||||
        <dc:title></dc:title>
 | 
			
		||||
      </cc:Work>
 | 
			
		||||
    </rdf:RDF>
 | 
			
		||||
  </metadata>
 | 
			
		||||
  <g
 | 
			
		||||
     inkscape:label="Layer 1"
 | 
			
		||||
     inkscape:groupmode="layer"
 | 
			
		||||
     id="layer1"
 | 
			
		||||
     transform="translate(-262.78425,-490.71933)">
 | 
			
		||||
    <path
 | 
			
		||||
       transform="matrix(0,-0.98149546,0.71467449,0,25.404986,578.15569)"
 | 
			
		||||
       d="M 88.830127,340 80.169873,340 84.5,332.5 88.830127,340 z"
 | 
			
		||||
       inkscape:randomized="0"
 | 
			
		||||
       inkscape:rounded="0"
 | 
			
		||||
       inkscape:flatsided="true"
 | 
			
		||||
       sodipodi:arg2="1.5707963"
 | 
			
		||||
       sodipodi:arg1="0.52359878"
 | 
			
		||||
       sodipodi:r2="2.5"
 | 
			
		||||
       sodipodi:r1="5"
 | 
			
		||||
       sodipodi:cy="337.5"
 | 
			
		||||
       sodipodi:cx="84.5"
 | 
			
		||||
       sodipodi:sides="3"
 | 
			
		||||
       id="path5497-5"
 | 
			
		||||
       style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.59699643;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
 | 
			
		||||
       sodipodi:type="star" />
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 2.8 KiB  | 
							
								
								
									
										87
									
								
								data/theme/section-more.svg
									
									
									
									
									
										Executable file
									
								
							
							
						
						@@ -0,0 +1,87 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
   xmlns:dc="http://purl.org/dc/elements/1.1/"
 | 
			
		||||
   xmlns:cc="http://creativecommons.org/ns#"
 | 
			
		||||
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 | 
			
		||||
   xmlns:svg="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   width="5.8600588"
 | 
			
		||||
   height="9"
 | 
			
		||||
   id="svg3647"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
   inkscape:version="0.46+devel"
 | 
			
		||||
   sodipodi:docname="New document 6">
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs3649">
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       sodipodi:type="inkscape:persp3d"
 | 
			
		||||
       inkscape:vp_x="0 : 526.18109 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_z="744.09448 : 526.18109 : 1"
 | 
			
		||||
       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
 | 
			
		||||
       id="perspective3655" />
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       id="perspective3603"
 | 
			
		||||
       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
 | 
			
		||||
       inkscape:vp_z="1 : 0.5 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_x="0 : 0.5 : 1"
 | 
			
		||||
       sodipodi:type="inkscape:persp3d" />
 | 
			
		||||
  </defs>
 | 
			
		||||
  <sodipodi:namedview
 | 
			
		||||
     id="base"
 | 
			
		||||
     pagecolor="#ffffff"
 | 
			
		||||
     bordercolor="#666666"
 | 
			
		||||
     borderopacity="1.0"
 | 
			
		||||
     inkscape:pageopacity="0.0"
 | 
			
		||||
     inkscape:pageshadow="2"
 | 
			
		||||
     inkscape:zoom="0.35"
 | 
			
		||||
     inkscape:cx="112.21575"
 | 
			
		||||
     inkscape:cy="-32.642856"
 | 
			
		||||
     inkscape:document-units="px"
 | 
			
		||||
     inkscape:current-layer="layer1"
 | 
			
		||||
     showgrid="false"
 | 
			
		||||
     inkscape:window-width="609"
 | 
			
		||||
     inkscape:window-height="501"
 | 
			
		||||
     inkscape:window-x="164"
 | 
			
		||||
     inkscape:window-y="26"
 | 
			
		||||
     inkscape:window-maximized="0" />
 | 
			
		||||
  <metadata
 | 
			
		||||
     id="metadata3652">
 | 
			
		||||
    <rdf:RDF>
 | 
			
		||||
      <cc:Work
 | 
			
		||||
         rdf:about="">
 | 
			
		||||
        <dc:format>image/svg+xml</dc:format>
 | 
			
		||||
        <dc:type
 | 
			
		||||
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 | 
			
		||||
        <dc:title></dc:title>
 | 
			
		||||
      </cc:Work>
 | 
			
		||||
    </rdf:RDF>
 | 
			
		||||
  </metadata>
 | 
			
		||||
  <g
 | 
			
		||||
     inkscape:label="Layer 1"
 | 
			
		||||
     inkscape:groupmode="layer"
 | 
			
		||||
     id="layer1"
 | 
			
		||||
     transform="translate(-262.78425,-490.71933)">
 | 
			
		||||
    <path
 | 
			
		||||
       transform="matrix(0,0.98149546,-0.71467449,0,506.02358,412.28296)"
 | 
			
		||||
       d="M 88.830127,340 80.169873,340 84.5,332.5 88.830127,340 z"
 | 
			
		||||
       inkscape:randomized="0"
 | 
			
		||||
       inkscape:rounded="0"
 | 
			
		||||
       inkscape:flatsided="true"
 | 
			
		||||
       sodipodi:arg2="1.5707963"
 | 
			
		||||
       sodipodi:arg1="0.52359878"
 | 
			
		||||
       sodipodi:r2="2.5"
 | 
			
		||||
       sodipodi:r1="5"
 | 
			
		||||
       sodipodi:cy="337.5"
 | 
			
		||||
       sodipodi:cx="84.5"
 | 
			
		||||
       sodipodi:sides="3"
 | 
			
		||||
       id="path5497-5"
 | 
			
		||||
       style="fill:#5f5f5f;fill-opacity:1;stroke:#5f5f5f;stroke-width:0.59699643;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
 | 
			
		||||
       sodipodi:type="star" />
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 2.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								data/theme/separator-white.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 531 B  | 
							
								
								
									
										81
									
								
								data/theme/single-view-active.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,81 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
   xmlns:dc="http://purl.org/dc/elements/1.1/"
 | 
			
		||||
   xmlns:cc="http://creativecommons.org/ns#"
 | 
			
		||||
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 | 
			
		||||
   xmlns:svg="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   width="24"
 | 
			
		||||
   height="16"
 | 
			
		||||
   id="svg6446"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
   inkscape:version="0.47pre4 r22446"
 | 
			
		||||
   sodipodi:docname="single-view-active.svg">
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs6448">
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       sodipodi:type="inkscape:persp3d"
 | 
			
		||||
       inkscape:vp_x="0 : 16 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_z="32 : 16 : 1"
 | 
			
		||||
       inkscape:persp3d-origin="16 : 10.666667 : 1"
 | 
			
		||||
       id="perspective6454" />
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       id="perspective6441"
 | 
			
		||||
       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
 | 
			
		||||
       inkscape:vp_z="1 : 0.5 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_x="0 : 0.5 : 1"
 | 
			
		||||
       sodipodi:type="inkscape:persp3d" />
 | 
			
		||||
  </defs>
 | 
			
		||||
  <sodipodi:namedview
 | 
			
		||||
     id="base"
 | 
			
		||||
     pagecolor="#ffffff"
 | 
			
		||||
     bordercolor="#666666"
 | 
			
		||||
     borderopacity="1.0"
 | 
			
		||||
     inkscape:pageopacity="0.0"
 | 
			
		||||
     inkscape:pageshadow="2"
 | 
			
		||||
     inkscape:zoom="11.197802"
 | 
			
		||||
     inkscape:cx="0.014720032"
 | 
			
		||||
     inkscape:cy="16"
 | 
			
		||||
     inkscape:current-layer="layer1"
 | 
			
		||||
     showgrid="true"
 | 
			
		||||
     inkscape:grid-bbox="true"
 | 
			
		||||
     inkscape:document-units="px"
 | 
			
		||||
     inkscape:window-width="1680"
 | 
			
		||||
     inkscape:window-height="997"
 | 
			
		||||
     inkscape:window-x="0"
 | 
			
		||||
     inkscape:window-y="26"
 | 
			
		||||
     inkscape:window-maximized="1" />
 | 
			
		||||
  <metadata
 | 
			
		||||
     id="metadata6451">
 | 
			
		||||
    <rdf:RDF>
 | 
			
		||||
      <cc:Work
 | 
			
		||||
         rdf:about="">
 | 
			
		||||
        <dc:format>image/svg+xml</dc:format>
 | 
			
		||||
        <dc:type
 | 
			
		||||
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 | 
			
		||||
        <dc:title />
 | 
			
		||||
      </cc:Work>
 | 
			
		||||
    </rdf:RDF>
 | 
			
		||||
  </metadata>
 | 
			
		||||
  <g
 | 
			
		||||
     id="layer1"
 | 
			
		||||
     inkscape:label="Layer 1"
 | 
			
		||||
     inkscape:groupmode="layer"
 | 
			
		||||
     transform="translate(0,-17)">
 | 
			
		||||
    <rect
 | 
			
		||||
       ry="0.5"
 | 
			
		||||
       rx="0.49999979"
 | 
			
		||||
       y="17.483809"
 | 
			
		||||
       x="0.53483802"
 | 
			
		||||
       height="15"
 | 
			
		||||
       width="23"
 | 
			
		||||
       id="rect5304"
 | 
			
		||||
       style="fill:#cccccc;fill-opacity:1;stroke:#cccccc;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 2.4 KiB  | 
							
								
								
									
										81
									
								
								data/theme/single-view.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,81 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
   xmlns:dc="http://purl.org/dc/elements/1.1/"
 | 
			
		||||
   xmlns:cc="http://creativecommons.org/ns#"
 | 
			
		||||
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 | 
			
		||||
   xmlns:svg="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   width="24"
 | 
			
		||||
   height="16"
 | 
			
		||||
   id="svg6446"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
   inkscape:version="0.47pre4 r22446"
 | 
			
		||||
   sodipodi:docname="single-view.svg">
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs6448">
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       sodipodi:type="inkscape:persp3d"
 | 
			
		||||
       inkscape:vp_x="0 : 16 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_z="32 : 16 : 1"
 | 
			
		||||
       inkscape:persp3d-origin="16 : 10.666667 : 1"
 | 
			
		||||
       id="perspective6454" />
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
       id="perspective6441"
 | 
			
		||||
       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
 | 
			
		||||
       inkscape:vp_z="1 : 0.5 : 1"
 | 
			
		||||
       inkscape:vp_y="0 : 1000 : 0"
 | 
			
		||||
       inkscape:vp_x="0 : 0.5 : 1"
 | 
			
		||||
       sodipodi:type="inkscape:persp3d" />
 | 
			
		||||
  </defs>
 | 
			
		||||
  <sodipodi:namedview
 | 
			
		||||
     id="base"
 | 
			
		||||
     pagecolor="#ffffff"
 | 
			
		||||
     bordercolor="#666666"
 | 
			
		||||
     borderopacity="1.0"
 | 
			
		||||
     inkscape:pageopacity="0.0"
 | 
			
		||||
     inkscape:pageshadow="2"
 | 
			
		||||
     inkscape:zoom="11.197802"
 | 
			
		||||
     inkscape:cx="0.014720032"
 | 
			
		||||
     inkscape:cy="16"
 | 
			
		||||
     inkscape:current-layer="layer1"
 | 
			
		||||
     showgrid="true"
 | 
			
		||||
     inkscape:grid-bbox="true"
 | 
			
		||||
     inkscape:document-units="px"
 | 
			
		||||
     inkscape:window-width="1680"
 | 
			
		||||
     inkscape:window-height="997"
 | 
			
		||||
     inkscape:window-x="0"
 | 
			
		||||
     inkscape:window-y="26"
 | 
			
		||||
     inkscape:window-maximized="1" />
 | 
			
		||||
  <metadata
 | 
			
		||||
     id="metadata6451">
 | 
			
		||||
    <rdf:RDF>
 | 
			
		||||
      <cc:Work
 | 
			
		||||
         rdf:about="">
 | 
			
		||||
        <dc:format>image/svg+xml</dc:format>
 | 
			
		||||
        <dc:type
 | 
			
		||||
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 | 
			
		||||
        <dc:title />
 | 
			
		||||
      </cc:Work>
 | 
			
		||||
    </rdf:RDF>
 | 
			
		||||
  </metadata>
 | 
			
		||||
  <g
 | 
			
		||||
     id="layer1"
 | 
			
		||||
     inkscape:label="Layer 1"
 | 
			
		||||
     inkscape:groupmode="layer"
 | 
			
		||||
     transform="translate(0,-17)">
 | 
			
		||||
    <rect
 | 
			
		||||
       ry="0.5"
 | 
			
		||||
       rx="0.49999979"
 | 
			
		||||
       y="17.483809"
 | 
			
		||||
       x="0.53483802"
 | 
			
		||||
       height="15"
 | 
			
		||||
       width="23"
 | 
			
		||||
       id="rect5304"
 | 
			
		||||
       style="fill:#626262;fill-opacity:1;stroke:#cccccc;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 2.4 KiB  | 
@@ -9,7 +9,7 @@
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   width="65"
 | 
			
		||||
   width="64"
 | 
			
		||||
   height="22"
 | 
			
		||||
   id="svg3273"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
 
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB  | 
@@ -9,7 +9,7 @@
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   width="65"
 | 
			
		||||
   width="64"
 | 
			
		||||
   height="22"
 | 
			
		||||
   id="svg3012"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
 
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB  | 
@@ -13,8 +13,8 @@
 | 
			
		||||
   height="22"
 | 
			
		||||
   id="svg3199"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
   inkscape:version="0.48.1 r9760"
 | 
			
		||||
   sodipodi:docname="toggle-on-intl.svg">
 | 
			
		||||
   inkscape:version="0.47 r22583"
 | 
			
		||||
   sodipodi:docname="New document 11">
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs3201">
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
@@ -39,14 +39,14 @@
 | 
			
		||||
     borderopacity="1.0"
 | 
			
		||||
     inkscape:pageopacity="0.0"
 | 
			
		||||
     inkscape:pageshadow="2"
 | 
			
		||||
     inkscape:zoom="1"
 | 
			
		||||
     inkscape:cx="49.147112"
 | 
			
		||||
     inkscape:cy="17.532036"
 | 
			
		||||
     inkscape:zoom="0.35"
 | 
			
		||||
     inkscape:cx="32.500004"
 | 
			
		||||
     inkscape:cy="10.999997"
 | 
			
		||||
     inkscape:document-units="px"
 | 
			
		||||
     inkscape:current-layer="layer1"
 | 
			
		||||
     showgrid="false"
 | 
			
		||||
     inkscape:window-width="1412"
 | 
			
		||||
     inkscape:window-height="1067"
 | 
			
		||||
     inkscape:window-width="609"
 | 
			
		||||
     inkscape:window-height="501"
 | 
			
		||||
     inkscape:window-x="0"
 | 
			
		||||
     inkscape:window-y="26"
 | 
			
		||||
     inkscape:window-maximized="0" />
 | 
			
		||||
@@ -58,7 +58,7 @@
 | 
			
		||||
        <dc:format>image/svg+xml</dc:format>
 | 
			
		||||
        <dc:type
 | 
			
		||||
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 | 
			
		||||
        <dc:title />
 | 
			
		||||
        <dc:title></dc:title>
 | 
			
		||||
      </cc:Work>
 | 
			
		||||
    </rdf:RDF>
 | 
			
		||||
  </metadata>
 | 
			
		||||
@@ -72,7 +72,7 @@
 | 
			
		||||
       transform="translate(-453.5,448.36218)"
 | 
			
		||||
       id="g16453">
 | 
			
		||||
      <rect
 | 
			
		||||
         style="color:#000000;fill:#4a90d9;fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:0.99999994000000003;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
 | 
			
		||||
         style="color:#000000;fill:#204a87;fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
 | 
			
		||||
         id="rect16256-9-4"
 | 
			
		||||
         width="63.000004"
 | 
			
		||||
         height="19"
 | 
			
		||||
 
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB  | 
@@ -13,8 +13,8 @@
 | 
			
		||||
   height="22"
 | 
			
		||||
   id="svg2857"
 | 
			
		||||
   version="1.1"
 | 
			
		||||
   inkscape:version="0.48.1 r9760"
 | 
			
		||||
   sodipodi:docname="toggle-on-us.svg">
 | 
			
		||||
   inkscape:version="0.47 r22583"
 | 
			
		||||
   sodipodi:docname="New document 2">
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs2859">
 | 
			
		||||
    <inkscape:perspective
 | 
			
		||||
@@ -40,18 +40,16 @@
 | 
			
		||||
     inkscape:pageopacity="0.0"
 | 
			
		||||
     inkscape:pageshadow="2"
 | 
			
		||||
     inkscape:zoom="1"
 | 
			
		||||
     inkscape:cx="19.689855"
 | 
			
		||||
     inkscape:cy="2.0517979"
 | 
			
		||||
     inkscape:cx="-69.642856"
 | 
			
		||||
     inkscape:cy="42.428569"
 | 
			
		||||
     inkscape:document-units="px"
 | 
			
		||||
     inkscape:current-layer="layer1"
 | 
			
		||||
     showgrid="false"
 | 
			
		||||
     inkscape:window-width="941"
 | 
			
		||||
     inkscape:window-height="751"
 | 
			
		||||
     inkscape:window-x="2577"
 | 
			
		||||
     inkscape:window-y="206"
 | 
			
		||||
     inkscape:window-maximized="0"
 | 
			
		||||
     borderlayer="true"
 | 
			
		||||
     inkscape:showpageshadow="false" />
 | 
			
		||||
     inkscape:window-width="609"
 | 
			
		||||
     inkscape:window-height="501"
 | 
			
		||||
     inkscape:window-x="0"
 | 
			
		||||
     inkscape:window-y="26"
 | 
			
		||||
     inkscape:window-maximized="0" />
 | 
			
		||||
  <metadata
 | 
			
		||||
     id="metadata2862">
 | 
			
		||||
    <rdf:RDF>
 | 
			
		||||
@@ -60,7 +58,7 @@
 | 
			
		||||
        <dc:format>image/svg+xml</dc:format>
 | 
			
		||||
        <dc:type
 | 
			
		||||
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 | 
			
		||||
        <dc:title />
 | 
			
		||||
        <dc:title></dc:title>
 | 
			
		||||
      </cc:Work>
 | 
			
		||||
    </rdf:RDF>
 | 
			
		||||
  </metadata>
 | 
			
		||||
@@ -74,7 +72,7 @@
 | 
			
		||||
       transform="translate(-351.35714,708.36218)"
 | 
			
		||||
       id="g16453">
 | 
			
		||||
      <rect
 | 
			
		||||
         style="color:#000000;fill:#4a90d9;fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:0.99999994000000003;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
 | 
			
		||||
         style="color:#000000;fill:#204a87;fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
 | 
			
		||||
         id="rect16256-9-4"
 | 
			
		||||
         width="63.000004"
 | 
			
		||||
         height="19"
 | 
			
		||||
 
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.7 KiB  | 
@@ -1 +0,0 @@
 | 
			
		||||
SUBDIRS = reference
 | 
			
		||||
@@ -1 +0,0 @@
 | 
			
		||||
SUBDIRS = shell st
 | 
			
		||||
@@ -1,113 +0,0 @@
 | 
			
		||||
## Process this file with automake to produce Makefile.in
 | 
			
		||||
 | 
			
		||||
# We require automake 1.6 at least.
 | 
			
		||||
AUTOMAKE_OPTIONS = 1.6
 | 
			
		||||
 | 
			
		||||
# This is a blank Makefile.am for using gtk-doc.
 | 
			
		||||
# Copy this to your project's API docs directory and modify the variables to
 | 
			
		||||
# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
 | 
			
		||||
# of using the various options.
 | 
			
		||||
 | 
			
		||||
# The name of the module, e.g. 'glib'.
 | 
			
		||||
DOC_MODULE=shell
 | 
			
		||||
 | 
			
		||||
# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
 | 
			
		||||
#DOC_MODULE_VERSION=2
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# The top-level SGML file. You can change this if you want to.
 | 
			
		||||
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
 | 
			
		||||
 | 
			
		||||
# Directories containing the source code
 | 
			
		||||
# gtk-doc will search all .c and .h files beneath these paths
 | 
			
		||||
# for inline comments documenting functions and macros.
 | 
			
		||||
DOC_SOURCE_DIR=$(top_srcdir)/src
 | 
			
		||||
 | 
			
		||||
# Extra options to pass to gtkdoc-scangobj. Not normally needed.
 | 
			
		||||
SCANGOBJ_OPTIONS=
 | 
			
		||||
 | 
			
		||||
# Extra options to supply to gtkdoc-scan.
 | 
			
		||||
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
 | 
			
		||||
SCAN_OPTIONS=--rebuild-types
 | 
			
		||||
 | 
			
		||||
# Extra options to supply to gtkdoc-mkdb.
 | 
			
		||||
# e.g. MKDB_OPTIONS=--xml-mode --output-format=xml
 | 
			
		||||
MKDB_OPTIONS=--xml-mode --output-format=xml
 | 
			
		||||
 | 
			
		||||
# Extra options to supply to gtkdoc-mktmpl
 | 
			
		||||
# e.g. MKTMPL_OPTIONS=--only-section-tmpl
 | 
			
		||||
MKTMPL_OPTIONS=
 | 
			
		||||
 | 
			
		||||
# Extra options to supply to gtkdoc-mkhtml
 | 
			
		||||
MKHTML_OPTIONS=
 | 
			
		||||
 | 
			
		||||
# Extra options to supply to gtkdoc-fixref. Not normally needed.
 | 
			
		||||
# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
 | 
			
		||||
FIXXREF_OPTIONS=
 | 
			
		||||
 | 
			
		||||
# Used for dependencies. The docs will be rebuilt if any of these change.
 | 
			
		||||
# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
 | 
			
		||||
# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
 | 
			
		||||
HFILE_GLOB=$(top_srcdir)/src/*.h
 | 
			
		||||
CFILE_GLOB=$(top_srcdir)/src/*.c
 | 
			
		||||
 | 
			
		||||
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
 | 
			
		||||
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
 | 
			
		||||
EXTRA_HFILES=
 | 
			
		||||
 | 
			
		||||
# Header files or dirs to ignore when scanning. Use base file/dir names
 | 
			
		||||
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
 | 
			
		||||
IGNORE_HFILES=					\
 | 
			
		||||
	calendar-server				\
 | 
			
		||||
	gvc					\
 | 
			
		||||
	hotplug-sniffer				\
 | 
			
		||||
	st					\
 | 
			
		||||
	tray					\
 | 
			
		||||
	gactionmuxer.h				\
 | 
			
		||||
	gactionobservable.h			\
 | 
			
		||||
	gactionobserver.h			\
 | 
			
		||||
	shell-recorder-src.h
 | 
			
		||||
 | 
			
		||||
# Images to copy into HTML directory.
 | 
			
		||||
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
 | 
			
		||||
HTML_IMAGES=
 | 
			
		||||
 | 
			
		||||
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
 | 
			
		||||
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
 | 
			
		||||
content_files=
 | 
			
		||||
 | 
			
		||||
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
 | 
			
		||||
# These files must be listed here *and* in content_files
 | 
			
		||||
# e.g. expand_content_files=running.sgml
 | 
			
		||||
expand_content_files=
 | 
			
		||||
 | 
			
		||||
# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
 | 
			
		||||
# Only needed if you are using gtkdoc-scangobj to dynamically query widget
 | 
			
		||||
# signals and properties.
 | 
			
		||||
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
 | 
			
		||||
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
 | 
			
		||||
GTKDOC_CFLAGS=$(GNOME_SHELL_CFLAGS)
 | 
			
		||||
GTKDOC_LIBS=$(GNOME_SHELL_LIBS) $(BLUETOOTH_LIBS) $(top_builddir)/src/libgnome-shell.la
 | 
			
		||||
 | 
			
		||||
# This includes the standard gtk-doc make rules, copied by gtkdocize.
 | 
			
		||||
include $(top_srcdir)/gtk-doc.make
 | 
			
		||||
 | 
			
		||||
# Other files to distribute
 | 
			
		||||
# e.g. EXTRA_DIST += version.xml.in
 | 
			
		||||
EXTRA_DIST +=
 | 
			
		||||
 | 
			
		||||
# Files not to distribute
 | 
			
		||||
# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
 | 
			
		||||
# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
 | 
			
		||||
DISTCLEANFILES = $(DOC_MODULES).types
 | 
			
		||||
 | 
			
		||||
# Comment this out if you want 'make check' to test you doc status
 | 
			
		||||
# and run some sanity checks
 | 
			
		||||
if ENABLE_GTK_DOC
 | 
			
		||||
TESTS_ENVIRONMENT = cd $(srcdir) && \
 | 
			
		||||
  DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \
 | 
			
		||||
  SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir)
 | 
			
		||||
#TESTS = $(GTKDOC_CHECK)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
-include $(top_srcdir)/git.mk
 | 
			
		||||
@@ -1,73 +0,0 @@
 | 
			
		||||
<?xml version="1.0"?>
 | 
			
		||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
 | 
			
		||||
               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
 | 
			
		||||
[
 | 
			
		||||
  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
 | 
			
		||||
]>
 | 
			
		||||
<book id="index">
 | 
			
		||||
  <bookinfo>
 | 
			
		||||
    <title>Shell Reference Manual</title>
 | 
			
		||||
    <releaseinfo>
 | 
			
		||||
      for Shell @VERSION@.
 | 
			
		||||
      <!--The latest version of this documentation can be found on-line at
 | 
			
		||||
      <ulink role="online-location" url="http://[SERVER]/shell/index.html">http://[SERVER]/shell/</ulink>.-->
 | 
			
		||||
    </releaseinfo>
 | 
			
		||||
  </bookinfo>
 | 
			
		||||
 | 
			
		||||
  <chapter>
 | 
			
		||||
    <title>Actors</title>
 | 
			
		||||
    <xi:include href="xml/shell-generic-container.xml"/>
 | 
			
		||||
    <xi:include href="xml/shell-slicer.xml"/>
 | 
			
		||||
    <xi:include href="xml/shell-stack.xml"/>
 | 
			
		||||
  </chapter>
 | 
			
		||||
  <chapter>
 | 
			
		||||
    <title>Application tracking</title>
 | 
			
		||||
    <xi:include href="xml/shell-app.xml"/>
 | 
			
		||||
    <xi:include href="xml/shell-app-usage.xml"/>
 | 
			
		||||
    <xi:include href="xml/shell-window-tracker.xml"/>
 | 
			
		||||
  </chapter>
 | 
			
		||||
  <chapter>
 | 
			
		||||
    <title>Search</title>
 | 
			
		||||
    <xi:include href="xml/shell-app-system.xml"/>
 | 
			
		||||
    <xi:include href="xml/shell-contact-system.xml"/>
 | 
			
		||||
    <xi:include href="xml/shell-doc-system.xml"/>
 | 
			
		||||
  </chapter>
 | 
			
		||||
  <chapter>
 | 
			
		||||
    <title>Tray Icons</title>
 | 
			
		||||
    <xi:include href="xml/shell-embedded-window.xml"/>
 | 
			
		||||
    <xi:include href="xml/shell-gtk-embed.xml"/>
 | 
			
		||||
    <xi:include href="xml/shell-tray-icon.xml"/>
 | 
			
		||||
    <xi:include href="xml/shell-tray-manager.xml"/>
 | 
			
		||||
  </chapter>
 | 
			
		||||
  <chapter>
 | 
			
		||||
    <title>Recorder</title>
 | 
			
		||||
    <xi:include href="xml/shell-recorder.xml"/>
 | 
			
		||||
    <xi:include href="xml/shell-recorder-src.xml"/>
 | 
			
		||||
  </chapter>
 | 
			
		||||
  <chapter>
 | 
			
		||||
    <title>Integration helpers and utilities</title>
 | 
			
		||||
    <xi:include href="xml/shell-global.xml"/>
 | 
			
		||||
    <xi:include href="xml/shell-wm.xml"/>
 | 
			
		||||
    <xi:include href="xml/shell-xfixes-cursor.xml"/>
 | 
			
		||||
    <xi:include href="xml/shell-util.xml"/>
 | 
			
		||||
    <xi:include href="xml/shell-mount-operation.xml"/>
 | 
			
		||||
    <xi:include href="xml/shell-mobile-providers.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>
 | 
			
		||||
  <chapter id="object-tree">
 | 
			
		||||
    <title>Object Hierarchy</title>
 | 
			
		||||
     <xi:include href="xml/tree_index.sgml"/>
 | 
			
		||||
  </chapter>
 | 
			
		||||
  <index id="api-index-full">
 | 
			
		||||
    <title>API Index</title>
 | 
			
		||||
    <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
 | 
			
		||||
  </index>
 | 
			
		||||
  <index id="deprecated-api-index" role="deprecated">
 | 
			
		||||
    <title>Index of deprecated API</title>
 | 
			
		||||
    <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
 | 
			
		||||
  </index>
 | 
			
		||||
 | 
			
		||||
  <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
 | 
			
		||||
</book>
 | 
			
		||||
@@ -1,104 +0,0 @@
 | 
			
		||||
## Process this file with automake to produce Makefile.in
 | 
			
		||||
 | 
			
		||||
# We require automake 1.6 at least.
 | 
			
		||||
AUTOMAKE_OPTIONS = 1.6
 | 
			
		||||
 | 
			
		||||
# This is a blank Makefile.am for using gtk-doc.
 | 
			
		||||
# Copy this to your project's API docs directory and modify the variables to
 | 
			
		||||
# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
 | 
			
		||||
# of using the various options.
 | 
			
		||||
 | 
			
		||||
# The name of the module, e.g. 'glib'.
 | 
			
		||||
DOC_MODULE=st
 | 
			
		||||
 | 
			
		||||
# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
 | 
			
		||||
#DOC_MODULE_VERSION=2
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# The top-level SGML file. You can change this if you want to.
 | 
			
		||||
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
 | 
			
		||||
 | 
			
		||||
# Directories containing the source code
 | 
			
		||||
# gtk-doc will search all .c and .h files beneath these paths
 | 
			
		||||
# for inline comments documenting functions and macros.
 | 
			
		||||
DOC_SOURCE_DIR=$(top_srcdir)/src/st
 | 
			
		||||
 | 
			
		||||
# Extra options to pass to gtkdoc-scangobj. Not normally needed.
 | 
			
		||||
SCANGOBJ_OPTIONS=
 | 
			
		||||
 | 
			
		||||
# Extra options to supply to gtkdoc-scan.
 | 
			
		||||
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
 | 
			
		||||
SCAN_OPTIONS=--rebuild-types --rebuild-sections
 | 
			
		||||
 | 
			
		||||
# Extra options to supply to gtkdoc-mkdb.
 | 
			
		||||
# e.g. MKDB_OPTIONS=--xml-mode --output-format=xml
 | 
			
		||||
MKDB_OPTIONS=--xml-mode --output-format=xml
 | 
			
		||||
 | 
			
		||||
# Extra options to supply to gtkdoc-mktmpl
 | 
			
		||||
# e.g. MKTMPL_OPTIONS=--only-section-tmpl
 | 
			
		||||
MKTMPL_OPTIONS=
 | 
			
		||||
 | 
			
		||||
# Extra options to supply to gtkdoc-mkhtml
 | 
			
		||||
MKHTML_OPTIONS=
 | 
			
		||||
 | 
			
		||||
# Extra options to supply to gtkdoc-fixref. Not normally needed.
 | 
			
		||||
# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
 | 
			
		||||
FIXXREF_OPTIONS=
 | 
			
		||||
 | 
			
		||||
# Used for dependencies. The docs will be rebuilt if any of these change.
 | 
			
		||||
# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
 | 
			
		||||
# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
 | 
			
		||||
HFILE_GLOB=$(top_srcdir)/src/st/*.h
 | 
			
		||||
CFILE_GLOB=$(top_srcdir)/src/st/*.c
 | 
			
		||||
 | 
			
		||||
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
 | 
			
		||||
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
 | 
			
		||||
EXTRA_HFILES=
 | 
			
		||||
 | 
			
		||||
# Header files or dirs to ignore when scanning. Use base file/dir names
 | 
			
		||||
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
 | 
			
		||||
IGNORE_HFILES=st-private.h st-theme-node-private.h
 | 
			
		||||
 | 
			
		||||
# Images to copy into HTML directory.
 | 
			
		||||
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
 | 
			
		||||
HTML_IMAGES=
 | 
			
		||||
 | 
			
		||||
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
 | 
			
		||||
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
 | 
			
		||||
content_files=
 | 
			
		||||
 | 
			
		||||
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
 | 
			
		||||
# These files must be listed here *and* in content_files
 | 
			
		||||
# e.g. expand_content_files=running.sgml
 | 
			
		||||
expand_content_files=
 | 
			
		||||
 | 
			
		||||
# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
 | 
			
		||||
# Only needed if you are using gtkdoc-scangobj to dynamically query widget
 | 
			
		||||
# signals and properties.
 | 
			
		||||
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
 | 
			
		||||
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
 | 
			
		||||
GTKDOC_CFLAGS=
 | 
			
		||||
GTKDOC_LIBS=$(top_builddir)/src/libst-1.0.la
 | 
			
		||||
 | 
			
		||||
# This includes the standard gtk-doc make rules, copied by gtkdocize.
 | 
			
		||||
include $(top_srcdir)/gtk-doc.make
 | 
			
		||||
 | 
			
		||||
# Other files to distribute
 | 
			
		||||
# e.g. EXTRA_DIST += version.xml.in
 | 
			
		||||
EXTRA_DIST +=
 | 
			
		||||
 | 
			
		||||
# Files not to distribute
 | 
			
		||||
# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
 | 
			
		||||
# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
 | 
			
		||||
DISTCLEANFILES = $(DOC_MODULE).types $(DOC_MODULE)-sections.txt
 | 
			
		||||
 | 
			
		||||
# Comment this out if you want 'make check' to test you doc status
 | 
			
		||||
# and run some sanity checks
 | 
			
		||||
if ENABLE_GTK_DOC
 | 
			
		||||
TESTS_ENVIRONMENT = cd $(srcdir) && \
 | 
			
		||||
  DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \
 | 
			
		||||
  SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir)
 | 
			
		||||
#TESTS = $(GTKDOC_CHECK)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
-include $(top_srcdir)/git.mk
 | 
			
		||||
@@ -1,64 +0,0 @@
 | 
			
		||||
<?xml version="1.0"?>
 | 
			
		||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
 | 
			
		||||
               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
 | 
			
		||||
[
 | 
			
		||||
  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
 | 
			
		||||
]>
 | 
			
		||||
<book id="index">
 | 
			
		||||
  <bookinfo>
 | 
			
		||||
    <title>St Reference Manual</title>
 | 
			
		||||
    <releaseinfo>
 | 
			
		||||
      for St @VERSION@.
 | 
			
		||||
      <!--The latest version of this documentation can be found on-line at
 | 
			
		||||
      <ulink role="online-location" url="http://[SERVER]/st/index.html">http://[SERVER]/st/</ulink>.-->
 | 
			
		||||
    </releaseinfo>
 | 
			
		||||
  </bookinfo>
 | 
			
		||||
 | 
			
		||||
  <part>
 | 
			
		||||
    <title>API reference</title>
 | 
			
		||||
    <chapter id="base">
 | 
			
		||||
      <title>Abstract classes and Interfaces</title>
 | 
			
		||||
      <xi:include href="xml/st-widget.xml"/>
 | 
			
		||||
      <xi:include href="xml/st-widget-accessible.xml"/>
 | 
			
		||||
      <xi:include href="xml/st-scrollable.xml"/>
 | 
			
		||||
    </chapter>
 | 
			
		||||
    <chapter id="widgets">
 | 
			
		||||
      <title>Widgets</title>
 | 
			
		||||
      <xi:include href="xml/st-button.xml"/>
 | 
			
		||||
      <xi:include href="xml/st-drawing-area.xml"/>
 | 
			
		||||
      <xi:include href="xml/st-entry.xml"/>
 | 
			
		||||
      <xi:include href="xml/st-icon.xml"/>
 | 
			
		||||
      <xi:include href="xml/st-label.xml"/>
 | 
			
		||||
    </chapter>
 | 
			
		||||
    <chapter id="containers">
 | 
			
		||||
      <title>Containers</title>
 | 
			
		||||
      <xi:include href="xml/st-bin.xml"/>
 | 
			
		||||
      <xi:include href="xml/st-box-layout.xml"/>
 | 
			
		||||
      <xi:include href="xml/st-scroll-view.xml"/>
 | 
			
		||||
      <xi:include href="xml/st-table.xml"/>
 | 
			
		||||
    </chapter>
 | 
			
		||||
 | 
			
		||||
    <chapter id="styling">
 | 
			
		||||
      <title>Styling</title>
 | 
			
		||||
      <xi:include href="xml/st-theme.xml"/>
 | 
			
		||||
      <xi:include href="xml/st-theme-context.xml"/>
 | 
			
		||||
      <xi:include href="xml/st-theme-node.xml"/>
 | 
			
		||||
      <xi:include href="xml/st-theme-node-transition.xml"/>
 | 
			
		||||
      <xi:include href="xml/st-texture-cache.xml"/>
 | 
			
		||||
    </chapter>
 | 
			
		||||
  </part>
 | 
			
		||||
  <chapter id="object-tree">
 | 
			
		||||
    <title>Object Hierarchy</title>
 | 
			
		||||
     <xi:include href="xml/tree_index.sgml"/>
 | 
			
		||||
  </chapter>
 | 
			
		||||
  <index id="api-index-full">
 | 
			
		||||
    <title>API Index</title>
 | 
			
		||||
    <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
 | 
			
		||||
  </index>
 | 
			
		||||
  <index id="deprecated-api-index" role="deprecated">
 | 
			
		||||
    <title>Index of deprecated API</title>
 | 
			
		||||
    <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
 | 
			
		||||
  </index>
 | 
			
		||||
 | 
			
		||||
  <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
 | 
			
		||||
</book>
 | 
			
		||||
@@ -66,11 +66,4 @@ its dependencies to build from tarballs.</description>
 | 
			
		||||
      <gnome:userid>marinaz</gnome:userid>
 | 
			
		||||
    </foaf:Person>
 | 
			
		||||
  </maintainer>
 | 
			
		||||
  <maintainer>
 | 
			
		||||
    <foaf:Person>
 | 
			
		||||
      <foaf:name>Florian Müllner</foaf:name>
 | 
			
		||||
      <foaf:mbox rdf:resource="mailto:fmuellner@gnome.org" />
 | 
			
		||||
      <gnome:userid>fmuellner</gnome:userid>
 | 
			
		||||
    </foaf:Person>
 | 
			
		||||
  </maintainer>
 | 
			
		||||
</Project>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,62 +1,32 @@
 | 
			
		||||
 | 
			
		||||
EXTRA_DIST = misc/config.js.in
 | 
			
		||||
CLEANFILES = misc/config.js
 | 
			
		||||
 | 
			
		||||
misc/config.js: misc/config.js.in Makefile
 | 
			
		||||
	[ -d $(@D) ] || $(mkdir_p) $(@D) ; \
 | 
			
		||||
	sed -e "s|[@]PACKAGE_NAME@|$(PACKAGE_NAME)|g" \
 | 
			
		||||
	    -e "s|[@]PACKAGE_VERSION@|$(PACKAGE_VERSION)|g" \
 | 
			
		||||
	    -e "s|[@]GJS_VERSION@|$(GJS_VERSION)|g" \
 | 
			
		||||
	    -e "s|[@]HAVE_BLUETOOTH@|$(HAVE_BLUETOOTH)|g" \
 | 
			
		||||
	    -e "s|[@]SHELL_SYSTEM_CA_FILE@|$(SHELL_SYSTEM_CA_FILE)|g" \
 | 
			
		||||
	    -e "s|[@]GETTEXT_PACKAGE@|$(GETTEXT_PACKAGE)|g" \
 | 
			
		||||
	    -e "s|[@]datadir@|$(datadir)|g" \
 | 
			
		||||
	    -e "s|[@]libexecdir@|$(libexecdir)|g" \
 | 
			
		||||
	    -e "s|[@]sysconfdir@|$(sysconfdir)|g" \
 | 
			
		||||
               $< > $@
 | 
			
		||||
 | 
			
		||||
jsdir = $(pkgdatadir)/js
 | 
			
		||||
 | 
			
		||||
nobase_dist_js_DATA = 	\
 | 
			
		||||
	gdm/batch.js		\
 | 
			
		||||
	gdm/consoleKit.js	\
 | 
			
		||||
	gdm/fingerprint.js	\
 | 
			
		||||
	gdm/loginDialog.js	\
 | 
			
		||||
	gdm/powerMenu.js	\
 | 
			
		||||
	gdm/systemd.js	 	\
 | 
			
		||||
	extensionPrefs/main.js	\
 | 
			
		||||
	misc/config.js		\
 | 
			
		||||
	misc/extensionUtils.js	\
 | 
			
		||||
	misc/docInfo.js		\
 | 
			
		||||
	misc/fileUtils.js	\
 | 
			
		||||
	misc/format.js		\
 | 
			
		||||
	misc/gnomeSession.js	\
 | 
			
		||||
	misc/history.js		\
 | 
			
		||||
	misc/jsParse.js		\
 | 
			
		||||
	misc/modemManager.js	\
 | 
			
		||||
	misc/params.js		\
 | 
			
		||||
	misc/screenSaver.js     \
 | 
			
		||||
	misc/util.js		\
 | 
			
		||||
	perf/core.js		\
 | 
			
		||||
	ui/altTab.js		\
 | 
			
		||||
	ui/appDisplay.js	\
 | 
			
		||||
	ui/appFavorites.js	\
 | 
			
		||||
	ui/automountManager.js  \
 | 
			
		||||
	ui/autorunManager.js    \
 | 
			
		||||
	ui/boxpointer.js	\
 | 
			
		||||
	ui/calendar.js		\
 | 
			
		||||
	ui/checkBox.js		\
 | 
			
		||||
	ui/contactDisplay.js \
 | 
			
		||||
	ui/chrome.js		\
 | 
			
		||||
	ui/ctrlAltTab.js	\
 | 
			
		||||
	ui/dash.js		\
 | 
			
		||||
	ui/dateMenu.js		\
 | 
			
		||||
	ui/dnd.js		\
 | 
			
		||||
	ui/docDisplay.js	\
 | 
			
		||||
	ui/endSessionDialog.js	\
 | 
			
		||||
	ui/environment.js	\
 | 
			
		||||
	ui/extensionSystem.js	\
 | 
			
		||||
	ui/flashspot.js		\
 | 
			
		||||
	ui/iconGrid.js		\
 | 
			
		||||
	ui/keyboard.js		\
 | 
			
		||||
	ui/keyringPrompt.js	\
 | 
			
		||||
	ui/layout.js		\
 | 
			
		||||
	ui/lightbox.js		\
 | 
			
		||||
	ui/link.js		\
 | 
			
		||||
	ui/lookingGlass.js	\
 | 
			
		||||
@@ -65,10 +35,6 @@ nobase_dist_js_DATA = 	\
 | 
			
		||||
	ui/main.js		\
 | 
			
		||||
	ui/messageTray.js	\
 | 
			
		||||
	ui/modalDialog.js	\
 | 
			
		||||
	ui/networkAgent.js	\
 | 
			
		||||
	ui/sessionMode.js	\
 | 
			
		||||
	ui/shellEntry.js	\
 | 
			
		||||
	ui/shellMountOperation.js \
 | 
			
		||||
	ui/notificationDaemon.js \
 | 
			
		||||
	ui/overview.js		\
 | 
			
		||||
	ui/panel.js		\
 | 
			
		||||
@@ -76,13 +42,13 @@ nobase_dist_js_DATA = 	\
 | 
			
		||||
	ui/placeDisplay.js	\
 | 
			
		||||
	ui/polkitAuthenticationAgent.js \
 | 
			
		||||
	ui/popupMenu.js		\
 | 
			
		||||
	ui/remoteSearch.js	\
 | 
			
		||||
	ui/runDialog.js		\
 | 
			
		||||
	ui/scripting.js		\
 | 
			
		||||
	ui/search.js		\
 | 
			
		||||
	ui/searchDisplay.js	\
 | 
			
		||||
	ui/shellDBus.js		\
 | 
			
		||||
	ui/statusIconDispatcher.js	\
 | 
			
		||||
	ui/statusMenu.js	\
 | 
			
		||||
	ui/status/accessibility.js	\
 | 
			
		||||
	ui/status/keyboard.js	\
 | 
			
		||||
	ui/status/network.js	\
 | 
			
		||||
@@ -91,9 +57,7 @@ nobase_dist_js_DATA = 	\
 | 
			
		||||
	ui/status/bluetooth.js	\
 | 
			
		||||
	ui/telepathyClient.js	\
 | 
			
		||||
	ui/tweener.js		\
 | 
			
		||||
	ui/userMenu.js		\
 | 
			
		||||
	ui/viewSelector.js	\
 | 
			
		||||
	ui/wanda.js		\
 | 
			
		||||
	ui/windowAttentionHandler.js	\
 | 
			
		||||
	ui/windowManager.js	\
 | 
			
		||||
	ui/workspace.js		\
 | 
			
		||||
 
 | 
			
		||||
@@ -1,278 +0,0 @@
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
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 Pango = imports.gi.Pango;
 | 
			
		||||
const Format = imports.format;
 | 
			
		||||
 | 
			
		||||
const _ = Gettext.gettext;
 | 
			
		||||
 | 
			
		||||
const Config = imports.misc.config;
 | 
			
		||||
const ExtensionUtils = imports.misc.extensionUtils;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const GnomeShellIface = <interface name="org.gnome.Shell">
 | 
			
		||||
<signal name="ExtensionStatusChanged">
 | 
			
		||||
    <arg type="s" name="uuid"/>
 | 
			
		||||
    <arg type="i" name="state"/>
 | 
			
		||||
    <arg type="s" name="error"/>
 | 
			
		||||
</signal>
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface);
 | 
			
		||||
 | 
			
		||||
function stripPrefix(string, prefix) {
 | 
			
		||||
    if (string.slice(0, prefix.length) == prefix)
 | 
			
		||||
        return string.slice(prefix.length);
 | 
			
		||||
    return string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Application = new Lang.Class({
 | 
			
		||||
    Name: 'Application',
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        GLib.set_prgname('gnome-shell-extension-prefs');
 | 
			
		||||
        this.application = new Gtk.Application({
 | 
			
		||||
            application_id: 'org.gnome.shell.ExtensionPrefs',
 | 
			
		||||
            flags: Gio.ApplicationFlags.HANDLES_COMMAND_LINE
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.application.connect('activate', Lang.bind(this, this._onActivate));
 | 
			
		||||
        this.application.connect('command-line', Lang.bind(this, this._onCommandLine));
 | 
			
		||||
        this.application.connect('startup', Lang.bind(this, this._onStartup));
 | 
			
		||||
 | 
			
		||||
        this._extensionPrefsModules = {};
 | 
			
		||||
 | 
			
		||||
        this._extensionIters = {};
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _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];
 | 
			
		||||
 | 
			
		||||
        if (!extension)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (ExtensionUtils.isOutOfDate(extension))
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (!extension.dir.get_child('prefs.js').query_exists(null))
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
 | 
			
		||||
        if (this._extensionPrefsModules.hasOwnProperty(uuid))
 | 
			
		||||
            return this._extensionPrefsModules[uuid];
 | 
			
		||||
 | 
			
		||||
        ExtensionUtils.installImporter(extension);
 | 
			
		||||
 | 
			
		||||
        let prefsModule = extension.imports.prefs;
 | 
			
		||||
        prefsModule.init(extension.metadata);
 | 
			
		||||
 | 
			
		||||
        this._extensionPrefsModules[uuid] = prefsModule;
 | 
			
		||||
        return prefsModule;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _selectExtension: function(uuid) {
 | 
			
		||||
        if (!this._extensionAvailable(uuid))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let extension = ExtensionUtils.extensions[uuid];
 | 
			
		||||
        let widget;
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            let prefsModule = this._getExtensionPrefsModule(extension);
 | 
			
		||||
            widget = prefsModule.buildPrefsWidget();
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            widget = this._buildErrorUI(extension, e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Destroy the current prefs widget, if it exists
 | 
			
		||||
        if (this._extensionPrefsBin.get_child())
 | 
			
		||||
            this._extensionPrefsBin.get_child().destroy();
 | 
			
		||||
 | 
			
		||||
        this._extensionPrefsBin.add(widget);
 | 
			
		||||
        this._extensionSelector.set_active_iter(this._extensionIters[uuid]);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _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) {
 | 
			
		||||
        let box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
 | 
			
		||||
        let label = new Gtk.Label({
 | 
			
		||||
            label: _("There was an error loading the preferences dialog for %s:").format(extension.metadata.name)
 | 
			
		||||
        });
 | 
			
		||||
        box.add(label);
 | 
			
		||||
 | 
			
		||||
        let errortext = '';
 | 
			
		||||
        errortext += exc;
 | 
			
		||||
        errortext += '\n\n';
 | 
			
		||||
        errortext += 'Stack trace:\n';
 | 
			
		||||
 | 
			
		||||
        // Indent stack trace.
 | 
			
		||||
        errortext += exc.stack.split('\n').map(function(line) {
 | 
			
		||||
            return '  ' + line;
 | 
			
		||||
        }).join('\n');
 | 
			
		||||
 | 
			
		||||
        let scroll = new Gtk.ScrolledWindow({ vexpand: true });
 | 
			
		||||
        let buffer = new Gtk.TextBuffer({ text: errortext });
 | 
			
		||||
        let textview = new Gtk.TextView({ buffer: buffer });
 | 
			
		||||
        textview.override_font(Pango.font_description_from_string('monospace'));
 | 
			
		||||
        scroll.add(textview);
 | 
			
		||||
        box.add(scroll);
 | 
			
		||||
 | 
			
		||||
        box.show_all();
 | 
			
		||||
        return box;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _buildUI: function(app) {
 | 
			
		||||
        this._window = new Gtk.ApplicationWindow({ application: app,
 | 
			
		||||
                                                   window_position: Gtk.WindowPosition.CENTER,
 | 
			
		||||
                                                   title: _("GNOME Shell Extension Preferences") });
 | 
			
		||||
 | 
			
		||||
        this._window.set_size_request(600, 400);
 | 
			
		||||
 | 
			
		||||
        let vbox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
 | 
			
		||||
        this._window.add(vbox);
 | 
			
		||||
 | 
			
		||||
        let toolbar = new Gtk.Toolbar();
 | 
			
		||||
        toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR);
 | 
			
		||||
        vbox.add(toolbar);
 | 
			
		||||
        let toolitem;
 | 
			
		||||
 | 
			
		||||
        let label = new Gtk.Label({ label: _("<b>Extension</b>"),
 | 
			
		||||
                                    use_markup: true });
 | 
			
		||||
        toolitem = new Gtk.ToolItem({ child: label });
 | 
			
		||||
        toolbar.add(toolitem);
 | 
			
		||||
 | 
			
		||||
        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), null);
 | 
			
		||||
        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]) {
 | 
			
		||||
            if (ExtensionUtils.extensions[uuid] !== undefined)
 | 
			
		||||
                this._scanExtensions();
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        this._window.show_all();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _scanExtensions: function() {
 | 
			
		||||
        ExtensionUtils.scanExtensions(Lang.bind(this, function(uuid, dir, type) {
 | 
			
		||||
            if (ExtensionUtils.extensions[uuid] !== undefined)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            let extension;
 | 
			
		||||
            try {
 | 
			
		||||
                extension = ExtensionUtils.createExtensionObject(uuid, dir, type);
 | 
			
		||||
            } catch(e) {
 | 
			
		||||
                logError(e, 'Could not create extensions object');
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let iter = this._model.append();
 | 
			
		||||
            this._model.set(iter, [0, 1], [uuid, extension.metadata.name]);
 | 
			
		||||
            this._extensionIters[uuid] = iter;
 | 
			
		||||
        }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onActivate: function() {
 | 
			
		||||
        this._window.present();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onStartup: function(app) {
 | 
			
		||||
        this._buildModel();
 | 
			
		||||
        this._buildUI(app);
 | 
			
		||||
        this._scanExtensions();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onCommandLine: function(app, commandLine) {
 | 
			
		||||
        app.activate();
 | 
			
		||||
        let args = commandLine.get_arguments();
 | 
			
		||||
        if (args.length) {
 | 
			
		||||
            let uuid = args[0];
 | 
			
		||||
 | 
			
		||||
            // Strip off "extension:///" prefix which fakes a URI, if it exists
 | 
			
		||||
            uuid = stripPrefix(uuid, "extension:///");
 | 
			
		||||
 | 
			
		||||
            if (!this._extensionAvailable(uuid))
 | 
			
		||||
                return 1;
 | 
			
		||||
 | 
			
		||||
            this._selectExtension(uuid);
 | 
			
		||||
        }
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function initEnvironment() {
 | 
			
		||||
    // Monkey-patch in a "global" object that fakes some Shell utilities
 | 
			
		||||
    // that ExtensionUtils depends on.
 | 
			
		||||
    window.global = {
 | 
			
		||||
        log: function() {
 | 
			
		||||
            print([].join.call(arguments, ', '));
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        logError: function(s) {
 | 
			
		||||
            log('ERROR: ' + s);
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        userdatadir: GLib.build_filenamev([GLib.get_user_data_dir(), 'gnome-shell'])
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    String.prototype.format = Format.format;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function main(argv) {
 | 
			
		||||
    initEnvironment();
 | 
			
		||||
    ExtensionUtils.init();
 | 
			
		||||
 | 
			
		||||
    Gettext.bindtextdomain(Config.GETTEXT_PACKAGE, Config.LOCALEDIR);
 | 
			
		||||
    Gettext.textdomain(Config.GETTEXT_PACKAGE);
 | 
			
		||||
 | 
			
		||||
    let app = new Application();
 | 
			
		||||
    app.application.run(argv);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										203
									
								
								js/gdm/batch.js
									
									
									
									
									
								
							
							
						
						@@ -1,203 +0,0 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2011 Red Hat, Inc
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 2, or (at your option)
 | 
			
		||||
 * any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 | 
			
		||||
 * 02111-1307, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const Task = new Lang.Class({
 | 
			
		||||
    Name: 'Task',
 | 
			
		||||
 | 
			
		||||
    _init: function(scope, handler) {
 | 
			
		||||
        if (scope)
 | 
			
		||||
            this.scope = scope;
 | 
			
		||||
        else
 | 
			
		||||
            this.scope = this;
 | 
			
		||||
 | 
			
		||||
        this.handler = handler;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    run: function() {
 | 
			
		||||
        if (this.handler)
 | 
			
		||||
            return this.handler.call(this.scope);
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(Task.prototype);
 | 
			
		||||
 | 
			
		||||
const Hold = new Lang.Class({
 | 
			
		||||
    Name: 'Hold',
 | 
			
		||||
    Extends: Task,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.parent(this, function () {
 | 
			
		||||
            return this;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._acquisitions = 1;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    acquire: function() {
 | 
			
		||||
        if (this._acquisitions <= 0)
 | 
			
		||||
            throw new Error("Cannot acquire hold after it's been released");
 | 
			
		||||
        this._acquisitions++;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    acquireUntilAfter: function(hold) {
 | 
			
		||||
        if (!hold.isAcquired())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this.acquire();
 | 
			
		||||
        let signalId = hold.connect('release', Lang.bind(this, function() {
 | 
			
		||||
                                        hold.disconnect(signalId);
 | 
			
		||||
                                        this.release();
 | 
			
		||||
                                    }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    release: function() {
 | 
			
		||||
        this._acquisitions--;
 | 
			
		||||
 | 
			
		||||
        if (this._acquisitions == 0)
 | 
			
		||||
            this.emit('release');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    isAcquired: function() {
 | 
			
		||||
        return this._acquisitions > 0;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(Hold.prototype);
 | 
			
		||||
 | 
			
		||||
const Batch = new Lang.Class({
 | 
			
		||||
    Name: 'Batch',
 | 
			
		||||
    Extends: Task,
 | 
			
		||||
 | 
			
		||||
    _init: function(scope, tasks) {
 | 
			
		||||
        this.parent();
 | 
			
		||||
 | 
			
		||||
        this.tasks = [];
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < tasks.length; i++) {
 | 
			
		||||
            let task;
 | 
			
		||||
 | 
			
		||||
            if (tasks[i] instanceof Task) {
 | 
			
		||||
                task = tasks[i];
 | 
			
		||||
            } else if (typeof tasks[i] == 'function') {
 | 
			
		||||
                task = new Task(scope, tasks[i]);
 | 
			
		||||
            } else {
 | 
			
		||||
                throw new Error('Batch tasks must be functions or Task, Hold or Batch objects');
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.tasks.push(task);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    process: function() {
 | 
			
		||||
        throw new Error('Not implemented');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    runTask: function() {
 | 
			
		||||
        if (!(this._currentTaskIndex in this.tasks)) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return this.tasks[this._currentTaskIndex].run();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _finish: function() {
 | 
			
		||||
        this.hold.release();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    nextTask: function() {
 | 
			
		||||
        this._currentTaskIndex++;
 | 
			
		||||
 | 
			
		||||
        // if the entire batch of tasks is finished, release
 | 
			
		||||
        // the hold and notify anyone waiting on the batch
 | 
			
		||||
        if (this._currentTaskIndex >= this.tasks.length) {
 | 
			
		||||
            this._finish();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.process();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _start: function() {
 | 
			
		||||
        // acquire a hold to get released when the entire
 | 
			
		||||
        // batch of tasks is finished
 | 
			
		||||
        this.hold = new Hold();
 | 
			
		||||
        this._currentTaskIndex = 0;
 | 
			
		||||
        this.process();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    run: function() {
 | 
			
		||||
        this._start();
 | 
			
		||||
 | 
			
		||||
        // hold may be destroyed at this point
 | 
			
		||||
        // if we're already done running
 | 
			
		||||
        return this.hold;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    cancel: function() {
 | 
			
		||||
        this.tasks = this.tasks.splice(0, this._currentTaskIndex + 1);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(Batch.prototype);
 | 
			
		||||
 | 
			
		||||
const ConcurrentBatch = new Lang.Class({
 | 
			
		||||
    Name: 'ConcurrentBatch',
 | 
			
		||||
    Extends: Batch,
 | 
			
		||||
 | 
			
		||||
    process: function() {
 | 
			
		||||
       let hold = this.runTask();
 | 
			
		||||
 | 
			
		||||
       if (hold) {
 | 
			
		||||
           this.hold.acquireUntilAfter(hold);
 | 
			
		||||
       }
 | 
			
		||||
 | 
			
		||||
       // Regardless of the state of the just run task,
 | 
			
		||||
       // fire off the next one, so all the tasks can run
 | 
			
		||||
       // concurrently.
 | 
			
		||||
       this.nextTask();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(ConcurrentBatch.prototype);
 | 
			
		||||
 | 
			
		||||
const ConsecutiveBatch = new Lang.Class({
 | 
			
		||||
    Name: 'ConsecutiveBatch',
 | 
			
		||||
    Extends: Batch,
 | 
			
		||||
 | 
			
		||||
    process: function() {
 | 
			
		||||
       let hold = this.runTask();
 | 
			
		||||
 | 
			
		||||
       if (hold && hold.isAcquired()) {
 | 
			
		||||
           // This task is inhibiting the batch. Wait on it
 | 
			
		||||
           // before processing the next one.
 | 
			
		||||
           let signalId = hold.connect('release',
 | 
			
		||||
                                       Lang.bind(this, function() {
 | 
			
		||||
                                           hold.disconnect(signalId);
 | 
			
		||||
                                           this.nextTask();
 | 
			
		||||
                                       }));
 | 
			
		||||
           return;
 | 
			
		||||
       } else {
 | 
			
		||||
           // This task finished, process the next one
 | 
			
		||||
           this.nextTask();
 | 
			
		||||
       }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(ConsecutiveBatch.prototype);
 | 
			
		||||
@@ -1,22 +0,0 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
 | 
			
		||||
const ConsoleKitManagerIface = <interface name='org.freedesktop.ConsoleKit.Manager'>
 | 
			
		||||
<method name='CanRestart'>
 | 
			
		||||
    <arg type='b' direction='out'/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name='CanStop'>
 | 
			
		||||
    <arg type='b' direction='out'/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name='Restart' />
 | 
			
		||||
<method name='Stop' />
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
const ConsoleKitProxy = Gio.DBusProxy.makeProxyWrapper(ConsoleKitManagerIface);
 | 
			
		||||
 | 
			
		||||
function ConsoleKitManager() {
 | 
			
		||||
    return new ConsoleKitProxy(Gio.DBus.system,
 | 
			
		||||
                               'org.freedesktop.ConsoleKit',
 | 
			
		||||
                               '/org/freedesktop/ConsoleKit/Manager');
 | 
			
		||||
};
 | 
			
		||||
@@ -1,27 +0,0 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const FprintManagerIface = <interface name='net.reactivated.Fprint.Manager'>
 | 
			
		||||
<method name='GetDefaultDevice'>
 | 
			
		||||
    <arg type='o' direction='out' />
 | 
			
		||||
</method>
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
const FprintManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(FprintManagerIface);
 | 
			
		||||
 | 
			
		||||
function FprintManager() {
 | 
			
		||||
    var self = new Gio.DBusProxy({ g_connection: Gio.DBus.system,
 | 
			
		||||
                                   g_interface_name: FprintManagerInfo.name,
 | 
			
		||||
                                   g_interface_info: FprintManagerInfo,
 | 
			
		||||
                                   g_name: 'net.reactivated.Fprint',
 | 
			
		||||
                                   g_object_path: '/net/reactivated/Fprint/Manager',
 | 
			
		||||
                                   g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START |
 | 
			
		||||
                                             Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
 | 
			
		||||
 | 
			
		||||
    self.init(null);
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,170 +0,0 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2011 Red Hat, Inc
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 2, or (at your option)
 | 
			
		||||
 * any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 | 
			
		||||
 * 02111-1307, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const UPowerGlib = imports.gi.UPowerGlib;
 | 
			
		||||
 | 
			
		||||
const ConsoleKit = imports.gdm.consoleKit;
 | 
			
		||||
const Systemd = imports.gdm.systemd;
 | 
			
		||||
 | 
			
		||||
const PanelMenu = imports.ui.panelMenu;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
 | 
			
		||||
const PowerMenuButton = new Lang.Class({
 | 
			
		||||
    Name: 'PowerMenuButton',
 | 
			
		||||
    Extends: PanelMenu.SystemStatusButton,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.parent('system-shutdown', null);
 | 
			
		||||
        this._upClient = new UPowerGlib.Client();
 | 
			
		||||
 | 
			
		||||
        if (Systemd.haveSystemd())
 | 
			
		||||
            this._systemdLoginManager = new Systemd.SystemdLoginManager();
 | 
			
		||||
        else
 | 
			
		||||
            this._consoleKitManager = new ConsoleKit.ConsoleKitManager();
 | 
			
		||||
 | 
			
		||||
        this._createSubMenu();
 | 
			
		||||
 | 
			
		||||
        this._upClient.connect('notify::can-suspend',
 | 
			
		||||
                               Lang.bind(this, this._updateHaveSuspend));
 | 
			
		||||
        this._updateHaveSuspend();
 | 
			
		||||
 | 
			
		||||
        // ConsoleKit doesn't send notifications when shutdown/reboot
 | 
			
		||||
        // are disabled, so we update the menu item each time the menu opens
 | 
			
		||||
        this.menu.connect('open-state-changed', Lang.bind(this,
 | 
			
		||||
            function(menu, open) {
 | 
			
		||||
                if (open) {
 | 
			
		||||
                    this._updateHaveShutdown();
 | 
			
		||||
                    this._updateHaveRestart();
 | 
			
		||||
                }
 | 
			
		||||
            }));
 | 
			
		||||
        this._updateHaveShutdown();
 | 
			
		||||
        this._updateHaveRestart();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateVisibility: function() {
 | 
			
		||||
        let shouldBeVisible = (this._haveSuspend || this._haveShutdown || this._haveRestart);
 | 
			
		||||
        this.actor.visible = shouldBeVisible;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateHaveShutdown: function() {
 | 
			
		||||
 | 
			
		||||
        if (Systemd.haveSystemd()) {
 | 
			
		||||
            this._systemdLoginManager.CanPowerOffRemote(Lang.bind(this,
 | 
			
		||||
                function(result, error) {
 | 
			
		||||
                    if (!error)
 | 
			
		||||
                        this._haveShutdown = result != 'no';
 | 
			
		||||
                    else
 | 
			
		||||
                        this._haveShutdown = false;
 | 
			
		||||
 | 
			
		||||
                    this._powerOffItem.actor.visible = this._haveShutdown;
 | 
			
		||||
                    this._updateVisibility();
 | 
			
		||||
                }));
 | 
			
		||||
        } else {
 | 
			
		||||
            this._consoleKitManager.CanStopRemote(Lang.bind(this,
 | 
			
		||||
                function(result, error) {
 | 
			
		||||
                    if (!error)
 | 
			
		||||
                        this._haveShutdown = result;
 | 
			
		||||
                    else
 | 
			
		||||
                        this._haveShutdown = false;
 | 
			
		||||
 | 
			
		||||
                    this._powerOffItem.actor.visible = this._haveShutdown;
 | 
			
		||||
                    this._updateVisibility();
 | 
			
		||||
                }));
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateHaveRestart: function() {
 | 
			
		||||
 | 
			
		||||
        if (Systemd.haveSystemd()) {
 | 
			
		||||
            this._systemdLoginManager.CanRebootRemote(Lang.bind(this,
 | 
			
		||||
                function(result, error) {
 | 
			
		||||
                    if (!error)
 | 
			
		||||
                        this._haveRestart = result != 'no';
 | 
			
		||||
                    else
 | 
			
		||||
                        this._haveRestart = false;
 | 
			
		||||
 | 
			
		||||
                    this._restartItem.actor.visible = this._haveRestart;
 | 
			
		||||
                    this._updateVisibility();
 | 
			
		||||
                }));
 | 
			
		||||
        } else {
 | 
			
		||||
            this._consoleKitManager.CanRestartRemote(Lang.bind(this,
 | 
			
		||||
                function(result, error) {
 | 
			
		||||
                    if (!error)
 | 
			
		||||
                        this._haveRestart = result;
 | 
			
		||||
                    else
 | 
			
		||||
                        this._haveRestart = false;
 | 
			
		||||
 | 
			
		||||
                    this._restartItem.actor.visible = this._haveRestart;
 | 
			
		||||
                    this._updateVisibility();
 | 
			
		||||
                }));
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateHaveSuspend: function() {
 | 
			
		||||
        this._haveSuspend = this._upClient.get_can_suspend();
 | 
			
		||||
        this._suspendItem.actor.visible = this._haveSuspend;
 | 
			
		||||
        this._updateVisibility();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createSubMenu: function() {
 | 
			
		||||
        let item;
 | 
			
		||||
 | 
			
		||||
        item = new PopupMenu.PopupMenuItem(_("Suspend"));
 | 
			
		||||
        item.connect('activate', Lang.bind(this, this._onActivateSuspend));
 | 
			
		||||
        this.menu.addMenuItem(item);
 | 
			
		||||
        this._suspendItem = item;
 | 
			
		||||
 | 
			
		||||
        item = new PopupMenu.PopupMenuItem(_("Restart"));
 | 
			
		||||
        item.connect('activate', Lang.bind(this, this._onActivateRestart));
 | 
			
		||||
        this.menu.addMenuItem(item);
 | 
			
		||||
        this._restartItem = item;
 | 
			
		||||
 | 
			
		||||
        item = new PopupMenu.PopupMenuItem(_("Power Off"));
 | 
			
		||||
        item.connect('activate', Lang.bind(this, this._onActivatePowerOff));
 | 
			
		||||
        this.menu.addMenuItem(item);
 | 
			
		||||
        this._powerOffItem = item;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onActivateSuspend: function() {
 | 
			
		||||
        if (this._haveSuspend)
 | 
			
		||||
            this._upClient.suspend_sync(null);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onActivateRestart: function() {
 | 
			
		||||
        if (!this._haveRestart)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (Systemd.haveSystemd())
 | 
			
		||||
            this._systemdLoginManager.RebootRemote(true);
 | 
			
		||||
        else
 | 
			
		||||
            this._consoleKitManager.RestartRemote();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onActivatePowerOff: function() {
 | 
			
		||||
        if (!this._haveShutdown)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (Systemd.haveSystemd())
 | 
			
		||||
            this._systemdLoginManager.PowerOffRemote(true);
 | 
			
		||||
        else
 | 
			
		||||
            this._consoleKitManager.StopRemote();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
@@ -1,31 +0,0 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
 | 
			
		||||
const SystemdLoginManagerIface = <interface name='org.freedesktop.login1.Manager'>
 | 
			
		||||
<method name='PowerOff'>
 | 
			
		||||
    <arg type='b' direction='in'/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name='Reboot'>
 | 
			
		||||
    <arg type='b' direction='in'/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name='CanPowerOff'>
 | 
			
		||||
    <arg type='s' direction='out'/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name='CanReboot'>
 | 
			
		||||
    <arg type='s' direction='out'/>
 | 
			
		||||
</method>
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
const SystemdLoginManagerProxy = Gio.DBusProxy.makeProxyWrapper(SystemdLoginManagerIface);
 | 
			
		||||
 | 
			
		||||
function SystemdLoginManager() {
 | 
			
		||||
    return new SystemdLoginManagerProxy(Gio.DBus.system,
 | 
			
		||||
                                        'org.freedesktop.login1',
 | 
			
		||||
                                        '/org/freedesktop/login1');
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function haveSystemd() {
 | 
			
		||||
    return GLib.access("/sys/fs/cgroup/systemd", 0) >= 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
/* mode: js2; indent-tabs-mode: nil; tab-size: 4 */
 | 
			
		||||
/* The name of this package (not localized) */
 | 
			
		||||
const PACKAGE_NAME = '@PACKAGE_NAME@';
 | 
			
		||||
/* The version of this package */
 | 
			
		||||
@@ -8,10 +7,4 @@ const PACKAGE_VERSION = '@PACKAGE_VERSION@';
 | 
			
		||||
const GJS_VERSION = '@GJS_VERSION@';
 | 
			
		||||
/* 1 if gnome-bluetooth is available, 0 otherwise */
 | 
			
		||||
const HAVE_BLUETOOTH = @HAVE_BLUETOOTH@;
 | 
			
		||||
/* gettext package */
 | 
			
		||||
const GETTEXT_PACKAGE = '@GETTEXT_PACKAGE@';
 | 
			
		||||
/* locale dir */
 | 
			
		||||
const LOCALEDIR = '@datadir@/locale';
 | 
			
		||||
/* other standard directories */
 | 
			
		||||
const LIBEXECDIR = '@libexecdir@';
 | 
			
		||||
const SYSCONFDIR = '@sysconfdir@';
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										140
									
								
								js/misc/docInfo.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,140 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const Search = imports.ui.search;
 | 
			
		||||
 | 
			
		||||
const THUMBNAIL_ICON_MARGIN = 2;
 | 
			
		||||
 | 
			
		||||
function DocInfo(recentInfo) {
 | 
			
		||||
    this._init(recentInfo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DocInfo.prototype = {
 | 
			
		||||
    _init : function(recentInfo) {
 | 
			
		||||
        this.recentInfo = recentInfo;
 | 
			
		||||
        // We actually used get_modified() instead of get_visited()
 | 
			
		||||
        // here, as GtkRecentInfo doesn't updated get_visited()
 | 
			
		||||
        // correctly. See http://bugzilla.gnome.org/show_bug.cgi?id=567094
 | 
			
		||||
        this.timestamp = recentInfo.get_modified();
 | 
			
		||||
        this.name = recentInfo.get_display_name();
 | 
			
		||||
        this._lowerName = this.name.toLowerCase();
 | 
			
		||||
        this.uri = recentInfo.get_uri();
 | 
			
		||||
        this.mimeType = recentInfo.get_mime_type();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    createIcon : function(size) {
 | 
			
		||||
        return St.TextureCache.get_default().load_recent_thumbnail(size, this.recentInfo);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    launch : function(workspaceIndex) {
 | 
			
		||||
        Shell.DocSystem.get_default().open(this.recentInfo, workspaceIndex);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    matchTerms: function(terms) {
 | 
			
		||||
        let mtype = Search.MatchType.NONE;
 | 
			
		||||
        for (let i = 0; i < terms.length; i++) {
 | 
			
		||||
            let term = terms[i];
 | 
			
		||||
            let idx = this._lowerName.indexOf(term);
 | 
			
		||||
            if (idx == 0) {
 | 
			
		||||
                mtype = Search.MatchType.PREFIX;
 | 
			
		||||
            } else if (idx > 0) {
 | 
			
		||||
                if (mtype == Search.MatchType.NONE)
 | 
			
		||||
                    mtype = Search.MatchType.SUBSTRING;
 | 
			
		||||
            } else {
 | 
			
		||||
                return Search.MatchType.NONE;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return mtype;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var docManagerInstance = null;
 | 
			
		||||
 | 
			
		||||
function getDocManager() {
 | 
			
		||||
    if (docManagerInstance == null)
 | 
			
		||||
        docManagerInstance = new DocManager();
 | 
			
		||||
    return docManagerInstance;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * DocManager wraps the DocSystem, primarily to expose DocInfo objects.
 | 
			
		||||
 */
 | 
			
		||||
function DocManager() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DocManager.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._docSystem = Shell.DocSystem.get_default();
 | 
			
		||||
        this._infosByTimestamp = [];
 | 
			
		||||
        this._infosByUri = {};
 | 
			
		||||
        this._docSystem.connect('changed', Lang.bind(this, this._reload));
 | 
			
		||||
        this._reload();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _reload: function() {
 | 
			
		||||
        let docs = this._docSystem.get_all();
 | 
			
		||||
        this._infosByTimestamp = [];
 | 
			
		||||
        this._infosByUri = {};
 | 
			
		||||
        for (let i = 0; i < docs.length; i++) {
 | 
			
		||||
            let recentInfo = docs[i];
 | 
			
		||||
 | 
			
		||||
            let docInfo = new DocInfo(recentInfo);
 | 
			
		||||
            this._infosByTimestamp.push(docInfo);
 | 
			
		||||
            this._infosByUri[docInfo.uri] = docInfo;
 | 
			
		||||
        }
 | 
			
		||||
        this.emit('changed');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getTimestampOrderedInfos: function() {
 | 
			
		||||
        return this._infosByTimestamp;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getInfosByUri: function() {
 | 
			
		||||
        return this._infosByUri;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    lookupByUri: function(uri) {
 | 
			
		||||
        return this._infosByUri[uri];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    queueExistenceCheck: function(count) {
 | 
			
		||||
        return this._docSystem.queue_existence_check(count);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _searchDocs: function(items, terms) {
 | 
			
		||||
        let multiplePrefixMatches = [];
 | 
			
		||||
        let prefixMatches = [];
 | 
			
		||||
        let multipleSubtringMatches = [];
 | 
			
		||||
        let substringMatches = [];
 | 
			
		||||
        for (let i = 0; i < items.length; i++) {
 | 
			
		||||
            let item = items[i];
 | 
			
		||||
            let mtype = item.matchTerms(terms);
 | 
			
		||||
            if (mtype == Search.MatchType.MULTIPLE_PREFIX)
 | 
			
		||||
                multiplePrefixMatches.push(item.uri);
 | 
			
		||||
            else if (mtype == Search.MatchType.PREFIX)
 | 
			
		||||
                prefixMatches.push(item.uri);
 | 
			
		||||
            else if (mtype == Search.MatchType.MULTIPLE_SUBSTRING)
 | 
			
		||||
                multipleSubtringMatches.push(item.uri);
 | 
			
		||||
            else if (mtype == Search.MatchType.SUBSTRING)
 | 
			
		||||
                substringMatches.push(item.uri);
 | 
			
		||||
         }
 | 
			
		||||
        return multiplePrefixMatches.concat(prefixMatches.concat(multipleSubtringMatches.concat(substringMatches)));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    initialSearch: function(terms) {
 | 
			
		||||
        return this._searchDocs(this._infosByTimestamp, terms);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    subsearch: function(previousResults, terms) {
 | 
			
		||||
        return this._searchDocs(previousResults.map(Lang.bind(this,
 | 
			
		||||
            function(url) {
 | 
			
		||||
                return this._infosByUri[url];
 | 
			
		||||
            })), terms);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Signals.addSignalMethods(DocManager.prototype);
 | 
			
		||||
@@ -1,199 +0,0 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
// Common utils for the extension system and the extension
 | 
			
		||||
// preferences tool
 | 
			
		||||
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const ShellJS = imports.gi.ShellJS;
 | 
			
		||||
 | 
			
		||||
const Config = imports.misc.config;
 | 
			
		||||
 | 
			
		||||
const ExtensionType = {
 | 
			
		||||
    SYSTEM: 1,
 | 
			
		||||
    PER_USER: 2
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// GFile for user extensions
 | 
			
		||||
var userExtensionsDir = null;
 | 
			
		||||
 | 
			
		||||
// Maps uuid -> metadata object
 | 
			
		||||
const extensions = {};
 | 
			
		||||
 | 
			
		||||
function getCurrentExtension() {
 | 
			
		||||
    let stack = (new Error()).stack;
 | 
			
		||||
 | 
			
		||||
    // Assuming we're importing this directly from an extension (and we shouldn't
 | 
			
		||||
    // ever not be), its UUID should be directly in the path here.
 | 
			
		||||
    let extensionStackLine = stack.split('\n')[1];
 | 
			
		||||
    if (!extensionStackLine)
 | 
			
		||||
        throw new Error('Could not find current extension');
 | 
			
		||||
 | 
			
		||||
    // The stack line is like:
 | 
			
		||||
    //   init([object Object])@/home/user/data/gnome-shell/extensions/u@u.id/prefs.js:8
 | 
			
		||||
    //
 | 
			
		||||
    // In the case that we're importing from
 | 
			
		||||
    // module scope, the first field is blank:
 | 
			
		||||
    //   @/home/user/data/gnome-shell/extensions/u@u.id/prefs.js:8
 | 
			
		||||
    let match = new RegExp('@(.+):\\d+').exec(extensionStackLine);
 | 
			
		||||
    if (!match)
 | 
			
		||||
        throw new Error('Could not find current extension');
 | 
			
		||||
 | 
			
		||||
    let path = match[1];
 | 
			
		||||
    let file = Gio.File.new_for_path(path);
 | 
			
		||||
 | 
			
		||||
    // Walk up the directory tree, looking for an extesion with
 | 
			
		||||
    // the same UUID as a directory name.
 | 
			
		||||
    while (file != null) {
 | 
			
		||||
        let extension = extensions[file.get_basename()];
 | 
			
		||||
        if (extension !== undefined)
 | 
			
		||||
            return extension;
 | 
			
		||||
        file = file.get_parent();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    throw new Error('Could not find current extension');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * versionCheck:
 | 
			
		||||
 * @required: an array of versions we're compatible with
 | 
			
		||||
 * @current: the version we have
 | 
			
		||||
 *
 | 
			
		||||
 * Check if a component is compatible for an extension.
 | 
			
		||||
 * @required is an array, and at least one version must match.
 | 
			
		||||
 * @current must be in the format <major>.<minor>.<point>.<micro>
 | 
			
		||||
 * <micro> is always ignored
 | 
			
		||||
 * <point> is ignored if <minor> is even (so you can target the
 | 
			
		||||
 * whole stable release)
 | 
			
		||||
 * <minor> and <major> must match
 | 
			
		||||
 * Each target version must be at least <major> and <minor>
 | 
			
		||||
 */
 | 
			
		||||
function versionCheck(required, current) {
 | 
			
		||||
    let currentArray = current.split('.');
 | 
			
		||||
    let major = currentArray[0];
 | 
			
		||||
    let minor = currentArray[1];
 | 
			
		||||
    let point = currentArray[2];
 | 
			
		||||
    for (let i = 0; i < required.length; i++) {
 | 
			
		||||
        let requiredArray = required[i].split('.');
 | 
			
		||||
        if (requiredArray[0] == major &&
 | 
			
		||||
            requiredArray[1] == minor &&
 | 
			
		||||
            (requiredArray[2] == point ||
 | 
			
		||||
             (requiredArray[2] == undefined && parseInt(minor) % 2 == 0)))
 | 
			
		||||
            return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function isOutOfDate(extension) {
 | 
			
		||||
    if (!versionCheck(extension.metadata['shell-version'], Config.PACKAGE_VERSION))
 | 
			
		||||
        return true;
 | 
			
		||||
 | 
			
		||||
    if (extension.metadata['js-version'] && !versionCheck(extension.metadata['js-version'], Config.GJS_VERSION))
 | 
			
		||||
        return true;
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function createExtensionObject(uuid, dir, type) {
 | 
			
		||||
    let info;
 | 
			
		||||
 | 
			
		||||
    let metadataFile = dir.get_child('metadata.json');
 | 
			
		||||
    if (!metadataFile.query_exists(null)) {
 | 
			
		||||
        throw new Error('Missing metadata.json');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let metadataContents, success, tag;
 | 
			
		||||
    try {
 | 
			
		||||
        [success, metadataContents, tag] = metadataFile.load_contents(null);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
        throw new Error('Failed to load metadata.json: ' + e);
 | 
			
		||||
    }
 | 
			
		||||
    let meta;
 | 
			
		||||
    try {
 | 
			
		||||
        meta = JSON.parse(metadataContents);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
        throw new Error('Failed to parse metadata.json: ' + e);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let requiredProperties = ['uuid', 'name', 'description', 'shell-version'];
 | 
			
		||||
    for (let i = 0; i < requiredProperties.length; i++) {
 | 
			
		||||
        let prop = requiredProperties[i];
 | 
			
		||||
        if (!meta[prop]) {
 | 
			
		||||
            throw new Error('missing "' + prop + '" property in metadata.json');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Encourage people to add this
 | 
			
		||||
    if (!meta.url) {
 | 
			
		||||
        log('Warning: Missing "url" property in %s/metadata.json'.format(uuid));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (uuid != meta.uuid) {
 | 
			
		||||
        throw new Error('uuid "' + meta.uuid + '" from metadata.json does not match directory name "' + uuid + '"');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let extension = {};
 | 
			
		||||
 | 
			
		||||
    extension.metadata = meta;
 | 
			
		||||
    extension.uuid = meta.uuid;
 | 
			
		||||
    extension.type = type;
 | 
			
		||||
    extension.dir = dir;
 | 
			
		||||
    extension.path = dir.get_path();
 | 
			
		||||
    extension.error = '';
 | 
			
		||||
    extension.hasPrefs = dir.get_child('prefs.js').query_exists(null);
 | 
			
		||||
 | 
			
		||||
    extensions[uuid] = extension;
 | 
			
		||||
 | 
			
		||||
    return extension;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _extension = null;
 | 
			
		||||
 | 
			
		||||
function installImporter(extension) {
 | 
			
		||||
    _extension = extension;
 | 
			
		||||
    ShellJS.add_extension_importer('imports.misc.extensionUtils._extension', 'imports', extension.path);
 | 
			
		||||
    _extension = null;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function init() {
 | 
			
		||||
    let userExtensionsPath = GLib.build_filenamev([global.userdatadir, 'extensions']);
 | 
			
		||||
    userExtensionsDir = Gio.file_new_for_path(userExtensionsPath);
 | 
			
		||||
    try {
 | 
			
		||||
        if (!userExtensionsDir.query_exists(null))
 | 
			
		||||
            userExtensionsDir.make_directory_with_parents(null);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
        logError(e, 'Could not create extensions directory');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function scanExtensionsInDirectory(callback, dir, type) {
 | 
			
		||||
    let fileEnum;
 | 
			
		||||
    let file, info;
 | 
			
		||||
    try {
 | 
			
		||||
        fileEnum = dir.enumerate_children('standard::*', Gio.FileQueryInfoFlags.NONE, null);
 | 
			
		||||
    } catch(e) {
 | 
			
		||||
        logError(e, 'Could not enumerate extensions directory');
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while ((info = fileEnum.next_file(null)) != null) {
 | 
			
		||||
        let fileType = info.get_file_type();
 | 
			
		||||
        if (fileType != Gio.FileType.DIRECTORY)
 | 
			
		||||
            continue;
 | 
			
		||||
        let uuid = info.get_name();
 | 
			
		||||
        let extensionDir = dir.get_child(uuid);
 | 
			
		||||
        callback(uuid, extensionDir, type);
 | 
			
		||||
    }
 | 
			
		||||
    fileEnum.close(null);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function scanExtensions(callback) {
 | 
			
		||||
    let systemDataDirs = GLib.get_system_data_dirs();
 | 
			
		||||
    scanExtensionsInDirectory(callback, userExtensionsDir, ExtensionType.PER_USER);
 | 
			
		||||
    for (let i = 0; i < systemDataDirs.length; i++) {
 | 
			
		||||
        let dirPath = GLib.build_filenamev([systemDataDirs[i], 'gnome-shell', 'extensions']);
 | 
			
		||||
        let dir = Gio.file_new_for_path(dirPath);
 | 
			
		||||
        if (dir.query_exists(null))
 | 
			
		||||
            scanExtensionsInDirectory(callback, dir, ExtensionType.SYSTEM);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,5 +1,3 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
 | 
			
		||||
@@ -22,25 +20,3 @@ function listDirAsync(file, callback) {
 | 
			
		||||
        enumerator.next_files_async(100, GLib.PRIORITY_LOW, null, onNextFileComplete);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function deleteGFile(file) {
 | 
			
		||||
    // Work around 'delete' being a keyword in JS.
 | 
			
		||||
    return file['delete'](null);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function recursivelyDeleteDir(dir) {
 | 
			
		||||
    let children = dir.enumerate_children('standard::name,standard::type',
 | 
			
		||||
                                          Gio.FileQueryInfoFlags.NONE, null);
 | 
			
		||||
 | 
			
		||||
    let info, child;
 | 
			
		||||
    while ((info = children.next_file(null)) != null) {
 | 
			
		||||
        let type = info.get_file_type();
 | 
			
		||||
        let child = dir.get_child(info.get_name());
 | 
			
		||||
        if (type == Gio.FileType.REGULAR)
 | 
			
		||||
            deleteGFile(child);
 | 
			
		||||
        else if (type == Gio.FileType.DIRECTORY)
 | 
			
		||||
            recursivelyDeleteDir(child);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    deleteGFile(dir);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										60
									
								
								js/misc/format.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,60 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This function is intended to extend the String object and provide
 | 
			
		||||
 * an String.format API for string formatting.
 | 
			
		||||
 * It has to be set up using String.prototype.format = Format.format;
 | 
			
		||||
 * Usage:
 | 
			
		||||
 * "somestring %s %d".format('hello', 5);
 | 
			
		||||
 * It supports %s, %d, %x and %f, for %f it also support precisions like
 | 
			
		||||
 * "%.2f".format(1.526). All specifiers can be prefixed with a minimum
 | 
			
		||||
 * field width, e.g. "%5s".format("foo"). Unless the width is prefixed
 | 
			
		||||
 * with '0', the formatted string will be padded with spaces.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
function format() {
 | 
			
		||||
    let str = this;
 | 
			
		||||
    let i = 0;
 | 
			
		||||
    let args = arguments;
 | 
			
		||||
 | 
			
		||||
    return str.replace(/%([0-9]+)?(?:\.([0-9]+))?(.)/g, function (str, widthGroup, precisionGroup, genericGroup) {
 | 
			
		||||
 | 
			
		||||
                    if (precisionGroup != '' && genericGroup != 'f')
 | 
			
		||||
                        throw new Error("Precision can only be specified for 'f'");
 | 
			
		||||
 | 
			
		||||
                    let fillChar = (widthGroup[0] == '0') ? '0' : ' ';
 | 
			
		||||
                    let width = parseInt(widthGroup, 10) || 0;
 | 
			
		||||
 | 
			
		||||
                    function fillWidth(s, c, w) {
 | 
			
		||||
                        let fill = '';
 | 
			
		||||
                        for (let i = 0; i < w; i++)
 | 
			
		||||
                            fill += c;
 | 
			
		||||
                        return fill.substr(s.length) + s;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    let s = '';
 | 
			
		||||
                    switch (genericGroup) {
 | 
			
		||||
                        case '%':
 | 
			
		||||
                            return '%';
 | 
			
		||||
                            break;
 | 
			
		||||
                        case 's':
 | 
			
		||||
                            s = args[i++].toString();
 | 
			
		||||
                            break;
 | 
			
		||||
                        case 'd':
 | 
			
		||||
                            s = parseInt(args[i++]).toString();
 | 
			
		||||
                            break;
 | 
			
		||||
                        case 'x':
 | 
			
		||||
                            s = parseInt(args[i++]).toString(16);
 | 
			
		||||
                            break;
 | 
			
		||||
                        case 'f':
 | 
			
		||||
                            if (precisionGroup == '')
 | 
			
		||||
                                s = parseFloat(args[i++]).toString();
 | 
			
		||||
                            else
 | 
			
		||||
                                s = parseFloat(args[i++]).toFixed(parseInt(precisionGroup));
 | 
			
		||||
                            break;
 | 
			
		||||
                        default:
 | 
			
		||||
                            throw new Error('Unsupported conversion character %' + genericGroup);
 | 
			
		||||
                    }
 | 
			
		||||
                    return fillWidth(s, fillChar, width);
 | 
			
		||||
                });
 | 
			
		||||
}
 | 
			
		||||
@@ -1,18 +1,20 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const PresenceIface = <interface name="org.gnome.SessionManager.Presence">
 | 
			
		||||
<method name="SetStatus">
 | 
			
		||||
    <arg type="u" direction="in"/>
 | 
			
		||||
</method>
 | 
			
		||||
<property name="status" type="u" access="readwrite"/>
 | 
			
		||||
<signal name="StatusChanged">
 | 
			
		||||
    <arg type="u" direction="out"/>
 | 
			
		||||
</signal>
 | 
			
		||||
</interface>;
 | 
			
		||||
const PresenceIface = {
 | 
			
		||||
    name: 'org.gnome.SessionManager.Presence',
 | 
			
		||||
    methods: [{ name: 'SetStatus',
 | 
			
		||||
                inSignature: 'u',
 | 
			
		||||
                outSignature: '' }],
 | 
			
		||||
    properties: [{ name: 'status',
 | 
			
		||||
                   signature: 'u',
 | 
			
		||||
                   access: 'readwrite' }],
 | 
			
		||||
    signals: [{ name: 'StatusChanged',
 | 
			
		||||
                inSignature: 'u' }]
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const PresenceStatus = {
 | 
			
		||||
    AVAILABLE: 0,
 | 
			
		||||
@@ -21,41 +23,103 @@ const PresenceStatus = {
 | 
			
		||||
    IDLE: 3
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var PresenceProxy = Gio.DBusProxy.makeProxyWrapper(PresenceIface);
 | 
			
		||||
function Presence(initCallback, cancellable) {
 | 
			
		||||
    return new PresenceProxy(Gio.DBus.session, 'org.gnome.SessionManager',
 | 
			
		||||
                             '/org/gnome/SessionManager/Presence', initCallback, cancellable);
 | 
			
		||||
function Presence() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Presence.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        DBus.session.proxifyObject(this, 'org.gnome.SessionManager', '/org/gnome/SessionManager/Presence', this);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getStatus: function(callback) {
 | 
			
		||||
        this.GetRemote('status', Lang.bind(this,
 | 
			
		||||
            function(status, ex) {
 | 
			
		||||
                if (!ex)
 | 
			
		||||
                    callback(this, status);
 | 
			
		||||
            }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setStatus: function(status) {
 | 
			
		||||
        this.SetStatusRemote(status);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
DBus.proxifyPrototype(Presence.prototype, PresenceIface);
 | 
			
		||||
 | 
			
		||||
// Note inhibitors are immutable objects, so they don't
 | 
			
		||||
// change at runtime (changes always come in the form
 | 
			
		||||
// of new inhibitors)
 | 
			
		||||
const InhibitorIface = <interface name="org.gnome.SessionManager.Inhibitor">
 | 
			
		||||
<method name="GetAppId">
 | 
			
		||||
    <arg type="s" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="GetReason">
 | 
			
		||||
    <arg type="s" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
</interface>;
 | 
			
		||||
const InhibitorIface = {
 | 
			
		||||
    name: 'org.gnome.SessionManager.Inhibitor',
 | 
			
		||||
    properties: [{ name: 'app_id',
 | 
			
		||||
                   signature: 's',
 | 
			
		||||
                   access: 'readonly' },
 | 
			
		||||
                 { name: 'client_id',
 | 
			
		||||
                   signature: 's',
 | 
			
		||||
                   access: 'readonly' },
 | 
			
		||||
                 { name: 'reason',
 | 
			
		||||
                   signature: 's',
 | 
			
		||||
                   access: 'readonly' },
 | 
			
		||||
                 { name: 'flags',
 | 
			
		||||
                   signature: 'u',
 | 
			
		||||
                   access: 'readonly' },
 | 
			
		||||
                 { name: 'toplevel_xid',
 | 
			
		||||
                   signature: 'u',
 | 
			
		||||
                   access: 'readonly' },
 | 
			
		||||
                 { name: 'cookie',
 | 
			
		||||
                   signature: 'u',
 | 
			
		||||
                   access: 'readonly' }],
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var InhibitorProxy = Gio.DBusProxy.makeProxyWrapper(InhibitorIface);
 | 
			
		||||
function Inhibitor(objectPath, initCallback, cancellable) {
 | 
			
		||||
    return new InhibitorProxy(Gio.DBus.session, 'org.gnome.SessionManager', objectPath, initCallback, cancellable);
 | 
			
		||||
function Inhibitor(objectPath) {
 | 
			
		||||
    this._init(objectPath);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Inhibitor.prototype = {
 | 
			
		||||
    _init: function(objectPath) {
 | 
			
		||||
        DBus.session.proxifyObject(this,
 | 
			
		||||
                                   "org.gnome.SessionManager",
 | 
			
		||||
                                   objectPath);
 | 
			
		||||
        this.isLoaded = false;
 | 
			
		||||
        this._loadingPropertiesCount = InhibitorIface.properties.length;
 | 
			
		||||
        for (let i = 0; i < InhibitorIface.properties.length; i++) {
 | 
			
		||||
            let propertyName = InhibitorIface.properties[i].name;
 | 
			
		||||
            this.GetRemote(propertyName, Lang.bind(this,
 | 
			
		||||
                function(value, exception) {
 | 
			
		||||
                    if (exception)
 | 
			
		||||
                        return;
 | 
			
		||||
 | 
			
		||||
                    this[propertyName] = value;
 | 
			
		||||
                    this._loadingPropertiesCount--;
 | 
			
		||||
 | 
			
		||||
                    if (this._loadingPropertiesCount == 0) {
 | 
			
		||||
                        this.isLoaded = true;
 | 
			
		||||
                        this.emit("is-loaded");
 | 
			
		||||
                    }
 | 
			
		||||
                }));
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
DBus.proxifyPrototype(Inhibitor.prototype, InhibitorIface);
 | 
			
		||||
Signals.addSignalMethods(Inhibitor.prototype);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Not the full interface, only the methods we use
 | 
			
		||||
const SessionManagerIface = <interface name="org.gnome.SessionManager">
 | 
			
		||||
<method name="Logout">
 | 
			
		||||
    <arg type="u" direction="in" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="Shutdown" />
 | 
			
		||||
<method name="CanShutdown">
 | 
			
		||||
    <arg type="b" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
</interface>;
 | 
			
		||||
const SessionManagerIface = {
 | 
			
		||||
    name: 'org.gnome.SessionManager',
 | 
			
		||||
    methods: [
 | 
			
		||||
        { name: 'Logout', inSignature: 'u', outSignature: '' },
 | 
			
		||||
        { name: 'Shutdown', inSignature: '', outSignature: '' }
 | 
			
		||||
    ]
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var SessionManagerProxy = Gio.DBusProxy.makeProxyWrapper(SessionManagerIface);
 | 
			
		||||
function SessionManager(initCallback, cancellable) {
 | 
			
		||||
    return new SessionManagerProxy(Gio.DBus.session, 'org.gnome.SessionManager', '/org/gnome/SessionManager', initCallback, cancellable);
 | 
			
		||||
function SessionManager() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SessionManager.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        DBus.session.proxifyObject(this, 'org.gnome.SessionManager', '/org/gnome/SessionManager');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
DBus.proxifyPrototype(SessionManager.prototype, SessionManagerIface);
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
@@ -7,9 +7,11 @@ const Params = imports.misc.params;
 | 
			
		||||
 | 
			
		||||
const DEFAULT_LIMIT = 512;
 | 
			
		||||
 | 
			
		||||
const HistoryManager = new Lang.Class({
 | 
			
		||||
    Name: 'HistoryManager',
 | 
			
		||||
function HistoryManager(params) {
 | 
			
		||||
    this._init(params);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HistoryManager.prototype = {
 | 
			
		||||
    _init: function(params) {
 | 
			
		||||
        params = Params.parse(params, { gsettingsKey: null,
 | 
			
		||||
                                        limit: DEFAULT_LIMIT,
 | 
			
		||||
@@ -109,5 +111,5 @@ const HistoryManager = new Lang.Class({
 | 
			
		||||
        if (this._key)
 | 
			
		||||
            global.settings.set_strv(this._key, this._history);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(HistoryManager.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,246 +0,0 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
// Returns a list of potential completions for text. Completions either
 | 
			
		||||
// follow a dot (e.g. foo.ba -> bar) or they are picked from globalCompletionList (e.g. fo -> foo)
 | 
			
		||||
// commandHeader is prefixed on any expression before it is eval'ed.  It will most likely
 | 
			
		||||
// consist of global constants that might not carry over from the calling environment.
 | 
			
		||||
//
 | 
			
		||||
// This function is likely the one you want to call from external modules
 | 
			
		||||
function getCompletions(text, commandHeader, globalCompletionList) {
 | 
			
		||||
    let methods = [];
 | 
			
		||||
    let expr, base;
 | 
			
		||||
    let attrHead = '';
 | 
			
		||||
    if (globalCompletionList == null) {
 | 
			
		||||
        globalCompletionList = [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let offset = getExpressionOffset(text, text.length - 1);
 | 
			
		||||
    if (offset >= 0) {
 | 
			
		||||
        text = text.slice(offset);
 | 
			
		||||
 | 
			
		||||
        // Look for expressions like "Main.panel.foo" and match Main.panel and foo
 | 
			
		||||
        let matches = text.match(/(.*)\.(.*)/);
 | 
			
		||||
        if (matches) {
 | 
			
		||||
            [expr, base, attrHead] = matches;
 | 
			
		||||
 | 
			
		||||
            methods = getPropertyNamesFromExpression(base, commandHeader).filter(function(attr) {
 | 
			
		||||
                return attr.slice(0, attrHead.length) == attrHead;
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Look for the empty expression or partially entered words
 | 
			
		||||
        // not proceeded by a dot and match them against global constants
 | 
			
		||||
        matches = text.match(/^(\w*)$/);
 | 
			
		||||
        if (text == '' || matches) {
 | 
			
		||||
            [expr, attrHead] = matches;
 | 
			
		||||
            methods = globalCompletionList.filter(function(attr) {
 | 
			
		||||
                return attr.slice(0, attrHead.length) == attrHead;
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return [methods, attrHead];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// A few functions for parsing strings of javascript code.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// Identify characters that delimit an expression.  That is,
 | 
			
		||||
// if we encounter anything that isn't a letter, '.', ')', or ']',
 | 
			
		||||
// we should stop parsing.
 | 
			
		||||
function isStopChar(c) {
 | 
			
		||||
    return !c.match(/[\w\.\)\]]/);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Given the ending position of a quoted string, find where it starts
 | 
			
		||||
function findMatchingQuote(expr, offset) {
 | 
			
		||||
    let quoteChar = expr.charAt(offset);
 | 
			
		||||
    for (let i = offset - 1; i >= 0; --i) {
 | 
			
		||||
        if (expr.charAt(i) == quoteChar && expr.charAt(i-1) != '\\'){
 | 
			
		||||
            return i;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Given the ending position of a regex, find where it starts
 | 
			
		||||
function findMatchingSlash(expr, offset) {
 | 
			
		||||
    for (let i = offset - 1; i >= 0; --i) {
 | 
			
		||||
        if (expr.charAt(i) == '/' && expr.charAt(i-1) != '\\'){
 | 
			
		||||
            return i;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// If expr.charAt(offset) is ')' or ']',
 | 
			
		||||
// return the position of the corresponding '(' or '[' bracket.
 | 
			
		||||
// This function does not check for syntactic correctness.  e.g.,
 | 
			
		||||
// findMatchingBrace("[(])", 3) returns 1.
 | 
			
		||||
function findMatchingBrace(expr, offset) {
 | 
			
		||||
    let closeBrace = expr.charAt(offset);
 | 
			
		||||
    let openBrace = ({')': '(', ']': '['})[closeBrace];
 | 
			
		||||
 | 
			
		||||
    function findTheBrace(expr, offset) {
 | 
			
		||||
        if (offset < 0) {
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (expr.charAt(offset) == openBrace) {
 | 
			
		||||
            return offset;
 | 
			
		||||
        }
 | 
			
		||||
        if (expr.charAt(offset).match(/['"]/)) {
 | 
			
		||||
            return findTheBrace(expr, findMatchingQuote(expr, offset) - 1);
 | 
			
		||||
        }
 | 
			
		||||
        if (expr.charAt(offset) == '/') {
 | 
			
		||||
            return findTheBrace(expr, findMatchingSlash(expr, offset) - 1);
 | 
			
		||||
        }
 | 
			
		||||
        if (expr.charAt(offset) == closeBrace) {
 | 
			
		||||
            return findTheBrace(expr, findTheBrace(expr, offset - 1) - 1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return findTheBrace(expr, offset - 1);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return findTheBrace(expr, offset - 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Walk expr backwards from offset looking for the beginning of an
 | 
			
		||||
// expression suitable for passing to eval.
 | 
			
		||||
// There is no guarantee of correct javascript syntax between the return
 | 
			
		||||
// value and offset.  This function is meant to take a string like
 | 
			
		||||
// "foo(Obj.We.Are.Completing" and allow you to extract "Obj.We.Are.Completing"
 | 
			
		||||
function getExpressionOffset(expr, offset) {
 | 
			
		||||
    while (offset >= 0) {
 | 
			
		||||
        let currChar = expr.charAt(offset);
 | 
			
		||||
 | 
			
		||||
        if (isStopChar(currChar)){
 | 
			
		||||
            return offset + 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (currChar.match(/[\)\]]/)) {
 | 
			
		||||
            offset = findMatchingBrace(expr, offset);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        --offset;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return offset + 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Things with non-word characters or that start with a number
 | 
			
		||||
// are not accessible via .foo notation and so aren't returned
 | 
			
		||||
function isValidPropertyName(w) {
 | 
			
		||||
    return !(w.match(/\W/) || w.match(/^\d/));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// To get all properties (enumerable and not), we need to walk
 | 
			
		||||
// the prototype chain ourselves
 | 
			
		||||
function getAllProps(obj) {
 | 
			
		||||
    if (obj === null || obj === undefined) {
 | 
			
		||||
        return [];
 | 
			
		||||
    }
 | 
			
		||||
    return Object.getOwnPropertyNames(obj).concat( getAllProps(Object.getPrototypeOf(obj)) );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Given a string _expr_, returns all methods
 | 
			
		||||
// that can be accessed via '.' notation.
 | 
			
		||||
// e.g., expr="({ foo: null, bar: null, 4: null })" will
 | 
			
		||||
// return ["foo", "bar", ...] but the list will not include "4",
 | 
			
		||||
// since methods accessed with '.' notation must star with a letter or _.
 | 
			
		||||
function getPropertyNamesFromExpression(expr, commandHeader) {
 | 
			
		||||
    if (commandHeader == null) {
 | 
			
		||||
        commandHeader = '';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let obj = {};
 | 
			
		||||
    if (!isUnsafeExpression(expr)) {
 | 
			
		||||
        try {
 | 
			
		||||
                obj = eval(commandHeader + expr);
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            return [];
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        return [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let propsUnique = {};
 | 
			
		||||
    if (typeof obj === 'object'){
 | 
			
		||||
        let allProps = getAllProps(obj);
 | 
			
		||||
        // Get only things we are allowed to complete following a '.'
 | 
			
		||||
        allProps = allProps.filter( isValidPropertyName );
 | 
			
		||||
 | 
			
		||||
        // Make sure propsUnique contains one key for every
 | 
			
		||||
        // property so we end up with a unique list of properties
 | 
			
		||||
        allProps.map(function(p){ propsUnique[p] = null; });
 | 
			
		||||
    }
 | 
			
		||||
    return Object.keys(propsUnique).sort();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Given a list of words, returns the longest prefix they all have in common
 | 
			
		||||
function getCommonPrefix(words) {
 | 
			
		||||
    let word = words[0];
 | 
			
		||||
    for (let i = 0; i < word.length; i++) {
 | 
			
		||||
        for (let w = 1; w < words.length; w++) {
 | 
			
		||||
            if (words[w].charAt(i) != word.charAt(i))
 | 
			
		||||
                return word.slice(0, i);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return word;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns true if there is reason to think that eval(str)
 | 
			
		||||
// will modify the global scope
 | 
			
		||||
function isUnsafeExpression(str) {
 | 
			
		||||
    // Remove any blocks that are quoted or are in a regex
 | 
			
		||||
    function removeLiterals(str) {
 | 
			
		||||
        if (str.length == 0) {
 | 
			
		||||
            return '';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let currChar = str.charAt(str.length - 1);
 | 
			
		||||
        if (currChar == '"' || currChar == '\'') {
 | 
			
		||||
            return removeLiterals(str.slice(0, findMatchingQuote(str, str.length - 1)));
 | 
			
		||||
        } else if (currChar == '/') {
 | 
			
		||||
            return removeLiterals(str.slice(0, findMatchingSlash(str, str.length - 1)));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return removeLiterals(str.slice(0, str.length - 1)) + currChar;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check for any sort of assignment
 | 
			
		||||
    // The strategy used is dumb: remove any quotes
 | 
			
		||||
    // or regexs and comparison operators and see if there is an '=' character.
 | 
			
		||||
    // If there is, it might be an unsafe assignment.
 | 
			
		||||
 | 
			
		||||
    let prunedStr = removeLiterals(str);
 | 
			
		||||
    prunedStr = prunedStr.replace(/[=!]==/g, '');    //replace === and !== with nothing
 | 
			
		||||
    prunedStr = prunedStr.replace(/[=<>!]=/g, '');    //replace ==, <=, >=, != with nothing
 | 
			
		||||
 | 
			
		||||
    if (prunedStr.match(/=/)) {
 | 
			
		||||
        return true;
 | 
			
		||||
    } else if (prunedStr.match(/;/)) {
 | 
			
		||||
        // If we contain a semicolon not inside of a quote/regex, assume we're unsafe as well
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns a list of global keywords derived from str
 | 
			
		||||
function getDeclaredConstants(str) {
 | 
			
		||||
    let ret = [];
 | 
			
		||||
    str.split(';').forEach(function(s) {
 | 
			
		||||
        let base, keyword;
 | 
			
		||||
        let match = s.match(/const\s+(\w+)\s*=/);
 | 
			
		||||
        if (match) {
 | 
			
		||||
            [base, keyword] = match;
 | 
			
		||||
            ret.push(keyword);
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
@@ -8,39 +8,33 @@ const Signals = imports.signals;
 | 
			
		||||
// The following are not the complete interfaces, just the methods we need
 | 
			
		||||
// (or may need in the future)
 | 
			
		||||
 | 
			
		||||
const ModemGsmNetworkInterface = <interface name="org.freedesktop.ModemManager.Modem.Gsm.Network">
 | 
			
		||||
<method name="GetRegistrationInfo">
 | 
			
		||||
    <arg type="(uss)" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="GetSignalQuality">
 | 
			
		||||
    <arg type="u" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<property name="AccessTechnology" type="u" access="read" />
 | 
			
		||||
<signal name="SignalQuality">
 | 
			
		||||
    <arg type="u" direction="out" />
 | 
			
		||||
</signal>
 | 
			
		||||
<signal name="RegistrationInfo">
 | 
			
		||||
    <arg type="u" direction="out" />
 | 
			
		||||
    <arg type="s" direction="out" />
 | 
			
		||||
    <arg type="s" direction="out" />
 | 
			
		||||
</signal>
 | 
			
		||||
</interface>;
 | 
			
		||||
const ModemGsmNetworkInterface = {
 | 
			
		||||
    name: 'org.freedesktop.ModemManager.Modem.Gsm.Network',
 | 
			
		||||
    methods: [
 | 
			
		||||
        { name: 'GetRegistrationInfo', inSignature: '', outSignature: 'uss' },
 | 
			
		||||
        { name: 'GetSignalQuality', inSignature: '', outSignature: 'u' }
 | 
			
		||||
    ],
 | 
			
		||||
    properties: [
 | 
			
		||||
        { name: 'AccessTechnology', signature: 'u', access: 'read' }
 | 
			
		||||
    ],
 | 
			
		||||
    signals: [
 | 
			
		||||
        { name: 'SignalQuality', inSignature: 'u' },
 | 
			
		||||
        { name: 'RegistrationInfo', inSignature: 'uss' }
 | 
			
		||||
    ]
 | 
			
		||||
};
 | 
			
		||||
const ModemGsmNetworkProxy = DBus.makeProxyClass(ModemGsmNetworkInterface);
 | 
			
		||||
 | 
			
		||||
const ModemGsmNetworkProxy = Gio.DBusProxy.makeProxyWrapper(ModemGsmNetworkInterface);
 | 
			
		||||
 | 
			
		||||
const ModemCdmaInterface = <interface name="org.freedesktop.ModemManager.Modem.Cdma">
 | 
			
		||||
<method name="GetSignalQuality">
 | 
			
		||||
    <arg type="u" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="GetServingSystem">
 | 
			
		||||
    <arg type="(usu)" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<signal name="SignalQuality">
 | 
			
		||||
    <arg type="u" direction="out" />
 | 
			
		||||
</signal>
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
const ModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(ModemCdmaInterface);
 | 
			
		||||
const ModemCdmaInterface = {
 | 
			
		||||
    name: 'org.freedesktop.ModemManager.Modem.Cdma',
 | 
			
		||||
    methods: [
 | 
			
		||||
        { name: 'GetSignalQuality', inSignature: '', outSignature: 'u' },
 | 
			
		||||
        { name: 'GetServingSystem', inSignature: '', outSignature: 'usu' }
 | 
			
		||||
    ],
 | 
			
		||||
    signals: [
 | 
			
		||||
        { name: 'SignalQuality', inSignature: 'u' }
 | 
			
		||||
    ]
 | 
			
		||||
};
 | 
			
		||||
const ModemCdmaProxy = DBus.makeProxyClass(ModemCdmaInterface);
 | 
			
		||||
 | 
			
		||||
let _providersTable;
 | 
			
		||||
function _getProvidersTable() {
 | 
			
		||||
@@ -50,25 +44,27 @@ function _getProvidersTable() {
 | 
			
		||||
    return _providersTable = providers;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ModemGsm = new Lang.Class({
 | 
			
		||||
    Name: 'ModemGsm',
 | 
			
		||||
function ModemGsm() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ModemGsm.prototype = {
 | 
			
		||||
    _init: function(path) {
 | 
			
		||||
        this._proxy = new ModemGsmNetworkProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
 | 
			
		||||
        this._proxy = new ModemGsmNetworkProxy(DBus.system, 'org.freedesktop.ModemManager', path);
 | 
			
		||||
 | 
			
		||||
        this.signal_quality = 0;
 | 
			
		||||
        this.operator_name = null;
 | 
			
		||||
 | 
			
		||||
        // Code is duplicated because the function have different signatures
 | 
			
		||||
        this._proxy.connectSignal('SignalQuality', Lang.bind(this, function(proxy, sender, [quality]) {
 | 
			
		||||
        this._proxy.connect('SignalQuality', Lang.bind(this, function(proxy, quality) {
 | 
			
		||||
            this.signal_quality = quality;
 | 
			
		||||
            this.emit('notify::signal-quality');
 | 
			
		||||
        }));
 | 
			
		||||
        this._proxy.connectSignal('RegistrationInfo', Lang.bind(this, function(proxy, sender, [status, code, name]) {
 | 
			
		||||
        this._proxy.connect('RegistrationInfo', Lang.bind(this, function(proxy, status, code, name) {
 | 
			
		||||
            this.operator_name = this._findOperatorName(name, code);
 | 
			
		||||
            this.emit('notify::operator-name');
 | 
			
		||||
        }));
 | 
			
		||||
        this._proxy.GetRegistrationInfoRemote(Lang.bind(this, function([result], err) {
 | 
			
		||||
        this._proxy.GetRegistrationInfoRemote(Lang.bind(this, function(result, err) {
 | 
			
		||||
            if (err) {
 | 
			
		||||
                log(err);
 | 
			
		||||
                return;
 | 
			
		||||
@@ -150,19 +146,21 @@ const ModemGsm = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        return name3 || name2 || null;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
}
 | 
			
		||||
Signals.addSignalMethods(ModemGsm.prototype);
 | 
			
		||||
 | 
			
		||||
const ModemCdma = new Lang.Class({
 | 
			
		||||
    Name: 'ModemCdma',
 | 
			
		||||
function ModemCdma() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ModemCdma.prototype = {
 | 
			
		||||
    _init: function(path) {
 | 
			
		||||
        this._proxy = new ModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
 | 
			
		||||
        this._proxy = new ModemCdmaProxy(DBus.system, 'org.freedesktop.ModemManager', path);
 | 
			
		||||
 | 
			
		||||
        this.signal_quality = 0;
 | 
			
		||||
        this.operator_name = null;
 | 
			
		||||
        this._proxy.connectSignal('SignalQuality', Lang.bind(this, function(proxy, sender, params) {
 | 
			
		||||
            this.signal_quality = params[0];
 | 
			
		||||
        this._proxy.connect('SignalQuality', Lang.bind(this, function(proxy, quality) {
 | 
			
		||||
            this.signal_quality = quality;
 | 
			
		||||
            this.emit('notify::signal-quality');
 | 
			
		||||
 | 
			
		||||
            // receiving this signal means the device got activated
 | 
			
		||||
@@ -183,7 +181,7 @@ const ModemCdma = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _refreshServingSystem: function() {
 | 
			
		||||
        this._proxy.GetServingSystemRemote(Lang.bind(this, function([result], err) {
 | 
			
		||||
        this._proxy.GetServingSystemRemote(Lang.bind(this, function(result, err) {
 | 
			
		||||
            if (err) {
 | 
			
		||||
                // it will return an error if the device is not connected
 | 
			
		||||
                this.operator_name = null;
 | 
			
		||||
@@ -223,5 +221,5 @@ const ModemCdma = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(ModemCdma.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
// parse:
 | 
			
		||||
// @params: caller-provided parameter object, or %null
 | 
			
		||||
 
 | 
			
		||||
@@ -1,48 +0,0 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
 | 
			
		||||
const ScreenSaverIface = <interface name="org.gnome.ScreenSaver">
 | 
			
		||||
<method name="GetActive">
 | 
			
		||||
    <arg type="b" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="Lock" />
 | 
			
		||||
<method name="SetActive">
 | 
			
		||||
    <arg type="b" direction="in" />
 | 
			
		||||
</method>
 | 
			
		||||
<signal name="ActiveChanged">
 | 
			
		||||
    <arg type="b" direction="out" />
 | 
			
		||||
</signal>
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
const ScreenSaverInfo = Gio.DBusInterfaceInfo.new_for_xml(ScreenSaverIface);
 | 
			
		||||
 | 
			
		||||
function ScreenSaverProxy() {
 | 
			
		||||
    var self = new Gio.DBusProxy({ g_connection: Gio.DBus.session,
 | 
			
		||||
				   g_interface_name: ScreenSaverInfo.name,
 | 
			
		||||
				   g_interface_info: ScreenSaverInfo,
 | 
			
		||||
				   g_name: 'org.gnome.ScreenSaver',
 | 
			
		||||
				   g_object_path: '/org/gnome/ScreenSaver',
 | 
			
		||||
                                   g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START |
 | 
			
		||||
                                             Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
 | 
			
		||||
    self.init(null);
 | 
			
		||||
    self.screenSaverActive = false;
 | 
			
		||||
 | 
			
		||||
    self.connectSignal('ActiveChanged', function(proxy, senderName, [isActive]) {
 | 
			
		||||
        self.screenSaverActive = isActive;
 | 
			
		||||
    });
 | 
			
		||||
    self.connect('notify::g-name-owner', function() {
 | 
			
		||||
        if (self.g_name_owner) {
 | 
			
		||||
            self.GetActiveRemote(function(result, excp) {
 | 
			
		||||
                if (result) {
 | 
			
		||||
                    let [isActive] = result;
 | 
			
		||||
                    self.screenSaverActive = isActive;
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        } else
 | 
			
		||||
            self.screenSaverActive = false;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										100
									
								
								js/misc/util.js
									
									
									
									
									
								
							
							
						
						@@ -1,4 +1,4 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const Gdk = imports.gi.Gdk;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
@@ -7,32 +7,11 @@ const Shell = imports.gi.Shell;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
 | 
			
		||||
// http://daringfireball.net/2010/07/improved_regex_for_matching_urls
 | 
			
		||||
const _balancedParens = '\\((?:[^\\s()<>]+|(?:\\(?:[^\\s()<>]+\\)))*\\)';
 | 
			
		||||
const _leadingJunk = '[\\s`(\\[{\'\\"<\u00AB\u201C\u2018]';
 | 
			
		||||
const _notTrailingJunk = '[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u201C\u201D\u2018\u2019]';
 | 
			
		||||
const Gettext = imports.gettext.domain('gnome-shell');
 | 
			
		||||
const _ = Gettext.gettext;
 | 
			
		||||
 | 
			
		||||
const _urlRegexp = new RegExp(
 | 
			
		||||
    '(^|' + _leadingJunk + ')' +
 | 
			
		||||
    '(' +
 | 
			
		||||
        '(?:' +
 | 
			
		||||
            '[a-z][\\w-]+://' +                   // scheme://
 | 
			
		||||
            '|' +
 | 
			
		||||
            'www\\d{0,3}[.]' +                    // www.
 | 
			
		||||
            '|' +
 | 
			
		||||
            '[a-z0-9.\\-]+[.][a-z]{2,4}/' +       // foo.xx/
 | 
			
		||||
        ')' +
 | 
			
		||||
        '(?:' +                                   // one or more:
 | 
			
		||||
            '[^\\s()<>]+' +                       // run of non-space non-()
 | 
			
		||||
            '|' +                                 // or
 | 
			
		||||
            _balancedParens +                     // balanced parens
 | 
			
		||||
        ')+' +
 | 
			
		||||
        '(?:' +                                   // end with:
 | 
			
		||||
            _balancedParens +                     // balanced parens
 | 
			
		||||
            '|' +                                 // or
 | 
			
		||||
            _notTrailingJunk +                    // last non-junk char
 | 
			
		||||
        ')' +
 | 
			
		||||
    ')', 'gi');
 | 
			
		||||
/* http://daringfireball.net/2010/07/improved_regex_for_matching_urls */
 | 
			
		||||
const _urlRegexp = new RegExp('\\b(([a-z][\\w-]+:(/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}/)([^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:\'\\".,<>?«»“”‘’]))', 'gi');
 | 
			
		||||
 | 
			
		||||
// findUrls:
 | 
			
		||||
// @str: string to find URLs in
 | 
			
		||||
@@ -45,7 +24,7 @@ const _urlRegexp = new RegExp(
 | 
			
		||||
function findUrls(str) {
 | 
			
		||||
    let res = [], match;
 | 
			
		||||
    while ((match = _urlRegexp.exec(str)))
 | 
			
		||||
        res.push({ url: match[2], pos: match.index + match[1].length });
 | 
			
		||||
        res.push({ url: match[0], pos: match.index });
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -69,7 +48,7 @@ function spawn(argv) {
 | 
			
		||||
// occur when trying to parse or start the program.
 | 
			
		||||
function spawnCommandLine(command_line) {
 | 
			
		||||
    try {
 | 
			
		||||
        let [success, argv] = GLib.shell_parse_argv(command_line);
 | 
			
		||||
        let [success, argc, argv] = GLib.shell_parse_argv(command_line);
 | 
			
		||||
        trySpawn(argv);
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        _handleSpawnError(command_line, err);
 | 
			
		||||
@@ -83,11 +62,10 @@ function spawnCommandLine(command_line) {
 | 
			
		||||
// this will throw an error.
 | 
			
		||||
function trySpawn(argv)
 | 
			
		||||
{
 | 
			
		||||
    var success, pid;
 | 
			
		||||
    try {
 | 
			
		||||
        [success, pid] = GLib.spawn_async(null, argv, null,
 | 
			
		||||
                                          GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD,
 | 
			
		||||
                                          null, null);
 | 
			
		||||
        GLib.spawn_async(null, argv, null,
 | 
			
		||||
                         GLib.SpawnFlags.SEARCH_PATH,
 | 
			
		||||
                         null, null);
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        if (err.code == GLib.SpawnError.G_SPAWN_ERROR_NOENT) {
 | 
			
		||||
            err.message = _("Command not found");
 | 
			
		||||
@@ -102,10 +80,6 @@ function trySpawn(argv)
 | 
			
		||||
 | 
			
		||||
        throw err;
 | 
			
		||||
    }
 | 
			
		||||
    // 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 () {}, null);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// trySpawnCommandLine:
 | 
			
		||||
@@ -114,10 +88,10 @@ function trySpawn(argv)
 | 
			
		||||
// Runs @command_line in the background. If launching @command_line
 | 
			
		||||
// fails, this will throw an error.
 | 
			
		||||
function trySpawnCommandLine(command_line) {
 | 
			
		||||
    let success, argv;
 | 
			
		||||
    let success, argc, argv;
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        [success, argv] = GLib.shell_parse_argv(command_line);
 | 
			
		||||
        [success, argc, argv] = GLib.shell_parse_argv(command_line);
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
        // Replace "Error invoking GLib.shell_parse_argv: " with
 | 
			
		||||
        // something nicer
 | 
			
		||||
@@ -237,53 +211,3 @@ function fixupPCIDescription(desc) {
 | 
			
		||||
 | 
			
		||||
    return out.join(' ');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// lowerBound:
 | 
			
		||||
// @array: an array or array-like object, already sorted
 | 
			
		||||
//         according to @cmp
 | 
			
		||||
// @val: the value to add
 | 
			
		||||
// @cmp: a comparator (or undefined to compare as numbers)
 | 
			
		||||
//
 | 
			
		||||
// Returns the position of the first element that is not
 | 
			
		||||
// lower than @val, according to @cmp.
 | 
			
		||||
// That is, returns the first position at which it
 | 
			
		||||
// is possible to insert @val without violating the
 | 
			
		||||
// order.
 | 
			
		||||
// This is quite like an ordinary binary search, except
 | 
			
		||||
// that it doesn't stop at first element comparing equal.
 | 
			
		||||
 | 
			
		||||
function lowerBound(array, val, cmp) {
 | 
			
		||||
    let min, max, mid, v;
 | 
			
		||||
    cmp = cmp || function(a, b) { return a - b; };
 | 
			
		||||
 | 
			
		||||
    if (array.length == 0)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    min = 0; max = array.length;
 | 
			
		||||
    while (min < (max - 1)) {
 | 
			
		||||
        mid = Math.floor((min + max) / 2);
 | 
			
		||||
        v = cmp(array[mid], val);
 | 
			
		||||
 | 
			
		||||
        if (v < 0)
 | 
			
		||||
            min = mid + 1;
 | 
			
		||||
        else
 | 
			
		||||
            max = mid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (min == max || cmp(array[min], val) < 0) ? max : min;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// insertSorted:
 | 
			
		||||
// @array: an array sorted according to @cmp
 | 
			
		||||
// @val: a value to insert
 | 
			
		||||
// @cmp: the sorting function
 | 
			
		||||
//
 | 
			
		||||
// Inserts @val into @array, preserving the
 | 
			
		||||
// sorting invariants.
 | 
			
		||||
// Returns the position at which it was inserted
 | 
			
		||||
function insertSorted(array, val, cmp) {
 | 
			
		||||
    let pos = lowerBound(array, val, cmp);
 | 
			
		||||
    array.splice(pos, 0, val);
 | 
			
		||||
 | 
			
		||||
    return pos;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Scripting = imports.ui.scripting;
 | 
			
		||||
@@ -113,10 +113,10 @@ function run() {
 | 
			
		||||
 | 
			
		||||
    for (let i = 0; i < 2; i++) {
 | 
			
		||||
        Scripting.scriptEvent('applicationsShowStart');
 | 
			
		||||
        Main.overview._viewSelector.switchTab('applications');
 | 
			
		||||
        Main.overview.viewSelector.switchTab('applications');
 | 
			
		||||
        yield Scripting.waitLeisure();
 | 
			
		||||
        Scripting.scriptEvent('applicationsShowDone');
 | 
			
		||||
        Main.overview._viewSelector.switchTab('windows');
 | 
			
		||||
        Main.overview.viewSelector.switchTab('windows');
 | 
			
		||||
        yield Scripting.waitLeisure();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										391
									
								
								js/ui/altTab.js
									
									
									
									
									
								
							
							
						
						@@ -1,23 +1,20 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gdk = imports.gi.Gdk;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Atk = imports.gi.Atk;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
 | 
			
		||||
const POPUP_APPICON_SIZE = 96;
 | 
			
		||||
const POPUP_SCROLL_TIME = 0.10; // seconds
 | 
			
		||||
const POPUP_DELAY_TIMEOUT = 150; // milliseconds
 | 
			
		||||
const POPUP_FADE_OUT_TIME = 0.1; // seconds
 | 
			
		||||
const POPUP_FADE_TIME = 0.1; // seconds
 | 
			
		||||
 | 
			
		||||
const APP_ICON_HOVER_TIMEOUT = 200; // milliseconds
 | 
			
		||||
 | 
			
		||||
@@ -33,21 +30,11 @@ function mod(a, b) {
 | 
			
		||||
    return (a + b) % b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function primaryModifier(mask) {
 | 
			
		||||
    if (mask == 0)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    let primary = 1;
 | 
			
		||||
    while (mask > 1) {
 | 
			
		||||
        mask >>= 1;
 | 
			
		||||
        primary <<= 1;
 | 
			
		||||
    }
 | 
			
		||||
    return primary;
 | 
			
		||||
function AltTabPopup() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const AltTabPopup = new Lang.Class({
 | 
			
		||||
    Name: 'AltTabPopup',
 | 
			
		||||
 | 
			
		||||
AltTabPopup.prototype = {
 | 
			
		||||
    _init : function() {
 | 
			
		||||
        this.actor = new Shell.GenericContainer({ name: 'altTabPopup',
 | 
			
		||||
                                                  reactive: true,
 | 
			
		||||
@@ -60,13 +47,11 @@ const AltTabPopup = new Lang.Class({
 | 
			
		||||
        this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
 | 
			
		||||
 | 
			
		||||
        this._haveModal = false;
 | 
			
		||||
        this._modifierMask = 0;
 | 
			
		||||
 | 
			
		||||
        this._currentApp = 0;
 | 
			
		||||
        this._currentWindow = -1;
 | 
			
		||||
        this._thumbnailTimeoutId = 0;
 | 
			
		||||
        this._motionTimeoutId = 0;
 | 
			
		||||
        this._initialDelayTimeoutId = 0;
 | 
			
		||||
 | 
			
		||||
        this.thumbnailsVisible = false;
 | 
			
		||||
 | 
			
		||||
@@ -89,7 +74,7 @@ const AltTabPopup = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _allocate: function (actor, box, flags) {
 | 
			
		||||
        let childBox = new Clutter.ActorBox();
 | 
			
		||||
        let primary = Main.layoutManager.primaryMonitor;
 | 
			
		||||
        let primary = global.get_primary_monitor();
 | 
			
		||||
 | 
			
		||||
        let leftPadding = this.actor.get_theme_node().get_padding(St.Side.LEFT);
 | 
			
		||||
        let rightPadding = this.actor.get_theme_node().get_padding(St.Side.RIGHT);
 | 
			
		||||
@@ -102,7 +87,7 @@ const AltTabPopup = new Lang.Class({
 | 
			
		||||
        let [childMinHeight, childNaturalHeight] = this._appSwitcher.actor.get_preferred_height(primary.width - hPadding);
 | 
			
		||||
        let [childMinWidth, childNaturalWidth] = this._appSwitcher.actor.get_preferred_width(childNaturalHeight);
 | 
			
		||||
        childBox.x1 = Math.max(primary.x + leftPadding, primary.x + Math.floor((primary.width - childNaturalWidth) / 2));
 | 
			
		||||
        childBox.x2 = Math.min(primary.x + primary.width - rightPadding, childBox.x1 + childNaturalWidth);
 | 
			
		||||
        childBox.x2 = Math.min(primary.x + primary.width - hPadding, childBox.x1 + childNaturalWidth);
 | 
			
		||||
        childBox.y1 = primary.y + Math.floor((primary.height - childNaturalHeight) / 2);
 | 
			
		||||
        childBox.y2 = childBox.y1 + childNaturalHeight;
 | 
			
		||||
        this._appSwitcher.actor.allocate(childBox, flags);
 | 
			
		||||
@@ -112,6 +97,8 @@ const AltTabPopup = new Lang.Class({
 | 
			
		||||
        // those calculations
 | 
			
		||||
        if (this._thumbnails) {
 | 
			
		||||
            let icon = this._appIcons[this._currentApp].actor;
 | 
			
		||||
            // Force a stage relayout to make sure we get the correct position
 | 
			
		||||
            global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, 0, 0);
 | 
			
		||||
            let [posX, posY] = icon.get_transformed_position();
 | 
			
		||||
            let thumbnailCenter = posX + icon.width / 2;
 | 
			
		||||
            let [childMinWidth, childNaturalWidth] = this._thumbnails.actor.get_preferred_width(-1);
 | 
			
		||||
@@ -127,57 +114,23 @@ const AltTabPopup = new Lang.Class({
 | 
			
		||||
            if (childBox.x2 > primary.x + primary.width - rightPadding)
 | 
			
		||||
                childBox.x2 = primary.x + primary.width - rightPadding;
 | 
			
		||||
            childBox.y1 = this._appSwitcher.actor.allocation.y2 + spacing;
 | 
			
		||||
            this._thumbnails.addClones(primary.y + primary.height - bottomPadding - childBox.y1);
 | 
			
		||||
            this._thumbnails.addClones(primary.height - bottomPadding - childBox.y1);
 | 
			
		||||
            let [childMinHeight, childNaturalHeight] = this._thumbnails.actor.get_preferred_height(-1);
 | 
			
		||||
            childBox.y2 = childBox.y1 + childNaturalHeight;
 | 
			
		||||
            this._thumbnails.actor.allocate(childBox, flags);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getAppLists: function() {
 | 
			
		||||
    show : function(backward, switch_group) {
 | 
			
		||||
        let tracker = Shell.WindowTracker.get_default();
 | 
			
		||||
        let appSys = Shell.AppSystem.get_default();
 | 
			
		||||
        let allApps = appSys.get_running ();
 | 
			
		||||
        let apps = tracker.get_running_apps ('');
 | 
			
		||||
 | 
			
		||||
        let screen = global.screen;
 | 
			
		||||
        let display = screen.get_display();
 | 
			
		||||
        let windows = display.get_tab_list(Meta.TabList.NORMAL_ALL, screen,
 | 
			
		||||
                                           screen.get_active_workspace());
 | 
			
		||||
 | 
			
		||||
        // windows is only the windows on the current workspace. For
 | 
			
		||||
        // each one, if it corresponds to an app we know, move that
 | 
			
		||||
        // app from allApps to apps.
 | 
			
		||||
        let apps = [];
 | 
			
		||||
        for (let i = 0; i < windows.length && allApps.length != 0; i++) {
 | 
			
		||||
            let app = tracker.get_window_app(windows[i]);
 | 
			
		||||
            let index = allApps.indexOf(app);
 | 
			
		||||
            if (index != -1) {
 | 
			
		||||
                apps.push(app);
 | 
			
		||||
                allApps.splice(index, 1);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Now @apps is a list of apps on the current workspace, in
 | 
			
		||||
        // standard Alt+Tab order (MRU except for minimized windows),
 | 
			
		||||
        // and allApps is a list of apps that only appear on other
 | 
			
		||||
        // workspaces, sorted by user_time, which is good enough.
 | 
			
		||||
        return [apps, allApps];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    show : function(backward, binding, mask) {
 | 
			
		||||
        let [localApps, otherApps] = this._getAppLists();
 | 
			
		||||
 | 
			
		||||
        if (localApps.length == 0 && otherApps.length == 0)
 | 
			
		||||
        if (!apps.length)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (!Main.pushModal(this.actor)) {
 | 
			
		||||
            // Probably someone else has a pointer grab, try again with keyboard only
 | 
			
		||||
            if (!Main.pushModal(this.actor, global.get_current_time(), Meta.ModalOptions.POINTER_ALREADY_GRABBED)) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (!Main.pushModal(this.actor))
 | 
			
		||||
            return false;
 | 
			
		||||
        this._haveModal = true;
 | 
			
		||||
        this._modifierMask = primaryModifier(mask);
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
 | 
			
		||||
        this.actor.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
 | 
			
		||||
@@ -185,21 +138,15 @@ const AltTabPopup = new Lang.Class({
 | 
			
		||||
        this.actor.connect('button-press-event', Lang.bind(this, this._clickedOutside));
 | 
			
		||||
        this.actor.connect('scroll-event', Lang.bind(this, this._onScroll));
 | 
			
		||||
 | 
			
		||||
        this._appSwitcher = new AppSwitcher(localApps, otherApps, this);
 | 
			
		||||
        this._appSwitcher = new AppSwitcher(apps, this);
 | 
			
		||||
        this.actor.add_actor(this._appSwitcher.actor);
 | 
			
		||||
        this._appSwitcher.connect('item-activated', Lang.bind(this, this._appActivated));
 | 
			
		||||
        this._appSwitcher.connect('item-entered', Lang.bind(this, this._appEntered));
 | 
			
		||||
 | 
			
		||||
        this._appIcons = this._appSwitcher.icons;
 | 
			
		||||
 | 
			
		||||
        // Need to force an allocation so we can figure out whether we
 | 
			
		||||
        // need to scroll when selecting
 | 
			
		||||
        this.actor.opacity = 0;
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
        this.actor.get_allocation_box();
 | 
			
		||||
 | 
			
		||||
        // Make the initial selection
 | 
			
		||||
        if (binding == 'switch-group') {
 | 
			
		||||
        if (switch_group) {
 | 
			
		||||
            if (backward) {
 | 
			
		||||
                this._select(0, this._appIcons[0].cachedWindows.length - 1);
 | 
			
		||||
            } else {
 | 
			
		||||
@@ -208,10 +155,6 @@ const AltTabPopup = new Lang.Class({
 | 
			
		||||
                else
 | 
			
		||||
                    this._select(0, 0);
 | 
			
		||||
            }
 | 
			
		||||
        } else if (binding == 'switch-group-backward') {
 | 
			
		||||
            this._select(0, this._appIcons[0].cachedWindows.length - 1);
 | 
			
		||||
        } else if (binding == 'switch-windows-backward') {
 | 
			
		||||
            this._select(this._appIcons.length - 1);
 | 
			
		||||
        } else if (this._appIcons.length == 1) {
 | 
			
		||||
            this._select(0);
 | 
			
		||||
        } else if (backward) {
 | 
			
		||||
@@ -226,18 +169,18 @@ const AltTabPopup = new Lang.Class({
 | 
			
		||||
        // details.) So we check now. (Have to do this after updating
 | 
			
		||||
        // selection.)
 | 
			
		||||
        let [x, y, mods] = global.get_pointer();
 | 
			
		||||
        if (!(mods & this._modifierMask)) {
 | 
			
		||||
        if (!(mods & Gdk.ModifierType.MOD1_MASK)) {
 | 
			
		||||
            this._finish();
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // We delay showing the popup so that fast Alt+Tab users aren't
 | 
			
		||||
        // disturbed by the popup briefly flashing.
 | 
			
		||||
        this._initialDelayTimeoutId = Mainloop.timeout_add(POPUP_DELAY_TIMEOUT,
 | 
			
		||||
                                                           Lang.bind(this, function () {
 | 
			
		||||
                                                               this.actor.opacity = 255;
 | 
			
		||||
                                                               this._initialDelayTimeoutId = 0;
 | 
			
		||||
                                                           }));
 | 
			
		||||
        this.actor.opacity = 0;
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
        Tweener.addTween(this.actor,
 | 
			
		||||
                         { opacity: 255,
 | 
			
		||||
                           time: POPUP_FADE_TIME,
 | 
			
		||||
                           transition: 'easeOutQuad'
 | 
			
		||||
                         });
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
@@ -266,31 +209,39 @@ const AltTabPopup = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _keyPressEvent : function(actor, event) {
 | 
			
		||||
        let keysym = event.get_key_symbol();
 | 
			
		||||
        let event_state = event.get_state();
 | 
			
		||||
        let event_state = Shell.get_event_state(event);
 | 
			
		||||
        let backwards = event_state & Clutter.ModifierType.SHIFT_MASK;
 | 
			
		||||
        let action = global.display.get_keybinding_action(event.get_key_code(), event_state);
 | 
			
		||||
        let action = global.screen.get_display().get_keybinding_action(event.get_key_code(), event_state);
 | 
			
		||||
 | 
			
		||||
        this._disableHover();
 | 
			
		||||
 | 
			
		||||
        if (keysym == Clutter.Escape) {
 | 
			
		||||
            this.destroy();
 | 
			
		||||
        } else if (action == Meta.KeyBindingAction.SWITCH_GROUP) {
 | 
			
		||||
        if (action == Meta.KeyBindingAction.SWITCH_GROUP)
 | 
			
		||||
            this._select(this._currentApp, backwards ? this._previousWindow() : this._nextWindow());
 | 
			
		||||
        } else if (action == Meta.KeyBindingAction.SWITCH_GROUP_BACKWARD) {
 | 
			
		||||
            this._select(this._currentApp, this._previousWindow());
 | 
			
		||||
        } else if (action == Meta.KeyBindingAction.SWITCH_WINDOWS) {
 | 
			
		||||
            this._select(backwards ? this._previousApp() : this._nextApp());
 | 
			
		||||
        } else if (action == Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD) {
 | 
			
		||||
            this._select(this._previousApp());
 | 
			
		||||
        } else if (this._thumbnailsFocused) {
 | 
			
		||||
            if (keysym == Clutter.Left)
 | 
			
		||||
        else if (keysym == Clutter.Escape)
 | 
			
		||||
            this.destroy();
 | 
			
		||||
        else if (this._thumbnailsFocused) {
 | 
			
		||||
            if (action == Meta.KeyBindingAction.SWITCH_WINDOWS)
 | 
			
		||||
                if (backwards) {
 | 
			
		||||
                    if (this._currentWindow == 0 || this._currentWindow == -1)
 | 
			
		||||
                        this._select(this._previousApp());
 | 
			
		||||
                    else
 | 
			
		||||
                        this._select(this._currentApp, this._previousWindow());
 | 
			
		||||
                } else {
 | 
			
		||||
                    if (this._currentWindow == this._appIcons[this._currentApp].cachedWindows.length - 1)
 | 
			
		||||
                        this._select(this._nextApp());
 | 
			
		||||
                    else
 | 
			
		||||
                        this._select(this._currentApp, this._nextWindow());
 | 
			
		||||
                }
 | 
			
		||||
            else if (keysym == Clutter.Left)
 | 
			
		||||
                this._select(this._currentApp, this._previousWindow());
 | 
			
		||||
            else if (keysym == Clutter.Right)
 | 
			
		||||
                this._select(this._currentApp, this._nextWindow());
 | 
			
		||||
            else if (keysym == Clutter.Up)
 | 
			
		||||
                this._select(this._currentApp, null, true);
 | 
			
		||||
        } else {
 | 
			
		||||
            if (keysym == Clutter.Left)
 | 
			
		||||
            if (action == Meta.KeyBindingAction.SWITCH_WINDOWS)
 | 
			
		||||
                this._select(backwards ? this._previousApp() : this._nextApp());
 | 
			
		||||
            else if (keysym == Clutter.Left)
 | 
			
		||||
                this._select(this._previousApp());
 | 
			
		||||
            else if (keysym == Clutter.Right)
 | 
			
		||||
                this._select(this._nextApp());
 | 
			
		||||
@@ -303,7 +254,7 @@ const AltTabPopup = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _keyReleaseEvent : function(actor, event) {
 | 
			
		||||
        let [x, y, mods] = global.get_pointer();
 | 
			
		||||
        let state = mods & this._modifierMask;
 | 
			
		||||
        let state = mods & Clutter.ModifierType.MOD1_MASK;
 | 
			
		||||
 | 
			
		||||
        if (state == 0)
 | 
			
		||||
            this._finish();
 | 
			
		||||
@@ -419,7 +370,7 @@ const AltTabPopup = new Lang.Class({
 | 
			
		||||
        if (this.actor.visible) {
 | 
			
		||||
            Tweener.addTween(this.actor,
 | 
			
		||||
                             { opacity: 0,
 | 
			
		||||
                               time: POPUP_FADE_OUT_TIME,
 | 
			
		||||
                               time: POPUP_FADE_TIME,
 | 
			
		||||
                               transition: 'easeOutQuad',
 | 
			
		||||
                               onComplete: Lang.bind(this,
 | 
			
		||||
                                   function() {
 | 
			
		||||
@@ -440,8 +391,6 @@ const AltTabPopup = new Lang.Class({
 | 
			
		||||
            Mainloop.source_remove(this._motionTimeoutId);
 | 
			
		||||
        if (this._thumbnailTimeoutId != 0)
 | 
			
		||||
            Mainloop.source_remove(this._thumbnailTimeoutId);
 | 
			
		||||
        if (this._initialDelayTimeoutId != 0)
 | 
			
		||||
            Mainloop.source_remove(this._initialDelayTimeoutId);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -519,7 +468,6 @@ const AltTabPopup = new Lang.Class({
 | 
			
		||||
                                                        })
 | 
			
		||||
                         });
 | 
			
		||||
        this._thumbnails = null;
 | 
			
		||||
        this._appSwitcher._items[this._currentApp].remove_accessible_state (Atk.StateType.EXPANDED);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createThumbnails : function() {
 | 
			
		||||
@@ -529,10 +477,6 @@ const AltTabPopup = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this.actor.add_actor(this._thumbnails.actor);
 | 
			
		||||
 | 
			
		||||
        // Need to force an allocation so we can figure out whether we
 | 
			
		||||
        // need to scroll when selecting
 | 
			
		||||
        this._thumbnails.actor.get_allocation_box();
 | 
			
		||||
 | 
			
		||||
        this._thumbnails.actor.opacity = 0;
 | 
			
		||||
        Tweener.addTween(this._thumbnails.actor,
 | 
			
		||||
                         { opacity: 255,
 | 
			
		||||
@@ -540,14 +484,14 @@ const AltTabPopup = new Lang.Class({
 | 
			
		||||
                           transition: 'easeOutQuad',
 | 
			
		||||
                           onComplete: Lang.bind(this, function () { this.thumbnailsVisible = true; })
 | 
			
		||||
                         });
 | 
			
		||||
 | 
			
		||||
        this._appSwitcher._items[this._currentApp].add_accessible_state (Atk.StateType.EXPANDED);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const SwitcherList = new Lang.Class({
 | 
			
		||||
    Name: 'SwitcherList',
 | 
			
		||||
function SwitcherList(squareItems) {
 | 
			
		||||
    this._init(squareItems);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SwitcherList.prototype = {
 | 
			
		||||
    _init : function(squareItems) {
 | 
			
		||||
        this.actor = new Shell.GenericContainer({ style_class: 'switcher-list' });
 | 
			
		||||
        this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
 | 
			
		||||
@@ -566,14 +510,14 @@ const SwitcherList = new Lang.Class({
 | 
			
		||||
        this._list.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
 | 
			
		||||
        this._list.connect('allocate', Lang.bind(this, this._allocate));
 | 
			
		||||
 | 
			
		||||
        this._scrollView = new St.ScrollView({ style_class: 'hfade',
 | 
			
		||||
                                               enable_mouse_scrolling: false });
 | 
			
		||||
        this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER);
 | 
			
		||||
        this._clipBin = new St.Bin({style_class: 'cbin'});
 | 
			
		||||
        this._clipBin.child = this._list;
 | 
			
		||||
        this.actor.add_actor(this._clipBin);
 | 
			
		||||
 | 
			
		||||
        let scrollBox = new St.BoxLayout();
 | 
			
		||||
        scrollBox.add_actor(this._list);
 | 
			
		||||
        this._scrollView.add_actor(scrollBox);
 | 
			
		||||
        this.actor.add_actor(this._scrollView);
 | 
			
		||||
        this._leftGradient = new St.BoxLayout({style_class: 'thumbnail-scroll-gradient-left', vertical: true});
 | 
			
		||||
        this._rightGradient = new St.BoxLayout({style_class: 'thumbnail-scroll-gradient-right', vertical: true});
 | 
			
		||||
        this.actor.add_actor(this._leftGradient);
 | 
			
		||||
        this.actor.add_actor(this._rightGradient);
 | 
			
		||||
 | 
			
		||||
        // Those arrows indicate whether scrolling in one direction is possible
 | 
			
		||||
        this._leftArrow = new St.DrawingArea({ style_class: 'switcher-arrow',
 | 
			
		||||
@@ -604,9 +548,21 @@ const SwitcherList = new Lang.Class({
 | 
			
		||||
        let childBox = new Clutter.ActorBox();
 | 
			
		||||
        let scrollable = this._minSize > box.x2 - box.x1;
 | 
			
		||||
 | 
			
		||||
        box.y1 -= this.actor.get_theme_node().get_padding(St.Side.TOP);
 | 
			
		||||
        box.y2 += this.actor.get_theme_node().get_padding(St.Side.BOTTOM);
 | 
			
		||||
        this._scrollView.allocate(box, flags);
 | 
			
		||||
        this._clipBin.allocate(box, flags);
 | 
			
		||||
 | 
			
		||||
        childBox.x1 = 0;
 | 
			
		||||
        childBox.y1 = 0;
 | 
			
		||||
        childBox.x2 = this._leftGradient.width;
 | 
			
		||||
        childBox.y2 = this.actor.height;
 | 
			
		||||
        this._leftGradient.allocate(childBox, flags);
 | 
			
		||||
        this._leftGradient.opacity = (this._scrollableLeft && scrollable) ? 255 : 0;
 | 
			
		||||
 | 
			
		||||
        childBox.x1 = (this.actor.allocation.x2 - this.actor.allocation.x1) - this._rightGradient.width;
 | 
			
		||||
        childBox.y1 = 0;
 | 
			
		||||
        childBox.x2 = childBox.x1 + this._rightGradient.width;
 | 
			
		||||
        childBox.y2 = this.actor.height;
 | 
			
		||||
        this._rightGradient.allocate(childBox, flags);
 | 
			
		||||
        this._rightGradient.opacity = (this._scrollableRight && scrollable) ? 255 : 0;
 | 
			
		||||
 | 
			
		||||
        let arrowWidth = Math.floor(leftPadding / 3);
 | 
			
		||||
        let arrowHeight = arrowWidth * 2;
 | 
			
		||||
@@ -615,7 +571,7 @@ const SwitcherList = new Lang.Class({
 | 
			
		||||
        childBox.x2 = childBox.x1 + arrowWidth;
 | 
			
		||||
        childBox.y2 = childBox.y1 + arrowHeight;
 | 
			
		||||
        this._leftArrow.allocate(childBox, flags);
 | 
			
		||||
        this._leftArrow.opacity = (this._scrollableLeft && scrollable) ? 255 : 0;
 | 
			
		||||
        this._leftArrow.opacity = this._leftGradient.opacity;
 | 
			
		||||
 | 
			
		||||
        arrowWidth = Math.floor(rightPadding / 3);
 | 
			
		||||
        arrowHeight = arrowWidth * 2;
 | 
			
		||||
@@ -624,10 +580,10 @@ const SwitcherList = new Lang.Class({
 | 
			
		||||
        childBox.x2 = childBox.x1 + arrowWidth;
 | 
			
		||||
        childBox.y2 = childBox.y1 + arrowHeight;
 | 
			
		||||
        this._rightArrow.allocate(childBox, flags);
 | 
			
		||||
        this._rightArrow.opacity = (this._scrollableRight && scrollable) ? 255 : 0;
 | 
			
		||||
        this._rightArrow.opacity = this._rightGradient.opacity;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addItem : function(item, label) {
 | 
			
		||||
    addItem : function(item) {
 | 
			
		||||
        let bbox = new St.Button({ style_class: 'item-box',
 | 
			
		||||
                                   reactive: true });
 | 
			
		||||
 | 
			
		||||
@@ -638,11 +594,7 @@ const SwitcherList = new Lang.Class({
 | 
			
		||||
        bbox.connect('clicked', Lang.bind(this, function() { this._onItemClicked(n); }));
 | 
			
		||||
        bbox.connect('enter-event', Lang.bind(this, function() { this._onItemEnter(n); }));
 | 
			
		||||
 | 
			
		||||
        bbox.label_actor = label;
 | 
			
		||||
 | 
			
		||||
        this._items.push(bbox);
 | 
			
		||||
 | 
			
		||||
        return bbox;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onItemClicked: function (index) {
 | 
			
		||||
@@ -674,66 +626,48 @@ const SwitcherList = new Lang.Class({
 | 
			
		||||
                this._items[this._highlighted].add_style_pseudo_class('selected');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let adjustment = this._scrollView.hscroll.adjustment;
 | 
			
		||||
        let [value, lower, upper, stepIncrement, pageIncrement, pageSize] = adjustment.get_values();
 | 
			
		||||
        let [absItemX, absItemY] = this._items[index].get_transformed_position();
 | 
			
		||||
        let [result, posX, posY] = this.actor.transform_stage_point(absItemX, 0);
 | 
			
		||||
        let [containerWidth, containerHeight] = this.actor.get_transformed_size();
 | 
			
		||||
        if (posX + this._items[index].get_width() > containerWidth)
 | 
			
		||||
        let monitor = global.get_primary_monitor();
 | 
			
		||||
        let itemSize = this._items[index].allocation.x2 - this._items[index].allocation.x1;
 | 
			
		||||
        let [posX, posY] = this._items[index].get_transformed_position();
 | 
			
		||||
        posX += this.actor.x;
 | 
			
		||||
        if (posX + itemSize > monitor.width + monitor.x)
 | 
			
		||||
            this._scrollToRight();
 | 
			
		||||
        else if (this._items[index].allocation.x1 - value < 0)
 | 
			
		||||
        else if (posX < 0)
 | 
			
		||||
            this._scrollToLeft();
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _scrollToLeft : function() {
 | 
			
		||||
        let adjustment = this._scrollView.hscroll.adjustment;
 | 
			
		||||
        let [value, lower, upper, stepIncrement, pageIncrement, pageSize] = adjustment.get_values();
 | 
			
		||||
 | 
			
		||||
        let item = this._items[this._highlighted];
 | 
			
		||||
 | 
			
		||||
        if (item.allocation.x1 < value)
 | 
			
		||||
            value = Math.min(0, item.allocation.x1);
 | 
			
		||||
        else if (item.allocation.x2 > value + pageSize)
 | 
			
		||||
            value = Math.max(upper, item.allocation.x2 - pageSize);
 | 
			
		||||
 | 
			
		||||
        let x = this._items[this._highlighted].allocation.x1;
 | 
			
		||||
        this._scrollableRight = true;
 | 
			
		||||
        Tweener.addTween(adjustment,
 | 
			
		||||
                         { value: value,
 | 
			
		||||
                           time: POPUP_SCROLL_TIME,
 | 
			
		||||
                           transition: 'easeOutQuad',
 | 
			
		||||
                           onComplete: Lang.bind(this, function () {
 | 
			
		||||
                                if (this._highlighted == 0) {
 | 
			
		||||
                                    this._scrollableLeft = false;
 | 
			
		||||
                                    this.actor.queue_relayout();
 | 
			
		||||
                                }
 | 
			
		||||
                           })
 | 
			
		||||
                          });
 | 
			
		||||
        Tweener.addTween(this._list, { anchor_x: x,
 | 
			
		||||
                                        time: POPUP_SCROLL_TIME,
 | 
			
		||||
                                        transition: 'easeOutQuad',
 | 
			
		||||
                                        onComplete: Lang.bind(this, function () {
 | 
			
		||||
                                                                        if (this._highlighted == 0) {
 | 
			
		||||
                                                                            this._scrollableLeft = false;
 | 
			
		||||
                                                                            this.actor.queue_relayout();
 | 
			
		||||
                                                                        }
 | 
			
		||||
                                                             })
 | 
			
		||||
                        });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _scrollToRight : function() {
 | 
			
		||||
        let adjustment = this._scrollView.hscroll.adjustment;
 | 
			
		||||
        let [value, lower, upper, stepIncrement, pageIncrement, pageSize] = adjustment.get_values();
 | 
			
		||||
 | 
			
		||||
        let item = this._items[this._highlighted];
 | 
			
		||||
 | 
			
		||||
        if (item.allocation.x1 < value)
 | 
			
		||||
            value = Math.max(0, item.allocation.x1);
 | 
			
		||||
        else if (item.allocation.x2 > value + pageSize)
 | 
			
		||||
            value = Math.min(upper, item.allocation.x2 - pageSize);
 | 
			
		||||
 | 
			
		||||
        this._scrollableLeft = true;
 | 
			
		||||
        Tweener.addTween(adjustment,
 | 
			
		||||
                         { value: value,
 | 
			
		||||
                           time: POPUP_SCROLL_TIME,
 | 
			
		||||
                           transition: 'easeOutQuad',
 | 
			
		||||
                           onComplete: Lang.bind(this, function () {
 | 
			
		||||
                                if (this._highlighted == this._items.length - 1) {
 | 
			
		||||
                                    this._scrollableRight = false;
 | 
			
		||||
                                    this.actor.queue_relayout();
 | 
			
		||||
                                }
 | 
			
		||||
                            })
 | 
			
		||||
                          });
 | 
			
		||||
        let monitor = global.get_primary_monitor();
 | 
			
		||||
        let padding = this.actor.get_theme_node().get_horizontal_padding();
 | 
			
		||||
        let parentPadding = this.actor.get_parent().get_theme_node().get_horizontal_padding();
 | 
			
		||||
        let x = this._items[this._highlighted].allocation.x2 - monitor.width + padding + parentPadding;
 | 
			
		||||
        Tweener.addTween(this._list, { anchor_x: x,
 | 
			
		||||
                                        time: POPUP_SCROLL_TIME,
 | 
			
		||||
                                        transition: 'easeOutQuad',
 | 
			
		||||
                                        onComplete: Lang.bind(this, function () {
 | 
			
		||||
                                                                        if (this._highlighted == this._items.length - 1) {
 | 
			
		||||
                                                                            this._scrollableRight = false;
 | 
			
		||||
                                                                            this.actor.queue_relayout();
 | 
			
		||||
                                                                        }
 | 
			
		||||
                                                             })
 | 
			
		||||
                        });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _itemActivated: function(n) {
 | 
			
		||||
@@ -817,8 +751,16 @@ const SwitcherList = new Lang.Class({
 | 
			
		||||
        let children = this._list.get_children();
 | 
			
		||||
        let childBox = new Clutter.ActorBox();
 | 
			
		||||
 | 
			
		||||
        let primary = Main.layoutManager.primaryMonitor;
 | 
			
		||||
        let primary = global.get_primary_monitor();
 | 
			
		||||
        let parentRightPadding = this.actor.get_parent().get_theme_node().get_padding(St.Side.RIGHT);
 | 
			
		||||
        if (this.actor.allocation.x2 == primary.x + primary.width - parentRightPadding) {
 | 
			
		||||
            if (this._squareItems)
 | 
			
		||||
                childWidth = childHeight;
 | 
			
		||||
            else {
 | 
			
		||||
                let [childMin, childNat] = children[0].get_preferred_width(childHeight);
 | 
			
		||||
                childWidth = childMin;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < children.length; i++) {
 | 
			
		||||
            if (this._items.indexOf(children[i]) != -1) {
 | 
			
		||||
@@ -844,14 +786,24 @@ const SwitcherList = new Lang.Class({
 | 
			
		||||
                // we don't allocate it.
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let leftPadding = this.actor.get_theme_node().get_padding(St.Side.LEFT);
 | 
			
		||||
        let rightPadding = this.actor.get_theme_node().get_padding(St.Side.RIGHT);
 | 
			
		||||
        let topPadding = this.actor.get_theme_node().get_padding(St.Side.TOP);
 | 
			
		||||
        let bottomPadding = this.actor.get_theme_node().get_padding(St.Side.BOTTOM);
 | 
			
		||||
 | 
			
		||||
        // Clip the area for scrolling
 | 
			
		||||
        this._clipBin.set_clip(0, -topPadding, (this.actor.allocation.x2 - this.actor.allocation.x1) - leftPadding - rightPadding, this.actor.height + bottomPadding);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Signals.addSignalMethods(SwitcherList.prototype);
 | 
			
		||||
 | 
			
		||||
const AppIcon = new Lang.Class({
 | 
			
		||||
    Name: 'AppIcon',
 | 
			
		||||
function AppIcon(app) {
 | 
			
		||||
    this._init(app);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AppIcon.prototype = {
 | 
			
		||||
    _init: function(app) {
 | 
			
		||||
        this.app = app;
 | 
			
		||||
        this.actor = new St.BoxLayout({ style_class: 'alt-tab-app',
 | 
			
		||||
@@ -869,32 +821,36 @@ const AppIcon = new Lang.Class({
 | 
			
		||||
        this._iconBin.set_size(size, size);
 | 
			
		||||
        this._iconBin.child = this.icon;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const AppSwitcher = new Lang.Class({
 | 
			
		||||
    Name: 'AppSwitcher',
 | 
			
		||||
    Extends: SwitcherList,
 | 
			
		||||
function AppSwitcher(apps, altTabPopup) {
 | 
			
		||||
    this._init(apps, altTabPopup);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    _init : function(localApps, otherApps, altTabPopup) {
 | 
			
		||||
        this.parent(true);
 | 
			
		||||
AppSwitcher.prototype = {
 | 
			
		||||
    __proto__ : SwitcherList.prototype,
 | 
			
		||||
 | 
			
		||||
        // Construct the AppIcons, add to the popup
 | 
			
		||||
    _init : function(apps, altTabPopup) {
 | 
			
		||||
        SwitcherList.prototype._init.call(this, true);
 | 
			
		||||
 | 
			
		||||
        // Construct the AppIcons, sort by time, add to the popup
 | 
			
		||||
        let activeWorkspace = global.screen.get_active_workspace();
 | 
			
		||||
        let workspaceIcons = [];
 | 
			
		||||
        let otherIcons = [];
 | 
			
		||||
        for (let i = 0; i < localApps.length; i++) {
 | 
			
		||||
            let appIcon = new AppIcon(localApps[i]);
 | 
			
		||||
        for (let i = 0; i < apps.length; i++) {
 | 
			
		||||
            let appIcon = new AppIcon(apps[i]);
 | 
			
		||||
            // Cache the window list now; we don't handle dynamic changes here,
 | 
			
		||||
            // and we don't want to be continually retrieving it
 | 
			
		||||
            appIcon.cachedWindows = appIcon.app.get_windows();
 | 
			
		||||
            workspaceIcons.push(appIcon);
 | 
			
		||||
        }
 | 
			
		||||
        for (let i = 0; i < otherApps.length; i++) {
 | 
			
		||||
            let appIcon = new AppIcon(otherApps[i]);
 | 
			
		||||
            appIcon.cachedWindows = appIcon.app.get_windows();
 | 
			
		||||
            otherIcons.push(appIcon);
 | 
			
		||||
            if (this._hasWindowsOnWorkspace(appIcon, activeWorkspace))
 | 
			
		||||
              workspaceIcons.push(appIcon);
 | 
			
		||||
            else
 | 
			
		||||
              otherIcons.push(appIcon);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        workspaceIcons.sort(Lang.bind(this, this._sortAppIcon));
 | 
			
		||||
        otherIcons.sort(Lang.bind(this, this._sortAppIcon));
 | 
			
		||||
 | 
			
		||||
        this.icons = [];
 | 
			
		||||
        this._arrows = [];
 | 
			
		||||
        for (let i = 0; i < workspaceIcons.length; i++)
 | 
			
		||||
@@ -925,7 +881,7 @@ const AppSwitcher = new Lang.Class({
 | 
			
		||||
           totalSpacing += this._separator.width + this._list.spacing;
 | 
			
		||||
 | 
			
		||||
        // We just assume the whole screen here due to weirdness happing with the passed width
 | 
			
		||||
        let primary = Main.layoutManager.primaryMonitor;
 | 
			
		||||
        let primary = global.get_primary_monitor();
 | 
			
		||||
        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;
 | 
			
		||||
@@ -955,7 +911,7 @@ const AppSwitcher = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _allocate: function (actor, box, flags) {
 | 
			
		||||
        // Allocate the main list items
 | 
			
		||||
        this.parent(actor, box, flags);
 | 
			
		||||
        SwitcherList.prototype._allocate.call(this, actor, box, flags);
 | 
			
		||||
 | 
			
		||||
        let arrowHeight = Math.floor(this.actor.get_theme_node().get_padding(St.Side.BOTTOM) / 3);
 | 
			
		||||
        let arrowWidth = arrowHeight * 2;
 | 
			
		||||
@@ -1010,7 +966,7 @@ const AppSwitcher = new Lang.Class({
 | 
			
		||||
                this._arrows[this._curApp].remove_style_pseudo_class('highlighted');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.parent(n, justOutline);
 | 
			
		||||
        SwitcherList.prototype.highlight.call(this, n, justOutline);
 | 
			
		||||
        this._curApp = n;
 | 
			
		||||
 | 
			
		||||
        if (this._curApp != -1) {
 | 
			
		||||
@@ -1023,7 +979,7 @@ const AppSwitcher = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _addIcon : function(appIcon) {
 | 
			
		||||
        this.icons.push(appIcon);
 | 
			
		||||
        let item = this.addItem(appIcon.actor, appIcon.label);
 | 
			
		||||
        this.addItem(appIcon.actor);
 | 
			
		||||
 | 
			
		||||
        let n = this._arrows.length;
 | 
			
		||||
        let arrow = new St.DrawingArea({ style_class: 'switcher-arrow' });
 | 
			
		||||
@@ -1033,17 +989,31 @@ const AppSwitcher = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        if (appIcon.cachedWindows.length == 1)
 | 
			
		||||
            arrow.hide();
 | 
			
		||||
        else
 | 
			
		||||
            item.add_accessible_state (Atk.StateType.EXPANDABLE);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
const ThumbnailList = new Lang.Class({
 | 
			
		||||
    Name: 'ThumbnailList',
 | 
			
		||||
    Extends: SwitcherList,
 | 
			
		||||
    _hasWindowsOnWorkspace: function(appIcon, workspace) {
 | 
			
		||||
        let windows = appIcon.cachedWindows;
 | 
			
		||||
        for (let i = 0; i < windows.length; i++) {
 | 
			
		||||
            if (windows[i].get_workspace() == workspace)
 | 
			
		||||
                return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _sortAppIcon : function(appIcon1, appIcon2) {
 | 
			
		||||
        return appIcon1.app.compare(appIcon2.app);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function ThumbnailList(windows) {
 | 
			
		||||
    this._init(windows);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ThumbnailList.prototype = {
 | 
			
		||||
    __proto__ : SwitcherList.prototype,
 | 
			
		||||
 | 
			
		||||
    _init : function(windows) {
 | 
			
		||||
        this.parent(false);
 | 
			
		||||
        SwitcherList.prototype._init.call(this);
 | 
			
		||||
 | 
			
		||||
        let activeWorkspace = global.screen.get_active_workspace();
 | 
			
		||||
 | 
			
		||||
@@ -1079,12 +1049,9 @@ const ThumbnailList = new Lang.Class({
 | 
			
		||||
                this._labels.push(bin);
 | 
			
		||||
                bin.add_actor(name);
 | 
			
		||||
                box.add_actor(bin);
 | 
			
		||||
 | 
			
		||||
                this.addItem(box, name);
 | 
			
		||||
            } else {
 | 
			
		||||
                this.addItem(box, null);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.addItem(box);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -1121,7 +1088,7 @@ const ThumbnailList = new Lang.Class({
 | 
			
		||||
        // Make sure we only do this once
 | 
			
		||||
        this._thumbnailBins = new Array();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function _drawArrow(area, side) {
 | 
			
		||||
    let themeNode = area.get_theme_node();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +1,16 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const GMenu = imports.gi.GMenu;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Atk = imports.gi.Atk;
 | 
			
		||||
const Gettext = imports.gettext.domain('gnome-shell');
 | 
			
		||||
const _ = Gettext.gettext;
 | 
			
		||||
 | 
			
		||||
const AppFavorites = imports.ui.appFavorites;
 | 
			
		||||
const DND = imports.ui.dnd;
 | 
			
		||||
@@ -27,15 +27,18 @@ const MAX_APPLICATION_WORK_MILLIS = 75;
 | 
			
		||||
const MENU_POPUP_TIMEOUT = 600;
 | 
			
		||||
const SCROLL_TIME = 0.1;
 | 
			
		||||
 | 
			
		||||
const AlphabeticalView = new Lang.Class({
 | 
			
		||||
    Name: 'AlphabeticalView',
 | 
			
		||||
function AlphabeticalView() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AlphabeticalView.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._grid = new IconGrid.IconGrid({ xAlign: St.Align.START });
 | 
			
		||||
        this._appSystem = Shell.AppSystem.get_default();
 | 
			
		||||
 | 
			
		||||
        this._pendingAppLaterId = 0;
 | 
			
		||||
        this._appIcons = {}; // desktop file id
 | 
			
		||||
        this._apps = [];
 | 
			
		||||
        this._filterApp = null;
 | 
			
		||||
 | 
			
		||||
        let box = new St.BoxLayout({ vertical: true });
 | 
			
		||||
        box.add(this._grid.actor, { y_align: St.Align.START, expand: true });
 | 
			
		||||
@@ -43,7 +46,7 @@ const AlphabeticalView = new Lang.Class({
 | 
			
		||||
        this.actor = new St.ScrollView({ x_fill: true,
 | 
			
		||||
                                         y_fill: false,
 | 
			
		||||
                                         y_align: St.Align.START,
 | 
			
		||||
                                         style_class: 'vfade' });
 | 
			
		||||
                                         vfade: true });
 | 
			
		||||
        this.actor.add_actor(box);
 | 
			
		||||
        this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
 | 
			
		||||
        this.actor.connect('notify::mapped', Lang.bind(this,
 | 
			
		||||
@@ -62,17 +65,20 @@ const AlphabeticalView = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _removeAll: function() {
 | 
			
		||||
        this._grid.removeAll();
 | 
			
		||||
        this._appIcons = {};
 | 
			
		||||
        this._apps = [];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _addApp: function(app) {
 | 
			
		||||
        var id = app.get_id();
 | 
			
		||||
        let appIcon = new AppWellIcon(app);
 | 
			
		||||
    _addApp: function(appInfo) {
 | 
			
		||||
        let appIcon = new AppWellIcon(this._appSystem.get_app(appInfo.get_id()));
 | 
			
		||||
 | 
			
		||||
        this._grid.addItem(appIcon.actor);
 | 
			
		||||
        appIcon.actor.connect('key-focus-in', Lang.bind(this, this._ensureIconVisible));
 | 
			
		||||
 | 
			
		||||
        this._appIcons[id] = appIcon;
 | 
			
		||||
        appIcon._appInfo = appInfo;
 | 
			
		||||
        if (this._filterApp && !this._filterApp(appInfo))
 | 
			
		||||
            appIcon.actor.hide();
 | 
			
		||||
 | 
			
		||||
        this._apps.push(appIcon);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _ensureIconVisible: function(icon) {
 | 
			
		||||
@@ -101,39 +107,60 @@ const AlphabeticalView = new Lang.Class({
 | 
			
		||||
                           transition: 'easeOutQuad' });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setVisibleApps: function(apps) {
 | 
			
		||||
        if (apps == null) { // null implies "all"
 | 
			
		||||
            for (var id in this._appIcons) {
 | 
			
		||||
                var icon = this._appIcons[id];
 | 
			
		||||
                icon.actor.visible = true;
 | 
			
		||||
            }
 | 
			
		||||
    setFilter: function(filter) {
 | 
			
		||||
        this._filterApp = filter;
 | 
			
		||||
        for (let i = 0; i < this._apps.length; i++)
 | 
			
		||||
            this._apps[i].actor.visible = filter(this._apps[i]._appInfo);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // Create actors for the applications in an idle to avoid blocking
 | 
			
		||||
    // for too long; see bug 647778
 | 
			
		||||
    _addPendingApps: function() {
 | 
			
		||||
        let i;
 | 
			
		||||
        let startTimeMillis = new Date().getTime();
 | 
			
		||||
        for (i = 0; i < this._pendingAppIds.length; i++) {
 | 
			
		||||
            let id = this._pendingAppIds[i];
 | 
			
		||||
            this._addApp(this._pendingApps[id]);
 | 
			
		||||
 | 
			
		||||
            let currentTimeMillis = new Date().getTime();
 | 
			
		||||
            if (currentTimeMillis - startTimeMillis > MAX_APPLICATION_WORK_MILLIS)
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        this._pendingAppIds.splice(0, i + 1);
 | 
			
		||||
        if (this._pendingAppIds.length > 0) {
 | 
			
		||||
            return true;
 | 
			
		||||
        } else {
 | 
			
		||||
            // Set everything to not-visible, then set to visible what we should see
 | 
			
		||||
            for (var id in this._appIcons) {
 | 
			
		||||
                var icon = this._appIcons[id];
 | 
			
		||||
                icon.actor.visible = false;
 | 
			
		||||
            }
 | 
			
		||||
            for (var i = 0; i < apps.length; i++) {
 | 
			
		||||
                var app = apps[i];
 | 
			
		||||
                var id = app.get_id();
 | 
			
		||||
                var icon = this._appIcons[id];
 | 
			
		||||
                icon.actor.visible = true;
 | 
			
		||||
            }
 | 
			
		||||
            this._pendingAppLaterId = 0;
 | 
			
		||||
            this._pendingAppIds = null;
 | 
			
		||||
            this._pendingApps = null;
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setAppList: function(apps) {
 | 
			
		||||
    refresh: function(apps) {
 | 
			
		||||
        let ids = [];
 | 
			
		||||
        for (let i in apps)
 | 
			
		||||
            ids.push(i);
 | 
			
		||||
        ids.sort(function(a, b) {
 | 
			
		||||
            return apps[a].get_name().localeCompare(apps[b].get_name());
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._removeAll();
 | 
			
		||||
        for (var i = 0; i < apps.length; i++) {
 | 
			
		||||
            var app = apps[i];
 | 
			
		||||
            this._addApp(app);
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
        this._pendingAppIds = ids;
 | 
			
		||||
        this._pendingApps = apps;
 | 
			
		||||
        if (this._pendingAppLaterId)
 | 
			
		||||
            Meta.later_remove(this._pendingAppLaterId);
 | 
			
		||||
        this._pendingAppLaterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
 | 
			
		||||
                                                 Lang.bind(this, this._addPendingApps));
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const ViewByCategories = new Lang.Class({
 | 
			
		||||
    Name: 'ViewByCategories',
 | 
			
		||||
function ViewByCategories() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ViewByCategories.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._appSystem = Shell.AppSystem.get_default();
 | 
			
		||||
        this.actor = new St.BoxLayout({ style_class: 'all-app' });
 | 
			
		||||
@@ -146,26 +173,21 @@ const ViewByCategories = new Lang.Class({
 | 
			
		||||
        // -2 is a flag to indicate that nothing is selected
 | 
			
		||||
        // (used only before the actor is mapped the first time)
 | 
			
		||||
        this._currentCategory = -2;
 | 
			
		||||
        this._categories = [];
 | 
			
		||||
        this._apps = null;
 | 
			
		||||
        this._filters = new St.BoxLayout({ vertical: true, reactive: true });
 | 
			
		||||
        this._filters.connect('scroll-event', Lang.bind(this, this._scrollFilter));
 | 
			
		||||
 | 
			
		||||
        this._categoryBox = new St.BoxLayout({ vertical: true,
 | 
			
		||||
                                               reactive: true,
 | 
			
		||||
                                               accessible_role: Atk.Role.LIST });
 | 
			
		||||
        this._categoryScroll = new St.ScrollView({ x_fill: false,
 | 
			
		||||
                                                   y_fill: false,
 | 
			
		||||
                                                   style_class: 'vfade' });
 | 
			
		||||
        this._categoryScroll.add_actor(this._categoryBox);
 | 
			
		||||
        this.actor.add(this._view.actor, { expand: true, x_fill: true, y_fill: true });
 | 
			
		||||
        this.actor.add(this._categoryScroll, { expand: false, y_fill: false, y_align: St.Align.START });
 | 
			
		||||
        this.actor.add(this._filters, { expand: false, y_fill: false, y_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        // Always select the "All" filter when switching to the app view
 | 
			
		||||
        this.actor.connect('notify::mapped', Lang.bind(this,
 | 
			
		||||
            function() {
 | 
			
		||||
                if (this.actor.mapped && this._allCategoryButton)
 | 
			
		||||
                if (this.actor.mapped && this._allFilter)
 | 
			
		||||
                    this._selectCategory(-1);
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
        this._sections = [];
 | 
			
		||||
 | 
			
		||||
        // We need a dummy actor to catch the keyboard focus if the
 | 
			
		||||
        // user Ctrl-Alt-Tabs here before the deferred work creates
 | 
			
		||||
        // our real contents
 | 
			
		||||
@@ -173,105 +195,78 @@ const ViewByCategories = new Lang.Class({
 | 
			
		||||
        this.actor.add(this._focusDummy);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _scrollFilter: function(actor, event) {
 | 
			
		||||
        let direction = event.get_scroll_direction();
 | 
			
		||||
        if (direction == Clutter.ScrollDirection.UP)
 | 
			
		||||
            this._selectCategory(Math.max(this._currentCategory - 1, -1))
 | 
			
		||||
        else if (direction == Clutter.ScrollDirection.DOWN)
 | 
			
		||||
            this._selectCategory(Math.min(this._currentCategory + 1, this._sections.length - 1));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _selectCategory: function(num) {
 | 
			
		||||
        if (this._currentCategory == num) // nothing to do
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._currentCategory = num;
 | 
			
		||||
 | 
			
		||||
        if (num != -1) {
 | 
			
		||||
            var category = this._categories[num];
 | 
			
		||||
            this._allCategoryButton.remove_style_pseudo_class('selected');
 | 
			
		||||
            this._view.setVisibleApps(category.apps);
 | 
			
		||||
        } else {
 | 
			
		||||
            this._allCategoryButton.add_style_pseudo_class('selected');
 | 
			
		||||
            this._view.setVisibleApps(null);
 | 
			
		||||
        }
 | 
			
		||||
        if (num != -1)
 | 
			
		||||
            this._allFilter.remove_style_pseudo_class('selected');
 | 
			
		||||
        else
 | 
			
		||||
            this._allFilter.add_style_pseudo_class('selected');
 | 
			
		||||
 | 
			
		||||
        for (var i = 0; i < this._categories.length; i++) {
 | 
			
		||||
        this._view.setFilter(Lang.bind(this, function(app) {
 | 
			
		||||
            if (num == -1)
 | 
			
		||||
                return true;
 | 
			
		||||
            return this._sections[num].name == app.get_section();
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < this._sections.length; i++) {
 | 
			
		||||
            if (i == num)
 | 
			
		||||
                this._categories[i].button.add_style_pseudo_class('selected');
 | 
			
		||||
                this._sections[i].filterActor.add_style_pseudo_class('selected');
 | 
			
		||||
            else
 | 
			
		||||
                this._categories[i].button.remove_style_pseudo_class('selected');
 | 
			
		||||
                this._sections[i].filterActor.remove_style_pseudo_class('selected');
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // Recursively load a GMenuTreeDirectory; we could put this in ShellAppSystem too
 | 
			
		||||
    _loadCategory: function(dir, appList) {
 | 
			
		||||
        var iter = dir.iter();
 | 
			
		||||
        var nextType;
 | 
			
		||||
        while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
 | 
			
		||||
            if (nextType == GMenu.TreeItemType.ENTRY) {
 | 
			
		||||
                var entry = iter.get_entry();
 | 
			
		||||
                var app = this._appSystem.lookup_app_by_tree_entry(entry);
 | 
			
		||||
                if (!entry.get_app_info().get_nodisplay())
 | 
			
		||||
                    appList.push(app);
 | 
			
		||||
            } else if (nextType == GMenu.TreeItemType.DIRECTORY) {
 | 
			
		||||
                if (!dir.get_is_nodisplay())
 | 
			
		||||
                    this._loadCategory(iter.get_directory(), appList);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _addCategory: function(name, index, dir, allApps) {
 | 
			
		||||
    _addFilter: function(name, num) {
 | 
			
		||||
        let button = new St.Button({ label: GLib.markup_escape_text (name, -1),
 | 
			
		||||
                                     style_class: 'app-filter',
 | 
			
		||||
                                     x_align: St.Align.START,
 | 
			
		||||
                                     can_focus: true ,
 | 
			
		||||
                                     accessible_role: Atk.Role.LIST_ITEM });
 | 
			
		||||
                                     can_focus: true });
 | 
			
		||||
        this._filters.add(button, { expand: true, x_fill: true, y_fill: false });
 | 
			
		||||
        button.connect('clicked', Lang.bind(this, function() {
 | 
			
		||||
            this._selectCategory(index);
 | 
			
		||||
            this._selectCategory(num);
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        var apps;
 | 
			
		||||
        if (dir == null) {
 | 
			
		||||
            apps = allApps;
 | 
			
		||||
            this._allCategoryButton = button;
 | 
			
		||||
        } else {
 | 
			
		||||
            apps = [];
 | 
			
		||||
            this._loadCategory(dir, apps);
 | 
			
		||||
            this._categories.push({ apps: apps,
 | 
			
		||||
                                    name: name,
 | 
			
		||||
                                    button: button });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._categoryBox.add(button, { expand: true, x_fill: true, y_fill: false });
 | 
			
		||||
        if (num != -1)
 | 
			
		||||
            this._sections[num] = { filterActor: button,
 | 
			
		||||
                                    name: name };
 | 
			
		||||
        else
 | 
			
		||||
            this._allFilter = button;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _removeAll: function() {
 | 
			
		||||
        this._categories = [];
 | 
			
		||||
        this._categoryBox.destroy_all_children();
 | 
			
		||||
        this._sections = [];
 | 
			
		||||
        this._filters.destroy_children();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    refresh: function() {
 | 
			
		||||
    refresh: function(apps) {
 | 
			
		||||
        this._removeAll();
 | 
			
		||||
 | 
			
		||||
        var allApps = Shell.AppSystem.get_default().get_all();
 | 
			
		||||
        allApps.sort(function(a, b) {
 | 
			
		||||
            return a.compare_by_name(b);
 | 
			
		||||
        });
 | 
			
		||||
        let sections = this._appSystem.get_sections();
 | 
			
		||||
        this._apps = apps;
 | 
			
		||||
 | 
			
		||||
        /* Translators: Filter to display all applications */
 | 
			
		||||
        this._addCategory(_("All"), -1, null, allApps);
 | 
			
		||||
        this._addFilter(_("All"), -1);
 | 
			
		||||
 | 
			
		||||
        var tree = this._appSystem.get_tree();
 | 
			
		||||
        var root = tree.get_root_directory();
 | 
			
		||||
        if (!sections)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        var iter = root.iter();
 | 
			
		||||
        var nextType;
 | 
			
		||||
        var i = 0;
 | 
			
		||||
        while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
 | 
			
		||||
            if (nextType == GMenu.TreeItemType.DIRECTORY) {
 | 
			
		||||
                var dir = iter.get_directory();
 | 
			
		||||
                if (dir.get_is_nodisplay())
 | 
			
		||||
                    continue;
 | 
			
		||||
                this._addCategory(dir.get_name(), i, dir);
 | 
			
		||||
                i++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        for (let i = 0; i < sections.length; i++)
 | 
			
		||||
            this._addFilter(sections[i], i);
 | 
			
		||||
 | 
			
		||||
        this._view.setAppList(allApps);
 | 
			
		||||
        this._selectCategory(-1);
 | 
			
		||||
        this._view.refresh(apps);
 | 
			
		||||
 | 
			
		||||
        if (this._focusDummy) {
 | 
			
		||||
            let focused = this._focusDummy.has_key_focus();
 | 
			
		||||
@@ -281,14 +276,16 @@ const ViewByCategories = new Lang.Class({
 | 
			
		||||
                this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* This class represents a display containing a collection of application items.
 | 
			
		||||
 * The applications are sorted based on their name.
 | 
			
		||||
 */
 | 
			
		||||
const AllAppDisplay = new Lang.Class({
 | 
			
		||||
    Name: 'AllAppDisplay',
 | 
			
		||||
function AllAppDisplay() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AllAppDisplay.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._appSystem = Shell.AppSystem.get_default();
 | 
			
		||||
        this._appSystem.connect('installed-changed', Lang.bind(this, function() {
 | 
			
		||||
@@ -302,142 +299,129 @@ const AllAppDisplay = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _redisplay: function() {
 | 
			
		||||
        this._appView.refresh();
 | 
			
		||||
        let apps = this._appSystem.get_flattened_apps().filter(function(app) {
 | 
			
		||||
            return !app.get_is_nodisplay();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._appView.refresh(apps);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const AppSearchProvider = new Lang.Class({
 | 
			
		||||
    Name: 'AppSearchProvider',
 | 
			
		||||
    Extends: Search.SearchProvider,
 | 
			
		||||
function BaseAppSearchProvider() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.parent(_("APPLICATIONS"));
 | 
			
		||||
BaseAppSearchProvider.prototype = {
 | 
			
		||||
    __proto__: Search.SearchProvider.prototype,
 | 
			
		||||
 | 
			
		||||
    _init: function(name) {
 | 
			
		||||
        Search.SearchProvider.prototype._init.call(this, name);
 | 
			
		||||
        this._appSys = Shell.AppSystem.get_default();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getResultMetas: function(apps, callback) {
 | 
			
		||||
        let metas = [];
 | 
			
		||||
        for (let i = 0; i < apps.length; i++) {
 | 
			
		||||
            let app = apps[i];
 | 
			
		||||
            metas.push({ 'id': app,
 | 
			
		||||
                         'name': app.get_name(),
 | 
			
		||||
                         'createIcon': function(size) {
 | 
			
		||||
                             return app.create_icon_texture(size);
 | 
			
		||||
                         }
 | 
			
		||||
                       });
 | 
			
		||||
        }
 | 
			
		||||
        callback(metas);
 | 
			
		||||
    getResultMeta: function(resultId) {
 | 
			
		||||
        let app = this._appSys.get_app(resultId);
 | 
			
		||||
        if (!app)
 | 
			
		||||
            return null;
 | 
			
		||||
        return { 'id': resultId,
 | 
			
		||||
                 'name': app.get_name(),
 | 
			
		||||
                 'createIcon': function(size) {
 | 
			
		||||
                                   return app.create_icon_texture(size);
 | 
			
		||||
                               }
 | 
			
		||||
               };
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getInitialResultSet: function(terms) {
 | 
			
		||||
        this.searchSystem.pushResults(this, this._appSys.initial_search(terms));
 | 
			
		||||
    },
 | 
			
		||||
    activateResult: function(id, params) {
 | 
			
		||||
        params = Params.parse(params, { workspace: null,
 | 
			
		||||
                                        timestamp: null });
 | 
			
		||||
 | 
			
		||||
    getSubsearchResultSet: function(previousResults, terms) {
 | 
			
		||||
        this.searchSystem.pushResults(this, this._appSys.subsearch(previousResults, terms));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    activateResult: function(app, params) {
 | 
			
		||||
        params = Params.parse(params, { workspace: -1,
 | 
			
		||||
                                        timestamp: 0 });
 | 
			
		||||
 | 
			
		||||
        let event = Clutter.get_current_event();
 | 
			
		||||
        let modifiers = event ? event.get_state() : 0;
 | 
			
		||||
        let openNewWindow = modifiers & Clutter.ModifierType.CONTROL_MASK;
 | 
			
		||||
 | 
			
		||||
        if (openNewWindow)
 | 
			
		||||
            app.open_new_window(params.workspace);
 | 
			
		||||
        else
 | 
			
		||||
            app.activate_full(params.workspace, params.timestamp);
 | 
			
		||||
        let app = this._appSys.get_app(id);
 | 
			
		||||
        app.activate(params.workspace ? params.workspace.index() : -1);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    dragActivateResult: function(id, params) {
 | 
			
		||||
        params = Params.parse(params, { workspace: -1,
 | 
			
		||||
                                        timestamp: 0 });
 | 
			
		||||
        params = Params.parse(params, { workspace: null,
 | 
			
		||||
                                        timestamp: null });
 | 
			
		||||
 | 
			
		||||
        let app = this._appSys.lookup_app(id);
 | 
			
		||||
        app.open_new_window(workspace);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    createResultActor: function (resultMeta, terms) {
 | 
			
		||||
        let app = resultMeta['id'];
 | 
			
		||||
        let icon = new AppWellIcon(app);
 | 
			
		||||
        return icon.actor;
 | 
			
		||||
        let app = this._appSys.get_app(id);
 | 
			
		||||
        app.open_new_window(params.workspace ? params.workspace.index() : -1);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const SettingsSearchProvider = new Lang.Class({
 | 
			
		||||
    Name: 'SettingsSearchProvider',
 | 
			
		||||
    Extends: Search.SearchProvider,
 | 
			
		||||
function AppSearchProvider() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AppSearchProvider.prototype = {
 | 
			
		||||
    __proto__: BaseAppSearchProvider.prototype,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.parent(_("SETTINGS"));
 | 
			
		||||
 | 
			
		||||
        this._appSys = Shell.AppSystem.get_default();
 | 
			
		||||
        this._gnomecc = this._appSys.lookup_app('gnome-control-center.desktop');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getResultMetas: function(prefs, callback) {
 | 
			
		||||
        let metas = [];
 | 
			
		||||
        for (let i = 0; i < prefs.length; i++) {
 | 
			
		||||
            let pref = prefs[i];
 | 
			
		||||
            metas.push({ 'id': pref,
 | 
			
		||||
                         'name': pref.get_name(),
 | 
			
		||||
                         'createIcon': function(size) {
 | 
			
		||||
                             return pref.create_icon_texture(size);
 | 
			
		||||
                         }
 | 
			
		||||
                       });
 | 
			
		||||
        }
 | 
			
		||||
        callback(metas);
 | 
			
		||||
         BaseAppSearchProvider.prototype._init.call(this, _("APPLICATIONS"));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getInitialResultSet: function(terms) {
 | 
			
		||||
        this.searchSystem.pushResults(this, this._appSys.search_settings(terms));
 | 
			
		||||
        return this._appSys.initial_search(false, terms);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getSubsearchResultSet: function(previousResults, terms) {
 | 
			
		||||
        this.searchSystem.pushResults(this, this._appSys.search_settings(terms));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    activateResult: function(pref, params) {
 | 
			
		||||
        params = Params.parse(params, { workspace: -1,
 | 
			
		||||
                                        timestamp: 0 });
 | 
			
		||||
 | 
			
		||||
        pref.activate_full(params.workspace, params.timestamp);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    dragActivateResult: function(pref, params) {
 | 
			
		||||
        this.activateResult(pref, params);
 | 
			
		||||
        return this._appSys.subsearch(false, previousResults, terms);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    createResultActor: function (resultMeta, terms) {
 | 
			
		||||
        let app = resultMeta['id'];
 | 
			
		||||
        let app = this._appSys.get_app(resultMeta['id']);
 | 
			
		||||
        let icon = new AppWellIcon(app);
 | 
			
		||||
        return icon.actor;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const AppIcon = new Lang.Class({
 | 
			
		||||
    Name: 'AppIcon',
 | 
			
		||||
    Extends: IconGrid.BaseIcon,
 | 
			
		||||
function PrefsSearchProvider() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PrefsSearchProvider.prototype = {
 | 
			
		||||
    __proto__: BaseAppSearchProvider.prototype,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        BaseAppSearchProvider.prototype._init.call(this, _("SETTINGS"));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getInitialResultSet: function(terms) {
 | 
			
		||||
        return this._appSys.initial_search(true, terms);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getSubsearchResultSet: function(previousResults, terms) {
 | 
			
		||||
        return this._appSys.subsearch(true, previousResults, terms);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function AppIcon(app, params) {
 | 
			
		||||
    this._init(app, params);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AppIcon.prototype = {
 | 
			
		||||
    __proto__:  IconGrid.BaseIcon.prototype,
 | 
			
		||||
 | 
			
		||||
    _init : function(app, params) {
 | 
			
		||||
        this.app = app;
 | 
			
		||||
 | 
			
		||||
        let label = this.app.get_name();
 | 
			
		||||
 | 
			
		||||
        this.parent(label, params);
 | 
			
		||||
        IconGrid.BaseIcon.prototype._init.call(this,
 | 
			
		||||
                                               label,
 | 
			
		||||
                                               params);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    createIcon: function(iconSize) {
 | 
			
		||||
        return this.app.create_icon_texture(iconSize);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const AppWellIcon = new Lang.Class({
 | 
			
		||||
    Name: 'AppWellIcon',
 | 
			
		||||
function AppWellIcon(app, iconParams) {
 | 
			
		||||
    this._init(app, iconParams);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    _init : function(app, iconParams, onActivateOverride) {
 | 
			
		||||
AppWellIcon.prototype = {
 | 
			
		||||
    _init : function(app, iconParams) {
 | 
			
		||||
        this.app = app;
 | 
			
		||||
        this.actor = new St.Button({ style_class: 'app-well-app',
 | 
			
		||||
                                     reactive: true,
 | 
			
		||||
@@ -450,10 +434,6 @@ const AppWellIcon = new Lang.Class({
 | 
			
		||||
        this.icon = new AppIcon(app, iconParams);
 | 
			
		||||
        this.actor.set_child(this.icon.actor);
 | 
			
		||||
 | 
			
		||||
        this.actor.label_actor = this.icon.label;
 | 
			
		||||
 | 
			
		||||
        // A function callback to override the default "app.activate()"; used by preferences
 | 
			
		||||
        this._onActivateOverride = onActivateOverride;
 | 
			
		||||
        this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
 | 
			
		||||
        this.actor.connect('clicked', Lang.bind(this, this._onClicked));
 | 
			
		||||
        this.actor.connect('popup-menu', Lang.bind(this, this._onKeyboardPopupMenu));
 | 
			
		||||
@@ -483,7 +463,6 @@ const AppWellIcon = new Lang.Class({
 | 
			
		||||
                                                Lang.bind(this,
 | 
			
		||||
                                                          this._onStateChanged));
 | 
			
		||||
        this._onStateChanged();
 | 
			
		||||
        this.isMenuUp = false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDestroy: function() {
 | 
			
		||||
@@ -556,7 +535,7 @@ const AppWellIcon = new Lang.Class({
 | 
			
		||||
            this._menu.connect('activate-window', Lang.bind(this, function (menu, window) {
 | 
			
		||||
                this.activateWindow(window);
 | 
			
		||||
            }));
 | 
			
		||||
            this._menu.connect('open-state-changed', Lang.bind(this, function (menu, isPoppedUp) {
 | 
			
		||||
            this._menu.connect('popup', Lang.bind(this, function (menu, isPoppedUp) {
 | 
			
		||||
                if (!isPoppedUp)
 | 
			
		||||
                    this._onMenuPoppedDown();
 | 
			
		||||
            }));
 | 
			
		||||
@@ -565,8 +544,8 @@ const AppWellIcon = new Lang.Class({
 | 
			
		||||
            this._menuManager.addMenu(this._menu);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.isMenuUp = true;
 | 
			
		||||
        this.actor.set_hover(true);
 | 
			
		||||
        this.actor.show_tooltip();
 | 
			
		||||
        this._menu.popup();
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
@@ -582,35 +561,30 @@ const AppWellIcon = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _onMenuPoppedDown: function() {
 | 
			
		||||
        this.actor.sync_hover();
 | 
			
		||||
        this.isMenuUp = false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onActivate: function (event) {
 | 
			
		||||
        this.emit('launching');
 | 
			
		||||
        let modifiers = event.get_state();
 | 
			
		||||
        let modifiers = Shell.get_event_state(event);
 | 
			
		||||
 | 
			
		||||
        if (this._onActivateOverride) {
 | 
			
		||||
            this._onActivateOverride(event);
 | 
			
		||||
        if (modifiers & Clutter.ModifierType.CONTROL_MASK
 | 
			
		||||
            && this.app.state == Shell.AppState.RUNNING) {
 | 
			
		||||
            this.app.open_new_window(-1);
 | 
			
		||||
        } else {
 | 
			
		||||
            if (modifiers & Clutter.ModifierType.CONTROL_MASK
 | 
			
		||||
                && this.app.state == Shell.AppState.RUNNING) {
 | 
			
		||||
                this.app.open_new_window(-1);
 | 
			
		||||
            } else {
 | 
			
		||||
                this.app.activate();
 | 
			
		||||
            }
 | 
			
		||||
            this.app.activate(-1);
 | 
			
		||||
        }
 | 
			
		||||
        Main.overview.hide();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    shellWorkspaceLaunch : function(params) {
 | 
			
		||||
        params = Params.parse(params, { workspace: -1,
 | 
			
		||||
                                        timestamp: 0 });
 | 
			
		||||
        params = Params.parse(params, { workspace: null,
 | 
			
		||||
                                        timestamp: null });
 | 
			
		||||
 | 
			
		||||
        this.app.open_new_window(params.workspace);
 | 
			
		||||
        this.app.open_new_window(params.workspace ? params.workspace.index() : -1);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getDragActor: function() {
 | 
			
		||||
        return this.app.create_icon_texture(Main.overview.dashIconSize);
 | 
			
		||||
        return this.app.create_icon_texture(Main.overview.dash.iconSize);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // Returns the original actor that should align with the actor
 | 
			
		||||
@@ -618,19 +592,22 @@ const AppWellIcon = new Lang.Class({
 | 
			
		||||
    getDragActorSource: function() {
 | 
			
		||||
        return this.icon.icon;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(AppWellIcon.prototype);
 | 
			
		||||
 | 
			
		||||
const AppIconMenu = new Lang.Class({
 | 
			
		||||
    Name: 'AppIconMenu',
 | 
			
		||||
    Extends: PopupMenu.PopupMenu,
 | 
			
		||||
function AppIconMenu(source) {
 | 
			
		||||
    this._init(source);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AppIconMenu.prototype = {
 | 
			
		||||
    __proto__: PopupMenu.PopupMenu.prototype,
 | 
			
		||||
 | 
			
		||||
    _init: function(source) {
 | 
			
		||||
        let side = St.Side.LEFT;
 | 
			
		||||
        if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
 | 
			
		||||
        if (St.Widget.get_default_direction() == St.TextDirection.RTL)
 | 
			
		||||
            side = St.Side.RIGHT;
 | 
			
		||||
 | 
			
		||||
        this.parent(source.actor, 0.5, side);
 | 
			
		||||
        PopupMenu.PopupMenu.prototype._init.call(this, source.actor, 0.5, side, 0);
 | 
			
		||||
 | 
			
		||||
        // We want to keep the item hovered while the menu is up
 | 
			
		||||
        this.blockSourceEvents = true;
 | 
			
		||||
@@ -638,6 +615,7 @@ const AppIconMenu = new Lang.Class({
 | 
			
		||||
        this._source = source;
 | 
			
		||||
 | 
			
		||||
        this.connect('activate', Lang.bind(this, this._onActivate));
 | 
			
		||||
        this.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
 | 
			
		||||
 | 
			
		||||
        this.actor.add_style_class_name('app-well-menu');
 | 
			
		||||
 | 
			
		||||
@@ -670,18 +648,17 @@ const AppIconMenu = new Lang.Class({
 | 
			
		||||
            item._window = windows[i];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!this._source.app.is_window_backed()) {
 | 
			
		||||
            if (windows.length > 0)
 | 
			
		||||
                this._appendSeparator();
 | 
			
		||||
 | 
			
		||||
            let isFavorite = AppFavorites.getAppFavorites().isFavorite(this._source.app.get_id());
 | 
			
		||||
 | 
			
		||||
            this._newWindowMenuItem = this._appendMenuItem(_("New Window"));
 | 
			
		||||
        if (windows.length > 0)
 | 
			
		||||
            this._appendSeparator();
 | 
			
		||||
 | 
			
		||||
            this._toggleFavoriteMenuItem = this._appendMenuItem(isFavorite ? _("Remove from Favorites")
 | 
			
		||||
                                                                : _("Add to Favorites"));
 | 
			
		||||
        }
 | 
			
		||||
        let isFavorite = AppFavorites.getAppFavorites().isFavorite(this._source.app.get_id());
 | 
			
		||||
 | 
			
		||||
        this._newWindowMenuItem = this._appendMenuItem(_("New Window"));
 | 
			
		||||
        this._appendSeparator();
 | 
			
		||||
 | 
			
		||||
        this._toggleFavoriteMenuItem = this._appendMenuItem(isFavorite ? _("Remove from Favorites")
 | 
			
		||||
                                                                    : _("Add to Favorites"));
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _appendSeparator: function () {
 | 
			
		||||
@@ -701,6 +678,14 @@ const AppIconMenu = new Lang.Class({
 | 
			
		||||
        this.open();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onOpenStateChanged: function (menu, open) {
 | 
			
		||||
        if (open) {
 | 
			
		||||
            this.emit('popup', true);
 | 
			
		||||
        } else {
 | 
			
		||||
            this.emit('popup', false);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onActivate: function (actor, child) {
 | 
			
		||||
        if (child._window) {
 | 
			
		||||
            let metaWindow = child._window;
 | 
			
		||||
@@ -718,5 +703,5 @@ const AppIconMenu = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
        this.close();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(AppIconMenu.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,18 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const Gettext = imports.gettext.domain('gnome-shell');
 | 
			
		||||
const _ = Gettext.gettext;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
 | 
			
		||||
const AppFavorites = new Lang.Class({
 | 
			
		||||
    Name: 'AppFavorites',
 | 
			
		||||
function AppFavorites() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AppFavorites.prototype = {
 | 
			
		||||
    FAVORITE_APPS_KEY: 'favorite-apps',
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
@@ -26,7 +30,7 @@ const AppFavorites = new Lang.Class({
 | 
			
		||||
        let ids = global.settings.get_strv(this.FAVORITE_APPS_KEY);
 | 
			
		||||
        let appSys = Shell.AppSystem.get_default();
 | 
			
		||||
        let apps = ids.map(function (id) {
 | 
			
		||||
                return appSys.lookup_app(id);
 | 
			
		||||
                return appSys.get_app(id);
 | 
			
		||||
            }).filter(function (app) {
 | 
			
		||||
                return app != null;
 | 
			
		||||
            });
 | 
			
		||||
@@ -63,7 +67,7 @@ const AppFavorites = new Lang.Class({
 | 
			
		||||
        if (appId in this._favorites)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        let app = Shell.AppSystem.get_default().lookup_app(appId);
 | 
			
		||||
        let app = Shell.AppSystem.get_default().get_app(appId);
 | 
			
		||||
 | 
			
		||||
        if (!app)
 | 
			
		||||
            return false;
 | 
			
		||||
@@ -82,9 +86,9 @@ const AppFavorites = new Lang.Class({
 | 
			
		||||
        if (!this._addFavorite(appId, pos))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let app = Shell.AppSystem.get_default().lookup_app(appId);
 | 
			
		||||
        let app = Shell.AppSystem.get_default().get_app(appId);
 | 
			
		||||
 | 
			
		||||
        Main.overview.setMessage(_("%s has been added to your favorites.").format(app.get_name()), Lang.bind(this, function () {
 | 
			
		||||
        Main.overview.shellInfo.setMessage(_("%s has been added to your favorites.").format(app.get_name()), Lang.bind(this, function () {
 | 
			
		||||
            this._removeFavorite(appId);
 | 
			
		||||
        }));
 | 
			
		||||
    },
 | 
			
		||||
@@ -115,12 +119,12 @@ const AppFavorites = new Lang.Class({
 | 
			
		||||
        if (!this._removeFavorite(appId))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        Main.overview.setMessage(_("%s has been removed from your favorites.").format(app.get_name()),
 | 
			
		||||
                                 Lang.bind(this, function () {
 | 
			
		||||
        Main.overview.shellInfo.setMessage(_("%s has been removed from your favorites.").format(app.get_name()),
 | 
			
		||||
                                         Lang.bind(this, function () {
 | 
			
		||||
            this._addFavorite(appId, pos);
 | 
			
		||||
        }));
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(AppFavorites.prototype);
 | 
			
		||||
 | 
			
		||||
var appFavoritesInstance = null;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,290 +0,0 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const ShellMountOperation = imports.ui.shellMountOperation;
 | 
			
		||||
const ScreenSaver = imports.misc.screenSaver;
 | 
			
		||||
 | 
			
		||||
// GSettings keys
 | 
			
		||||
const SETTINGS_SCHEMA = 'org.gnome.desktop.media-handling';
 | 
			
		||||
const SETTING_ENABLE_AUTOMOUNT = 'automount';
 | 
			
		||||
 | 
			
		||||
const AUTORUN_EXPIRE_TIMEOUT_SECS = 10;
 | 
			
		||||
 | 
			
		||||
const ConsoleKitSessionIface = <interface name="org.freedesktop.ConsoleKit.Session">
 | 
			
		||||
<method name="IsActive">
 | 
			
		||||
    <arg type="b" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<signal name="ActiveChanged">
 | 
			
		||||
    <arg type="b" direction="out" />
 | 
			
		||||
</signal>
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
const ConsoleKitSessionProxy = Gio.DBusProxy.makeProxyWrapper(ConsoleKitSessionIface);
 | 
			
		||||
 | 
			
		||||
const ConsoleKitManagerIface = <interface name="org.freedesktop.ConsoleKit.Manager">
 | 
			
		||||
<method name="GetCurrentSession">
 | 
			
		||||
    <arg type="o" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
const ConsoleKitManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(ConsoleKitManagerIface);
 | 
			
		||||
 | 
			
		||||
function ConsoleKitManager() {
 | 
			
		||||
    var self = new Gio.DBusProxy({ g_connection: Gio.DBus.system,
 | 
			
		||||
				   g_interface_name: ConsoleKitManagerInfo.name,
 | 
			
		||||
				   g_interface_info: ConsoleKitManagerInfo,
 | 
			
		||||
				   g_name: 'org.freedesktop.ConsoleKit',
 | 
			
		||||
				   g_object_path: '/org/freedesktop/ConsoleKit/Manager',
 | 
			
		||||
                                   g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START |
 | 
			
		||||
                                             Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
 | 
			
		||||
 | 
			
		||||
    self._updateSessionActive = function() {
 | 
			
		||||
        if (self.g_name_owner) {
 | 
			
		||||
            self.GetCurrentSessionRemote(function([session]) {
 | 
			
		||||
                self._ckSession = new ConsoleKitSessionProxy(Gio.DBus.system, 'org.freedesktop.ConsoleKit', session);
 | 
			
		||||
 | 
			
		||||
                self._ckSession.connectSignal('ActiveChanged', function(object, senderName, [isActive]) {
 | 
			
		||||
                    self.sessionActive = isActive;
 | 
			
		||||
                });
 | 
			
		||||
                self._ckSession.IsActiveRemote(function([isActive]) {
 | 
			
		||||
                    self.sessionActive = isActive;
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
        } else {
 | 
			
		||||
            self.sessionActive = true;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    self.connect('notify::g-name-owner',
 | 
			
		||||
                 Lang.bind(self, self._updateSessionActive));
 | 
			
		||||
 | 
			
		||||
    self._updateSessionActive();
 | 
			
		||||
    self.init(null);
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function haveSystemd() {
 | 
			
		||||
    return GLib.access("/sys/fs/cgroup/systemd", 0) >= 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const AutomountManager = new Lang.Class({
 | 
			
		||||
    Name: 'AutomountManager',
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
 | 
			
		||||
        this._volumeQueue = [];
 | 
			
		||||
 | 
			
		||||
        if (!haveSystemd())
 | 
			
		||||
            this.ckListener = new ConsoleKitManager();
 | 
			
		||||
 | 
			
		||||
        this._ssProxy = new ScreenSaver.ScreenSaverProxy();
 | 
			
		||||
        this._ssProxy.connectSignal('ActiveChanged',
 | 
			
		||||
                                    Lang.bind(this, this._screenSaverActiveChanged));
 | 
			
		||||
 | 
			
		||||
        this._volumeMonitor = Gio.VolumeMonitor.get();
 | 
			
		||||
 | 
			
		||||
        this._volumeMonitor.connect('volume-added',
 | 
			
		||||
                                    Lang.bind(this,
 | 
			
		||||
                                              this._onVolumeAdded));
 | 
			
		||||
        this._volumeMonitor.connect('volume-removed',
 | 
			
		||||
                                    Lang.bind(this,
 | 
			
		||||
                                              this._onVolumeRemoved));
 | 
			
		||||
        this._volumeMonitor.connect('drive-connected',
 | 
			
		||||
                                    Lang.bind(this,
 | 
			
		||||
                                              this._onDriveConnected));
 | 
			
		||||
        this._volumeMonitor.connect('drive-disconnected',
 | 
			
		||||
                                    Lang.bind(this,
 | 
			
		||||
                                              this._onDriveDisconnected));
 | 
			
		||||
        this._volumeMonitor.connect('drive-eject-button',
 | 
			
		||||
                                    Lang.bind(this,
 | 
			
		||||
                                              this._onDriveEjectButton));
 | 
			
		||||
 | 
			
		||||
        Mainloop.idle_add(Lang.bind(this, this._startupMountAll));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _screenSaverActiveChanged: function(object, senderName, [isActive]) {
 | 
			
		||||
        if (!isActive) {
 | 
			
		||||
            this._volumeQueue.forEach(Lang.bind(this, function(volume) {
 | 
			
		||||
                this._checkAndMountVolume(volume);
 | 
			
		||||
            }));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // clear the queue anyway
 | 
			
		||||
        this._volumeQueue = [];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _startupMountAll: function() {
 | 
			
		||||
        let volumes = this._volumeMonitor.get_volumes();
 | 
			
		||||
        volumes.forEach(Lang.bind(this, function(volume) {
 | 
			
		||||
            this._checkAndMountVolume(volume, { checkSession: false,
 | 
			
		||||
                                                useMountOp: false });
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    isSessionActive: function() {
 | 
			
		||||
        // Return whether the current session is active, using the
 | 
			
		||||
        // right mechanism: either systemd if available or ConsoleKit
 | 
			
		||||
        // as fallback.
 | 
			
		||||
 | 
			
		||||
        if (haveSystemd())
 | 
			
		||||
            return Shell.session_is_active_for_systemd();
 | 
			
		||||
 | 
			
		||||
        return this.ckListener.sessionActive;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDriveConnected: function() {
 | 
			
		||||
        // if we're not in the current ConsoleKit session,
 | 
			
		||||
        // or screensaver is active, don't play sounds
 | 
			
		||||
        if (!this.isSessionActive())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (this._ssProxy.screenSaverActive)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        global.play_theme_sound(0, 'device-added-media');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDriveDisconnected: function() {
 | 
			
		||||
        // if we're not in the current ConsoleKit session,
 | 
			
		||||
        // or screensaver is active, don't play sounds
 | 
			
		||||
        if (!this.isSessionActive())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (this._ssProxy.screenSaverActive)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        global.play_theme_sound(0, 'device-removed-media');        
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDriveEjectButton: function(monitor, drive) {
 | 
			
		||||
        // TODO: this code path is not tested, as the GVfs volume monitor
 | 
			
		||||
        // doesn't emit this signal just yet.
 | 
			
		||||
        if (!this.isSessionActive())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        // we force stop/eject in this case, so we don't have to pass a
 | 
			
		||||
        // mount operation object
 | 
			
		||||
        if (drive.can_stop()) {
 | 
			
		||||
            drive.stop
 | 
			
		||||
                (Gio.MountUnmountFlags.FORCE, null, null,
 | 
			
		||||
                 Lang.bind(this, function(drive, res) {
 | 
			
		||||
                     try {
 | 
			
		||||
                         drive.stop_finish(res);
 | 
			
		||||
                     } catch (e) {
 | 
			
		||||
                         log("Unable to stop the drive after drive-eject-button " + e.toString());
 | 
			
		||||
                     }
 | 
			
		||||
                 }));
 | 
			
		||||
        } else if (drive.can_eject()) {
 | 
			
		||||
            drive.eject_with_operation 
 | 
			
		||||
                (Gio.MountUnmountFlags.FORCE, null, null,
 | 
			
		||||
                 Lang.bind(this, function(drive, res) {
 | 
			
		||||
                     try {
 | 
			
		||||
                         drive.eject_with_operation_finish(res);
 | 
			
		||||
                     } catch (e) {
 | 
			
		||||
                         log("Unable to eject the drive after drive-eject-button " + e.toString());
 | 
			
		||||
                     }
 | 
			
		||||
                 }));
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onVolumeAdded: function(monitor, volume) {
 | 
			
		||||
        this._checkAndMountVolume(volume);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _checkAndMountVolume: function(volume, params) {
 | 
			
		||||
        params = Params.parse(params, { checkSession: true,
 | 
			
		||||
                                        useMountOp: true });
 | 
			
		||||
 | 
			
		||||
        if (params.checkSession) {
 | 
			
		||||
            // if we're not in the current ConsoleKit session,
 | 
			
		||||
            // don't attempt automount
 | 
			
		||||
            if (!this.isSessionActive())
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            if (this._ssProxy.screenSaverActive) {
 | 
			
		||||
                if (this._volumeQueue.indexOf(volume) == -1)
 | 
			
		||||
                    this._volumeQueue.push(volume);
 | 
			
		||||
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Volume is already mounted, don't bother.
 | 
			
		||||
        if (volume.get_mount())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (!this._settings.get_boolean(SETTING_ENABLE_AUTOMOUNT) ||
 | 
			
		||||
            !volume.should_automount() ||
 | 
			
		||||
            !volume.can_mount()) {
 | 
			
		||||
            // allow the autorun to run anyway; this can happen if the
 | 
			
		||||
            // mount gets added programmatically later, even if 
 | 
			
		||||
            // should_automount() or can_mount() are false, like for
 | 
			
		||||
            // blank optical media.
 | 
			
		||||
            this._allowAutorun(volume);
 | 
			
		||||
            this._allowAutorunExpire(volume);
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (params.useMountOp) {
 | 
			
		||||
            let operation = new ShellMountOperation.ShellMountOperation(volume);
 | 
			
		||||
            this._mountVolume(volume, operation.mountOp);
 | 
			
		||||
        } else {
 | 
			
		||||
            this._mountVolume(volume, null);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _mountVolume: function(volume, operation) {
 | 
			
		||||
        this._allowAutorun(volume);
 | 
			
		||||
        volume.mount(0, operation, null,
 | 
			
		||||
                     Lang.bind(this, this._onVolumeMounted));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onVolumeMounted: function(volume, res) {
 | 
			
		||||
        this._allowAutorunExpire(volume);
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            volume.mount_finish(res);
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            let string = e.toString();
 | 
			
		||||
 | 
			
		||||
            // FIXME: needs proper error code handling instead of this
 | 
			
		||||
            // See https://bugzilla.gnome.org/show_bug.cgi?id=591480
 | 
			
		||||
            if (string.indexOf('No key available with this passphrase') != -1)
 | 
			
		||||
                this._reaskPassword(volume);
 | 
			
		||||
            else
 | 
			
		||||
                log('Unable to mount volume ' + volume.get_name() + ': ' + string);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onVolumeRemoved: function(monitor, volume) {
 | 
			
		||||
        this._volumeQueue = 
 | 
			
		||||
            this._volumeQueue.filter(function(element) {
 | 
			
		||||
                return (element != volume);
 | 
			
		||||
            });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _reaskPassword: function(volume) {
 | 
			
		||||
        let operation = new ShellMountOperation.ShellMountOperation(volume, { reaskPassword: true });
 | 
			
		||||
        this._mountVolume(volume, operation.mountOp);        
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _allowAutorun: function(volume) {
 | 
			
		||||
        volume.allowAutorun = true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _allowAutorunExpire: function(volume) {
 | 
			
		||||
        Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, function() {
 | 
			
		||||
            volume.allowAutorun = false;
 | 
			
		||||
            return false;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
@@ -1,596 +0,0 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const MessageTray = imports.ui.messageTray;
 | 
			
		||||
const ShellMountOperation = imports.ui.shellMountOperation;
 | 
			
		||||
 | 
			
		||||
// GSettings keys
 | 
			
		||||
const SETTINGS_SCHEMA = 'org.gnome.desktop.media-handling';
 | 
			
		||||
const SETTING_DISABLE_AUTORUN = 'autorun-never';
 | 
			
		||||
const SETTING_START_APP = 'autorun-x-content-start-app';
 | 
			
		||||
const SETTING_IGNORE = 'autorun-x-content-ignore';
 | 
			
		||||
const SETTING_OPEN_FOLDER = 'autorun-x-content-open-folder';
 | 
			
		||||
 | 
			
		||||
const AutorunSetting = {
 | 
			
		||||
    RUN: 0,
 | 
			
		||||
    IGNORE: 1,
 | 
			
		||||
    FILES: 2,
 | 
			
		||||
    ASK: 3
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// misc utils
 | 
			
		||||
function ignoreAutorunForMount(mount) {
 | 
			
		||||
    let root = mount.get_root();
 | 
			
		||||
    let volume = mount.get_volume();
 | 
			
		||||
 | 
			
		||||
    if ((root.is_native() && !isMountRootHidden(root)) ||
 | 
			
		||||
        (volume && volume.allowAutorun && volume.should_automount()))
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function isMountRootHidden(root) {
 | 
			
		||||
    let path = root.get_path();
 | 
			
		||||
 | 
			
		||||
    // skip any mounts in hidden directory hierarchies
 | 
			
		||||
    return (path.indexOf('/.') != -1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function startAppForMount(app, mount) {
 | 
			
		||||
    let files = [];
 | 
			
		||||
    let root = mount.get_root();
 | 
			
		||||
    let retval = false;
 | 
			
		||||
 | 
			
		||||
    files.push(root);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        retval = app.launch(files, 
 | 
			
		||||
                            global.create_app_launch_context())
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
        log('Unable to launch the application ' + app.get_name()
 | 
			
		||||
            + ': ' + e.toString());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/******************************************/
 | 
			
		||||
 | 
			
		||||
const HotplugSnifferIface = <interface name="org.gnome.Shell.HotplugSniffer">
 | 
			
		||||
<method name="SniffURI">
 | 
			
		||||
    <arg type="s" direction="in" />
 | 
			
		||||
    <arg type="as" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
const HotplugSnifferProxy = Gio.DBusProxy.makeProxyWrapper(HotplugSnifferIface);
 | 
			
		||||
function HotplugSniffer() {
 | 
			
		||||
    return new HotplugSnifferProxy(Gio.DBus.session,
 | 
			
		||||
                                   'org.gnome.Shell.HotplugSniffer',
 | 
			
		||||
                                   '/org/gnome/Shell/HotplugSniffer');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ContentTypeDiscoverer = new Lang.Class({
 | 
			
		||||
    Name: 'ContentTypeDiscoverer',
 | 
			
		||||
 | 
			
		||||
    _init: function(callback) {
 | 
			
		||||
        this._callback = callback;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    guessContentTypes: function(mount) {
 | 
			
		||||
        // guess mount's content types using GIO
 | 
			
		||||
        mount.guess_content_type(false, null,
 | 
			
		||||
                                 Lang.bind(this,
 | 
			
		||||
                                           this._onContentTypeGuessed));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onContentTypeGuessed: function(mount, res) {
 | 
			
		||||
        let contentTypes = [];
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            contentTypes = mount.guess_content_type_finish(res);
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            log('Unable to guess content types on added mount ' + mount.get_name()
 | 
			
		||||
                + ': ' + e.toString());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (contentTypes.length) {
 | 
			
		||||
            this._emitCallback(mount, contentTypes);
 | 
			
		||||
        } else {
 | 
			
		||||
            let root = mount.get_root();
 | 
			
		||||
 | 
			
		||||
            let hotplugSniffer = new HotplugSniffer();
 | 
			
		||||
            hotplugSniffer.SniffURIRemote(root.get_uri(),
 | 
			
		||||
                 Lang.bind(this, function([contentTypes]) {
 | 
			
		||||
                     this._emitCallback(mount, contentTypes);
 | 
			
		||||
                 }));
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _emitCallback: function(mount, contentTypes) {
 | 
			
		||||
        if (!contentTypes)
 | 
			
		||||
            contentTypes = [];
 | 
			
		||||
 | 
			
		||||
        // we're not interested in win32 software content types here
 | 
			
		||||
        contentTypes = contentTypes.filter(function(type) {
 | 
			
		||||
            return (type != 'x-content/win32-software');
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        let apps = [];
 | 
			
		||||
        contentTypes.forEach(function(type) {
 | 
			
		||||
            let app = Gio.app_info_get_default_for_type(type, false);
 | 
			
		||||
 | 
			
		||||
            if (app)
 | 
			
		||||
                apps.push(app);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        if (apps.length == 0)
 | 
			
		||||
            apps.push(Gio.app_info_get_default_for_type('inode/directory', false));
 | 
			
		||||
 | 
			
		||||
        this._callback(mount, apps, contentTypes);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const AutorunManager = new Lang.Class({
 | 
			
		||||
    Name: 'AutorunManager',
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._volumeMonitor = Gio.VolumeMonitor.get();
 | 
			
		||||
 | 
			
		||||
        this._volumeMonitor.connect('mount-added',
 | 
			
		||||
                                    Lang.bind(this,
 | 
			
		||||
                                              this._onMountAdded));
 | 
			
		||||
        this._volumeMonitor.connect('mount-removed',
 | 
			
		||||
                                    Lang.bind(this,
 | 
			
		||||
                                              this._onMountRemoved));
 | 
			
		||||
 | 
			
		||||
        this._transDispatcher = new AutorunTransientDispatcher();
 | 
			
		||||
        this._createResidentSource();
 | 
			
		||||
 | 
			
		||||
        let mounts = this._volumeMonitor.get_mounts();
 | 
			
		||||
 | 
			
		||||
        mounts.forEach(Lang.bind(this, function (mount) {
 | 
			
		||||
            let discoverer = new ContentTypeDiscoverer(Lang.bind (this, 
 | 
			
		||||
                function (mount, apps) {
 | 
			
		||||
                    this._residentSource.addMount(mount, apps);
 | 
			
		||||
                }));
 | 
			
		||||
 | 
			
		||||
            discoverer.guessContentTypes(mount);
 | 
			
		||||
        }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createResidentSource: function() {
 | 
			
		||||
        this._residentSource = new AutorunResidentSource();
 | 
			
		||||
        this._residentSource.connect('destroy',
 | 
			
		||||
                                     Lang.bind(this,
 | 
			
		||||
                                               this._createResidentSource));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onMountAdded: function(monitor, mount) {
 | 
			
		||||
        // don't do anything if our session is not the currently
 | 
			
		||||
        // active one
 | 
			
		||||
        if (!Main.automountManager.isSessionActive())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let discoverer = new ContentTypeDiscoverer(Lang.bind (this,
 | 
			
		||||
            function (mount, apps, contentTypes) {
 | 
			
		||||
                this._transDispatcher.addMount(mount, apps, contentTypes);
 | 
			
		||||
                this._residentSource.addMount(mount, apps);
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
        discoverer.guessContentTypes(mount);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onMountRemoved: function(monitor, mount) {
 | 
			
		||||
        this._transDispatcher.removeMount(mount);
 | 
			
		||||
        this._residentSource.removeMount(mount);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    ejectMount: function(mount) {
 | 
			
		||||
        let mountOp = new ShellMountOperation.ShellMountOperation(mount);
 | 
			
		||||
 | 
			
		||||
        // first, see if we have a drive
 | 
			
		||||
        let drive = mount.get_drive();
 | 
			
		||||
        let volume = mount.get_volume();
 | 
			
		||||
 | 
			
		||||
        if (drive &&
 | 
			
		||||
            drive.get_start_stop_type() == Gio.DriveStartStopType.SHUTDOWN &&
 | 
			
		||||
            drive.can_stop()) {
 | 
			
		||||
            drive.stop(0, mountOp.mountOp, null,
 | 
			
		||||
                       Lang.bind(this, this._onStop));
 | 
			
		||||
        } else {
 | 
			
		||||
            if (mount.can_eject()) {
 | 
			
		||||
                mount.eject_with_operation(0, mountOp.mountOp, null,
 | 
			
		||||
                                           Lang.bind(this, this._onEject));
 | 
			
		||||
            } else if (volume && volume.can_eject()) {
 | 
			
		||||
                volume.eject_with_operation(0, mountOp.mountOp, null,
 | 
			
		||||
                                            Lang.bind(this, this._onEject));
 | 
			
		||||
            } else if (drive && drive.can_eject()) {
 | 
			
		||||
                drive.eject_with_operation(0, mountOp.mountOp, null,
 | 
			
		||||
                                           Lang.bind(this, this._onEject));
 | 
			
		||||
            } else if (mount.can_unmount()) {
 | 
			
		||||
                mount.unmount_with_operation(0, mountOp.mountOp, null,
 | 
			
		||||
                                             Lang.bind(this, this._onUnmount));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onUnmount: function(mount, res) {
 | 
			
		||||
        try {
 | 
			
		||||
            mount.unmount_with_operation_finish(res);
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            // FIXME: we need to ignore G_IO_ERROR_FAILED_HANDLED errors here
 | 
			
		||||
            // but we can't access the error code from JS.
 | 
			
		||||
            // See https://bugzilla.gnome.org/show_bug.cgi?id=591480
 | 
			
		||||
            log('Unable to eject the mount ' + mount.get_name() 
 | 
			
		||||
                + ': ' + e.toString());
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onEject: function(source, res) {
 | 
			
		||||
        try {
 | 
			
		||||
            source.eject_with_operation_finish(res);
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            // FIXME: we need to ignore G_IO_ERROR_FAILED_HANDLED errors here
 | 
			
		||||
            // but we can't access the error code from JS.
 | 
			
		||||
            // See https://bugzilla.gnome.org/show_bug.cgi?id=591480
 | 
			
		||||
            log('Unable to eject the drive ' + source.get_name() 
 | 
			
		||||
                + ': ' + e.toString());
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onStop: function(drive, res) {
 | 
			
		||||
        try {
 | 
			
		||||
            drive.stop_finish(res);
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            // FIXME: we need to ignore G_IO_ERROR_FAILED_HANDLED errors here
 | 
			
		||||
            // but we can't access the error code from JS.
 | 
			
		||||
            // See https://bugzilla.gnome.org/show_bug.cgi?id=591480
 | 
			
		||||
            log('Unable to stop the drive ' + drive.get_name() 
 | 
			
		||||
                + ': ' + e.toString());
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const AutorunResidentSource = new Lang.Class({
 | 
			
		||||
    Name: 'AutorunResidentSource',
 | 
			
		||||
    Extends: MessageTray.Source,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.parent(_("Removable Devices"), 'media-removable', St.IconType.FULLCOLOR);
 | 
			
		||||
 | 
			
		||||
        this._mounts = [];
 | 
			
		||||
 | 
			
		||||
        this._notification = new AutorunResidentNotification(this);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addMount: function(mount, apps) {
 | 
			
		||||
        if (ignoreAutorunForMount(mount))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let filtered = this._mounts.filter(function (element) {
 | 
			
		||||
            return (element.mount == mount);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        if (filtered.length != 0)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let element = { mount: mount, apps: apps };
 | 
			
		||||
        this._mounts.push(element);
 | 
			
		||||
        this._redisplay();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    removeMount: function(mount) {
 | 
			
		||||
        this._mounts =
 | 
			
		||||
            this._mounts.filter(function (element) {
 | 
			
		||||
                return (element.mount != mount);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        this._redisplay();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _redisplay: function() {
 | 
			
		||||
        if (this._mounts.length == 0) {
 | 
			
		||||
            this._notification.destroy();
 | 
			
		||||
            this.destroy();
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._notification.updateForMounts(this._mounts);
 | 
			
		||||
 | 
			
		||||
        // add ourselves as a source, and push the notification
 | 
			
		||||
        if (!Main.messageTray.contains(this)) {
 | 
			
		||||
            Main.messageTray.add(this);
 | 
			
		||||
            this.pushNotification(this._notification);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const AutorunResidentNotification = new Lang.Class({
 | 
			
		||||
    Name: 'AutorunResidentNotification',
 | 
			
		||||
    Extends: MessageTray.Notification,
 | 
			
		||||
 | 
			
		||||
    _init: function(source) {
 | 
			
		||||
        this.parent(source, source.title, null, { customContent: true });
 | 
			
		||||
 | 
			
		||||
        // set the notification as resident
 | 
			
		||||
        this.setResident(true);
 | 
			
		||||
 | 
			
		||||
        this._layout = new St.BoxLayout ({ style_class: 'hotplug-resident-box',
 | 
			
		||||
                                           vertical: true });
 | 
			
		||||
 | 
			
		||||
        this.addActor(this._layout,
 | 
			
		||||
                      { x_expand: true,
 | 
			
		||||
                        x_fill: true });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    updateForMounts: function(mounts) {
 | 
			
		||||
        // remove all the layout content
 | 
			
		||||
        this._layout.destroy_all_children();
 | 
			
		||||
 | 
			
		||||
        for (let idx = 0; idx < mounts.length; idx++) {
 | 
			
		||||
            let element = mounts[idx];
 | 
			
		||||
 | 
			
		||||
            let actor = this._itemForMount(element.mount, element.apps);
 | 
			
		||||
            this._layout.add(actor, { x_fill: true,
 | 
			
		||||
                                      expand: true });
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _itemForMount: function(mount, apps) {
 | 
			
		||||
        let item = new St.BoxLayout();
 | 
			
		||||
 | 
			
		||||
        // prepare the mount button content
 | 
			
		||||
        let mountLayout = new St.BoxLayout();
 | 
			
		||||
 | 
			
		||||
        let mountIcon = new St.Icon({ gicon: mount.get_icon(),
 | 
			
		||||
                                      style_class: 'hotplug-resident-mount-icon' });
 | 
			
		||||
        mountLayout.add_actor(mountIcon);
 | 
			
		||||
 | 
			
		||||
        let labelBin = new St.Bin({ y_align: St.Align.MIDDLE });
 | 
			
		||||
        let mountLabel =
 | 
			
		||||
            new St.Label({ text: mount.get_name(),
 | 
			
		||||
                           style_class: 'hotplug-resident-mount-label',
 | 
			
		||||
                           track_hover: true,
 | 
			
		||||
                           reactive: true });
 | 
			
		||||
        labelBin.add_actor(mountLabel);
 | 
			
		||||
        mountLayout.add_actor(labelBin);
 | 
			
		||||
 | 
			
		||||
        let mountButton = new St.Button({ child: mountLayout,
 | 
			
		||||
                                          x_align: St.Align.START,
 | 
			
		||||
                                          x_fill: true,
 | 
			
		||||
                                          style_class: 'hotplug-resident-mount',
 | 
			
		||||
                                          button_mask: St.ButtonMask.ONE });
 | 
			
		||||
        item.add(mountButton, { x_align: St.Align.START,
 | 
			
		||||
                                expand: true });
 | 
			
		||||
 | 
			
		||||
        let ejectIcon = 
 | 
			
		||||
            new St.Icon({ icon_name: 'media-eject',
 | 
			
		||||
                          style_class: 'hotplug-resident-eject-icon' });
 | 
			
		||||
 | 
			
		||||
        let ejectButton =
 | 
			
		||||
            new St.Button({ style_class: 'hotplug-resident-eject-button',
 | 
			
		||||
                            button_mask: St.ButtonMask.ONE,
 | 
			
		||||
                            child: ejectIcon });
 | 
			
		||||
        item.add(ejectButton, { x_align: St.Align.END });
 | 
			
		||||
 | 
			
		||||
        // now connect signals
 | 
			
		||||
        mountButton.connect('clicked', Lang.bind(this, function(actor, event) {
 | 
			
		||||
            startAppForMount(apps[0], mount);
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        ejectButton.connect('clicked', Lang.bind(this, function() {
 | 
			
		||||
            Main.autorunManager.ejectMount(mount);
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        return item;
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const AutorunTransientDispatcher = new Lang.Class({
 | 
			
		||||
    Name: 'AutorunTransientDispatcher',
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._sources = [];
 | 
			
		||||
        this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getAutorunSettingForType: function(contentType) {
 | 
			
		||||
        let runApp = this._settings.get_strv(SETTING_START_APP);
 | 
			
		||||
        if (runApp.indexOf(contentType) != -1)
 | 
			
		||||
            return AutorunSetting.RUN;
 | 
			
		||||
 | 
			
		||||
        let ignore = this._settings.get_strv(SETTING_IGNORE);
 | 
			
		||||
        if (ignore.indexOf(contentType) != -1)
 | 
			
		||||
            return AutorunSetting.IGNORE;
 | 
			
		||||
 | 
			
		||||
        let openFiles = this._settings.get_strv(SETTING_OPEN_FOLDER);
 | 
			
		||||
        if (openFiles.indexOf(contentType) != -1)
 | 
			
		||||
            return AutorunSetting.FILES;
 | 
			
		||||
 | 
			
		||||
        return AutorunSetting.ASK;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getSourceForMount: function(mount) {
 | 
			
		||||
        let filtered =
 | 
			
		||||
            this._sources.filter(function (source) {
 | 
			
		||||
                return (source.mount == mount);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        // we always make sure not to add two sources for the same
 | 
			
		||||
        // mount in addMount(), so it's safe to assume filtered.length
 | 
			
		||||
        // is always either 1 or 0.
 | 
			
		||||
        if (filtered.length == 1)
 | 
			
		||||
            return filtered[0];
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _addSource: function(mount, apps) {
 | 
			
		||||
        // if we already have a source showing for this 
 | 
			
		||||
        // mount, return
 | 
			
		||||
        if (this._getSourceForMount(mount))
 | 
			
		||||
            return;
 | 
			
		||||
     
 | 
			
		||||
        // add a new source
 | 
			
		||||
        this._sources.push(new AutorunTransientSource(mount, apps));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addMount: function(mount, apps, contentTypes) {
 | 
			
		||||
        // if autorun is disabled globally, return
 | 
			
		||||
        if (this._settings.get_boolean(SETTING_DISABLE_AUTORUN))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        // if the mount doesn't want to be autorun, return
 | 
			
		||||
        if (ignoreAutorunForMount(mount))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let setting = this._getAutorunSettingForType(contentTypes[0]);
 | 
			
		||||
 | 
			
		||||
        // check at the settings for the first content type
 | 
			
		||||
        // to see whether we should ask
 | 
			
		||||
        if (setting == AutorunSetting.IGNORE)
 | 
			
		||||
            return; // return right away
 | 
			
		||||
 | 
			
		||||
        let success = false;
 | 
			
		||||
        let app = null;
 | 
			
		||||
 | 
			
		||||
        if (setting == AutorunSetting.RUN) {
 | 
			
		||||
            app = Gio.app_info_get_default_for_type(contentTypes[0], false);
 | 
			
		||||
        } else if (setting == AutorunSetting.FILES) {
 | 
			
		||||
            app = Gio.app_info_get_default_for_type('inode/directory', false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (app)
 | 
			
		||||
            success = startAppForMount(app, mount);
 | 
			
		||||
 | 
			
		||||
        // we fallback here also in case the settings did not specify 'ask',
 | 
			
		||||
        // but we failed launching the default app or the default file manager
 | 
			
		||||
        if (!success)
 | 
			
		||||
            this._addSource(mount, apps);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    removeMount: function(mount) {
 | 
			
		||||
        let source = this._getSourceForMount(mount);
 | 
			
		||||
        
 | 
			
		||||
        // if we aren't tracking this mount, don't do anything
 | 
			
		||||
        if (!source)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        // destroy the notification source
 | 
			
		||||
        source.destroy();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const AutorunTransientSource = new Lang.Class({
 | 
			
		||||
    Name: 'AutorunTransientSource',
 | 
			
		||||
    Extends: MessageTray.Source,
 | 
			
		||||
 | 
			
		||||
    _init: function(mount, apps) {
 | 
			
		||||
        this.mount = mount;
 | 
			
		||||
        this.apps = apps;
 | 
			
		||||
 | 
			
		||||
        this.parent(mount.get_name());
 | 
			
		||||
 | 
			
		||||
        this._notification = new AutorunTransientNotification(this);
 | 
			
		||||
        this._setSummaryIcon(this.createNotificationIcon());
 | 
			
		||||
 | 
			
		||||
        // add ourselves as a source, and popup the notification
 | 
			
		||||
        Main.messageTray.add(this);
 | 
			
		||||
        this.notify(this._notification);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    createNotificationIcon: function() {
 | 
			
		||||
        return new St.Icon({ gicon: this.mount.get_icon(),
 | 
			
		||||
                             icon_size: this.ICON_SIZE });
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const AutorunTransientNotification = new Lang.Class({
 | 
			
		||||
    Name: 'AutorunTransientNotification',
 | 
			
		||||
    Extends: MessageTray.Notification,
 | 
			
		||||
 | 
			
		||||
    _init: function(source) {
 | 
			
		||||
        this.parent(source, source.title, null, { customContent: true });
 | 
			
		||||
 | 
			
		||||
        this._box = new St.BoxLayout({ style_class: 'hotplug-transient-box',
 | 
			
		||||
                                       vertical: true });
 | 
			
		||||
        this.addActor(this._box);
 | 
			
		||||
 | 
			
		||||
        this._mount = source.mount;
 | 
			
		||||
 | 
			
		||||
        source.apps.forEach(Lang.bind(this, function (app) {
 | 
			
		||||
            let actor = this._buttonForApp(app);
 | 
			
		||||
 | 
			
		||||
            if (actor)
 | 
			
		||||
                this._box.add(actor, { x_fill: true,
 | 
			
		||||
                                       x_align: St.Align.START });
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        this._box.add(this._buttonForEject(), { x_fill: true,
 | 
			
		||||
                                                x_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        // set the notification to transient and urgent, so that it
 | 
			
		||||
        // expands out
 | 
			
		||||
        this.setTransient(true);
 | 
			
		||||
        this.setUrgency(MessageTray.Urgency.CRITICAL);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _buttonForApp: function(app) {
 | 
			
		||||
        let box = new St.BoxLayout();
 | 
			
		||||
        let icon = new St.Icon({ gicon: app.get_icon(),
 | 
			
		||||
                                 style_class: 'hotplug-notification-item-icon' });
 | 
			
		||||
        box.add(icon);
 | 
			
		||||
 | 
			
		||||
        let label = new St.Bin({ y_align: St.Align.MIDDLE,
 | 
			
		||||
                                 child: new St.Label
 | 
			
		||||
                                 ({ text: _("Open with %s").format(app.get_name()) })
 | 
			
		||||
                               });
 | 
			
		||||
        box.add(label);
 | 
			
		||||
 | 
			
		||||
        let button = new St.Button({ child: box,
 | 
			
		||||
                                     x_fill: true,
 | 
			
		||||
                                     x_align: St.Align.START,
 | 
			
		||||
                                     button_mask: St.ButtonMask.ONE,
 | 
			
		||||
                                     style_class: 'hotplug-notification-item' });
 | 
			
		||||
 | 
			
		||||
        button.connect('clicked', Lang.bind(this, function() {
 | 
			
		||||
            startAppForMount(app, this._mount);
 | 
			
		||||
            this.destroy();
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        return button;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _buttonForEject: function() {
 | 
			
		||||
        let box = new St.BoxLayout();
 | 
			
		||||
        let icon = new St.Icon({ icon_name: 'media-eject',
 | 
			
		||||
                                 style_class: 'hotplug-notification-item-icon' });
 | 
			
		||||
        box.add(icon);
 | 
			
		||||
 | 
			
		||||
        let label = new St.Bin({ y_align: St.Align.MIDDLE,
 | 
			
		||||
                                 child: new St.Label
 | 
			
		||||
                                 ({ text: _("Eject") })
 | 
			
		||||
                               });
 | 
			
		||||
        box.add(label);
 | 
			
		||||
 | 
			
		||||
        let button = new St.Button({ child: box,
 | 
			
		||||
                                     x_fill: true,
 | 
			
		||||
                                     x_align: St.Align.START,
 | 
			
		||||
                                     button_mask: St.ButtonMask.ONE,
 | 
			
		||||
                                     style_class: 'hotplug-notification-item' });
 | 
			
		||||
 | 
			
		||||
        button.connect('clicked', Lang.bind(this, function() {
 | 
			
		||||
            Main.autorunManager.ejectMount(this._mount);
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        return button;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
@@ -6,7 +6,6 @@ const Meta = imports.gi.Meta;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
 | 
			
		||||
const POPUP_ANIMATION_TIME = 0.15;
 | 
			
		||||
@@ -21,9 +20,11 @@ const POPUP_ANIMATION_TIME = 0.15;
 | 
			
		||||
 * placed.  The arrow position may be controlled via setArrowOrigin().
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
const BoxPointer = new Lang.Class({
 | 
			
		||||
    Name: 'BoxPointer',
 | 
			
		||||
function BoxPointer(side, binProperties) {
 | 
			
		||||
    this._init(side, binProperties);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BoxPointer.prototype = {
 | 
			
		||||
    _init: function(arrowSide, binProperties) {
 | 
			
		||||
        this._arrowSide = arrowSide;
 | 
			
		||||
        this._arrowOrigin = 0;
 | 
			
		||||
@@ -44,22 +45,6 @@ const BoxPointer = new Lang.Class({
 | 
			
		||||
        this._yOffset = 0;
 | 
			
		||||
        this._xPosition = 0;
 | 
			
		||||
        this._yPosition = 0;
 | 
			
		||||
        this._sourceAlignment = 0.5;
 | 
			
		||||
        this._capturedEventId = 0;
 | 
			
		||||
        this._muteInput();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _muteInput: function() {
 | 
			
		||||
        if (this._capturedEventId == 0)
 | 
			
		||||
            this._capturedEventId = this.actor.connect('captured-event',
 | 
			
		||||
                                                       function() { return true; });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _unmuteInput: function() {
 | 
			
		||||
        if (this._capturedEventId != 0) {
 | 
			
		||||
            this.actor.disconnect(this._capturedEventId);
 | 
			
		||||
            this._capturedEventId = 0;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    show: function(animate, onComplete) {
 | 
			
		||||
@@ -89,12 +74,8 @@ const BoxPointer = new Lang.Class({
 | 
			
		||||
        Tweener.addTween(this, { opacity: 255,
 | 
			
		||||
                                 xOffset: 0,
 | 
			
		||||
                                 yOffset: 0,
 | 
			
		||||
                                 transition: 'linear',
 | 
			
		||||
                                 onComplete: Lang.bind(this, function() {
 | 
			
		||||
                                     this._unmuteInput();
 | 
			
		||||
                                     if (onComplete)
 | 
			
		||||
                                         onComplete();
 | 
			
		||||
                                 }),
 | 
			
		||||
                                 transition: "linear",
 | 
			
		||||
                                 onComplete: onComplete,
 | 
			
		||||
                                 time: POPUP_ANIMATION_TIME });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -121,12 +102,10 @@ const BoxPointer = new Lang.Class({
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._muteInput();
 | 
			
		||||
 | 
			
		||||
        Tweener.addTween(this, { opacity: 0,
 | 
			
		||||
                                 xOffset: xOffset,
 | 
			
		||||
                                 yOffset: yOffset,
 | 
			
		||||
                                 transition: 'linear',
 | 
			
		||||
                                 transition: "linear",
 | 
			
		||||
                                 time: POPUP_ANIMATION_TIME,
 | 
			
		||||
                                 onComplete: Lang.bind(this, function () {
 | 
			
		||||
                                     this.actor.hide();
 | 
			
		||||
@@ -200,7 +179,7 @@ const BoxPointer = new Lang.Class({
 | 
			
		||||
        this.bin.allocate(childBox, flags);
 | 
			
		||||
 | 
			
		||||
        if (this._sourceActor && this._sourceActor.mapped)
 | 
			
		||||
            this._reposition(this._sourceActor, this._arrowAlignment);
 | 
			
		||||
            this._reposition(this._sourceActor, this._gap, this._alignment);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _drawBorder: function(area) {
 | 
			
		||||
@@ -326,43 +305,31 @@ const BoxPointer = new Lang.Class({
 | 
			
		||||
        cr.stroke();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setPosition: function(sourceActor, alignment) {
 | 
			
		||||
    setPosition: function(sourceActor, gap, alignment) {
 | 
			
		||||
        // We need to show it now to force an allocation,
 | 
			
		||||
        // so that we can query the correct size.
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
 | 
			
		||||
        this._sourceActor = sourceActor;
 | 
			
		||||
        this._arrowAlignment = alignment;
 | 
			
		||||
        this._gap = gap;
 | 
			
		||||
        this._alignment = alignment;
 | 
			
		||||
 | 
			
		||||
        this._reposition(sourceActor, alignment);
 | 
			
		||||
        this._reposition(sourceActor, gap, alignment);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setSourceAlignment: function(alignment) {
 | 
			
		||||
        this._sourceAlignment = alignment;
 | 
			
		||||
 | 
			
		||||
        if (!this._sourceActor)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        // We need to show it now to force an allocation,
 | 
			
		||||
        // so that we can query the correct size.
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
 | 
			
		||||
        this._reposition(this._sourceActor, this._arrowAlignment);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _reposition: function(sourceActor, alignment) {
 | 
			
		||||
    _reposition: function(sourceActor, gap, alignment) {
 | 
			
		||||
        // Position correctly relative to the sourceActor
 | 
			
		||||
        let sourceNode = sourceActor.get_theme_node();
 | 
			
		||||
        let sourceContentBox = sourceNode.get_content_box(sourceActor.get_allocation_box());
 | 
			
		||||
        let sourceAllocation = Shell.util_get_transformed_allocation(sourceActor);
 | 
			
		||||
        let sourceCenterX = sourceAllocation.x1 + sourceContentBox.x1 + (sourceContentBox.x2 - sourceContentBox.x1) * this._sourceAlignment;
 | 
			
		||||
        let sourceCenterY = sourceAllocation.y1 + sourceContentBox.y1 + (sourceContentBox.y2 - sourceContentBox.y1) * this._sourceAlignment;
 | 
			
		||||
        let sourceCenterX = sourceAllocation.x1 + sourceContentBox.x1 + (sourceContentBox.x2 - sourceContentBox.x1) / 2;
 | 
			
		||||
        let sourceCenterY = sourceAllocation.y1 + sourceContentBox.y1 + (sourceContentBox.y2 - sourceContentBox.y1) / 2;
 | 
			
		||||
        let [minWidth, minHeight, natWidth, natHeight] = this.actor.get_preferred_size();
 | 
			
		||||
 | 
			
		||||
        // We also want to keep it onscreen, and separated from the
 | 
			
		||||
        // edge by the same distance as the main part of the box is
 | 
			
		||||
        // separated from its sourceActor
 | 
			
		||||
        let monitor = Main.layoutManager.findMonitorForActor(sourceActor);
 | 
			
		||||
        let primary = global.get_primary_monitor();
 | 
			
		||||
        let themeNode = this.actor.get_theme_node();
 | 
			
		||||
        let borderWidth = themeNode.get_length('-arrow-border-width');
 | 
			
		||||
        let arrowBase = themeNode.get_length('-arrow-base');
 | 
			
		||||
@@ -370,9 +337,6 @@ const BoxPointer = new Lang.Class({
 | 
			
		||||
        let margin = (4 * borderRadius + borderWidth + arrowBase);
 | 
			
		||||
        let halfMargin = margin / 2;
 | 
			
		||||
 | 
			
		||||
        let themeNode = this.actor.get_theme_node();
 | 
			
		||||
        let gap = themeNode.get_length('-boxpointer-gap');
 | 
			
		||||
 | 
			
		||||
        let resX, resY;
 | 
			
		||||
 | 
			
		||||
        switch (this._arrowSide) {
 | 
			
		||||
@@ -397,8 +361,8 @@ const BoxPointer = new Lang.Class({
 | 
			
		||||
        case St.Side.BOTTOM:
 | 
			
		||||
            resX = sourceCenterX - (halfMargin + (natWidth - margin) * alignment);
 | 
			
		||||
 | 
			
		||||
            resX = Math.max(resX, monitor.x + 10);
 | 
			
		||||
            resX = Math.min(resX, monitor.x + monitor.width - (10 + natWidth));
 | 
			
		||||
            resX = Math.max(resX, primary.x + 10);
 | 
			
		||||
            resX = Math.min(resX, primary.x + primary.width - (10 + natWidth));
 | 
			
		||||
            this.setArrowOrigin(sourceCenterX - resX);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
@@ -406,8 +370,8 @@ const BoxPointer = new Lang.Class({
 | 
			
		||||
        case St.Side.RIGHT:
 | 
			
		||||
            resY = sourceCenterY - (halfMargin + (natHeight - margin) * alignment);
 | 
			
		||||
 | 
			
		||||
            resY = Math.max(resY, monitor.y + 10);
 | 
			
		||||
            resY = Math.min(resY, monitor.y + monitor.height - (10 + natHeight));
 | 
			
		||||
            resY = Math.max(resY, primary.y + 10);
 | 
			
		||||
            resY = Math.min(resY, primary.y + primary.height - (10 + natHeight));
 | 
			
		||||
 | 
			
		||||
            this.setArrowOrigin(sourceCenterY - resY);
 | 
			
		||||
            break;
 | 
			
		||||
@@ -471,4 +435,4 @@ const BoxPointer = new Lang.Class({
 | 
			
		||||
    get opacity() {
 | 
			
		||||
        return this.actor.opacity;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
@@ -7,6 +8,9 @@ const St = imports.gi.St;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const Pango = imports.gi.Pango;
 | 
			
		||||
const Gettext_gtk30 = imports.gettext.domain('gtk30');
 | 
			
		||||
const Gettext = imports.gettext.domain('gnome-shell');
 | 
			
		||||
const _ = Gettext.gettext;
 | 
			
		||||
const C_ = Gettext.pgettext;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
 | 
			
		||||
@@ -155,24 +159,28 @@ function _getEventDayAbbreviation(dayNumber) {
 | 
			
		||||
 | 
			
		||||
// Abstraction for an appointment/event in a calendar
 | 
			
		||||
 | 
			
		||||
const CalendarEvent = new Lang.Class({
 | 
			
		||||
    Name: 'CalendarEvent',
 | 
			
		||||
function CalendarEvent(date, end, summary, allDay) {
 | 
			
		||||
    this._init(date, end, summary, allDay);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CalendarEvent.prototype = {
 | 
			
		||||
    _init: function(date, end, summary, allDay) {
 | 
			
		||||
        this.date = date;
 | 
			
		||||
        this.end = end;
 | 
			
		||||
        this.summary = summary;
 | 
			
		||||
        this.allDay = allDay;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Interface for appointments/events - e.g. the contents of a calendar
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// First, an implementation with no events
 | 
			
		||||
const EmptyEventSource = new Lang.Class({
 | 
			
		||||
    Name: 'EmptyEventSource',
 | 
			
		||||
function EmptyEventSource() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EmptyEventSource.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -187,32 +195,33 @@ const EmptyEventSource = new Lang.Class({
 | 
			
		||||
    hasEvents: function(day) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(EmptyEventSource.prototype);
 | 
			
		||||
 | 
			
		||||
const CalendarServerIface = <interface name="org.gnome.Shell.CalendarServer">
 | 
			
		||||
<method name="GetEvents">
 | 
			
		||||
    <arg type="x" direction="in" />
 | 
			
		||||
    <arg type="x" direction="in" />
 | 
			
		||||
    <arg type="b" direction="in" />
 | 
			
		||||
    <arg type="a(sssbxxa{sv})" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<signal name="Changed" />
 | 
			
		||||
</interface>;
 | 
			
		||||
const CalendarServerIface = {
 | 
			
		||||
    name: 'org.gnome.Shell.CalendarServer',
 | 
			
		||||
    methods: [{ name: 'GetEvents',
 | 
			
		||||
                inSignature: 'xxb',
 | 
			
		||||
                outSignature: 'a(sssbxxa{sv})' }],
 | 
			
		||||
    signals: [{ name: 'Changed',
 | 
			
		||||
                inSignature: '' }]
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const CalendarServerInfo  = Gio.DBusInterfaceInfo.new_for_xml(CalendarServerIface);
 | 
			
		||||
const CalendarServer = function () {
 | 
			
		||||
    this._init();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function CalendarServer() {
 | 
			
		||||
    var self = new Gio.DBusProxy({ g_connection: Gio.DBus.session,
 | 
			
		||||
				   g_interface_name: CalendarServerInfo.name,
 | 
			
		||||
				   g_interface_info: CalendarServerInfo,
 | 
			
		||||
				   g_name: 'org.gnome.Shell.CalendarServer',
 | 
			
		||||
				   g_object_path: '/org/gnome/Shell/CalendarServer',
 | 
			
		||||
                                   g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START |
 | 
			
		||||
                                             Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
 | 
			
		||||
CalendarServer.prototype = {
 | 
			
		||||
     _init: function() {
 | 
			
		||||
         DBus.session.proxifyObject(this, 'org.gnome.Shell.CalendarServer', '/org/gnome/Shell/CalendarServer');
 | 
			
		||||
     }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
    self.init(null);
 | 
			
		||||
    return self;
 | 
			
		||||
DBus.proxifyPrototype(CalendarServer.prototype, CalendarServerIface);
 | 
			
		||||
 | 
			
		||||
// an implementation that reads data from a session bus service
 | 
			
		||||
function DBusEventSource(owner) {
 | 
			
		||||
    this._init(owner);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function _datesEqual(a, b) {
 | 
			
		||||
@@ -233,22 +242,18 @@ function _dateIntervalsOverlap(a0, a1, b0, b1)
 | 
			
		||||
        return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// an implementation that reads data from a session bus service
 | 
			
		||||
const DBusEventSource = new Lang.Class({
 | 
			
		||||
    Name: 'DBusEventSource',
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
DBusEventSource.prototype = {
 | 
			
		||||
    _init: function(owner) {
 | 
			
		||||
        this._resetCache();
 | 
			
		||||
 | 
			
		||||
        this._dbusProxy = new CalendarServer();
 | 
			
		||||
        this._dbusProxy.connectSignal('Changed', Lang.bind(this, this._onChanged));
 | 
			
		||||
        this._dbusProxy = new CalendarServer(owner);
 | 
			
		||||
        this._dbusProxy.connect('Changed', Lang.bind(this, this._onChanged));
 | 
			
		||||
 | 
			
		||||
        this._dbusProxy.connect('notify::g-name-owner', Lang.bind(this, function() {
 | 
			
		||||
            if (this._dbusProxy.g_name_owner)
 | 
			
		||||
                this._onNameAppeared();
 | 
			
		||||
            else
 | 
			
		||||
                this._onNameVanished();
 | 
			
		||||
        }));
 | 
			
		||||
        DBus.session.watch_name('org.gnome.Shell.CalendarServer',
 | 
			
		||||
                                false, // do not launch a name-owner if none exists
 | 
			
		||||
                                Lang.bind(this, this._onNameAppeared),
 | 
			
		||||
                                Lang.bind(this, this._onNameVanished));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _resetCache: function() {
 | 
			
		||||
@@ -271,7 +276,7 @@ const DBusEventSource = new Lang.Class({
 | 
			
		||||
        this._loadEvents(false);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onEventsReceived: function([appointments]) {
 | 
			
		||||
    _onEventsReceived: function(appointments) {
 | 
			
		||||
        let newEvents = [];
 | 
			
		||||
        if (appointments != null) {
 | 
			
		||||
            for (let n = 0; n < appointments.length; n++) {
 | 
			
		||||
@@ -294,9 +299,9 @@ const DBusEventSource = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _loadEvents: function(forceReload) {
 | 
			
		||||
        if (this._curRequestBegin && this._curRequestEnd){
 | 
			
		||||
            let callFlags = Gio.DBusCallFlags.NO_AUTO_START;
 | 
			
		||||
            let callFlags = 0;
 | 
			
		||||
            if (forceReload)
 | 
			
		||||
                callFlags = Gio.DBusCallFlags.NONE;
 | 
			
		||||
                callFlags |= DBus.CALL_FLAG_START;
 | 
			
		||||
            this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000,
 | 
			
		||||
                                            this._curRequestEnd.getTime() / 1000,
 | 
			
		||||
                                            forceReload,
 | 
			
		||||
@@ -337,26 +342,29 @@ const DBusEventSource = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(DBusEventSource.prototype);
 | 
			
		||||
 | 
			
		||||
// Calendar:
 | 
			
		||||
// @eventSource: is an object implementing the EventSource API, e.g. the
 | 
			
		||||
// requestRange(), getEvents(), hasEvents() methods and the ::changed signal.
 | 
			
		||||
const Calendar = new Lang.Class({
 | 
			
		||||
    Name: 'Calendar',
 | 
			
		||||
function Calendar(eventSource) {
 | 
			
		||||
    this._init(eventSource);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Calendar.prototype = {
 | 
			
		||||
    _init: function(eventSource) {
 | 
			
		||||
        if (eventSource) {
 | 
			
		||||
            this._eventSource = eventSource;
 | 
			
		||||
        this._eventSource = eventSource;
 | 
			
		||||
 | 
			
		||||
            this._eventSource.connect('changed', Lang.bind(this,
 | 
			
		||||
                                                           function() {
 | 
			
		||||
                                                               this._update(false);
 | 
			
		||||
                                                           }));
 | 
			
		||||
        }
 | 
			
		||||
        this._eventSource.connect('changed', Lang.bind(this,
 | 
			
		||||
                                                       function() {
 | 
			
		||||
                                                           this._update(false);
 | 
			
		||||
                                                       }));
 | 
			
		||||
 | 
			
		||||
        this._weekStart = Shell.util_get_week_start();
 | 
			
		||||
        // FIXME: This is actually the fallback method for GTK+ for the week start;
 | 
			
		||||
        // GTK+ by preference uses nl_langinfo (NL_TIME_FIRST_WEEKDAY). We probably
 | 
			
		||||
        // should add a C function so we can do the full handling.
 | 
			
		||||
        this._weekStart = NaN;
 | 
			
		||||
        this._weekdate = NaN;
 | 
			
		||||
        this._digitWidth = NaN;
 | 
			
		||||
        this._settings = new Gio.Settings({ schema: 'org.gnome.shell.calendar' });
 | 
			
		||||
@@ -364,6 +372,16 @@ const Calendar = new Lang.Class({
 | 
			
		||||
        this._settings.connect('changed::' + SHOW_WEEKDATE_KEY, Lang.bind(this, this._onSettingsChange));
 | 
			
		||||
        this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY);
 | 
			
		||||
 | 
			
		||||
        let weekStartString = Gettext_gtk30.gettext('calendar:week_start:0');
 | 
			
		||||
        if (weekStartString.indexOf('calendar:week_start:') == 0) {
 | 
			
		||||
            this._weekStart = parseInt(weekStartString.substring(20));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (isNaN(this._weekStart) || this._weekStart < 0 || this._weekStart > 6) {
 | 
			
		||||
            log('Translation of "calendar:week_start:0" in GTK+ is not correct');
 | 
			
		||||
            this._weekStart = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Find the ordering for month/year in the calendar heading
 | 
			
		||||
        this._headerFormatWithoutYear = '%B';
 | 
			
		||||
        switch (Gettext_gtk30.gettext('calendar:MY')) {
 | 
			
		||||
@@ -406,7 +424,7 @@ const Calendar = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _buildHeader: function() {
 | 
			
		||||
        let offsetCols = this._useWeekdate ? 1 : 0;
 | 
			
		||||
        this.actor.destroy_all_children();
 | 
			
		||||
        this.actor.destroy_children();
 | 
			
		||||
 | 
			
		||||
        // Top line of the calendar '<| September 2009 |>'
 | 
			
		||||
        this._topBox = new St.BoxLayout();
 | 
			
		||||
@@ -552,16 +570,13 @@ const Calendar = new Lang.Class({
 | 
			
		||||
        while (true) {
 | 
			
		||||
            let button = new St.Button({ label: iter.getDate().toString() });
 | 
			
		||||
 | 
			
		||||
            if (!this._eventSource)
 | 
			
		||||
                button.reactive = false;
 | 
			
		||||
 | 
			
		||||
            let iterStr = iter.toUTCString();
 | 
			
		||||
            button.connect('clicked', Lang.bind(this, function() {
 | 
			
		||||
                let newlySelectedDate = new Date(iterStr);
 | 
			
		||||
                this.setDate(newlySelectedDate, false);
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
            let hasEvents = this._eventSource && this._eventSource.hasEvents(iter);
 | 
			
		||||
            let hasEvents = this._eventSource.hasEvents(iter);
 | 
			
		||||
            let styleClass = 'calendar-day-base calendar-day';
 | 
			
		||||
            if (_isWorkDay(iter))
 | 
			
		||||
                styleClass += ' calendar-work-day'
 | 
			
		||||
@@ -608,16 +623,17 @@ const Calendar = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
        // Signal to the event source that we are interested in events
 | 
			
		||||
        // only from this date range
 | 
			
		||||
        if (this._eventSource)
 | 
			
		||||
            this._eventSource.requestRange(beginDate, iter, forceReload);
 | 
			
		||||
        this._eventSource.requestRange(beginDate, iter, forceReload);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Signals.addSignalMethods(Calendar.prototype);
 | 
			
		||||
 | 
			
		||||
const EventsList = new Lang.Class({
 | 
			
		||||
    Name: 'EventsList',
 | 
			
		||||
function EventsList(eventSource) {
 | 
			
		||||
    this._init(eventSource);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EventsList.prototype = {
 | 
			
		||||
    _init: function(eventSource) {
 | 
			
		||||
        this.actor = new St.BoxLayout({ vertical: true, style_class: 'events-header-vbox'});
 | 
			
		||||
        this._date = new Date();
 | 
			
		||||
@@ -625,7 +641,17 @@ const EventsList = new Lang.Class({
 | 
			
		||||
        this._eventSource.connect('changed', Lang.bind(this, this._update));
 | 
			
		||||
        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();
 | 
			
		||||
        let weekStartString = Gettext_gtk30.gettext('calendar:week_start:0');
 | 
			
		||||
        if (weekStartString.indexOf('calendar:week_start:') == 0) {
 | 
			
		||||
            this._weekStart = parseInt(weekStartString.substring(20));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (isNaN(this._weekStart) ||
 | 
			
		||||
                  this._weekStart < 0 ||
 | 
			
		||||
                  this._weekStart > 6) {
 | 
			
		||||
            log('Translation of "calendar:week_start:0" in GTK+ is not correct');
 | 
			
		||||
            this._weekStart = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._update();
 | 
			
		||||
    },
 | 
			
		||||
@@ -644,9 +670,6 @@ const EventsList = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _addPeriod: function(header, begin, end, includeDayName, showNothingScheduled) {
 | 
			
		||||
        if (!this._eventSource)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let events = this._eventSource.getEvents(begin, end);
 | 
			
		||||
 | 
			
		||||
        let clockFormat = this._desktopSettings.get_string(CLOCK_FORMAT_KEY);;
 | 
			
		||||
@@ -685,7 +708,7 @@ const EventsList = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showOtherDay: function(day) {
 | 
			
		||||
        this.actor.destroy_all_children();
 | 
			
		||||
        this.actor.destroy_children();
 | 
			
		||||
 | 
			
		||||
        let dayBegin = _getBeginningOfDay(day);
 | 
			
		||||
        let dayEnd = _getEndOfDay(day);
 | 
			
		||||
@@ -702,7 +725,7 @@ const EventsList = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showToday: function() {
 | 
			
		||||
        this.actor.destroy_all_children();
 | 
			
		||||
        this.actor.destroy_children();
 | 
			
		||||
 | 
			
		||||
        let now = new Date();
 | 
			
		||||
        let dayBegin = _getBeginningOfDay(now);
 | 
			
		||||
@@ -748,4 +771,4 @@ const EventsList = new Lang.Class({
 | 
			
		||||
            this._showOtherDay(this._date);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,115 +0,0 @@
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Pango = imports.gi.Pango;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
 | 
			
		||||
const CheckBoxContainer = new Lang.Class({
 | 
			
		||||
    Name: 'CheckBoxContainer',
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.actor = new Shell.GenericContainer();
 | 
			
		||||
        this.actor.connect('get-preferred-width',
 | 
			
		||||
                           Lang.bind(this, this._getPreferredWidth));
 | 
			
		||||
        this.actor.connect('get-preferred-height',
 | 
			
		||||
                           Lang.bind(this, this._getPreferredHeight));
 | 
			
		||||
        this.actor.connect('allocate',
 | 
			
		||||
                           Lang.bind(this, this._allocate));
 | 
			
		||||
        this.actor.connect('style-changed', Lang.bind(this,
 | 
			
		||||
            function() {
 | 
			
		||||
                let node = this.actor.get_theme_node();
 | 
			
		||||
                this._spacing = node.get_length('spacing');
 | 
			
		||||
            }));
 | 
			
		||||
        this.actor.request_mode = Clutter.RequestMode.HEIGHT_FOR_WIDTH;
 | 
			
		||||
 | 
			
		||||
        this._box = new St.Bin();
 | 
			
		||||
        this.actor.add_actor(this._box);
 | 
			
		||||
 | 
			
		||||
        this.label = new St.Label();
 | 
			
		||||
        this.label.clutter_text.set_line_wrap(true);
 | 
			
		||||
        this.label.clutter_text.set_ellipsize(Pango.EllipsizeMode.NONE);
 | 
			
		||||
        this.actor.add_actor(this.label);
 | 
			
		||||
 | 
			
		||||
        this._spacing = 0;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getPreferredWidth: function(actor, forHeight, alloc) {
 | 
			
		||||
        let [minWidth, natWidth] = this._box.get_preferred_width(forHeight);
 | 
			
		||||
 | 
			
		||||
        alloc.min_size = minWidth + this._spacing;
 | 
			
		||||
        alloc.natural_size = natWidth + this._spacing;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getPreferredHeight: function(actor, forWidth, alloc) {
 | 
			
		||||
        /* FIXME: StBoxlayout currently does not handle
 | 
			
		||||
           height-for-width children correctly, so hard-code
 | 
			
		||||
           two lines for the label until that problem is fixed.
 | 
			
		||||
 | 
			
		||||
           https://bugzilla.gnome.org/show_bug.cgi?id=672543 */
 | 
			
		||||
/*
 | 
			
		||||
        let [minBoxHeight, natBoxHeight] =
 | 
			
		||||
            this._box.get_preferred_height(forWidth);
 | 
			
		||||
        let [minLabelHeight, natLabelHeight] =
 | 
			
		||||
            this.label.get_preferred_height(forWidth);
 | 
			
		||||
 | 
			
		||||
        alloc.min_size = Math.max(minBoxHeight, minLabelHeight);
 | 
			
		||||
        alloc.natural_size = Math.max(natBoxHeight, natLabelHeight);
 | 
			
		||||
*/
 | 
			
		||||
        let [minBoxHeight, natBoxHeight] =
 | 
			
		||||
            this._box.get_preferred_height(-1);
 | 
			
		||||
        let [minLabelHeight, natLabelHeight] =
 | 
			
		||||
            this.label.get_preferred_height(-1);
 | 
			
		||||
 | 
			
		||||
        alloc.min_size = Math.max(minBoxHeight, 2 * minLabelHeight);
 | 
			
		||||
        alloc.natural_size = Math.max(natBoxHeight, 2 * natLabelHeight);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _allocate: function(actor, box, flags) {
 | 
			
		||||
        let availWidth = box.x2 - box.x1;
 | 
			
		||||
        let availHeight = box.y2 - box.y1;
 | 
			
		||||
 | 
			
		||||
        let childBox = new Clutter.ActorBox();
 | 
			
		||||
        let [minBoxWidth, natBoxWidth] =
 | 
			
		||||
            this._box.get_preferred_width(-1);
 | 
			
		||||
        let [minBoxHeight, natBoxHeight] =
 | 
			
		||||
            this._box.get_preferred_height(-1);
 | 
			
		||||
        childBox.x1 = box.x1;
 | 
			
		||||
        childBox.x2 = box.x1 + natBoxWidth;
 | 
			
		||||
        childBox.y1 = box.y1;
 | 
			
		||||
        childBox.y2 = box.y1 + natBoxHeight;
 | 
			
		||||
        this._box.allocate(childBox, flags);
 | 
			
		||||
 | 
			
		||||
        childBox.x1 = box.x1 + natBoxWidth + this._spacing;
 | 
			
		||||
        childBox.x2 = availWidth - childBox.x1;
 | 
			
		||||
        childBox.y1 = box.y1;
 | 
			
		||||
        childBox.y2 = box.y2;
 | 
			
		||||
        this.label.allocate(childBox, flags);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const CheckBox = new Lang.Class({
 | 
			
		||||
    Name: 'CheckBox',
 | 
			
		||||
 | 
			
		||||
    _init: function(label) {
 | 
			
		||||
        this.actor = new St.Button({ style_class: 'check-box',
 | 
			
		||||
                                     button_mask: St.ButtonMask.ONE,
 | 
			
		||||
                                     toggle_mode: true,
 | 
			
		||||
                                     can_focus: true,
 | 
			
		||||
                                     x_fill: true,
 | 
			
		||||
                                     y_fill: true });
 | 
			
		||||
        this._container = new CheckBoxContainer();
 | 
			
		||||
        this.actor.set_child(this._container.actor);
 | 
			
		||||
 | 
			
		||||
        if (label)
 | 
			
		||||
            this.setLabel(label);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setLabel: function(label) {
 | 
			
		||||
        this._container.label.set_text(label);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getLabelActor: function() {
 | 
			
		||||
        return this._container.label;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										454
									
								
								js/ui/chrome.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,454 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
 | 
			
		||||
// This manages the shell "chrome"; the UI that's visible in the
 | 
			
		||||
// normal mode (ie, outside the Overview), that surrounds the main
 | 
			
		||||
// workspace content.
 | 
			
		||||
 | 
			
		||||
const defaultParams = {
 | 
			
		||||
    visibleInOverview: false,
 | 
			
		||||
    visibleInFullscreen: false,
 | 
			
		||||
    affectsStruts: true,
 | 
			
		||||
    affectsInputRegion: true
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function Chrome() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Chrome.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        // The group itself has zero size so it doesn't interfere with DND
 | 
			
		||||
        this.actor = new Shell.GenericContainer({ width: 0, height: 0 });
 | 
			
		||||
        Main.uiGroup.add_actor(this.actor);
 | 
			
		||||
        this.actor.connect('allocate', Lang.bind(this, this._allocated));
 | 
			
		||||
 | 
			
		||||
        this._monitors = [];
 | 
			
		||||
        this._inOverview = false;
 | 
			
		||||
 | 
			
		||||
        this._trackedActors = [];
 | 
			
		||||
 | 
			
		||||
        global.screen.connect('monitors-changed',
 | 
			
		||||
                              Lang.bind(this, this._monitorsChanged));
 | 
			
		||||
        global.screen.connect('restacked',
 | 
			
		||||
                              Lang.bind(this, this._windowsRestacked));
 | 
			
		||||
 | 
			
		||||
        // Need to update struts on new workspaces when they are added
 | 
			
		||||
        global.screen.connect('notify::n-workspaces',
 | 
			
		||||
                              Lang.bind(this, this._queueUpdateRegions));
 | 
			
		||||
 | 
			
		||||
        Main.overview.connect('showing',
 | 
			
		||||
                             Lang.bind(this, this._overviewShowing));
 | 
			
		||||
        Main.overview.connect('hidden',
 | 
			
		||||
                             Lang.bind(this, this._overviewHidden));
 | 
			
		||||
 | 
			
		||||
        this._updateMonitors();
 | 
			
		||||
        this._updateFullscreen();
 | 
			
		||||
        this._queueUpdateRegions();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _allocated: function(actor, box, flags) {
 | 
			
		||||
        let children = this.actor.get_children();
 | 
			
		||||
        for (let i = 0; i < children.length; i++)
 | 
			
		||||
            children[i].allocate_preferred_size(flags);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // addActor:
 | 
			
		||||
    // @actor: an actor to add to the chrome layer
 | 
			
		||||
    // @params: (optional) additional params
 | 
			
		||||
    //
 | 
			
		||||
    // Adds @actor to the chrome layer and extends the input region
 | 
			
		||||
    // and window manager struts to include it. (Window manager struts
 | 
			
		||||
    // will only be affected if @actor is touching a screen edge.)
 | 
			
		||||
    // Changes in @actor's size and position will automatically result
 | 
			
		||||
    // in appropriate changes to the input region and struts. Changes
 | 
			
		||||
    // in its visibility will affect the input region, but NOT the
 | 
			
		||||
    // struts.
 | 
			
		||||
    //
 | 
			
		||||
    // If %visibleInOverview is %true in @params, @actor will remain
 | 
			
		||||
    // visible when the overview is brought up. Otherwise it will
 | 
			
		||||
    // automatically be hidden. Likewise, if %visibleInFullscreen is
 | 
			
		||||
    // %true, the actor will be visible even when a fullscreen window
 | 
			
		||||
    // should be covering it.
 | 
			
		||||
    //
 | 
			
		||||
    // If %affectsStruts or %affectsInputRegion is %false, the actor
 | 
			
		||||
    // will not have the indicated effect.
 | 
			
		||||
    addActor: function(actor, params) {
 | 
			
		||||
        this.actor.add_actor(actor);
 | 
			
		||||
        this._trackActor(actor, params);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // trackActor:
 | 
			
		||||
    // @actor: a descendant of the chrome to begin tracking
 | 
			
		||||
    // @params: parameters describing how to track @actor
 | 
			
		||||
    //
 | 
			
		||||
    // Tells the chrome to track @actor, which must be a descendant
 | 
			
		||||
    // of an actor added via addActor(). This can be used to extend the
 | 
			
		||||
    // struts or input region to cover specific children.
 | 
			
		||||
    //
 | 
			
		||||
    // @params can have any of the same values as in addActor(), though
 | 
			
		||||
    // some possibilities don't make sense (eg, trying to have a
 | 
			
		||||
    // %visibleInOverview child of a non-%visibleInOverview parent).
 | 
			
		||||
    // By default, @actor has the same params as its chrome ancestor.
 | 
			
		||||
    trackActor: function(actor, params) {
 | 
			
		||||
        let ancestor = actor.get_parent();
 | 
			
		||||
        let index = this._findActor(ancestor);
 | 
			
		||||
        while (ancestor && index == -1) {
 | 
			
		||||
            ancestor = ancestor.get_parent();
 | 
			
		||||
            index = this._findActor(ancestor);
 | 
			
		||||
        }
 | 
			
		||||
        if (!ancestor)
 | 
			
		||||
            throw new Error('actor is not a descendent of the chrome layer');
 | 
			
		||||
 | 
			
		||||
        let ancestorData = this._trackedActors[index];
 | 
			
		||||
        if (!params)
 | 
			
		||||
            params = {};
 | 
			
		||||
        // We can't use Params.parse here because we want to drop
 | 
			
		||||
        // the extra values like ancestorData.actor
 | 
			
		||||
        for (let prop in defaultParams) {
 | 
			
		||||
            if (!params[prop])
 | 
			
		||||
                params[prop] = ancestorData[prop];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._trackActor(actor, params);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // untrackActor:
 | 
			
		||||
    // @actor: an actor previously tracked via trackActor()
 | 
			
		||||
    //
 | 
			
		||||
    // Undoes the effect of trackActor()
 | 
			
		||||
    untrackActor: function(actor) {
 | 
			
		||||
        this._untrackActor(actor);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // removeActor:
 | 
			
		||||
    // @actor: a child of the chrome layer
 | 
			
		||||
    //
 | 
			
		||||
    // Removes @actor from the chrome layer
 | 
			
		||||
    removeActor: function(actor) {
 | 
			
		||||
        this.actor.remove_actor(actor);
 | 
			
		||||
        this._untrackActor(actor);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _findActor: function(actor) {
 | 
			
		||||
        for (let i = 0; i < this._trackedActors.length; i++) {
 | 
			
		||||
            let actorData = this._trackedActors[i];
 | 
			
		||||
            if (actorData.actor == actor)
 | 
			
		||||
                return i;
 | 
			
		||||
        }
 | 
			
		||||
        return -1;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _trackActor: function(actor, params) {
 | 
			
		||||
        if (this._findActor(actor) != -1)
 | 
			
		||||
            throw new Error('trying to re-track existing chrome actor');
 | 
			
		||||
 | 
			
		||||
        let actorData = Params.parse(params, defaultParams);
 | 
			
		||||
        actorData.actor = actor;
 | 
			
		||||
        actorData.visibleId = actor.connect('notify::visible',
 | 
			
		||||
                                            Lang.bind(this, this._queueUpdateRegions));
 | 
			
		||||
        actorData.allocationId = actor.connect('notify::allocation',
 | 
			
		||||
                                               Lang.bind(this, this._queueUpdateRegions));
 | 
			
		||||
        actorData.parentSetId = actor.connect('parent-set',
 | 
			
		||||
                                              Lang.bind(this, this._actorReparented));
 | 
			
		||||
        // Note that destroying actor will unset its parent, so we don't
 | 
			
		||||
        // need to connect to 'destroy' too.
 | 
			
		||||
 | 
			
		||||
        this._trackedActors.push(actorData);
 | 
			
		||||
        this._queueUpdateRegions();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _untrackActor: function(actor) {
 | 
			
		||||
        let i = this._findActor(actor);
 | 
			
		||||
 | 
			
		||||
        if (i == -1)
 | 
			
		||||
            return;
 | 
			
		||||
        let actorData = this._trackedActors[i];
 | 
			
		||||
 | 
			
		||||
        this._trackedActors.splice(i, 1);
 | 
			
		||||
        actor.disconnect(actorData.visibleId);
 | 
			
		||||
        actor.disconnect(actorData.allocationId);
 | 
			
		||||
        actor.disconnect(actorData.parentSetId);
 | 
			
		||||
 | 
			
		||||
        this._queueUpdateRegions();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _actorReparented: function(actor, oldParent) {
 | 
			
		||||
        if (!this.actor.contains(actor))
 | 
			
		||||
            this._untrackActor(actor);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateVisibility: function() {
 | 
			
		||||
        for (let i = 0; i < this._trackedActors.length; i++) {
 | 
			
		||||
            let actorData = this._trackedActors[i];
 | 
			
		||||
            if (this._inOverview && !actorData.visibleInOverview)
 | 
			
		||||
                this.actor.set_skip_paint(actorData.actor, true);
 | 
			
		||||
            else if (!this._inOverview && !actorData.visibleInFullscreen &&
 | 
			
		||||
                     this._findMonitorForActor(actorData.actor).inFullscreen)
 | 
			
		||||
                this.actor.set_skip_paint(actorData.actor, true);
 | 
			
		||||
            else
 | 
			
		||||
                this.actor.set_skip_paint(actorData.actor, false);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _overviewShowing: function() {
 | 
			
		||||
        this._inOverview = true;
 | 
			
		||||
        this._updateVisibility();
 | 
			
		||||
        this._queueUpdateRegions();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _overviewHidden: function() {
 | 
			
		||||
        this._inOverview = false;
 | 
			
		||||
        this._updateVisibility();
 | 
			
		||||
        this._queueUpdateRegions();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateMonitors: function() {
 | 
			
		||||
        let monitors = global.get_monitors();
 | 
			
		||||
        let primary = global.get_primary_monitor();
 | 
			
		||||
        this._monitors = monitors;
 | 
			
		||||
        for (let i = 0; i < monitors.length; i++) {
 | 
			
		||||
            let monitor = monitors[i];
 | 
			
		||||
            if (monitor.x == primary.x &&
 | 
			
		||||
                monitor.y == primary.y &&
 | 
			
		||||
                monitor.width == primary.width &&
 | 
			
		||||
                monitor.height == primary.height)
 | 
			
		||||
                this._primaryMonitor = monitor;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _findMonitorForRect: function(x, y, w, h) {
 | 
			
		||||
        // First look at what monitor the center of the rectangle is at
 | 
			
		||||
        let cx = x + w/2;
 | 
			
		||||
        let cy = y + h/2;
 | 
			
		||||
        for (let i = 0; i < this._monitors.length; i++) {
 | 
			
		||||
            let monitor = this._monitors[i];
 | 
			
		||||
            if (cx >= monitor.x && cx < monitor.x + monitor.width &&
 | 
			
		||||
                cy >= monitor.y && cy < monitor.y + monitor.height)
 | 
			
		||||
                return monitor;
 | 
			
		||||
        }
 | 
			
		||||
        // If the center is not on a monitor, return the first overlapping monitor
 | 
			
		||||
        for (let i = 0; i < this._monitors.length; i++) {
 | 
			
		||||
            let monitor = this._monitors[i];
 | 
			
		||||
            if (x + w > monitor.x && x < monitor.x + monitor.width &&
 | 
			
		||||
                y + h > monitor.y && y < monitor.y + monitor.height)
 | 
			
		||||
                return monitor;
 | 
			
		||||
        }
 | 
			
		||||
        // otherwise on no monitor
 | 
			
		||||
        return null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _findMonitorForWindow: function(window) {
 | 
			
		||||
        return this._findMonitorForRect(window.x, window.y, window.width, window.height);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // This call guarantees that we return some monitor to simplify usage of it
 | 
			
		||||
    // In practice all tracked actors should be visible on some monitor anyway
 | 
			
		||||
    _findMonitorForActor: function(actor) {
 | 
			
		||||
        let [x, y] = actor.get_transformed_position();
 | 
			
		||||
        let [w, h] = actor.get_transformed_size();
 | 
			
		||||
        let monitor = this._findMonitorForRect(x, y, w, h);
 | 
			
		||||
        if (monitor)
 | 
			
		||||
            return monitor;
 | 
			
		||||
        return this._primaryMonitor; // Not on any monitor, pretend its on the primary
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _monitorsChanged: function() {
 | 
			
		||||
        this._updateMonitors();
 | 
			
		||||
 | 
			
		||||
        // Update everything that depends on monitor positions
 | 
			
		||||
        this._updateFullscreen();
 | 
			
		||||
        this._updateVisibility();
 | 
			
		||||
        this._queueUpdateRegions();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _queueUpdateRegions: function() {
 | 
			
		||||
        if (!this._updateRegionIdle)
 | 
			
		||||
            this._updateRegionIdle = Mainloop.idle_add(Lang.bind(this, this._updateRegions),
 | 
			
		||||
                                                       Meta.PRIORITY_BEFORE_REDRAW);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateFullscreen: function() {
 | 
			
		||||
        let windows = Main.getWindowActorsForWorkspace(global.screen.get_active_workspace_index());
 | 
			
		||||
 | 
			
		||||
        // Reset all monitors to not fullscreen
 | 
			
		||||
        for (let i = 0; i < this._monitors.length; i++)
 | 
			
		||||
            this._monitors[i].inFullscreen = false;
 | 
			
		||||
 | 
			
		||||
        // The chrome layer should be visible unless there is a window
 | 
			
		||||
        // with layer FULLSCREEN, or a window with layer
 | 
			
		||||
        // OVERRIDE_REDIRECT that covers the whole screen.
 | 
			
		||||
        // ('override_redirect' is not actually a layer above all
 | 
			
		||||
        // other windows, but this seems to be how mutter treats it
 | 
			
		||||
        // currently...) If we wanted to be extra clever, we could
 | 
			
		||||
        // figure out when an OVERRIDE_REDIRECT window was trying to
 | 
			
		||||
        // partially overlap us, and then adjust the input region and
 | 
			
		||||
        // our clip region accordingly...
 | 
			
		||||
 | 
			
		||||
        // @windows is sorted bottom to top.
 | 
			
		||||
 | 
			
		||||
        for (let i = windows.length - 1; i > -1; i--) {
 | 
			
		||||
            let window = windows[i];
 | 
			
		||||
            let layer = window.get_meta_window().get_layer();
 | 
			
		||||
 | 
			
		||||
            if (layer == Meta.StackLayer.FULLSCREEN) {
 | 
			
		||||
                let monitor = this._findMonitorForWindow(window);
 | 
			
		||||
                if (monitor)
 | 
			
		||||
                    monitor.inFullscreen = true;
 | 
			
		||||
            }
 | 
			
		||||
            if (layer == Meta.StackLayer.OVERRIDE_REDIRECT) {
 | 
			
		||||
                let monitor = this._findMonitorForWindow(window);
 | 
			
		||||
                if (monitor &&
 | 
			
		||||
                    window.x <= monitor.x &&
 | 
			
		||||
                    window.x + window.width >= monitor.x + monitor.width &&
 | 
			
		||||
                    window.y <= monitor.y &&
 | 
			
		||||
                    window.y + window.height >= monitor.y + monitor.height)
 | 
			
		||||
                    monitor.inFullscreen = true;
 | 
			
		||||
            } else
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _windowsRestacked: function() {
 | 
			
		||||
        let wasInFullscreen = [];
 | 
			
		||||
        for (let i = 0; i < this._monitors.length; i++)
 | 
			
		||||
            wasInFullscreen[i] = this._monitors[i].inFullscreen;
 | 
			
		||||
 | 
			
		||||
        this._updateFullscreen();
 | 
			
		||||
 | 
			
		||||
        let changed = false;
 | 
			
		||||
        for (let i = 0; i < wasInFullscreen.length; i++) {
 | 
			
		||||
            if (wasInFullscreen[i] != this._monitors[i].inFullscreen) {
 | 
			
		||||
                changed = true;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (changed) {
 | 
			
		||||
            this._updateVisibility();
 | 
			
		||||
            this._queueUpdateRegions();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Figure out where the pointer is in case we lost track of
 | 
			
		||||
        // it during a grab. (In particular, if a trayicon popup menu
 | 
			
		||||
        // is dismissed, see if we need to close the message tray.)
 | 
			
		||||
        global.sync_pointer();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateRegions: function() {
 | 
			
		||||
        let rects = [], struts = [], i;
 | 
			
		||||
 | 
			
		||||
        delete this._updateRegionIdle;
 | 
			
		||||
 | 
			
		||||
        for (i = 0; i < this._trackedActors.length; i++) {
 | 
			
		||||
            let actorData = this._trackedActors[i];
 | 
			
		||||
            if (!actorData.affectsInputRegion && !actorData.affectsStruts)
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            let [x, y] = actorData.actor.get_transformed_position();
 | 
			
		||||
            let [w, h] = actorData.actor.get_transformed_size();
 | 
			
		||||
            x = Math.round(x);
 | 
			
		||||
            y = Math.round(y);
 | 
			
		||||
            w = Math.round(w);
 | 
			
		||||
            h = Math.round(h);
 | 
			
		||||
            let rect = new Meta.Rectangle({ x: x, y: y, width: w, height: h});
 | 
			
		||||
 | 
			
		||||
            if (actorData.affectsInputRegion &&
 | 
			
		||||
                actorData.actor.get_paint_visibility() &&
 | 
			
		||||
                !this.actor.get_skip_paint(actorData.actor))
 | 
			
		||||
                rects.push(rect);
 | 
			
		||||
 | 
			
		||||
            if (!actorData.affectsStruts)
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            // Limit struts to the size of the screen
 | 
			
		||||
            let x1 = Math.max(x, 0);
 | 
			
		||||
            let x2 = Math.min(x + w, global.screen_width);
 | 
			
		||||
            let y1 = Math.max(y, 0);
 | 
			
		||||
            let y2 = Math.min(y + h, global.screen_height);
 | 
			
		||||
 | 
			
		||||
            // NetWM struts are not really powerful enought to handle
 | 
			
		||||
            // a multi-monitor scenario, they only describe what happens
 | 
			
		||||
            // around the outer sides of the full display region. However
 | 
			
		||||
            // it can describe a partial region along each side, so
 | 
			
		||||
            // we can support having the struts only affect the
 | 
			
		||||
            // primary monitor. This should be enough as we only have
 | 
			
		||||
            // chrome affecting the struts on the primary monitor so
 | 
			
		||||
            // far.
 | 
			
		||||
            //
 | 
			
		||||
            // Metacity wants to know what side of the screen the
 | 
			
		||||
            // strut is considered to be attached to. If the actor is
 | 
			
		||||
            // only touching one edge, or is touching the entire
 | 
			
		||||
            // border of the primary monitor, then it's obvious which
 | 
			
		||||
            // side to call it. If it's in a corner, we pick a side
 | 
			
		||||
            // arbitrarily. If it doesn't touch any edges, or it spans
 | 
			
		||||
            // the width/height across the middle of the screen, then
 | 
			
		||||
            // we don't create a strut for it at all.
 | 
			
		||||
            let side;
 | 
			
		||||
            let primary = this._primaryMonitor;
 | 
			
		||||
            if (x1 <= primary.x && x2 >= primary.x + primary.width) {
 | 
			
		||||
                if (y1 <= primary.y)
 | 
			
		||||
                    side = Meta.Side.TOP;
 | 
			
		||||
                else if (y2 >= primary.y + primary.height)
 | 
			
		||||
                    side = Meta.Side.BOTTOM;
 | 
			
		||||
                else
 | 
			
		||||
                    continue;
 | 
			
		||||
            } else if (y1 <= primary.y && y2 >= primary.y + primary.height) {
 | 
			
		||||
                if (x1 <= 0)
 | 
			
		||||
                    side = Meta.Side.LEFT;
 | 
			
		||||
                else if (x2 >= global.screen_width)
 | 
			
		||||
                    side = Meta.Side.RIGHT;
 | 
			
		||||
                else
 | 
			
		||||
                    continue;
 | 
			
		||||
            } else if (x1 <= 0)
 | 
			
		||||
                side = Meta.Side.LEFT;
 | 
			
		||||
            else if (y1 <= 0)
 | 
			
		||||
                side = Meta.Side.TOP;
 | 
			
		||||
            else if (x2 >= global.screen_width)
 | 
			
		||||
                side = Meta.Side.RIGHT;
 | 
			
		||||
            else if (y2 >= global.screen_height)
 | 
			
		||||
                side = Meta.Side.BOTTOM;
 | 
			
		||||
            else
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            // Ensure that the strut rects goes all the way to the screen edge,
 | 
			
		||||
            // as this really what mutter expects.
 | 
			
		||||
            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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        global.set_stage_input_region(rects);
 | 
			
		||||
 | 
			
		||||
        let screen = global.screen;
 | 
			
		||||
        for (let w = 0; w < screen.n_workspaces; w++) {
 | 
			
		||||
            let workspace = screen.get_workspace_by_index(w);
 | 
			
		||||
            workspace.set_builtin_struts(struts);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(Chrome.prototype);
 | 
			
		||||
@@ -1,196 +0,0 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Folks = imports.gi.Folks
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Atk = imports.gi.Atk;
 | 
			
		||||
 | 
			
		||||
const Util = imports.misc.util;
 | 
			
		||||
const IconGrid = imports.ui.iconGrid;
 | 
			
		||||
const Search = imports.ui.search;
 | 
			
		||||
const SearchDisplay = imports.ui.searchDisplay;
 | 
			
		||||
 | 
			
		||||
const MAX_SEARCH_RESULTS_ROWS = 1;
 | 
			
		||||
const ICON_SIZE = 81;
 | 
			
		||||
 | 
			
		||||
function launchContact(id) {
 | 
			
		||||
    Util.spawn(['gnome-contacts', '-i', id]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* This class represents a shown contact search result in the overview */
 | 
			
		||||
const Contact = new Lang.Class({
 | 
			
		||||
    Name: 'Contact',
 | 
			
		||||
 | 
			
		||||
    _init: function(id) {
 | 
			
		||||
        this._contactSys = Shell.ContactSystem.get_default();
 | 
			
		||||
        this.individual = this._contactSys.get_individual(id);
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.Bin({ style_class: 'contact',
 | 
			
		||||
                                  reactive: true,
 | 
			
		||||
                                  can_focus: true,
 | 
			
		||||
                                  track_hover: true,
 | 
			
		||||
                                  accessible_role: Atk.Role.PUSH_BUTTON });
 | 
			
		||||
 | 
			
		||||
        let content = new St.BoxLayout( { style_class: 'contact-content',
 | 
			
		||||
                                          vertical: false });
 | 
			
		||||
        this.actor.set_child(content);
 | 
			
		||||
 | 
			
		||||
        let icon = new St.Icon({ icon_type: St.IconType.FULLCOLOR,
 | 
			
		||||
                                 icon_size: ICON_SIZE,
 | 
			
		||||
                                 style_class: 'contact-icon' });
 | 
			
		||||
        if (this.individual.avatar != null)
 | 
			
		||||
            icon.gicon = this.individual.avatar;
 | 
			
		||||
        else
 | 
			
		||||
            icon.icon_name = 'avatar-default';
 | 
			
		||||
 | 
			
		||||
        content.add(icon, { x_fill: true,
 | 
			
		||||
                            y_fill: false,
 | 
			
		||||
                            x_align: St.Align.START,
 | 
			
		||||
                            y_align: St.Align.MIDDLE });
 | 
			
		||||
 | 
			
		||||
        let details = new St.BoxLayout({ style_class: 'contact-details',
 | 
			
		||||
                                         vertical: true });
 | 
			
		||||
        content.add(details, { x_fill: true,
 | 
			
		||||
                               y_fill: false,
 | 
			
		||||
                               x_align: St.Align.START,
 | 
			
		||||
                               y_align: St.Align.MIDDLE });
 | 
			
		||||
 | 
			
		||||
        let email = this._contactSys.get_email_for_display(this.individual);
 | 
			
		||||
        let aliasText = this.individual.alias     ||
 | 
			
		||||
                        this.individual.full_name ||
 | 
			
		||||
                        this.individual.nickname  ||
 | 
			
		||||
                        email                     ||
 | 
			
		||||
                        C_("contact", "Unknown");
 | 
			
		||||
        let aliasLabel = new St.Label({ text: aliasText,
 | 
			
		||||
                                        style_class: 'contact-details-alias' });
 | 
			
		||||
        details.add(aliasLabel, { x_fill: true,
 | 
			
		||||
                                  y_fill: false,
 | 
			
		||||
                                  x_align: St.Align.START,
 | 
			
		||||
                                  y_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        this.actor.label_actor = aliasLabel;
 | 
			
		||||
 | 
			
		||||
        let presence = this._createPresence(this.individual.presence_type);
 | 
			
		||||
        details.add(presence, { x_fill: false,
 | 
			
		||||
                                y_fill: true,
 | 
			
		||||
                                x_align: St.Align.START,
 | 
			
		||||
                                y_align: St.Align.END });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createPresence: function(presence) {
 | 
			
		||||
        let text;
 | 
			
		||||
        let iconName;
 | 
			
		||||
 | 
			
		||||
        switch(presence) {
 | 
			
		||||
          case Folks.PresenceType.AVAILABLE:
 | 
			
		||||
            text = _("Available");
 | 
			
		||||
            iconName = 'user-available';
 | 
			
		||||
            break;
 | 
			
		||||
          case Folks.PresenceType.AWAY:
 | 
			
		||||
          case Folks.PresenceType.EXTENDED_AWAY:
 | 
			
		||||
            text = _("Away");
 | 
			
		||||
            iconName = 'user-away';
 | 
			
		||||
            break;
 | 
			
		||||
          case Folks.PresenceType.BUSY:
 | 
			
		||||
            text = _("Busy");
 | 
			
		||||
            iconName = 'user-busy';
 | 
			
		||||
            break;
 | 
			
		||||
          case Folks.PresenceType.OFFLINE:
 | 
			
		||||
            text = _("Offline");
 | 
			
		||||
            iconName = 'user-offline';
 | 
			
		||||
            break;
 | 
			
		||||
          default:
 | 
			
		||||
            text = '';
 | 
			
		||||
            iconName = null;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
        let box = new St.BoxLayout({ vertical: false,
 | 
			
		||||
                                     style_class: 'contact-details-status' });
 | 
			
		||||
 | 
			
		||||
        if (iconName) {
 | 
			
		||||
            let icon = new St.Icon({ icon_name: iconName,
 | 
			
		||||
                                     icon_type: St.IconType.FULLCOLOR,
 | 
			
		||||
                                     icon_size: 16,
 | 
			
		||||
                                     style_class: 'contact-details-status-icon' });
 | 
			
		||||
            box.add(icon, { x_fill: true,
 | 
			
		||||
                            y_fill: false,
 | 
			
		||||
                            x_align: St.Align.START,
 | 
			
		||||
                            y_align: St.Align.START });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let label = new St.Label({ text: text });
 | 
			
		||||
 | 
			
		||||
        box.add(label, { x_fill: true,
 | 
			
		||||
                         y_fill: false,
 | 
			
		||||
                         x_align: St.Align.END,
 | 
			
		||||
                         y_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        return box;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    createIcon: function(size) {
 | 
			
		||||
        let tc = St.TextureCache.get_default();
 | 
			
		||||
        let icon = this.individual.avatar;
 | 
			
		||||
 | 
			
		||||
        if (icon != null) {
 | 
			
		||||
            return tc.load_gicon(null, icon, size);
 | 
			
		||||
        } else {
 | 
			
		||||
            return tc.load_icon_name(null, 'avatar-default', St.IconType.FULLCOLOR, size);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Searches for and returns contacts */
 | 
			
		||||
const ContactSearchProvider = new Lang.Class({
 | 
			
		||||
    Name: 'ContactSearchProvider',
 | 
			
		||||
    Extends: Search.SearchProvider,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.parent(_("CONTACTS"));
 | 
			
		||||
        this._contactSys = Shell.ContactSystem.get_default();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getResultMetas: function(ids, callback) {
 | 
			
		||||
        let metas = [];
 | 
			
		||||
        for (let i = 0; i < ids.length; i++) {
 | 
			
		||||
            let contact = new Contact(ids[i]);
 | 
			
		||||
            metas.push({ 'id': ids[i],
 | 
			
		||||
                         'name': contact.alias,
 | 
			
		||||
                         'createIcon': function(size) {
 | 
			
		||||
                             return contact.createIcon(size);
 | 
			
		||||
                         }
 | 
			
		||||
                       });
 | 
			
		||||
        }
 | 
			
		||||
        callback(metas);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getInitialResultSet: function(terms) {
 | 
			
		||||
        this.searchSystem.pushResults(this, this._contactSys.initial_search(terms));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getSubsearchResultSet: function(previousResults, terms) {
 | 
			
		||||
        this.searchSystem.pushResults(this, this._contactSys.subsearch(previousResults, terms));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    createResultActor: function(resultMeta, terms) {
 | 
			
		||||
        let contact = new Contact(resultMeta.id);
 | 
			
		||||
        return contact.actor;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    createResultContainerActor: function() {
 | 
			
		||||
        let grid = new IconGrid.IconGrid({ rowLimit: MAX_SEARCH_RESULTS_ROWS,
 | 
			
		||||
                                             xAlign: St.Align.START });
 | 
			
		||||
        grid.actor.style_class = 'contact-grid';
 | 
			
		||||
 | 
			
		||||
        let actor = new SearchDisplay.GridSearchResults(this, grid);
 | 
			
		||||
        return actor;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    activateResult: function(id, params) {
 | 
			
		||||
        launchContact(id);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gdk = imports.gi.Gdk;
 | 
			
		||||
@@ -22,9 +22,11 @@ const SortGroup = {
 | 
			
		||||
    BOTTOM: 2
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const CtrlAltTabManager = new Lang.Class({
 | 
			
		||||
    Name: 'CtrlAltTabManager',
 | 
			
		||||
function CtrlAltTabManager() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CtrlAltTabManager.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._items = [];
 | 
			
		||||
        this._focusManager = St.FocusManager.get_for_stage(global.stage);
 | 
			
		||||
@@ -92,7 +94,7 @@ const CtrlAltTabManager = new Lang.Class({
 | 
			
		||||
        return a.x - b.x;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    popup: function(backwards, mask) {
 | 
			
		||||
    popup: function(backwards) {
 | 
			
		||||
        // Start with the set of focus groups that are currently mapped
 | 
			
		||||
        let items = this._items.filter(function (item) { return item.proxy.mapped; });
 | 
			
		||||
 | 
			
		||||
@@ -121,26 +123,19 @@ const CtrlAltTabManager = new Lang.Class({
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        items.sort(Lang.bind(this, this._sortItems));
 | 
			
		||||
 | 
			
		||||
        if (!this._popup) {
 | 
			
		||||
            this._popup = new CtrlAltTabPopup();
 | 
			
		||||
            this._popup.show(items, backwards, mask);
 | 
			
		||||
 | 
			
		||||
            this._popup.actor.connect('destroy',
 | 
			
		||||
                                      Lang.bind(this, function() {
 | 
			
		||||
                                          this._popup = null;
 | 
			
		||||
                                      }));
 | 
			
		||||
        }
 | 
			
		||||
        new CtrlAltTabPopup().show(items, backwards);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function mod(a, b) {
 | 
			
		||||
    return (a + b) % b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const CtrlAltTabPopup = new Lang.Class({
 | 
			
		||||
    Name: 'CtrlAltTabPopup',
 | 
			
		||||
function CtrlAltTabPopup() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CtrlAltTabPopup.prototype = {
 | 
			
		||||
    _init : function() {
 | 
			
		||||
        this.actor = new Shell.GenericContainer({ name: 'ctrlAltTabPopup',
 | 
			
		||||
                                                  reactive: true });
 | 
			
		||||
@@ -152,21 +147,20 @@ const CtrlAltTabPopup = new Lang.Class({
 | 
			
		||||
        this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
 | 
			
		||||
 | 
			
		||||
        this._haveModal = false;
 | 
			
		||||
        this._modifierMask = 0;
 | 
			
		||||
        this._selection = 0;
 | 
			
		||||
 | 
			
		||||
        Main.uiGroup.add_actor(this.actor);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getPreferredWidth: function (actor, forHeight, alloc) {
 | 
			
		||||
        let primary = Main.layoutManager.primaryMonitor;
 | 
			
		||||
        let primary = global.get_primary_monitor();
 | 
			
		||||
 | 
			
		||||
        alloc.min_size = primary.width;
 | 
			
		||||
        alloc.natural_size = primary.width;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getPreferredHeight: function (actor, forWidth, alloc) {
 | 
			
		||||
        let primary = Main.layoutManager.primaryMonitor;
 | 
			
		||||
        let primary = global.get_primary_monitor();
 | 
			
		||||
 | 
			
		||||
        alloc.min_size = primary.height;
 | 
			
		||||
        alloc.natural_size = primary.height;
 | 
			
		||||
@@ -174,7 +168,7 @@ const CtrlAltTabPopup = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _allocate: function (actor, box, flags) {
 | 
			
		||||
        let childBox = new Clutter.ActorBox();
 | 
			
		||||
        let primary = Main.layoutManager.primaryMonitor;
 | 
			
		||||
        let primary = global.get_primary_monitor();
 | 
			
		||||
 | 
			
		||||
        let leftPadding = this.actor.get_theme_node().get_padding(St.Side.LEFT);
 | 
			
		||||
        let vPadding = this.actor.get_theme_node().get_vertical_padding();
 | 
			
		||||
@@ -183,17 +177,16 @@ const CtrlAltTabPopup = new Lang.Class({
 | 
			
		||||
        let [childMinHeight, childNaturalHeight] = this._switcher.actor.get_preferred_height(primary.width - hPadding);
 | 
			
		||||
        let [childMinWidth, childNaturalWidth] = this._switcher.actor.get_preferred_width(childNaturalHeight);
 | 
			
		||||
        childBox.x1 = Math.max(primary.x + leftPadding, primary.x + Math.floor((primary.width - childNaturalWidth) / 2));
 | 
			
		||||
        childBox.x2 = Math.min(primary.x + primary.width - hPadding, childBox.x1 + childNaturalWidth);
 | 
			
		||||
        childBox.x2 = Math.min(primary.width - hPadding, childBox.x1 + childNaturalWidth);
 | 
			
		||||
        childBox.y1 = primary.y + Math.floor((primary.height - childNaturalHeight) / 2);
 | 
			
		||||
        childBox.y2 = childBox.y1 + childNaturalHeight;
 | 
			
		||||
        this._switcher.actor.allocate(childBox, flags);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    show : function(items, startBackwards, mask) {
 | 
			
		||||
    show : function(items, startBackwards) {
 | 
			
		||||
        if (!Main.pushModal(this.actor))
 | 
			
		||||
            return false;
 | 
			
		||||
        this._haveModal = true;
 | 
			
		||||
        this._modifierMask = AltTab.primaryModifier(mask);
 | 
			
		||||
 | 
			
		||||
        this._keyPressEventId = this.actor.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
 | 
			
		||||
        this._keyReleaseEventId = this.actor.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
 | 
			
		||||
@@ -207,7 +200,7 @@ const CtrlAltTabPopup = new Lang.Class({
 | 
			
		||||
        this._select(this._selection);
 | 
			
		||||
 | 
			
		||||
        let [x, y, mods] = global.get_pointer();
 | 
			
		||||
        if (!(mods & this._modifierMask)) {
 | 
			
		||||
        if (!(mods & Gdk.ModifierType.MOD1_MASK)) {
 | 
			
		||||
            this._finish();
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
@@ -233,7 +226,7 @@ const CtrlAltTabPopup = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _keyPressEvent : function(actor, event) {
 | 
			
		||||
        let keysym = event.get_key_symbol();
 | 
			
		||||
        let shift = (event.get_state() & Clutter.ModifierType.SHIFT_MASK);
 | 
			
		||||
        let shift = (Shell.get_event_state(event) & Clutter.ModifierType.SHIFT_MASK);
 | 
			
		||||
        if (shift && keysym == Clutter.KEY_Tab)
 | 
			
		||||
            keysym = Clutter.ISO_Left_Tab;
 | 
			
		||||
 | 
			
		||||
@@ -253,7 +246,7 @@ const CtrlAltTabPopup = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _keyReleaseEvent : function(actor, event) {
 | 
			
		||||
        let [x, y, mods] = global.get_pointer();
 | 
			
		||||
        let state = mods & this._modifierMask;
 | 
			
		||||
        let state = mods & Clutter.ModifierType.MOD1_MASK;
 | 
			
		||||
 | 
			
		||||
        if (state == 0)
 | 
			
		||||
            this._finish();
 | 
			
		||||
@@ -299,14 +292,17 @@ const CtrlAltTabPopup = new Lang.Class({
 | 
			
		||||
        this._selection = num;
 | 
			
		||||
        this._switcher.highlight(num);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const CtrlAltTabSwitcher = new Lang.Class({
 | 
			
		||||
    Name: 'CtrlAltTabSwitcher',
 | 
			
		||||
    Extends: AltTab.SwitcherList,
 | 
			
		||||
function CtrlAltTabSwitcher(items) {
 | 
			
		||||
    this._init(items);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CtrlAltTabSwitcher.prototype = {
 | 
			
		||||
    __proto__ : AltTab.SwitcherList.prototype,
 | 
			
		||||
 | 
			
		||||
    _init : function(items) {
 | 
			
		||||
        this.parent(true);
 | 
			
		||||
        AltTab.SwitcherList.prototype._init.call(this, true);
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < items.length; i++)
 | 
			
		||||
            this._addIcon(items[i]);
 | 
			
		||||
@@ -327,6 +323,6 @@ const CtrlAltTabSwitcher = new Lang.Class({
 | 
			
		||||
        let text = new St.Label({ text: item.name });
 | 
			
		||||
        box.add(text, { x_fill: false });
 | 
			
		||||
 | 
			
		||||
        this.addItem(box, text);
 | 
			
		||||
        this.addItem(box);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										339
									
								
								js/ui/dash.js
									
									
									
									
									
								
							
							
						
						@@ -1,4 +1,4 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
@@ -6,7 +6,8 @@ const Lang = imports.lang;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Gettext = imports.gettext.domain('gnome-shell');
 | 
			
		||||
const _ = Gettext.gettext;
 | 
			
		||||
 | 
			
		||||
const AppDisplay = imports.ui.appDisplay;
 | 
			
		||||
const AppFavorites = imports.ui.appFavorites;
 | 
			
		||||
@@ -17,15 +18,14 @@ const Tweener = imports.ui.tweener;
 | 
			
		||||
const Workspace = imports.ui.workspace;
 | 
			
		||||
 | 
			
		||||
const DASH_ANIMATION_TIME = 0.2;
 | 
			
		||||
const DASH_ITEM_LABEL_SHOW_TIME = 0.15;
 | 
			
		||||
const DASH_ITEM_LABEL_HIDE_TIME = 0.1;
 | 
			
		||||
const DASH_ITEM_HOVER_TIMEOUT = 300;
 | 
			
		||||
 | 
			
		||||
// A container like StBin, but taking the child's scale into account
 | 
			
		||||
// when requesting a size
 | 
			
		||||
const DashItemContainer = new Lang.Class({
 | 
			
		||||
    Name: 'DashItemContainer',
 | 
			
		||||
function DashItemContainer() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DashItemContainer.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.actor = new Shell.GenericContainer({ style_class: 'dash-item-container' });
 | 
			
		||||
        this.actor.connect('get-preferred-width',
 | 
			
		||||
@@ -36,12 +36,9 @@ const DashItemContainer = new Lang.Class({
 | 
			
		||||
                           Lang.bind(this, this._allocate));
 | 
			
		||||
        this.actor._delegate = this;
 | 
			
		||||
 | 
			
		||||
        this.label = null;
 | 
			
		||||
 | 
			
		||||
        this.child = null;
 | 
			
		||||
        this._childScale = 1;
 | 
			
		||||
        this._childOpacity = 255;
 | 
			
		||||
        this.animatingOut = false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _allocate: function(actor, box, flags) {
 | 
			
		||||
@@ -90,65 +87,11 @@ const DashItemContainer = new Lang.Class({
 | 
			
		||||
        alloc.natural_size = natWidth * this.child.scale_y;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    showLabel: function() {
 | 
			
		||||
        if (this.label == null)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this.label.opacity = 0;
 | 
			
		||||
        this.label.show();
 | 
			
		||||
 | 
			
		||||
        let [stageX, stageY] = this.actor.get_transformed_position();
 | 
			
		||||
 | 
			
		||||
        let itemHeight = this.actor.allocation.y2 - this.actor.allocation.y1;
 | 
			
		||||
 | 
			
		||||
        let labelHeight = this.label.get_height();
 | 
			
		||||
        let yOffset = Math.floor((itemHeight - labelHeight) / 2)
 | 
			
		||||
 | 
			
		||||
        let y = stageY + yOffset;
 | 
			
		||||
 | 
			
		||||
        let node = this.label.get_theme_node();
 | 
			
		||||
        let xOffset = node.get_length('-x-offset');
 | 
			
		||||
 | 
			
		||||
        let x;
 | 
			
		||||
        if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
 | 
			
		||||
            x = stageX - this.label.get_width() - xOffset;
 | 
			
		||||
        else
 | 
			
		||||
            x = stageX + this.actor.get_width() + xOffset;
 | 
			
		||||
 | 
			
		||||
        this.label.set_position(x, y);
 | 
			
		||||
        Tweener.addTween(this.label,
 | 
			
		||||
                         { opacity: 255,
 | 
			
		||||
                           time: DASH_ITEM_LABEL_SHOW_TIME,
 | 
			
		||||
                           transition: 'easeOutQuad',
 | 
			
		||||
                         });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setLabelText: function(text) {
 | 
			
		||||
        if (this.label == null)
 | 
			
		||||
            this.label = new St.Label({ style_class: 'dash-label'});
 | 
			
		||||
 | 
			
		||||
        this.label.set_text(text);
 | 
			
		||||
        Main.layoutManager.addChrome(this.label);
 | 
			
		||||
        this.label.hide();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hideLabel: function () {
 | 
			
		||||
        this.label.opacity = 255;
 | 
			
		||||
        Tweener.addTween(this.label,
 | 
			
		||||
                         { opacity: 0,
 | 
			
		||||
                           time: DASH_ITEM_LABEL_HIDE_TIME,
 | 
			
		||||
                           transition: 'easeOutQuad',
 | 
			
		||||
                           onComplete: Lang.bind(this, function() {
 | 
			
		||||
                               this.label.hide();
 | 
			
		||||
                           })
 | 
			
		||||
                         });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setChild: function(actor) {
 | 
			
		||||
        if (this.child == actor)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this.actor.destroy_all_children();
 | 
			
		||||
        this.actor.destroy_children();
 | 
			
		||||
 | 
			
		||||
        this.child = actor;
 | 
			
		||||
        this.actor.add_actor(this.child);
 | 
			
		||||
@@ -168,23 +111,12 @@ const DashItemContainer = new Lang.Class({
 | 
			
		||||
                         });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    destroy: function() {
 | 
			
		||||
        if (this.label)
 | 
			
		||||
            this.label.destroy();
 | 
			
		||||
 | 
			
		||||
        this.actor.destroy();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    animateOutAndDestroy: function() {
 | 
			
		||||
        if (this.label)
 | 
			
		||||
            this.label.destroy();
 | 
			
		||||
 | 
			
		||||
        if (this.child == null) {
 | 
			
		||||
            this.actor.destroy();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.animatingOut = true;
 | 
			
		||||
        this.childScale = 1.0;
 | 
			
		||||
        Tweener.addTween(this,
 | 
			
		||||
                         { childScale: 0.0,
 | 
			
		||||
@@ -225,14 +157,17 @@ const DashItemContainer = new Lang.Class({
 | 
			
		||||
    get childOpacity() {
 | 
			
		||||
        return this._childOpacity;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const RemoveFavoriteIcon = new Lang.Class({
 | 
			
		||||
    Name: 'RemoveFavoriteIcon',
 | 
			
		||||
    Extends: DashItemContainer,
 | 
			
		||||
function RemoveFavoriteIcon() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RemoveFavoriteIcon.prototype = {
 | 
			
		||||
    __proto__: DashItemContainer.prototype,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.parent();
 | 
			
		||||
        DashItemContainer.prototype._init.call(this);
 | 
			
		||||
 | 
			
		||||
        this._iconBin = new St.Bin({ style_class: 'remove-favorite' });
 | 
			
		||||
        this._iconActor = null;
 | 
			
		||||
@@ -244,6 +179,12 @@ const RemoveFavoriteIcon = new Lang.Class({
 | 
			
		||||
        this._iconBin._delegate = this;
 | 
			
		||||
 | 
			
		||||
        this.setChild(this._iconBin);
 | 
			
		||||
        this.hiding = false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    animateOutAndDestroy: function() {
 | 
			
		||||
        DashItemContainer.prototype.animateOutAndDestroy.call(this);
 | 
			
		||||
        this.hiding = true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createIcon: function(size) {
 | 
			
		||||
@@ -268,7 +209,7 @@ const RemoveFavoriteIcon = new Lang.Class({
 | 
			
		||||
        let app = null;
 | 
			
		||||
        if (source instanceof AppDisplay.AppWellIcon) {
 | 
			
		||||
            let appSystem = Shell.AppSystem.get_default();
 | 
			
		||||
            app = appSystem.lookup_app(source.getId());
 | 
			
		||||
            app = appSystem.get_app(source.getId());
 | 
			
		||||
        } else if (source.metaWindow) {
 | 
			
		||||
            let tracker = Shell.WindowTracker.get_default();
 | 
			
		||||
            app = tracker.get_window_app(source.metaWindow);
 | 
			
		||||
@@ -284,21 +225,28 @@ const RemoveFavoriteIcon = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const DragPlaceholderItem = new Lang.Class({
 | 
			
		||||
    Name: 'DragPlaceholderItem',
 | 
			
		||||
    Extends: DashItemContainer,
 | 
			
		||||
 | 
			
		||||
function DragPlaceholderItem() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DragPlaceholderItem.prototype = {
 | 
			
		||||
    __proto__: DashItemContainer.prototype,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.parent();
 | 
			
		||||
        this.setChild(new St.Bin({ style_class: 'placeholder' }));
 | 
			
		||||
        DashItemContainer.prototype._init.call(this);
 | 
			
		||||
        this.setChild(new St.Bin({ style_class: 'dash-placeholder' }));
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const Dash = new Lang.Class({
 | 
			
		||||
    Name: 'Dash',
 | 
			
		||||
 | 
			
		||||
function Dash() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Dash.prototype = {
 | 
			
		||||
    _init : function() {
 | 
			
		||||
        this._maxHeight = -1;
 | 
			
		||||
        this.iconSize = 64;
 | 
			
		||||
@@ -308,9 +256,6 @@ const Dash = new Lang.Class({
 | 
			
		||||
        this._dragPlaceholderPos = -1;
 | 
			
		||||
        this._animatingPlaceholdersCount = 0;
 | 
			
		||||
        this._favRemoveTarget = null;
 | 
			
		||||
        this._showLabelTimeoutId = 0;
 | 
			
		||||
        this._resetHoverTimeoutId = 0;
 | 
			
		||||
        this._labelShowing = false;
 | 
			
		||||
 | 
			
		||||
        this._box = new St.BoxLayout({ name: 'dash',
 | 
			
		||||
                                       vertical: true,
 | 
			
		||||
@@ -332,7 +277,7 @@ const Dash = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._appSystem.connect('installed-changed', Lang.bind(this, this._queueRedisplay));
 | 
			
		||||
        AppFavorites.getAppFavorites().connect('changed', Lang.bind(this, this._queueRedisplay));
 | 
			
		||||
        this._appSystem.connect('app-state-changed', Lang.bind(this, this._queueRedisplay));
 | 
			
		||||
        this._tracker.connect('app-state-changed', Lang.bind(this, this._queueRedisplay));
 | 
			
		||||
 | 
			
		||||
        Main.overview.connect('item-drag-begin',
 | 
			
		||||
                              Lang.bind(this, this._onDragBegin));
 | 
			
		||||
@@ -371,20 +316,23 @@ const Dash = new Lang.Class({
 | 
			
		||||
    _endDrag: function() {
 | 
			
		||||
        this._clearDragPlaceholder();
 | 
			
		||||
        if (this._favRemoveTarget) {
 | 
			
		||||
            this._favRemoveTarget.actor.hide();
 | 
			
		||||
            this._adjustIconSize();
 | 
			
		||||
            this._favRemoveTarget.actor.show();
 | 
			
		||||
 | 
			
		||||
            this._favRemoveTarget.animateOutAndDestroy();
 | 
			
		||||
            this._favRemoveTarget.actor.connect('destroy', Lang.bind(this,
 | 
			
		||||
                function() {
 | 
			
		||||
                    this._favRemoveTarget = null;
 | 
			
		||||
                }));
 | 
			
		||||
            this._adjustIconSize();
 | 
			
		||||
        }
 | 
			
		||||
        DND.removeDragMonitor(this._dragMonitor);
 | 
			
		||||
        DND.removeMonitor(this._dragMonitor);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDragMotion: function(dragEvent) {
 | 
			
		||||
        let app = null;
 | 
			
		||||
        if (dragEvent.source instanceof AppDisplay.AppWellIcon)
 | 
			
		||||
            app = this._appSystem.lookup_app(dragEvent.source.getId());
 | 
			
		||||
            app = this._appSystem.get_app(dragEvent.source.getId());
 | 
			
		||||
        else if (dragEvent.source.metaWindow)
 | 
			
		||||
            app = this._tracker.get_window_app(dragEvent.source.metaWindow);
 | 
			
		||||
        else
 | 
			
		||||
@@ -396,11 +344,7 @@ const Dash = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        let srcIsFavorite = (id in favorites);
 | 
			
		||||
 | 
			
		||||
        if (srcIsFavorite &&
 | 
			
		||||
            app.get_state() != Shell.AppState.RUNNING &&
 | 
			
		||||
            dragEvent.source.actor &&
 | 
			
		||||
            this.actor.contains (dragEvent.source.actor) &&
 | 
			
		||||
            this._favRemoveTarget == null) {
 | 
			
		||||
        if (srcIsFavorite && this._favRemoveTarget == null) {
 | 
			
		||||
                this._favRemoveTarget = new RemoveFavoriteIcon();
 | 
			
		||||
                this._favRemoveTarget.icon.setIconSize(this.iconSize);
 | 
			
		||||
                this._box.add(this._favRemoveTarget.actor);
 | 
			
		||||
@@ -445,66 +389,19 @@ const Dash = new Lang.Class({
 | 
			
		||||
                                   Lang.bind(this, function() {
 | 
			
		||||
                                       display.actor.opacity = 255;
 | 
			
		||||
                                   }));
 | 
			
		||||
        display.actor.set_tooltip_text(app.get_name());
 | 
			
		||||
 | 
			
		||||
        let item = new DashItemContainer();
 | 
			
		||||
        item.setChild(display.actor);
 | 
			
		||||
 | 
			
		||||
        item.setLabelText(app.get_name());
 | 
			
		||||
        // Override default AppWellIcon label_actor
 | 
			
		||||
        display.actor.label_actor = item.label;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        display.icon.setIconSize(this.iconSize);
 | 
			
		||||
        display.actor.connect('notify::hover',
 | 
			
		||||
                               Lang.bind(this, function() {
 | 
			
		||||
                                   this._onHover(item, display)
 | 
			
		||||
                               }));
 | 
			
		||||
 | 
			
		||||
        return item;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onHover: function (item, display) {
 | 
			
		||||
        if (display.actor.get_hover() && !display.isMenuUp) {
 | 
			
		||||
            if (this._showLabelTimeoutId == 0) {
 | 
			
		||||
                let timeout = this._labelShowing ? 0 : DASH_ITEM_HOVER_TIMEOUT;
 | 
			
		||||
                this._showLabelTimeoutId = Mainloop.timeout_add(timeout,
 | 
			
		||||
                    Lang.bind(this, function() {
 | 
			
		||||
                        this._labelShowing = true;
 | 
			
		||||
                        item.showLabel();
 | 
			
		||||
                        return false;
 | 
			
		||||
                    }));
 | 
			
		||||
                if (this._resetHoverTimeoutId > 0) {
 | 
			
		||||
                    Mainloop.source_remove(this._resetHoverTimeoutId);
 | 
			
		||||
                this._resetHoverTimeoutId = 0;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            if (this._showLabelTimeoutId > 0)
 | 
			
		||||
                Mainloop.source_remove(this._showLabelTimeoutId);
 | 
			
		||||
            this._showLabelTimeoutId = 0;
 | 
			
		||||
            item.hideLabel();
 | 
			
		||||
            if (this._labelShowing) {
 | 
			
		||||
                this._resetHoverTimeoutId = Mainloop.timeout_add(DASH_ITEM_HOVER_TIMEOUT,
 | 
			
		||||
                    Lang.bind(this, function() {
 | 
			
		||||
                        this._labelShowing = false;
 | 
			
		||||
                        return false;
 | 
			
		||||
                    }));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _adjustIconSize: function() {
 | 
			
		||||
        // For the icon size, we only consider children which are "proper"
 | 
			
		||||
        // icons (i.e. ignoring drag placeholders) and which are not
 | 
			
		||||
        // animating out (which means they will be destroyed at the end of
 | 
			
		||||
        // the animation)
 | 
			
		||||
        let iconChildren = this._box.get_children().filter(function(actor) {
 | 
			
		||||
            return actor._delegate.child &&
 | 
			
		||||
                   actor._delegate.child._delegate &&
 | 
			
		||||
                   actor._delegate.child._delegate.icon &&
 | 
			
		||||
                   !actor._delegate.animatingOut;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        if (iconChildren.length == 0) {
 | 
			
		||||
        let children = this._box.get_children();
 | 
			
		||||
        if (children.length == 0) {
 | 
			
		||||
            this._box.add_style_pseudo_class('empty');
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
@@ -514,45 +411,23 @@ const Dash = new Lang.Class({
 | 
			
		||||
        if (this._maxHeight == -1)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let iconChildren = children.filter(function(actor) {
 | 
			
		||||
            return actor.visible &&
 | 
			
		||||
                   actor._delegate.child &&
 | 
			
		||||
                   actor._delegate.child._delegate &&
 | 
			
		||||
                   actor._delegate.child._delegate.icon;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        let themeNode = this._box.get_theme_node();
 | 
			
		||||
        let maxAllocation = new Clutter.ActorBox({ x1: 0, y1: 0,
 | 
			
		||||
                                                   x2: 42 /* whatever */,
 | 
			
		||||
                                                   y2: this._maxHeight });
 | 
			
		||||
        let maxContent = themeNode.get_content_box(maxAllocation);
 | 
			
		||||
        let availHeight = maxContent.y2 - maxContent.y1;
 | 
			
		||||
        let spacing = themeNode.get_length('spacing');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        let firstIcon = iconChildren[0]._delegate.child._delegate.icon;
 | 
			
		||||
 | 
			
		||||
        let minHeight, natHeight;
 | 
			
		||||
 | 
			
		||||
        // Enforce the current icon size during the size request if
 | 
			
		||||
        // the icon is animating
 | 
			
		||||
        if (firstIcon._animating) {
 | 
			
		||||
            let [currentWidth, currentHeight] = firstIcon.icon.get_size();
 | 
			
		||||
 | 
			
		||||
            firstIcon.icon.set_size(this.iconSize, this.iconSize);
 | 
			
		||||
            [minHeight, natHeight] = iconChildren[0].get_preferred_height(-1);
 | 
			
		||||
 | 
			
		||||
            firstIcon.icon.set_size(currentWidth, currentHeight);
 | 
			
		||||
        } else {
 | 
			
		||||
            [minHeight, natHeight] = iconChildren[0].get_preferred_height(-1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // Subtract icon padding and box spacing from the available height
 | 
			
		||||
        availHeight -= iconChildren.length * (natHeight - this.iconSize) +
 | 
			
		||||
                       (iconChildren.length - 1) * spacing;
 | 
			
		||||
 | 
			
		||||
        let availSize = availHeight / iconChildren.length;
 | 
			
		||||
        // Compute the amount of extra space (or missing space) we have
 | 
			
		||||
        // per icon with the current icon size
 | 
			
		||||
        let [minHeight, natHeight] = this.actor.get_preferred_height(-1);
 | 
			
		||||
        let diff = (this._maxHeight - natHeight) / iconChildren.length;
 | 
			
		||||
 | 
			
		||||
        let iconSizes = [ 16, 22, 24, 32, 48, 64 ];
 | 
			
		||||
 | 
			
		||||
        let newIconSize = 16;
 | 
			
		||||
        for (let i = 0; i < iconSizes.length; i++) {
 | 
			
		||||
            if (iconSizes[i] < availSize)
 | 
			
		||||
            if (iconSizes[i] < this.iconSize + diff)
 | 
			
		||||
                newIconSize = iconSizes[i];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -561,7 +436,6 @@ const Dash = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        let oldIconSize = this.iconSize;
 | 
			
		||||
        this.iconSize = newIconSize;
 | 
			
		||||
        this.emit('icon-size-changed');
 | 
			
		||||
 | 
			
		||||
        let scale = oldIconSize / newIconSize;
 | 
			
		||||
        for (let i = 0; i < iconChildren.length; i++) {
 | 
			
		||||
@@ -583,15 +457,11 @@ const Dash = new Lang.Class({
 | 
			
		||||
            icon.icon.set_size(icon.icon.width * scale,
 | 
			
		||||
                               icon.icon.height * scale);
 | 
			
		||||
 | 
			
		||||
            icon._animating = true;
 | 
			
		||||
            Tweener.addTween(icon.icon,
 | 
			
		||||
                             { width: targetWidth,
 | 
			
		||||
                               height: targetHeight,
 | 
			
		||||
                               time: DASH_ANIMATION_TIME,
 | 
			
		||||
                               transition: 'easeOutQuad',
 | 
			
		||||
                               onComplete: function() {
 | 
			
		||||
                                   icon._animating = false;
 | 
			
		||||
                               }
 | 
			
		||||
                               transition: 'easeOutQuad'
 | 
			
		||||
                             });
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
@@ -599,7 +469,10 @@ const Dash = new Lang.Class({
 | 
			
		||||
    _redisplay: function () {
 | 
			
		||||
        let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
 | 
			
		||||
 | 
			
		||||
        let running = this._appSystem.get_running();
 | 
			
		||||
        /* hardcode here pending some design about how exactly desktop contexts behave */
 | 
			
		||||
        let contextId = '';
 | 
			
		||||
 | 
			
		||||
        let running = this._tracker.get_running_apps(contextId);
 | 
			
		||||
 | 
			
		||||
        let children = this._box.get_children().filter(function(actor) {
 | 
			
		||||
                return actor._delegate.child &&
 | 
			
		||||
@@ -691,21 +564,23 @@ const Dash = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < addedItems.length; i++)
 | 
			
		||||
            this._box.insert_child_at_index(addedItems[i].item.actor,
 | 
			
		||||
                                            addedItems[i].pos);
 | 
			
		||||
            this._box.insert_actor(addedItems[i].item.actor,
 | 
			
		||||
                                   addedItems[i].pos);
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < removedActors.length; i++) {
 | 
			
		||||
            let item = removedActors[i]._delegate;
 | 
			
		||||
        // Hide removed actors to not take them into account
 | 
			
		||||
        // when adjusting the icon size ...
 | 
			
		||||
        for (let i = 0; i < removedActors.length; i++)
 | 
			
		||||
            removedActors[i].hide();
 | 
			
		||||
 | 
			
		||||
            // Don't animate item removal when the overview is hidden
 | 
			
		||||
            if (Main.overview.visible)
 | 
			
		||||
                item.animateOutAndDestroy();
 | 
			
		||||
            else
 | 
			
		||||
                item.destroy();
 | 
			
		||||
        }
 | 
			
		||||
        // ... and do the same for the remove target if necessary
 | 
			
		||||
        if (this._favRemoveTarget && this._favRemoveTarget.hiding)
 | 
			
		||||
            this._favRemoveTarget.actor.hide();
 | 
			
		||||
 | 
			
		||||
        this._adjustIconSize();
 | 
			
		||||
 | 
			
		||||
        if (this._favRemoveTarget && this._favRemoveTarget.hiding)
 | 
			
		||||
            this._favRemoveTarget.actor.show();
 | 
			
		||||
 | 
			
		||||
        // Skip animations on first run when adding the initial set
 | 
			
		||||
        // of items, to avoid all items zooming in at once
 | 
			
		||||
        if (!this._shownInitially) {
 | 
			
		||||
@@ -713,6 +588,17 @@ const Dash = new Lang.Class({
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < removedActors.length; i++) {
 | 
			
		||||
            removedActors[i].show();
 | 
			
		||||
            let item = removedActors[i]._delegate;
 | 
			
		||||
 | 
			
		||||
            // Don't animate item removal when the overview is hidden
 | 
			
		||||
            if (Main.overview.visible)
 | 
			
		||||
                item.animateOutAndDestroy();
 | 
			
		||||
            else
 | 
			
		||||
                item.actor.destroy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Don't animate item addition when the overview is hidden
 | 
			
		||||
        if (!Main.overview.visible)
 | 
			
		||||
            return;
 | 
			
		||||
@@ -732,12 +618,12 @@ const Dash = new Lang.Class({
 | 
			
		||||
    handleDragOver : function(source, actor, x, y, time) {
 | 
			
		||||
        let app = null;
 | 
			
		||||
        if (source instanceof AppDisplay.AppWellIcon)
 | 
			
		||||
            app = this._appSystem.lookup_app(source.getId());
 | 
			
		||||
            app = this._appSystem.get_app(source.getId());
 | 
			
		||||
        else if (source.metaWindow)
 | 
			
		||||
            app = this._tracker.get_window_app(source.metaWindow);
 | 
			
		||||
 | 
			
		||||
        // Don't allow favoriting of transient apps
 | 
			
		||||
        if (app == null || app.is_window_backed())
 | 
			
		||||
        if (app == null || app.is_transient())
 | 
			
		||||
            return DND.DragMotionResult.NO_DROP;
 | 
			
		||||
 | 
			
		||||
        let favorites = AppFavorites.getAppFavorites().getFavorites();
 | 
			
		||||
@@ -757,10 +643,20 @@ const Dash = new Lang.Class({
 | 
			
		||||
            numChildren--;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let pos = Math.floor(y * numChildren / boxHeight);
 | 
			
		||||
        let pos = Math.round(y * numChildren / boxHeight);
 | 
			
		||||
 | 
			
		||||
        if (pos != this._dragPlaceholderPos && pos <= numFavorites && this._animatingPlaceholdersCount == 0) {
 | 
			
		||||
            this._dragPlaceholderPos = pos;
 | 
			
		||||
        if (pos != this._dragPlaceholderPos && pos <= numFavorites) {
 | 
			
		||||
            if (this._animatingPlaceholdersCount > 0) {
 | 
			
		||||
                let appChildren = children.filter(function(actor) {
 | 
			
		||||
                    return actor._delegate &&
 | 
			
		||||
                           actor._delegate.child &&
 | 
			
		||||
                           actor._delegate.child._delegate &&
 | 
			
		||||
                           actor._delegate.child._delegate.app;
 | 
			
		||||
                });
 | 
			
		||||
                this._dragPlaceholderPos = children.indexOf(appChildren[pos]);
 | 
			
		||||
            } else {
 | 
			
		||||
                this._dragPlaceholderPos = pos;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Don't allow positioning before or after self
 | 
			
		||||
            if (favPos != -1 && (pos == favPos || pos == favPos + 1)) {
 | 
			
		||||
@@ -789,22 +685,12 @@ const Dash = new Lang.Class({
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this._dragPlaceholder = new DragPlaceholderItem();
 | 
			
		||||
            this._dragPlaceholder.child.set_width (this.iconSize);
 | 
			
		||||
            this._dragPlaceholder.child.set_height (this.iconSize / 2);
 | 
			
		||||
            this._box.insert_child_at_index(this._dragPlaceholder.actor,
 | 
			
		||||
                                            this._dragPlaceholderPos);
 | 
			
		||||
            this._box.insert_actor(this._dragPlaceholder.actor,
 | 
			
		||||
                                   this._dragPlaceholderPos);
 | 
			
		||||
            if (fadeIn)
 | 
			
		||||
                this._dragPlaceholder.animateIn();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Remove the drag placeholder if we are not in the
 | 
			
		||||
        // "favorites zone"
 | 
			
		||||
        if (pos > numFavorites && this._dragPlaceholder) {
 | 
			
		||||
            this._clearDragPlaceholder();
 | 
			
		||||
        }
 | 
			
		||||
        if (!this._dragPlaceholder)
 | 
			
		||||
            return DND.DragMotionResult.NO_DROP;
 | 
			
		||||
 | 
			
		||||
        let srcIsFavorite = (favPos != -1);
 | 
			
		||||
 | 
			
		||||
        if (srcIsFavorite)
 | 
			
		||||
@@ -817,13 +703,13 @@ const Dash = new Lang.Class({
 | 
			
		||||
    acceptDrop : function(source, actor, x, y, time) {
 | 
			
		||||
        let app = null;
 | 
			
		||||
        if (source instanceof AppDisplay.AppWellIcon) {
 | 
			
		||||
            app = this._appSystem.lookup_app(source.getId());
 | 
			
		||||
            app = this._appSystem.get_app(source.getId());
 | 
			
		||||
        } else if (source.metaWindow) {
 | 
			
		||||
            app = this._tracker.get_window_app(source.metaWindow);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Don't allow favoriting of transient apps
 | 
			
		||||
        if (app == null || app.is_window_backed()) {
 | 
			
		||||
        if (app == null || app.is_transient()) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -847,11 +733,6 @@ const Dash = new Lang.Class({
 | 
			
		||||
                favPos++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // No drag placeholder means we don't wan't to favorite the app
 | 
			
		||||
        // and we are dragging it to its original position
 | 
			
		||||
        if (!this._dragPlaceholder)
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
 | 
			
		||||
            function () {
 | 
			
		||||
                let appFavorites = AppFavorites.getAppFavorites();
 | 
			
		||||
@@ -864,6 +745,6 @@ const Dash = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Signals.addSignalMethods(Dash.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
@@ -8,15 +8,14 @@ const Cairo = imports.cairo;
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Atk = imports.gi.Atk;
 | 
			
		||||
const Gettext = imports.gettext.domain('gnome-shell');
 | 
			
		||||
const _ = Gettext.gettext;
 | 
			
		||||
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const Util = imports.misc.util;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const PanelMenu = imports.ui.panelMenu;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
const Calendar = imports.ui.calendar;
 | 
			
		||||
const UPowerGlib = imports.gi.UPowerGlib;
 | 
			
		||||
 | 
			
		||||
// in org.gnome.desktop.interface
 | 
			
		||||
const CLOCK_FORMAT_KEY        = 'clock-format';
 | 
			
		||||
@@ -41,29 +40,29 @@ function _onVertSepRepaint (area)
 | 
			
		||||
    cr.stroke();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const DateMenuButton = new Lang.Class({
 | 
			
		||||
    Name: 'DateMenuButton',
 | 
			
		||||
    Extends: PanelMenu.Button,
 | 
			
		||||
function DateMenuButton() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DateMenuButton.prototype = {
 | 
			
		||||
    __proto__: PanelMenu.Button.prototype,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        let item;
 | 
			
		||||
        let hbox;
 | 
			
		||||
        let vbox;
 | 
			
		||||
 | 
			
		||||
        let menuAlignment = 0.25;
 | 
			
		||||
        if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
 | 
			
		||||
            menuAlignment = 1.0 - menuAlignment;
 | 
			
		||||
        this.parent(menuAlignment);
 | 
			
		||||
        this._eventSource = new Calendar.DBusEventSource();
 | 
			
		||||
 | 
			
		||||
        // At this moment calendar menu is not keyboard navigable at
 | 
			
		||||
        // all (so not accessible), so it doesn't make sense to set as
 | 
			
		||||
        // role ATK_ROLE_MENU like other elements of the panel.
 | 
			
		||||
        this.actor.accessible_role = Atk.Role.LABEL;
 | 
			
		||||
        let menuAlignment = 0.25;
 | 
			
		||||
        if (St.Widget.get_default_direction() == St.TextDirection.RTL)
 | 
			
		||||
            menuAlignment = 1.0 - menuAlignment;
 | 
			
		||||
        PanelMenu.Button.prototype._init.call(this, menuAlignment);
 | 
			
		||||
 | 
			
		||||
        this._clock = new St.Label();
 | 
			
		||||
        this.actor.add_actor(this._clock);
 | 
			
		||||
        this.actor.set_child(this._clock);
 | 
			
		||||
 | 
			
		||||
        hbox = new St.BoxLayout({name: 'calendarArea' });
 | 
			
		||||
        hbox = new St.BoxLayout({name: 'calendarArea'});
 | 
			
		||||
        this.menu.addActor(hbox);
 | 
			
		||||
 | 
			
		||||
        // Fill up the first column
 | 
			
		||||
@@ -73,62 +72,46 @@ const DateMenuButton = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        // Date
 | 
			
		||||
        this._date = new St.Label();
 | 
			
		||||
        this.actor.label_actor = this._clock;
 | 
			
		||||
        this._date.style_class = 'datemenu-date-label';
 | 
			
		||||
        vbox.add(this._date);
 | 
			
		||||
 | 
			
		||||
        if (Main.sessionMode.showCalendarEvents) {
 | 
			
		||||
            this._eventSource = new Calendar.DBusEventSource();
 | 
			
		||||
            this._eventList = new Calendar.EventsList(this._eventSource);
 | 
			
		||||
        } else {
 | 
			
		||||
            this._eventSource = null;
 | 
			
		||||
            this._eventList = null;
 | 
			
		||||
        }
 | 
			
		||||
        this._eventList = new Calendar.EventsList(this._eventSource);
 | 
			
		||||
 | 
			
		||||
        // Calendar
 | 
			
		||||
        this._calendar = new Calendar.Calendar(this._eventSource);
 | 
			
		||||
 | 
			
		||||
        this._calendar.connect('selected-date-changed',
 | 
			
		||||
                               Lang.bind(this, function(calendar, date) {
 | 
			
		||||
                                  // we know this._eventList is defined here, because selected-data-changed
 | 
			
		||||
                                  // only gets emitted when the user clicks a date in the calendar,
 | 
			
		||||
                                  // and the calender makes those dates unclickable when instantiated with
 | 
			
		||||
                                  // a null event source
 | 
			
		||||
                                   this._eventList.setDate(date);
 | 
			
		||||
                               }));
 | 
			
		||||
        vbox.add(this._calendar.actor);
 | 
			
		||||
 | 
			
		||||
        item = this.menu.addSettingsAction(_("Date and Time Settings"), 'gnome-datetime-panel.desktop');
 | 
			
		||||
        if (item) {
 | 
			
		||||
            let separator = new PopupMenu.PopupSeparatorMenuItem();
 | 
			
		||||
            separator.setColumnWidths(1);
 | 
			
		||||
            vbox.add(separator.actor, {y_align: St.Align.END, expand: true, y_fill: false});
 | 
			
		||||
        item = new PopupMenu.PopupSeparatorMenuItem();
 | 
			
		||||
        item.setColumnWidths(1);
 | 
			
		||||
        vbox.add(item.actor, {y_align: St.Align.END, expand: true, y_fill: false});
 | 
			
		||||
        item = new PopupMenu.PopupMenuItem(_("Date and Time Settings"));
 | 
			
		||||
        item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
 | 
			
		||||
        item.actor.can_focus = false;
 | 
			
		||||
        vbox.add(item.actor);
 | 
			
		||||
 | 
			
		||||
            item.actor.can_focus = false;
 | 
			
		||||
            item.actor.reparent(vbox);
 | 
			
		||||
        }
 | 
			
		||||
        // Add vertical separator
 | 
			
		||||
 | 
			
		||||
        if (Main.sessionMode.showCalendarEvents) {
 | 
			
		||||
            // Add vertical separator
 | 
			
		||||
        item = new St.DrawingArea({ style_class: 'calendar-vertical-separator',
 | 
			
		||||
                                    pseudo_class: 'highlighted' });
 | 
			
		||||
        item.connect('repaint', Lang.bind(this, _onVertSepRepaint));
 | 
			
		||||
        hbox.add(item);
 | 
			
		||||
 | 
			
		||||
            item = new St.DrawingArea({ style_class: 'calendar-vertical-separator',
 | 
			
		||||
                                        pseudo_class: 'highlighted' });
 | 
			
		||||
            item.connect('repaint', Lang.bind(this, _onVertSepRepaint));
 | 
			
		||||
            hbox.add(item);
 | 
			
		||||
        // Fill up the second column
 | 
			
		||||
 | 
			
		||||
            // Fill up the second column
 | 
			
		||||
            vbox = new St.BoxLayout({name:     'calendarEventsArea',
 | 
			
		||||
                                     vertical: true});
 | 
			
		||||
            hbox.add(vbox, { expand: true });
 | 
			
		||||
        vbox = new St.BoxLayout({vertical: true});
 | 
			
		||||
        hbox.add(vbox, { expand: true });
 | 
			
		||||
 | 
			
		||||
            // Event list
 | 
			
		||||
            vbox.add(this._eventList.actor, { expand: true });
 | 
			
		||||
        // Event list
 | 
			
		||||
        vbox.add(this._eventList.actor, { expand: true });
 | 
			
		||||
 | 
			
		||||
            item = new PopupMenu.PopupMenuItem(_("Open Calendar"));
 | 
			
		||||
            item.connect('activate', Lang.bind(this, this._onOpenCalendarActivate));
 | 
			
		||||
            item.actor.can_focus = false;
 | 
			
		||||
            vbox.add(item.actor, {y_align: St.Align.END, expand: true, y_fill: false});
 | 
			
		||||
        }
 | 
			
		||||
        item = new PopupMenu.PopupMenuItem(_("Open Calendar"));
 | 
			
		||||
        item.connect('activate', Lang.bind(this, this._onOpenCalendarActivate));
 | 
			
		||||
        item.actor.can_focus = false;
 | 
			
		||||
        vbox.add(item.actor, {y_align: St.Align.END, expand: true, y_fill: false});
 | 
			
		||||
 | 
			
		||||
        // Whenever the menu is opened, select today
 | 
			
		||||
        this.menu.connect('open-state-changed', Lang.bind(this, function(menu, isOpen) {
 | 
			
		||||
@@ -161,10 +144,6 @@ const DateMenuButton = new Lang.Class({
 | 
			
		||||
        this._desktopSettings.connect('changed', Lang.bind(this, this._updateClockAndDate));
 | 
			
		||||
        this._clockSettings.connect('changed', Lang.bind(this, this._updateClockAndDate));
 | 
			
		||||
 | 
			
		||||
        // https://bugzilla.gnome.org/show_bug.cgi?id=655129
 | 
			
		||||
        this._upClient = new UPowerGlib.Client();
 | 
			
		||||
        this._upClient.connect('notify-resume', Lang.bind(this, this._updateClockAndDate));
 | 
			
		||||
 | 
			
		||||
        // Start the clock
 | 
			
		||||
        this._updateClockAndDate();
 | 
			
		||||
    },
 | 
			
		||||
@@ -180,12 +159,12 @@ const DateMenuButton = new Lang.Class({
 | 
			
		||||
        switch (format) {
 | 
			
		||||
            case '24h':
 | 
			
		||||
                if (showDate)
 | 
			
		||||
                    /* Translators: This is the time format with date used
 | 
			
		||||
	            /* Translators: This is the time format with date used
 | 
			
		||||
                       in 24-hour mode. */
 | 
			
		||||
                    clockFormat = showSeconds ? _("%a %b %e, %R:%S")
 | 
			
		||||
                                              : _("%a %b %e, %R");
 | 
			
		||||
                else
 | 
			
		||||
                    /* Translators: This is the time format without date used
 | 
			
		||||
	            /* Translators: This is the time format without date used
 | 
			
		||||
                       in 24-hour mode. */
 | 
			
		||||
                    clockFormat = showSeconds ? _("%a %R:%S")
 | 
			
		||||
                                              : _("%a %R");
 | 
			
		||||
@@ -193,12 +172,12 @@ const DateMenuButton = new Lang.Class({
 | 
			
		||||
            case '12h':
 | 
			
		||||
            default:
 | 
			
		||||
                if (showDate)
 | 
			
		||||
                    /* Translators: This is a time format with date used
 | 
			
		||||
	            /* Translators: This is a time format with date used
 | 
			
		||||
                       for AM/PM. */
 | 
			
		||||
                    clockFormat = showSeconds ? _("%a %b %e, %l:%M:%S %p")
 | 
			
		||||
                                              : _("%a %b %e, %l:%M %p");
 | 
			
		||||
                else
 | 
			
		||||
                    /* Translators: This is a time format without date used
 | 
			
		||||
	            /* Translators: This is a time format without date used
 | 
			
		||||
                       for AM/PM. */
 | 
			
		||||
                    clockFormat = showSeconds ? _("%a %l:%M:%S %p")
 | 
			
		||||
                                              : _("%a %l:%M %p");
 | 
			
		||||
@@ -219,26 +198,15 @@ const DateMenuButton = new Lang.Class({
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onPreferencesActivate: function() {
 | 
			
		||||
        this.menu.close();
 | 
			
		||||
        let app = Shell.AppSystem.get_default().get_app('gnome-datetime-panel.desktop');
 | 
			
		||||
        app.activate(-1);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onOpenCalendarActivate: function() {
 | 
			
		||||
        this.menu.close();
 | 
			
		||||
        let calendarSettings = new Gio.Settings({ schema: 'org.gnome.desktop.default-applications.office.calendar' });
 | 
			
		||||
        let tool = calendarSettings.get_string('exec');
 | 
			
		||||
        if (tool.length == 0 || tool == 'evolution') {
 | 
			
		||||
            // TODO: pass the selected day
 | 
			
		||||
            Util.spawn(['evolution', '-c', 'calendar']);
 | 
			
		||||
        } else {
 | 
			
		||||
            let needTerm = calendarSettings.get_boolean('needs-term');
 | 
			
		||||
            if (needTerm) {
 | 
			
		||||
                let terminalSettings = new Gio.Settings({ schema: 'org.gnome.desktop.default-applications.terminal' });
 | 
			
		||||
                let term = terminalSettings.get_string('exec');
 | 
			
		||||
                let arg = terminalSettings.get_string('exec-arg');
 | 
			
		||||
                if (arg != '')
 | 
			
		||||
                    Util.spawn([term, arg, tool]);
 | 
			
		||||
                else
 | 
			
		||||
                    Util.spawn([term, tool]);
 | 
			
		||||
            } else {
 | 
			
		||||
                Util.spawnCommandLine(tool)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // TODO: pass the selected day
 | 
			
		||||
        Util.spawn(['evolution', '-c', 'calendar']);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										46
									
								
								js/ui/dnd.js
									
									
									
									
									
								
							
							
						
						@@ -1,4 +1,4 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
@@ -61,7 +61,7 @@ function addDragMonitor(monitor) {
 | 
			
		||||
    dragMonitors.push(monitor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function removeDragMonitor(monitor) {
 | 
			
		||||
function removeMonitor(monitor) {
 | 
			
		||||
    for (let i = 0; i < dragMonitors.length; i++)
 | 
			
		||||
        if (dragMonitors[i] == monitor) {
 | 
			
		||||
            dragMonitors.splice(i, 1);
 | 
			
		||||
@@ -69,9 +69,11 @@ function removeDragMonitor(monitor) {
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const _Draggable = new Lang.Class({
 | 
			
		||||
    Name: 'Draggable',
 | 
			
		||||
function _Draggable(actor, params) {
 | 
			
		||||
    this._init(actor, params);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_Draggable.prototype = {
 | 
			
		||||
    _init : function(actor, params) {
 | 
			
		||||
        params = Params.parse(params, { manualMode: false,
 | 
			
		||||
                                        restoreOnSuccess: false,
 | 
			
		||||
@@ -103,8 +105,8 @@ const _Draggable = new Lang.Class({
 | 
			
		||||
        this._dragInProgress = false; // The drag has been started, and has not been dropped or cancelled yet.
 | 
			
		||||
        this._animationInProgress = false; // The drag is over and the item is in the process of animating to its original position (snapping back or reverting).
 | 
			
		||||
 | 
			
		||||
        // During the drag, we eat enter/leave events so that actors don't prelight.
 | 
			
		||||
        // But we remember the actors that we first left/last entered so we can
 | 
			
		||||
        // During the drag, we eat enter/leave events so that actors don't prelight or show
 | 
			
		||||
        // tooltips. But we remember the actors that we first left/last entered so we can
 | 
			
		||||
        // fix up the hover state after the drag ends.
 | 
			
		||||
        this._firstLeaveActor = null;
 | 
			
		||||
        this._lastEnterActor = null;
 | 
			
		||||
@@ -120,7 +122,13 @@ const _Draggable = new Lang.Class({
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        this._buttonDown = true;
 | 
			
		||||
        this._grabActor();
 | 
			
		||||
        // special case St.Button: grabbing the pointer would mess up the
 | 
			
		||||
        // internal state, so we start the drag manually on hover change
 | 
			
		||||
        if (this.actor instanceof St.Button)
 | 
			
		||||
            this.actor.connect('notify::hover',
 | 
			
		||||
                               Lang.bind(this, this._onButtonHoverChanged));
 | 
			
		||||
        else
 | 
			
		||||
            this._grabActor();
 | 
			
		||||
 | 
			
		||||
        let [stageX, stageY] = event.get_coords();
 | 
			
		||||
        this._dragStartX = stageX;
 | 
			
		||||
@@ -129,6 +137,15 @@ const _Draggable = new Lang.Class({
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onButtonHoverChanged: function(button) {
 | 
			
		||||
        if (button.hover || !button.pressed)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        button.fake_release();
 | 
			
		||||
        this.startDrag(this._dragStartX, this._dragStartY,
 | 
			
		||||
                       global.get_current_time());
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _grabActor: function() {
 | 
			
		||||
        Clutter.grab_pointer(this.actor);
 | 
			
		||||
        this._onEventId = this.actor.connect('event',
 | 
			
		||||
@@ -217,13 +234,6 @@ const _Draggable = new Lang.Class({
 | 
			
		||||
        currentDraggable = this;
 | 
			
		||||
        this._dragInProgress = true;
 | 
			
		||||
 | 
			
		||||
        // Special-case St.Button: the pointer grab messes with the internal
 | 
			
		||||
        // state, so force a reset to a reasonable state here
 | 
			
		||||
        if (this.actor instanceof St.Button) {
 | 
			
		||||
            this.actor.fake_release();
 | 
			
		||||
            this.actor.hover = false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.emit('drag-begin', time);
 | 
			
		||||
        if (this._onEventId)
 | 
			
		||||
            this._ungrabActor();
 | 
			
		||||
@@ -274,13 +284,13 @@ const _Draggable = new Lang.Class({
 | 
			
		||||
            this._dragOffsetY = actorStageY - this._dragStartY;
 | 
			
		||||
 | 
			
		||||
            // 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 stage
 | 
			
		||||
            let [scaledWidth, scaledHeight] = this.actor.get_transformed_size();
 | 
			
		||||
            this.actor.set_scale(scaledWidth / this.actor.width,
 | 
			
		||||
                                 scaledHeight / this.actor.height);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._dragActor.reparent(Main.uiGroup);
 | 
			
		||||
        this._dragActor.reparent(this.actor.get_stage());
 | 
			
		||||
        this._dragActor.raise_top();
 | 
			
		||||
        Shell.util_set_hidden_from_pick(this._dragActor, true);
 | 
			
		||||
 | 
			
		||||
@@ -432,7 +442,7 @@ const _Draggable = new Lang.Class({
 | 
			
		||||
                        return true;
 | 
			
		||||
                    // If it accepted the drop without taking the actor,
 | 
			
		||||
                    // handle it ourselves.
 | 
			
		||||
                    if (this._dragActor.get_parent() == Main.uiGroup) {
 | 
			
		||||
                    if (this._dragActor.get_parent() == this._dragActor.get_stage()) {
 | 
			
		||||
                        if (this._restoreOnSuccess) {
 | 
			
		||||
                            this._restoreDragActor(event.get_time());
 | 
			
		||||
                            return true;
 | 
			
		||||
@@ -586,7 +596,7 @@ const _Draggable = new Lang.Class({
 | 
			
		||||
        this._dragActor = undefined;
 | 
			
		||||
        currentDraggable = null;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Signals.addSignalMethods(_Draggable.prototype);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										50
									
								
								js/ui/docDisplay.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,50 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const Gettext = imports.gettext.domain('gnome-shell');
 | 
			
		||||
const _ = Gettext.gettext;
 | 
			
		||||
 | 
			
		||||
const DocInfo = imports.misc.docInfo;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const Search = imports.ui.search;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function DocSearchProvider() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DocSearchProvider.prototype = {
 | 
			
		||||
    __proto__: Search.SearchProvider.prototype,
 | 
			
		||||
 | 
			
		||||
    _init: function(name) {
 | 
			
		||||
        Search.SearchProvider.prototype._init.call(this, _("RECENT ITEMS"));
 | 
			
		||||
        this._docManager = DocInfo.getDocManager();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getResultMeta: function(resultId) {
 | 
			
		||||
        let docInfo = this._docManager.lookupByUri(resultId);
 | 
			
		||||
        if (!docInfo)
 | 
			
		||||
            return null;
 | 
			
		||||
        return { 'id': resultId,
 | 
			
		||||
                 'name': docInfo.name,
 | 
			
		||||
                 'createIcon': function(size) {
 | 
			
		||||
                                   return docInfo.createIcon(size);
 | 
			
		||||
                               }
 | 
			
		||||
               };
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    activateResult: function(id, params) {
 | 
			
		||||
        params = Params.parse(params, { workspace: null,
 | 
			
		||||
                                        timestamp: null });
 | 
			
		||||
 | 
			
		||||
        let docInfo = this._docManager.lookupByUri(id);
 | 
			
		||||
        docInfo.launch(params.workspace ? params.workspace.index() : -1);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getInitialResultSet: function(terms) {
 | 
			
		||||
        return this._docManager.initialSearch(terms);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getSubsearchResultSet: function(previousResults, terms) {
 | 
			
		||||
        return this._docManager.subsearch(previousResults, terms);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/*
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2010 Red Hat, Inc
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
@@ -18,19 +18,22 @@
 | 
			
		||||
 * 02111-1307, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const AccountsService = imports.gi.AccountsService;
 | 
			
		||||
const Gettext = imports.gettext.domain('gnome-shell');
 | 
			
		||||
const _ = Gettext.gettext;
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Gdm = imports.gi.Gdm;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Pango = imports.gi.Pango;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
 | 
			
		||||
const GnomeSession = imports.misc.gnomeSession;
 | 
			
		||||
const GnomeSession = imports.misc.gnomeSession
 | 
			
		||||
const Lightbox = imports.ui.lightbox;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const ModalDialog = imports.ui.modalDialog;
 | 
			
		||||
@@ -43,68 +46,51 @@ const _DIALOG_ICON_SIZE = 32;
 | 
			
		||||
 | 
			
		||||
const GSM_SESSION_MANAGER_LOGOUT_FORCE = 2;
 | 
			
		||||
 | 
			
		||||
const EndSessionDialogIface = <interface name="org.gnome.SessionManager.EndSessionDialog">
 | 
			
		||||
<method name="Open">
 | 
			
		||||
    <arg type="u" direction="in" />
 | 
			
		||||
    <arg type="u" direction="in" />
 | 
			
		||||
    <arg type="u" direction="in" />
 | 
			
		||||
    <arg type="ao" direction="in" />
 | 
			
		||||
</method>
 | 
			
		||||
<signal name="ConfirmedLogout" />
 | 
			
		||||
<signal name="ConfirmedReboot" />
 | 
			
		||||
<signal name="ConfirmedShutdown" />
 | 
			
		||||
<signal name="Canceled" />
 | 
			
		||||
<signal name="Closed" />
 | 
			
		||||
</interface>;
 | 
			
		||||
const EndSessionDialogIface = {
 | 
			
		||||
    name: 'org.gnome.SessionManager.EndSessionDialog',
 | 
			
		||||
    methods: [{ name: 'Open',
 | 
			
		||||
                inSignature: 'uuuao',
 | 
			
		||||
                outSignature: ''
 | 
			
		||||
              }
 | 
			
		||||
             ],
 | 
			
		||||
    signals: [{ name: 'Canceled',
 | 
			
		||||
                inSignature: '',
 | 
			
		||||
              }],
 | 
			
		||||
    properties: []
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const logoutDialogContent = {
 | 
			
		||||
    subjectWithUser: C_("title", "Log Out %s"),
 | 
			
		||||
    subject: C_("title", "Log Out"),
 | 
			
		||||
    subjectWithUser: _("Log Out %s"),
 | 
			
		||||
    subject: _("Log Out"),
 | 
			
		||||
    inhibitedDescription: _("Click Log Out to quit these applications and log out of the system."),
 | 
			
		||||
    uninhibitedDescriptionWithUser: function(user, seconds) {
 | 
			
		||||
        return ngettext("%s will be logged out automatically in %d second.",
 | 
			
		||||
                        "%s will be logged out automatically in %d seconds.",
 | 
			
		||||
                        seconds).format(user, seconds);
 | 
			
		||||
    },
 | 
			
		||||
    uninhibitedDescription: function(seconds) {
 | 
			
		||||
        return ngettext("You will be logged out automatically in %d second.",
 | 
			
		||||
                        "You will be logged out automatically in %d seconds.",
 | 
			
		||||
                        seconds).format(seconds);
 | 
			
		||||
    },
 | 
			
		||||
    uninhibitedDescriptionWithUser: _("%s will be logged out automatically in %d seconds."),
 | 
			
		||||
    uninhibitedDescription: _("You will be logged out automatically in %d seconds."),
 | 
			
		||||
    endDescription: _("Logging out of the system."),
 | 
			
		||||
    confirmButtons: [{ signal: 'ConfirmedLogout',
 | 
			
		||||
                       label:  C_("button", "Log Out") }],
 | 
			
		||||
                       label:  _("Log Out") }],
 | 
			
		||||
    iconStyleClass: 'end-session-dialog-logout-icon'
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const shutdownDialogContent = {
 | 
			
		||||
    subject: C_("title", "Power Off"),
 | 
			
		||||
    subject: _("Power Off"),
 | 
			
		||||
    inhibitedDescription: _("Click Power Off to quit these applications and power off the system."),
 | 
			
		||||
    uninhibitedDescription: 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);
 | 
			
		||||
    },
 | 
			
		||||
    uninhibitedDescription: _("The system will power off automatically in %d seconds."),
 | 
			
		||||
    endDescription: _("Powering off the system."),
 | 
			
		||||
    confirmButtons: [{ signal: 'ConfirmedReboot',
 | 
			
		||||
                       label:  C_("button", "Restart") },
 | 
			
		||||
                       label:  _("Restart") },
 | 
			
		||||
                     { signal: 'ConfirmedShutdown',
 | 
			
		||||
                       label:  C_("button", "Power Off") }],
 | 
			
		||||
                       label:  _("Power Off") }],
 | 
			
		||||
    iconName: 'system-shutdown',
 | 
			
		||||
    iconStyleClass: 'end-session-dialog-shutdown-icon'
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const restartDialogContent = {
 | 
			
		||||
    subject: C_("title", "Restart"),
 | 
			
		||||
    subject: _("Restart"),
 | 
			
		||||
    inhibitedDescription: _("Click Restart to quit these applications and restart the system."),
 | 
			
		||||
    uninhibitedDescription: function(seconds) {
 | 
			
		||||
        return ngettext("The system will restart automatically in %d second.",
 | 
			
		||||
                        "The system will restart automatically in %d seconds.",
 | 
			
		||||
                        seconds).format(seconds);
 | 
			
		||||
    },
 | 
			
		||||
    uninhibitedDescription: _("The system will restart automatically in %d seconds."),
 | 
			
		||||
    endDescription: _("Restarting the system."),
 | 
			
		||||
    confirmButtons: [{ signal: 'ConfirmedReboot',
 | 
			
		||||
                       label:  C_("button", "Restart") }],
 | 
			
		||||
                       label:  _("Restart") }],
 | 
			
		||||
    iconName: 'system-shutdown',
 | 
			
		||||
    iconStyleClass: 'end-session-dialog-shutdown-icon'
 | 
			
		||||
};
 | 
			
		||||
@@ -116,17 +102,37 @@ const DialogContent = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function findAppFromInhibitor(inhibitor) {
 | 
			
		||||
    let [desktopFile] = inhibitor.GetAppIdSync();
 | 
			
		||||
    let desktopFile = inhibitor.app_id;
 | 
			
		||||
 | 
			
		||||
    if (!GLib.str_has_suffix(desktopFile, '.desktop'))
 | 
			
		||||
        desktopFile += '.desktop';
 | 
			
		||||
      desktopFile += '.desktop';
 | 
			
		||||
 | 
			
		||||
    return Shell.AppSystem.get_default().lookup_heuristic_basename(desktopFile);
 | 
			
		||||
    let candidateDesktopFiles = [];
 | 
			
		||||
 | 
			
		||||
    candidateDesktopFiles.push(desktopFile);
 | 
			
		||||
    candidateDesktopFiles.push('gnome-' + desktopFile);
 | 
			
		||||
 | 
			
		||||
    let appSystem = Shell.AppSystem.get_default();
 | 
			
		||||
    let app = null;
 | 
			
		||||
    for (let i = 0; i < candidateDesktopFiles.length; i++) {
 | 
			
		||||
        try {
 | 
			
		||||
            app = appSystem.get_app(candidateDesktopFiles[i]);
 | 
			
		||||
 | 
			
		||||
            if (app)
 | 
			
		||||
                break;
 | 
			
		||||
        } catch(e) {
 | 
			
		||||
            // ignore errors
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return app;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ListItem = new Lang.Class({
 | 
			
		||||
    Name: 'ListItem',
 | 
			
		||||
function ListItem(app, reason) {
 | 
			
		||||
    this._init(app, reason);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ListItem.prototype = {
 | 
			
		||||
    _init: function(app, reason) {
 | 
			
		||||
        this._app = app;
 | 
			
		||||
        this._reason = reason;
 | 
			
		||||
@@ -170,9 +176,9 @@ const ListItem = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _onClicked: function() {
 | 
			
		||||
        this.emit('activate');
 | 
			
		||||
        this._app.activate();
 | 
			
		||||
        this._app.activate(-1);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(ListItem.prototype);
 | 
			
		||||
 | 
			
		||||
// The logout timer only shows updates every 10 seconds
 | 
			
		||||
@@ -210,21 +216,31 @@ function _setLabelText(label, text) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function EndSessionDialog() {
 | 
			
		||||
    if (_endSessionDialog == null) {
 | 
			
		||||
        this._init();
 | 
			
		||||
        DBus.session.exportObject('/org/gnome/SessionManager/EndSessionDialog',
 | 
			
		||||
                                  this);
 | 
			
		||||
        _endSessionDialog = this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return _endSessionDialog;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function init() {
 | 
			
		||||
    // This always returns the same singleton object
 | 
			
		||||
    // By instantiating it initially, we register the
 | 
			
		||||
    // bus object, etc.
 | 
			
		||||
    _endSessionDialog = new EndSessionDialog();
 | 
			
		||||
    let dialog = new EndSessionDialog();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const EndSessionDialog = new Lang.Class({
 | 
			
		||||
    Name: 'EndSessionDialog',
 | 
			
		||||
    Extends: ModalDialog.ModalDialog,
 | 
			
		||||
EndSessionDialog.prototype = {
 | 
			
		||||
    __proto__: ModalDialog.ModalDialog.prototype,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.parent({ styleClass: 'end-session-dialog' });
 | 
			
		||||
        ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'end-session-dialog' });
 | 
			
		||||
 | 
			
		||||
        this._user = AccountsService.UserManager.get_default().get_user(GLib.get_user_name());
 | 
			
		||||
        this._user = Gdm.UserManager.ref_default().get_user(GLib.get_user_name());
 | 
			
		||||
 | 
			
		||||
        this._secondsLeft = 0;
 | 
			
		||||
        this._totalSecondsToStayOpen = 0;
 | 
			
		||||
@@ -297,9 +313,6 @@ const EndSessionDialog = new Lang.Class({
 | 
			
		||||
                                          if (this._applicationList.get_children().length == 0)
 | 
			
		||||
                                              scrollView.hide();
 | 
			
		||||
                                      }));
 | 
			
		||||
 | 
			
		||||
        this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(EndSessionDialogIface, this);
 | 
			
		||||
        this._dbusImpl.export(Gio.DBus.session, '/org/gnome/SessionManager/EndSessionDialog');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDestroy: function() {
 | 
			
		||||
@@ -315,8 +328,7 @@ const EndSessionDialog = new Lang.Class({
 | 
			
		||||
        this._iconBin.child = null;
 | 
			
		||||
        if (iconFile) {
 | 
			
		||||
            this._iconBin.show();
 | 
			
		||||
            this._iconBin.set_style('background-image: url("' + iconFile + '");' +
 | 
			
		||||
                                    'background-size: contain;');
 | 
			
		||||
            this._iconBin.set_style('background-image: url("' + iconFile + '");');
 | 
			
		||||
        } else {
 | 
			
		||||
            this._iconBin.hide();
 | 
			
		||||
        }
 | 
			
		||||
@@ -342,7 +354,7 @@ const EndSessionDialog = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateDescription: function() {
 | 
			
		||||
    _updateContent: function() {
 | 
			
		||||
        if (this.state != ModalDialog.State.OPENING &&
 | 
			
		||||
            this.state != ModalDialog.State.OPENED)
 | 
			
		||||
            return;
 | 
			
		||||
@@ -352,6 +364,17 @@ const EndSessionDialog = new Lang.Class({
 | 
			
		||||
        let subject = dialogContent.subject;
 | 
			
		||||
        let description;
 | 
			
		||||
 | 
			
		||||
        if (this._user.is_loaded && !dialogContent.iconName) {
 | 
			
		||||
            let iconFile = this._user.get_icon_file();
 | 
			
		||||
            if (GLib.file_test(iconFile, GLib.FileTest.EXISTS))
 | 
			
		||||
                this._setIconFromFile(iconFile, dialogContent.iconStyleClass);
 | 
			
		||||
            else
 | 
			
		||||
                this._setIconFromName('avatar-default', dialogContent.iconStyleClass);
 | 
			
		||||
        } else if (dialogContent.iconName) {
 | 
			
		||||
            this._setIconFromName(dialogContent.iconName,
 | 
			
		||||
                                  dialogContent.iconStyleClass);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._inhibitors.length > 0) {
 | 
			
		||||
            this._stopTimer();
 | 
			
		||||
            description = dialogContent.inhibitedDescription;
 | 
			
		||||
@@ -368,14 +391,14 @@ const EndSessionDialog = new Lang.Class({
 | 
			
		||||
                        subject = dialogContent.subjectWithUser.format(realName);
 | 
			
		||||
 | 
			
		||||
                    if (dialogContent.uninhibitedDescriptionWithUser)
 | 
			
		||||
                        description = dialogContent.uninhibitedDescriptionWithUser(realName, displayTime);
 | 
			
		||||
                        description = dialogContent.uninhibitedDescriptionWithUser.format(realName, displayTime);
 | 
			
		||||
                    else
 | 
			
		||||
                        description = dialogContent.uninhibitedDescription(displayTime);
 | 
			
		||||
                        description = dialogContent.uninhibitedDescription.format(displayTime);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!description)
 | 
			
		||||
                description = dialogContent.uninhibitedDescription(displayTime);
 | 
			
		||||
                description = dialogContent.uninhibitedDescription.format(displayTime);
 | 
			
		||||
        } else {
 | 
			
		||||
            description = dialogContent.endDescription;
 | 
			
		||||
        }
 | 
			
		||||
@@ -384,27 +407,6 @@ const EndSessionDialog = new Lang.Class({
 | 
			
		||||
        _setLabelText(this._descriptionLabel, description);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateContent: function() {
 | 
			
		||||
        if (this.state != ModalDialog.State.OPENING &&
 | 
			
		||||
            this.state != ModalDialog.State.OPENED)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let dialogContent = DialogContent[this._type];
 | 
			
		||||
 | 
			
		||||
        if (this._user.is_loaded && !dialogContent.iconName) {
 | 
			
		||||
            let iconFile = this._user.get_icon_file();
 | 
			
		||||
            if (GLib.file_test(iconFile, GLib.FileTest.EXISTS))
 | 
			
		||||
                this._setIconFromFile(iconFile, dialogContent.iconStyleClass);
 | 
			
		||||
            else
 | 
			
		||||
                this._setIconFromName('avatar-default', dialogContent.iconStyleClass);
 | 
			
		||||
        } else if (dialogContent.iconName) {
 | 
			
		||||
            this._setIconFromName(dialogContent.iconName,
 | 
			
		||||
                                  dialogContent.iconStyleClass);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._updateDescription();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateButtons: function() {
 | 
			
		||||
        let dialogContent = DialogContent[this._type];
 | 
			
		||||
        let buttons = [{ action: Lang.bind(this, this.cancel),
 | 
			
		||||
@@ -424,20 +426,26 @@ const EndSessionDialog = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    close: function() {
 | 
			
		||||
        this.parent();
 | 
			
		||||
        this._dbusImpl.emit_signal('Closed', null);
 | 
			
		||||
        ModalDialog.ModalDialog.prototype.close.call(this);
 | 
			
		||||
        DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
 | 
			
		||||
                                 'org.gnome.SessionManager.EndSessionDialog',
 | 
			
		||||
                                 'Closed', '', []);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    cancel: function() {
 | 
			
		||||
        this._stopTimer();
 | 
			
		||||
        this._dbusImpl.emit_signal('Canceled', null);
 | 
			
		||||
        DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
 | 
			
		||||
                                 'org.gnome.SessionManager.EndSessionDialog',
 | 
			
		||||
                                 'Canceled', '', []);
 | 
			
		||||
        this.close(global.get_current_time());
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _confirm: function(signal) {
 | 
			
		||||
        this._fadeOutDialog();
 | 
			
		||||
        this._stopTimer();
 | 
			
		||||
        this._dbusImpl.emit_signal(signal, null);
 | 
			
		||||
        DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
 | 
			
		||||
                                 'org.gnome.SessionManager.EndSessionDialog',
 | 
			
		||||
                                 signal, '', []);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onOpened: function() {
 | 
			
		||||
@@ -451,7 +459,7 @@ const EndSessionDialog = new Lang.Class({
 | 
			
		||||
                         { _secondsLeft: 0,
 | 
			
		||||
                           time: this._secondsLeft,
 | 
			
		||||
                           transition: 'linear',
 | 
			
		||||
                           onUpdate: Lang.bind(this, this._updateDescription),
 | 
			
		||||
                           onUpdate: Lang.bind(this, this._updateContent),
 | 
			
		||||
                           onComplete: Lang.bind(this, function() {
 | 
			
		||||
                                           let dialogContent = DialogContent[this._type];
 | 
			
		||||
                                           let button = dialogContent.confirmButtons[dialogContent.confirmButtons.length - 1];
 | 
			
		||||
@@ -474,8 +482,7 @@ const EndSessionDialog = new Lang.Class({
 | 
			
		||||
        let app = findAppFromInhibitor(inhibitor);
 | 
			
		||||
 | 
			
		||||
        if (app) {
 | 
			
		||||
            let [reason] = inhibitor.GetReasonSync();
 | 
			
		||||
            let item = new ListItem(app, reason);
 | 
			
		||||
            let item = new ListItem(app, inhibitor.reason);
 | 
			
		||||
            item.connect('activate',
 | 
			
		||||
                         Lang.bind(this, function() {
 | 
			
		||||
                             this.close(global.get_current_time());
 | 
			
		||||
@@ -490,41 +497,39 @@ const EndSessionDialog = new Lang.Class({
 | 
			
		||||
        this._updateContent();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    OpenAsync: function(parameters, invocation) {
 | 
			
		||||
        let [type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths] = parameters;
 | 
			
		||||
    OpenAsync: function(type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths, callback) {
 | 
			
		||||
        this._totalSecondsToStayOpen = totalSecondsToStayOpen;
 | 
			
		||||
        this._inhibitors = [];
 | 
			
		||||
        this._applicationList.destroy_all_children();
 | 
			
		||||
        this._applicationList.destroy_children();
 | 
			
		||||
        this._type = type;
 | 
			
		||||
 | 
			
		||||
        if (!(this._type in DialogContent)) {
 | 
			
		||||
            invocation.return_dbus_error('org.gnome.Shell.ModalDialog.TypeError',
 | 
			
		||||
                                         "Unknown dialog type requested");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if (!(this._type in DialogContent))
 | 
			
		||||
            throw new DBus.DBusError('org.gnome.Shell.ModalDialog.TypeError',
 | 
			
		||||
                                     "Unknown dialog type requested");
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < inhibitorObjectPaths.length; i++) {
 | 
			
		||||
            let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i], Lang.bind(this, function(proxy, error) {
 | 
			
		||||
                this._onInhibitorLoaded(proxy);
 | 
			
		||||
            }));
 | 
			
		||||
            let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i]);
 | 
			
		||||
 | 
			
		||||
            inhibitor.connect('is-loaded',
 | 
			
		||||
                              Lang.bind(this, function() {
 | 
			
		||||
                                  this._onInhibitorLoaded(inhibitor);
 | 
			
		||||
                              }));
 | 
			
		||||
            this._inhibitors.push(inhibitor);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._updateButtons();
 | 
			
		||||
 | 
			
		||||
        if (!this.open(timestamp)) {
 | 
			
		||||
            invocation.return_dbus_error('org.gnome.Shell.ModalDialog.GrabError',
 | 
			
		||||
                                         "Cannot grab pointer and keyboard");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if (!this.open(timestamp))
 | 
			
		||||
            throw new DBus.DBusError('org.gnome.Shell.ModalDialog.GrabError',
 | 
			
		||||
                                     "Cannot grab pointer and keyboard");
 | 
			
		||||
 | 
			
		||||
        this._updateContent();
 | 
			
		||||
 | 
			
		||||
        let signalId = this.connect('opened',
 | 
			
		||||
                                    Lang.bind(this, function() {
 | 
			
		||||
                                        invocation.return_value(null);
 | 
			
		||||
                                        callback();
 | 
			
		||||
                                        this.disconnect(signalId);
 | 
			
		||||
                                    }));
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
DBus.conformExport(EndSessionDialog.prototype, EndSessionDialogIface);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,22 +1,14 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
imports.gi.versions.Clutter = '1.0';
 | 
			
		||||
imports.gi.versions.Gio = '2.0';
 | 
			
		||||
imports.gi.versions.Gdk = '3.0';
 | 
			
		||||
imports.gi.versions.GdkPixbuf = '2.0';
 | 
			
		||||
imports.gi.versions.Gtk = '3.0';
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;;
 | 
			
		||||
const Gettext = imports.gettext;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Gettext_gtk30 = imports.gettext.domain('gtk30');
 | 
			
		||||
 | 
			
		||||
// We can't import shell JS modules yet, because they may have
 | 
			
		||||
// variable initializations, etc, that depend on init() already having
 | 
			
		||||
// been run.
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
 | 
			
		||||
const Format = imports.misc.format;
 | 
			
		||||
 | 
			
		||||
// "monkey patch" in some varargs ClutterContainer methods; we need
 | 
			
		||||
// to do this per-container class since there is no representation
 | 
			
		||||
@@ -39,49 +31,49 @@ function _patchContainerClass(containerClass) {
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function _makeLoggingFunc(func) {
 | 
			
		||||
    return function() {
 | 
			
		||||
        return func([].join.call(arguments, ', '));
 | 
			
		||||
// Replace @method with something that throws an error instead
 | 
			
		||||
function _blockMethod(method, replacement, reason) {
 | 
			
		||||
    let match = method.match(/^(.+)\.([^.]+)$/);
 | 
			
		||||
    if (!match)
 | 
			
		||||
        throw new Error('Bad method name "' + method + '"');
 | 
			
		||||
    let proto = 'imports.gi.' + match[1] + '.prototype';
 | 
			
		||||
    let property = match[2];
 | 
			
		||||
 | 
			
		||||
    if (!global.set_property_mutable(proto, property, true))
 | 
			
		||||
        throw new Error('Bad method name "' + method + '"');
 | 
			
		||||
 | 
			
		||||
    // eval() is evil in general, but we know it's safe here since
 | 
			
		||||
    // set_property_mutable() would have failed if proto was
 | 
			
		||||
    // malformed.
 | 
			
		||||
    let node = eval(proto);
 | 
			
		||||
 | 
			
		||||
    let msg = 'Do not use "' + method + '".';
 | 
			
		||||
    if (replacement)
 | 
			
		||||
        msg += ' Use "' + replacement + '" instead.';
 | 
			
		||||
    if (reason)
 | 
			
		||||
        msg += ' (' + reason + ')';
 | 
			
		||||
 | 
			
		||||
    node[property] = function() {
 | 
			
		||||
        throw new Error(msg);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    global.set_property_mutable(proto, property, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function init() {
 | 
			
		||||
    // Add some bindings to the global JS namespace; (gjs keeps the web
 | 
			
		||||
    // browser convention of having that namespace be called 'window'.)
 | 
			
		||||
    window.global = Shell.Global.get();
 | 
			
		||||
 | 
			
		||||
    window.log = _makeLoggingFunc(window.log);
 | 
			
		||||
 | 
			
		||||
    window._ = Gettext.gettext;
 | 
			
		||||
    window.C_ = Gettext.pgettext;
 | 
			
		||||
    window.ngettext = Gettext.ngettext;
 | 
			
		||||
 | 
			
		||||
    // Miscellaneous monkeypatching
 | 
			
		||||
    _patchContainerClass(St.BoxLayout);
 | 
			
		||||
    _patchContainerClass(St.Table);
 | 
			
		||||
 | 
			
		||||
    Clutter.Actor.prototype.toString = function() {
 | 
			
		||||
        return St.describe_actor(this);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let origToString = Object.prototype.toString;
 | 
			
		||||
    Object.prototype.toString = function() {
 | 
			
		||||
        let base = origToString.call(this);
 | 
			
		||||
        try {
 | 
			
		||||
            if ('actor' in this && this.actor instanceof Clutter.Actor)
 | 
			
		||||
                return base.replace(/\]$/, ' delegate for ' + this.actor.toString().substring(1));
 | 
			
		||||
            else
 | 
			
		||||
                return base;
 | 
			
		||||
        } catch(e) {
 | 
			
		||||
            return base;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    Tweener.init();
 | 
			
		||||
    String.prototype.format = Format.format;
 | 
			
		||||
 | 
			
		||||
    // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=508783
 | 
			
		||||
    Date.prototype.toLocaleFormat = function(format) {
 | 
			
		||||
        return Shell.util_format_date(format, this.getTime());
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Set the default direction for St widgets (this needs to be done before any use of St)
 | 
			
		||||
    if (Gettext_gtk30.gettext('default:LTR') == 'default:RTL') {
 | 
			
		||||
        St.Widget.set_default_direction(St.TextDirection.RTL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let slowdownEnv = GLib.getenv('GNOME_SHELL_SLOWDOWN_FACTOR');
 | 
			
		||||
    if (slowdownEnv) {
 | 
			
		||||
        let factor = parseFloat(slowdownEnv);
 | 
			
		||||
@@ -89,10 +81,24 @@ function init() {
 | 
			
		||||
            St.set_slow_down_factor(factor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // OK, now things are initialized enough that we can import shell JS
 | 
			
		||||
    const Format = imports.format;
 | 
			
		||||
    const Tweener = imports.ui.tweener;
 | 
			
		||||
    _patchContainerClass(St.BoxLayout);
 | 
			
		||||
    _patchContainerClass(St.Table);
 | 
			
		||||
 | 
			
		||||
    Tweener.init();
 | 
			
		||||
    String.prototype.format = Format.format;
 | 
			
		||||
    Clutter.Actor.prototype.toString = function() {
 | 
			
		||||
        return St.describe_actor(this);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (window.global === undefined) // test environment
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    _blockMethod('Clutter.Event.get_state', 'Shell.get_event_state',
 | 
			
		||||
                 'gjs\'s handling of Clutter.ModifierType is broken. See bug 597292.');
 | 
			
		||||
    _blockMethod('Gdk.Window.get_device_position', 'global.get_pointer',
 | 
			
		||||
                 'gjs\'s handling of Gdk.ModifierType is broken. See bug 597292.');
 | 
			
		||||
 | 
			
		||||
    // Now close the back door to prevent extensions from trying to
 | 
			
		||||
    // abuse it. We can't actually delete it since
 | 
			
		||||
    // Shell.Global.prototype itself is read-only.
 | 
			
		||||
    global.set_property_mutable('imports.gi.Shell.Global.prototype', 'set_property_mutable', true);
 | 
			
		||||
    Shell.Global.prototype.set_property_mutable = undefined;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,272 +1,132 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Soup = imports.gi.Soup;
 | 
			
		||||
 | 
			
		||||
const Config = imports.misc.config;
 | 
			
		||||
const ExtensionUtils = imports.misc.extensionUtils;
 | 
			
		||||
const FileUtils = imports.misc.fileUtils;
 | 
			
		||||
const ModalDialog = imports.ui.modalDialog;
 | 
			
		||||
 | 
			
		||||
const API_VERSION = 1;
 | 
			
		||||
 | 
			
		||||
const ExtensionState = {
 | 
			
		||||
    ENABLED: 1,
 | 
			
		||||
    DISABLED: 2,
 | 
			
		||||
    ERROR: 3,
 | 
			
		||||
    OUT_OF_DATE: 4,
 | 
			
		||||
    DOWNLOADING: 5,
 | 
			
		||||
    INITIALIZED: 6,
 | 
			
		||||
 | 
			
		||||
    // Used as an error state for operations on unknown extensions,
 | 
			
		||||
    // should never be in a real extensionMeta object.
 | 
			
		||||
    UNINSTALLED: 99
 | 
			
		||||
    OUT_OF_DATE: 4
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const REPOSITORY_URL_BASE = 'https://extensions.gnome.org';
 | 
			
		||||
const REPOSITORY_URL_DOWNLOAD = REPOSITORY_URL_BASE + '/download-extension/%s.shell-extension.zip';
 | 
			
		||||
const REPOSITORY_URL_INFO =     REPOSITORY_URL_BASE + '/extension-info/';
 | 
			
		||||
const ExtensionType = {
 | 
			
		||||
    SYSTEM: 1,
 | 
			
		||||
    PER_USER: 2
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const _httpSession = new Soup.SessionAsync({ ssl_use_system_ca_file: true });
 | 
			
		||||
// Maps uuid -> metadata object
 | 
			
		||||
const extensionMeta = {};
 | 
			
		||||
// Maps uuid -> importer object (extension directory tree)
 | 
			
		||||
const extensions = {};
 | 
			
		||||
// Array of uuids
 | 
			
		||||
var disabledExtensions;
 | 
			
		||||
// GFile for user extensions
 | 
			
		||||
var userExtensionsDir = null;
 | 
			
		||||
 | 
			
		||||
// See: https://bugzilla.gnome.org/show_bug.cgi?id=655189 for context.
 | 
			
		||||
// _httpSession.add_feature(new Soup.ProxyResolverDefault());
 | 
			
		||||
Soup.Session.prototype.add_feature.call(_httpSession, new Soup.ProxyResolverDefault());
 | 
			
		||||
 | 
			
		||||
// Arrays of uuids
 | 
			
		||||
var enabledExtensions;
 | 
			
		||||
// Contains the order that extensions were enabled in.
 | 
			
		||||
const extensionOrder = [];
 | 
			
		||||
 | 
			
		||||
// We don't really have a class to add signals on. So, create
 | 
			
		||||
// a simple dummy object, add the signal methods, and export those
 | 
			
		||||
// publically.
 | 
			
		||||
var _signals = {};
 | 
			
		||||
Signals.addSignalMethods(_signals);
 | 
			
		||||
 | 
			
		||||
const connect = Lang.bind(_signals, _signals.connect);
 | 
			
		||||
const disconnect = Lang.bind(_signals, _signals.disconnect);
 | 
			
		||||
 | 
			
		||||
const ENABLED_EXTENSIONS_KEY = 'enabled-extensions';
 | 
			
		||||
 | 
			
		||||
function installExtensionFromUUID(uuid) {
 | 
			
		||||
    let params = { uuid: uuid,
 | 
			
		||||
                   shell_version: Config.PACKAGE_VERSION };
 | 
			
		||||
 | 
			
		||||
    let message = Soup.form_request_new_from_hash('GET', REPOSITORY_URL_INFO, params);
 | 
			
		||||
 | 
			
		||||
    _httpSession.queue_message(message,
 | 
			
		||||
                               function(session, message) {
 | 
			
		||||
                                   let info = JSON.parse(message.response_body.data);
 | 
			
		||||
                                   let dialog = new InstallExtensionDialog(uuid, info);
 | 
			
		||||
                                   dialog.open(global.get_current_time());
 | 
			
		||||
                               });
 | 
			
		||||
/**
 | 
			
		||||
 * versionCheck:
 | 
			
		||||
 * @required: an array of versions we're compatible with
 | 
			
		||||
 * @current: the version we have
 | 
			
		||||
 *
 | 
			
		||||
 * Check if a component is compatible for an extension.
 | 
			
		||||
 * @required is an array, and at least one version must match.
 | 
			
		||||
 * @current must be in the format <major>.<minor>.<point>.<micro>
 | 
			
		||||
 * <micro> is always ignored
 | 
			
		||||
 * <point> is ignored if <minor> is even (so you can target the
 | 
			
		||||
 * whole stable release)
 | 
			
		||||
 * <minor> and <major> must match
 | 
			
		||||
 * Each target version must be at least <major> and <minor>
 | 
			
		||||
 */
 | 
			
		||||
function versionCheck(required, current) {
 | 
			
		||||
    let currentArray = current.split('.');
 | 
			
		||||
    let major = currentArray[0];
 | 
			
		||||
    let minor = currentArray[1];
 | 
			
		||||
    let point = currentArray[2];
 | 
			
		||||
    for (let i = 0; i < required.length; i++) {
 | 
			
		||||
        let requiredArray = required[i].split('.');
 | 
			
		||||
        if (requiredArray[0] == major &&
 | 
			
		||||
            requiredArray[1] == minor &&
 | 
			
		||||
            (requiredArray[2] == point ||
 | 
			
		||||
             (requiredArray[2] == undefined && parseInt(minor) % 2 == 0)))
 | 
			
		||||
            return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function uninstallExtensionFromUUID(uuid) {
 | 
			
		||||
    let extension = ExtensionUtils.extensions[uuid];
 | 
			
		||||
    if (!extension)
 | 
			
		||||
        return false;
 | 
			
		||||
function loadExtension(dir, enabled, type) {
 | 
			
		||||
    let info;
 | 
			
		||||
    let baseErrorString = 'While loading extension from "' + dir.get_parse_name() + '": ';
 | 
			
		||||
 | 
			
		||||
    // Try to disable it -- if it's ERROR'd, we can't guarantee that,
 | 
			
		||||
    // but it will be removed on next reboot, and hopefully nothing
 | 
			
		||||
    // broke too much.
 | 
			
		||||
    disableExtension(uuid);
 | 
			
		||||
 | 
			
		||||
    // Don't try to uninstall system extensions
 | 
			
		||||
    if (extension.type != ExtensionUtils.ExtensionType.PER_USER)
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    extension.state = ExtensionState.UNINSTALLED;
 | 
			
		||||
    _signals.emit('extension-state-changed', extension);
 | 
			
		||||
 | 
			
		||||
    delete ExtensionUtils.extensions[uuid];
 | 
			
		||||
 | 
			
		||||
    FileUtils.recursivelyDeleteDir(Gio.file_new_for_path(extension.path));
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function gotExtensionZipFile(session, message, uuid) {
 | 
			
		||||
    if (message.status_code != Soup.KnownStatusCode.OK) {
 | 
			
		||||
        logExtensionError(uuid, 'downloading extension: ' + message.status_code);
 | 
			
		||||
    let metadataFile = dir.get_child('metadata.json');
 | 
			
		||||
    if (!metadataFile.query_exists(null)) {
 | 
			
		||||
        global.logError(baseErrorString + 'Missing metadata.json');
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let [file, stream] = Gio.File.new_tmp('XXXXXX.shell-extension.zip');
 | 
			
		||||
    let dir = ExtensionUtils.userExtensionsDir.get_child(uuid);
 | 
			
		||||
    let contents = message.response_body.flatten().as_bytes();
 | 
			
		||||
    stream.output_stream.write_bytes(contents, null);
 | 
			
		||||
    stream.close(null);
 | 
			
		||||
    let [success, pid] = GLib.spawn_async(null,
 | 
			
		||||
                                          ['unzip', '-uod', dir.get_path(), '--', file.get_path()],
 | 
			
		||||
                                          null,
 | 
			
		||||
                                          GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD,
 | 
			
		||||
                                          null);
 | 
			
		||||
 | 
			
		||||
    if (!success) {
 | 
			
		||||
        logExtensionError(uuid, 'extract: could not extract');
 | 
			
		||||
    let metadataContents;
 | 
			
		||||
    try {
 | 
			
		||||
        metadataContents = Shell.get_file_contents_utf8_sync(metadataFile.get_path());
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
        global.logError(baseErrorString + 'Failed to load metadata.json: ' + e);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, function(pid, status) {
 | 
			
		||||
        GLib.spawn_close_pid(pid);
 | 
			
		||||
 | 
			
		||||
        // Add extension to 'enabled-extensions' for the user, always...
 | 
			
		||||
        let enabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
 | 
			
		||||
        if (enabledExtensions.indexOf(uuid) == -1) {
 | 
			
		||||
            enabledExtensions.push(uuid);
 | 
			
		||||
            global.settings.set_strv(ENABLED_EXTENSIONS_KEY, enabledExtensions);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        loadExtension(dir, ExtensionUtils.ExtensionType.PER_USER, true);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function disableExtension(uuid) {
 | 
			
		||||
    let extension = ExtensionUtils.extensions[uuid];
 | 
			
		||||
    if (!extension)
 | 
			
		||||
    let meta;
 | 
			
		||||
    try {
 | 
			
		||||
        meta = JSON.parse(metadataContents);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
        global.logError(baseErrorString + 'Failed to parse metadata.json: ' + e);
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (extension.state != ExtensionState.ENABLED)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    // "Rebase" the extension order by disabling and then enabling extensions
 | 
			
		||||
    // in order to help prevent conflicts.
 | 
			
		||||
 | 
			
		||||
    // Example:
 | 
			
		||||
    //   order = [A, B, C, D, E]
 | 
			
		||||
    //   user disables C
 | 
			
		||||
    //   this should: disable E, disable D, disable C, enable D, enable E
 | 
			
		||||
 | 
			
		||||
    let orderIdx = extensionOrder.indexOf(uuid);
 | 
			
		||||
    let order = extensionOrder.slice(orderIdx + 1);
 | 
			
		||||
    let orderReversed = order.slice().reverse();
 | 
			
		||||
 | 
			
		||||
    for (let i = 0; i < orderReversed.length; i++) {
 | 
			
		||||
        let uuid = orderReversed[i];
 | 
			
		||||
        try {
 | 
			
		||||
            ExtensionUtils.extensions[uuid].stateObj.disable();
 | 
			
		||||
        } catch(e) {
 | 
			
		||||
            logExtensionError(uuid, e.toString());
 | 
			
		||||
    }
 | 
			
		||||
    let requiredProperties = ['uuid', 'name', 'description', 'shell-version'];
 | 
			
		||||
    for (let i = 0; i < requiredProperties.length; i++) {
 | 
			
		||||
        let prop = requiredProperties[i];
 | 
			
		||||
        if (!meta[prop]) {
 | 
			
		||||
            global.logError(baseErrorString + 'missing "' + prop + '" property in metadata.json');
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        extension.stateObj.disable();
 | 
			
		||||
    } catch(e) {
 | 
			
		||||
        logExtensionError(uuid, e.toString());
 | 
			
		||||
    if (extensions[meta.uuid] != undefined) {
 | 
			
		||||
        global.logError(baseErrorString + "extension already loaded");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (let i = 0; i < order.length; i++) {
 | 
			
		||||
        let uuid = order[i];
 | 
			
		||||
        try {
 | 
			
		||||
            ExtensionUtils.extensions[uuid].stateObj.enable();
 | 
			
		||||
        } catch(e) {
 | 
			
		||||
            logExtensionError(uuid, e.toString());
 | 
			
		||||
        }
 | 
			
		||||
    // Encourage people to add this
 | 
			
		||||
    if (!meta['url']) {
 | 
			
		||||
        global.log(baseErrorString + 'Warning: Missing "url" property in metadata.json');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    extensionOrder.splice(orderIdx, 1);
 | 
			
		||||
 | 
			
		||||
    extension.state = ExtensionState.DISABLED;
 | 
			
		||||
    _signals.emit('extension-state-changed', extension);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function enableExtension(uuid) {
 | 
			
		||||
    let extension = ExtensionUtils.extensions[uuid];
 | 
			
		||||
    if (!extension)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (extension.state == ExtensionState.INITIALIZED)
 | 
			
		||||
        initExtension(uuid);
 | 
			
		||||
 | 
			
		||||
    if (extension.state != ExtensionState.DISABLED)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    extensionOrder.push(uuid);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        extension.stateObj.enable();
 | 
			
		||||
    } catch(e) {
 | 
			
		||||
        logExtensionError(uuid, e.toString());
 | 
			
		||||
    let base = dir.get_basename();
 | 
			
		||||
    if (base != meta.uuid) {
 | 
			
		||||
        global.logError(baseErrorString + 'uuid "' + meta.uuid + '" from metadata.json does not match directory name "' + base + '"');
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    extension.state = ExtensionState.ENABLED;
 | 
			
		||||
    _signals.emit('extension-state-changed', extension);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function logExtensionError(uuid, message, state) {
 | 
			
		||||
    let extension = ExtensionUtils.extensions[uuid];
 | 
			
		||||
    if (!extension)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (!extension.errors)
 | 
			
		||||
        extension.errors = [];
 | 
			
		||||
 | 
			
		||||
    extension.errors.push(message);
 | 
			
		||||
    log('Extension "%s" had error: %s'.format(uuid, message));
 | 
			
		||||
    state = state || ExtensionState.ERROR;
 | 
			
		||||
    _signals.emit('extension-state-changed', { uuid: uuid,
 | 
			
		||||
                                               error: message,
 | 
			
		||||
                                               state: state });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function loadExtension(dir, type, enabled) {
 | 
			
		||||
    let uuid = dir.get_basename();
 | 
			
		||||
    let extension;
 | 
			
		||||
 | 
			
		||||
    if (ExtensionUtils.extensions[uuid] != undefined) {
 | 
			
		||||
        log('Extension "%s" is already loaded'.format(uuid));
 | 
			
		||||
    if (!versionCheck(meta['shell-version'], Config.PACKAGE_VERSION) ||
 | 
			
		||||
        (meta['js-version'] && !versionCheck(meta['js-version'], Config.GJS_VERSION))) {
 | 
			
		||||
        global.logError(baseErrorString + 'extension is not compatible with current GNOME Shell and/or GJS version');
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        extension = ExtensionUtils.createExtensionObject(uuid, dir, type);
 | 
			
		||||
    } catch(e) {
 | 
			
		||||
        logExtensionError(uuid, e.message);
 | 
			
		||||
    extensionMeta[meta.uuid] = meta;
 | 
			
		||||
    extensionMeta[meta.uuid].type = type;
 | 
			
		||||
    extensionMeta[meta.uuid].path = dir.get_path();
 | 
			
		||||
    if (!enabled) {
 | 
			
		||||
        extensionMeta[meta.uuid].state = ExtensionState.DISABLED;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Default to error, we set success as the last step
 | 
			
		||||
    extension.state = ExtensionState.ERROR;
 | 
			
		||||
 | 
			
		||||
    if (ExtensionUtils.isOutOfDate(extension)) {
 | 
			
		||||
        logExtensionError(uuid, 'extension is not compatible with current GNOME Shell and/or GJS version', ExtensionState.OUT_OF_DATE);
 | 
			
		||||
        extension.state = ExtensionState.OUT_OF_DATE;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (enabled) {
 | 
			
		||||
        initExtension(uuid);
 | 
			
		||||
        if (extension.state == ExtensionState.DISABLED)
 | 
			
		||||
            enableExtension(uuid);
 | 
			
		||||
    } else {
 | 
			
		||||
        extension.state = ExtensionState.INITIALIZED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _signals.emit('extension-state-changed', extension);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function initExtension(uuid) {
 | 
			
		||||
    let extension = ExtensionUtils.extensions[uuid];
 | 
			
		||||
    let dir = extension.dir;
 | 
			
		||||
 | 
			
		||||
    if (!extension)
 | 
			
		||||
        throw new Error("Extension was not properly created. Call loadExtension first");
 | 
			
		||||
    extensionMeta[meta.uuid].state = ExtensionState.ERROR;
 | 
			
		||||
 | 
			
		||||
    let extensionJs = dir.get_child('extension.js');
 | 
			
		||||
    if (!extensionJs.query_exists(null)) {
 | 
			
		||||
        logExtensionError(uuid, 'Missing extension.js');
 | 
			
		||||
        global.logError(baseErrorString + 'Missing extension.js');
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    let stylesheetPath = null;
 | 
			
		||||
@@ -277,153 +137,78 @@ function initExtension(uuid) {
 | 
			
		||||
        try {
 | 
			
		||||
            theme.load_stylesheet(stylesheetFile.get_path());
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            logExtensionError(uuid, 'Stylesheet parse error: ' + e);
 | 
			
		||||
            global.logError(baseErrorString + 'Stylesheet parse error: ' + e);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let extensionModule;
 | 
			
		||||
    let extensionState = null;
 | 
			
		||||
    try {
 | 
			
		||||
        ExtensionUtils.installImporter(extension);
 | 
			
		||||
        extensionModule = extension.imports.extension;
 | 
			
		||||
        global.add_extension_importer('imports.ui.extensionSystem.extensions', meta.uuid, dir.get_path());
 | 
			
		||||
        extensionModule = extensions[meta.uuid].extension;
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
        if (stylesheetPath != null)
 | 
			
		||||
            theme.unload_stylesheet(stylesheetPath);
 | 
			
		||||
        logExtensionError(uuid, '' + e);
 | 
			
		||||
        global.logError(baseErrorString + e);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!extensionModule.init) {
 | 
			
		||||
        logExtensionError(uuid, 'missing \'init\' function');
 | 
			
		||||
    if (!extensionModule.main) {
 | 
			
		||||
        global.logError(baseErrorString + 'missing \'main\' function');
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        extensionState = extensionModule.init(extension);
 | 
			
		||||
        extensionModule.main(meta);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
        if (stylesheetPath != null)
 | 
			
		||||
            theme.unload_stylesheet(stylesheetPath);
 | 
			
		||||
        logExtensionError(uuid, 'Failed to evaluate init function:' + e);
 | 
			
		||||
        global.logError(baseErrorString + 'Failed to evaluate main function:' + e);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!extensionState)
 | 
			
		||||
        extensionState = extensionModule;
 | 
			
		||||
    extension.stateObj = extensionState;
 | 
			
		||||
 | 
			
		||||
    if (!extensionState.enable) {
 | 
			
		||||
        logExtensionError(uuid, 'missing \'enable\' function');
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (!extensionState.disable) {
 | 
			
		||||
        logExtensionError(uuid, 'missing \'disable\' function');
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    extension.state = ExtensionState.DISABLED;
 | 
			
		||||
 | 
			
		||||
    _signals.emit('extension-loaded', uuid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function onEnabledExtensionsChanged() {
 | 
			
		||||
    let newEnabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
 | 
			
		||||
 | 
			
		||||
    // Find and enable all the newly enabled extensions: UUIDs found in the
 | 
			
		||||
    // new setting, but not in the old one.
 | 
			
		||||
    newEnabledExtensions.filter(function(uuid) {
 | 
			
		||||
        return enabledExtensions.indexOf(uuid) == -1;
 | 
			
		||||
    }).forEach(function(uuid) {
 | 
			
		||||
        enableExtension(uuid);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // Find and disable all the newly disabled extensions: UUIDs found in the
 | 
			
		||||
    // old setting, but not in the new one.
 | 
			
		||||
    enabledExtensions.filter(function(item) {
 | 
			
		||||
        return newEnabledExtensions.indexOf(item) == -1;
 | 
			
		||||
    }).forEach(function(uuid) {
 | 
			
		||||
        disableExtension(uuid);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    enabledExtensions = newEnabledExtensions;
 | 
			
		||||
    extensionMeta[meta.uuid].state = ExtensionState.ENABLED;
 | 
			
		||||
    global.log('Loaded extension ' + meta.uuid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function init() {
 | 
			
		||||
    ExtensionUtils.init();
 | 
			
		||||
    let userExtensionsPath = GLib.build_filenamev([global.userdatadir, 'extensions']);
 | 
			
		||||
    userExtensionsDir = Gio.file_new_for_path(userExtensionsPath);
 | 
			
		||||
    try {
 | 
			
		||||
        userExtensionsDir.make_directory_with_parents(null);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
        global.logError('' + e);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    global.settings.connect('changed::' + ENABLED_EXTENSIONS_KEY, onEnabledExtensionsChanged);
 | 
			
		||||
    enabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
 | 
			
		||||
    disabledExtensions = global.settings.get_strv('disabled-extensions', -1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function _loadExtensionsIn(dir, type) {
 | 
			
		||||
    let fileEnum;
 | 
			
		||||
    let file, info;
 | 
			
		||||
    try {
 | 
			
		||||
        fileEnum = dir.enumerate_children('standard::*', Gio.FileQueryInfoFlags.NONE, null);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
        global.logError('' + e);
 | 
			
		||||
       return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while ((info = fileEnum.next_file(null)) != null) {
 | 
			
		||||
        let fileType = info.get_file_type();
 | 
			
		||||
        if (fileType != Gio.FileType.DIRECTORY)
 | 
			
		||||
            continue;
 | 
			
		||||
        let name = info.get_name();
 | 
			
		||||
        let enabled = disabledExtensions.indexOf(name) < 0;
 | 
			
		||||
        let child = dir.get_child(name);
 | 
			
		||||
        loadExtension(child, enabled, type);
 | 
			
		||||
    }
 | 
			
		||||
    fileEnum.close(null);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function loadExtensions() {
 | 
			
		||||
    ExtensionUtils.scanExtensions(function(uuid, dir, type) {
 | 
			
		||||
        let enabled = enabledExtensions.indexOf(uuid) != -1;
 | 
			
		||||
        loadExtension(dir, type, enabled);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const InstallExtensionDialog = new Lang.Class({
 | 
			
		||||
    Name: 'InstallExtensionDialog',
 | 
			
		||||
    Extends: ModalDialog.ModalDialog,
 | 
			
		||||
 | 
			
		||||
    _init: function(uuid, info) {
 | 
			
		||||
        this.parent({ styleClass: 'extension-dialog' });
 | 
			
		||||
 | 
			
		||||
        this._uuid = uuid;
 | 
			
		||||
        this._info = info;
 | 
			
		||||
 | 
			
		||||
        this.setButtons([{ label: _("Cancel"),
 | 
			
		||||
                           action: Lang.bind(this, this._onCancelButtonPressed),
 | 
			
		||||
                           key:    Clutter.Escape
 | 
			
		||||
                         },
 | 
			
		||||
                         { label:  _("Install"),
 | 
			
		||||
                           action: Lang.bind(this, this._onInstallButtonPressed)
 | 
			
		||||
                         }]);
 | 
			
		||||
 | 
			
		||||
        let message = _("Download and install '%s' from extensions.gnome.org?").format(info.name);
 | 
			
		||||
 | 
			
		||||
        let box = new St.BoxLayout();
 | 
			
		||||
        this.contentLayout.add(box);
 | 
			
		||||
 | 
			
		||||
        let gicon = new Gio.FileIcon({ file: Gio.File.new_for_uri(REPOSITORY_URL_BASE + info.icon) })
 | 
			
		||||
        let icon = new St.Icon({ gicon: gicon });
 | 
			
		||||
        box.add(icon);
 | 
			
		||||
 | 
			
		||||
        let label = new St.Label({ text: message });
 | 
			
		||||
        box.add(label);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onCancelButtonPressed: function(button, event) {
 | 
			
		||||
        this.close(global.get_current_time());
 | 
			
		||||
 | 
			
		||||
        // Even though the extension is already "uninstalled", send through
 | 
			
		||||
        // a state-changed signal for any users who want to know if the install
 | 
			
		||||
        // went through correctly -- using proper async DBus would block more
 | 
			
		||||
        // traditional clients like the plugin
 | 
			
		||||
        let meta = { uuid: this._uuid,
 | 
			
		||||
                     state: ExtensionState.UNINSTALLED,
 | 
			
		||||
                     error: '' };
 | 
			
		||||
 | 
			
		||||
        _signals.emit('extension-state-changed', meta);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onInstallButtonPressed: function(button, event) {
 | 
			
		||||
        let state = { uuid: this._uuid,
 | 
			
		||||
                      state: ExtensionState.DOWNLOADING,
 | 
			
		||||
                      error: '' };
 | 
			
		||||
 | 
			
		||||
        _signals.emit('extension-state-changed', state);
 | 
			
		||||
 | 
			
		||||
        let params = { shell_version: Config.PACKAGE_VERSION };
 | 
			
		||||
 | 
			
		||||
        let url = REPOSITORY_URL_DOWNLOAD.format(this._uuid);
 | 
			
		||||
        let message = Soup.form_request_new_from_hash('GET', url, params);
 | 
			
		||||
 | 
			
		||||
        _httpSession.queue_message(message,
 | 
			
		||||
                                   Lang.bind(this, function(session, message) {
 | 
			
		||||
                                       gotExtensionZipFile(session, message, this._uuid);
 | 
			
		||||
                                   }));
 | 
			
		||||
 | 
			
		||||
        this.close(global.get_current_time());
 | 
			
		||||
    _loadExtensionsIn(userExtensionsDir, ExtensionType.PER_USER);
 | 
			
		||||
    let systemDataDirs = GLib.get_system_data_dirs();
 | 
			
		||||
    for (let i = 0; i < systemDataDirs.length; i++) {
 | 
			
		||||
        let dirPath = systemDataDirs[i] + '/gnome-shell/extensions';
 | 
			
		||||
        let dir = Gio.file_new_for_path(dirPath);
 | 
			
		||||
        if (dir.query_exists(null))
 | 
			
		||||
            _loadExtensionsIn(dir, ExtensionType.SYSTEM);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,45 +0,0 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
 | 
			
		||||
const Lightbox = imports.ui.lightbox;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
 | 
			
		||||
const FLASHSPOT_ANIMATION_TIME = 0.25; // seconds
 | 
			
		||||
 | 
			
		||||
const Flashspot = new Lang.Class({
 | 
			
		||||
    Name: 'Flashspot',
 | 
			
		||||
    Extends: Lightbox.Lightbox,
 | 
			
		||||
 | 
			
		||||
    _init: function(area) {
 | 
			
		||||
        this.parent(Main.uiGroup, { inhibitEvents: true,
 | 
			
		||||
                                    width: area.width,
 | 
			
		||||
                                    height: area.height });
 | 
			
		||||
 | 
			
		||||
        this.actor.style_class = 'flashspot';
 | 
			
		||||
        this.actor.set_position(area.x, area.y);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    fire: function() {
 | 
			
		||||
        this.actor.opacity = 0;
 | 
			
		||||
        Tweener.addTween(this.actor,
 | 
			
		||||
                         { opacity: 255,
 | 
			
		||||
                           time: FLASHSPOT_ANIMATION_TIME,
 | 
			
		||||
                           transition: 'linear',
 | 
			
		||||
                           onComplete: Lang.bind(this, this._onFireShowComplete)
 | 
			
		||||
                         });
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onFireShowComplete: function() {
 | 
			
		||||
        Tweener.addTween(this.actor,
 | 
			
		||||
                         { opacity: 0,
 | 
			
		||||
                           time: FLASHSPOT_ANIMATION_TIME,
 | 
			
		||||
                           transition: 'linear',
 | 
			
		||||
                           onComplete: Lang.bind(this, function() {
 | 
			
		||||
                               this.destroy();
 | 
			
		||||
                           })
 | 
			
		||||
                         });
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
@@ -10,9 +10,11 @@ const Params = imports.misc.params;
 | 
			
		||||
const ICON_SIZE = 48;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const BaseIcon = new Lang.Class({
 | 
			
		||||
    Name: 'BaseIcon',
 | 
			
		||||
function BaseIcon(label, createIcon) {
 | 
			
		||||
    this._init(label, createIcon);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BaseIcon.prototype = {
 | 
			
		||||
    _init : function(label, params) {
 | 
			
		||||
        params = Params.parse(params, { createIcon: null,
 | 
			
		||||
                                        setSizeManually: false,
 | 
			
		||||
@@ -35,16 +37,15 @@ const BaseIcon = new Lang.Class({
 | 
			
		||||
        this.actor.set_child(box);
 | 
			
		||||
 | 
			
		||||
        this.iconSize = ICON_SIZE;
 | 
			
		||||
        this._iconBin = new St.Bin({ x_align: St.Align.MIDDLE,
 | 
			
		||||
                                     y_align: St.Align.MIDDLE });
 | 
			
		||||
        this._iconBin = new St.Bin();
 | 
			
		||||
 | 
			
		||||
        box.add_actor(this._iconBin);
 | 
			
		||||
 | 
			
		||||
        if (params.showLabel) {
 | 
			
		||||
            this.label = new St.Label({ text: label });
 | 
			
		||||
            box.add_actor(this.label);
 | 
			
		||||
            this._name = new St.Label({ text: label });
 | 
			
		||||
            box.add_actor(this._name);
 | 
			
		||||
        } else {
 | 
			
		||||
            this.label = null;
 | 
			
		||||
            this._name = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (params.createIcon)
 | 
			
		||||
@@ -66,8 +67,8 @@ const BaseIcon = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        let childBox = new Clutter.ActorBox();
 | 
			
		||||
 | 
			
		||||
        if (this.label) {
 | 
			
		||||
            let [labelMinHeight, labelNatHeight] = this.label.get_preferred_height(-1);
 | 
			
		||||
        if (this._name) {
 | 
			
		||||
            let [labelMinHeight, labelNatHeight] = this._name.get_preferred_height(-1);
 | 
			
		||||
            preferredHeight += this._spacing + labelNatHeight;
 | 
			
		||||
 | 
			
		||||
            let labelHeight = availHeight >= preferredHeight ? labelNatHeight
 | 
			
		||||
@@ -78,7 +79,7 @@ const BaseIcon = new Lang.Class({
 | 
			
		||||
            childBox.x2 = availWidth;
 | 
			
		||||
            childBox.y1 = iconSize + this._spacing;
 | 
			
		||||
            childBox.y2 = childBox.y1 + labelHeight;
 | 
			
		||||
            this.label.allocate(childBox, flags);
 | 
			
		||||
            this._name.allocate(childBox, flags);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        childBox.x1 = Math.floor((availWidth - iconNatWidth) / 2);
 | 
			
		||||
@@ -97,8 +98,8 @@ const BaseIcon = new Lang.Class({
 | 
			
		||||
        alloc.min_size = iconMinHeight;
 | 
			
		||||
        alloc.natural_size = iconNatHeight;
 | 
			
		||||
 | 
			
		||||
        if (this.label) {
 | 
			
		||||
            let [labelMinHeight, labelNatHeight] = this.label.get_preferred_height(forWidth);
 | 
			
		||||
        if (this._name) {
 | 
			
		||||
            let [labelMinHeight, labelNatHeight] = this._name.get_preferred_height(forWidth);
 | 
			
		||||
            alloc.min_size += this._spacing + labelMinHeight;
 | 
			
		||||
            alloc.natural_size += this._spacing + labelNatHeight;
 | 
			
		||||
        }
 | 
			
		||||
@@ -126,12 +127,12 @@ const BaseIcon = new Lang.Class({
 | 
			
		||||
        this.iconSize = size;
 | 
			
		||||
        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);
 | 
			
		||||
        this.icon.set_size(this.iconSize, this.iconSize);
 | 
			
		||||
 | 
			
		||||
        this._iconBin.child = this.icon;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onStyleChanged: function() {
 | 
			
		||||
@@ -148,11 +149,13 @@ const BaseIcon = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._createIconTexture(size);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const IconGrid = new Lang.Class({
 | 
			
		||||
    Name: 'IconGrid',
 | 
			
		||||
function IconGrid(params) {
 | 
			
		||||
    this._init(params);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IconGrid.prototype = {
 | 
			
		||||
    _init: function(params) {
 | 
			
		||||
        params = Params.parse(params, { rowLimit: null,
 | 
			
		||||
                                        columnLimit: null,
 | 
			
		||||
@@ -165,7 +168,7 @@ const IconGrid = new Lang.Class({
 | 
			
		||||
                                        vertical: true });
 | 
			
		||||
        // Pulled from CSS, but hardcode some defaults here
 | 
			
		||||
        this._spacing = 0;
 | 
			
		||||
        this._hItemSize = this._vItemSize = ICON_SIZE;
 | 
			
		||||
        this._item_size = ICON_SIZE;
 | 
			
		||||
        this._grid = new Shell.GenericContainer();
 | 
			
		||||
        this.actor.add(this._grid, { expand: true, y_align: St.Align.START });
 | 
			
		||||
        this.actor.connect('style-changed', Lang.bind(this, this._onStyleChanged));
 | 
			
		||||
@@ -184,8 +187,8 @@ const IconGrid = new Lang.Class({
 | 
			
		||||
        // Kind of a lie, but not really an issue right now.  If
 | 
			
		||||
        // we wanted to support some sort of hidden/overflow that would
 | 
			
		||||
        // need higher level design
 | 
			
		||||
        alloc.min_size = this._hItemSize;
 | 
			
		||||
        alloc.natural_size = nColumns * this._hItemSize + totalSpacing;
 | 
			
		||||
        alloc.min_size = this._item_size;
 | 
			
		||||
        alloc.natural_size = nColumns * this._item_size + totalSpacing;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getVisibleChildren: function() {
 | 
			
		||||
@@ -207,7 +210,7 @@ const IconGrid = new Lang.Class({
 | 
			
		||||
        if (this._rowLimit)
 | 
			
		||||
            nRows = Math.min(nRows, this._rowLimit);
 | 
			
		||||
        let totalSpacing = Math.max(0, nRows - 1) * this._spacing;
 | 
			
		||||
        let height = nRows * this._vItemSize + totalSpacing;
 | 
			
		||||
        let height = nRows * this._item_size + totalSpacing;
 | 
			
		||||
        alloc.min_size = height;
 | 
			
		||||
        alloc.natural_size = height;
 | 
			
		||||
    },
 | 
			
		||||
@@ -240,13 +243,13 @@ const IconGrid = new Lang.Class({
 | 
			
		||||
                = children[i].get_preferred_size();
 | 
			
		||||
 | 
			
		||||
            /* Center the item in its allocation horizontally */
 | 
			
		||||
            let width = Math.min(this._hItemSize, childNaturalWidth);
 | 
			
		||||
            let width = Math.min(this._item_size, childNaturalWidth);
 | 
			
		||||
            let childXSpacing = Math.max(0, width - childNaturalWidth) / 2;
 | 
			
		||||
            let height = Math.min(this._vItemSize, childNaturalHeight);
 | 
			
		||||
            let height = Math.min(this._item_size, childNaturalHeight);
 | 
			
		||||
            let childYSpacing = Math.max(0, height - childNaturalHeight) / 2;
 | 
			
		||||
 | 
			
		||||
            let childBox = new Clutter.ActorBox();
 | 
			
		||||
            if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) {
 | 
			
		||||
            if (St.Widget.get_default_direction() == St.TextDirection.RTL) {
 | 
			
		||||
                let _x = box.x2 - (x + width);
 | 
			
		||||
                childBox.x1 = Math.floor(_x - childXSpacing);
 | 
			
		||||
            } else {
 | 
			
		||||
@@ -270,10 +273,10 @@ const IconGrid = new Lang.Class({
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (columnIndex == 0) {
 | 
			
		||||
                y += this._vItemSize + this._spacing;
 | 
			
		||||
                y += this._item_size + this._spacing;
 | 
			
		||||
                x = box.x1 + leftPadding;
 | 
			
		||||
            } else {
 | 
			
		||||
                x += this._hItemSize + this._spacing;
 | 
			
		||||
                x += this._item_size + this._spacing;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
@@ -282,16 +285,12 @@ const IconGrid = new Lang.Class({
 | 
			
		||||
        return this._computeLayout(rowWidth)[0];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getRowLimit: function() {
 | 
			
		||||
        return this._rowLimit;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _computeLayout: function (forWidth) {
 | 
			
		||||
        let nColumns = 0;
 | 
			
		||||
        let usedWidth = 0;
 | 
			
		||||
        while ((this._colLimit == null || nColumns < this._colLimit) &&
 | 
			
		||||
               (usedWidth + this._hItemSize <= forWidth)) {
 | 
			
		||||
            usedWidth += this._hItemSize + this._spacing;
 | 
			
		||||
               (usedWidth + this._item_size <= forWidth)) {
 | 
			
		||||
            usedWidth += this._item_size + this._spacing;
 | 
			
		||||
            nColumns += 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -304,8 +303,7 @@ const IconGrid = new Lang.Class({
 | 
			
		||||
    _onStyleChanged: function() {
 | 
			
		||||
        let themeNode = this.actor.get_theme_node();
 | 
			
		||||
        this._spacing = themeNode.get_length('spacing');
 | 
			
		||||
        this._hItemSize = themeNode.get_length('-shell-grid-horizontal-item-size') || ICON_SIZE;
 | 
			
		||||
        this._vItemSize = themeNode.get_length('-shell-grid-vertical-item-size') || ICON_SIZE;
 | 
			
		||||
        this._item_size = themeNode.get_length('-shell-grid-item-size');
 | 
			
		||||
        this._grid.queue_relayout();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -326,4 +324,4 @@ const IconGrid = new Lang.Class({
 | 
			
		||||
    visibleItemsCount: function() {
 | 
			
		||||
        return this._grid.get_children().length - this._grid.get_n_skip_paint();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,560 +0,0 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Caribou = imports.gi.Caribou;
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Gdk = imports.gi.Gdk;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const BoxPointer = imports.ui.boxpointer;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const MessageTray = imports.ui.messageTray;
 | 
			
		||||
 | 
			
		||||
const KEYBOARD_SCHEMA = 'org.gnome.shell.keyboard';
 | 
			
		||||
const KEYBOARD_TYPE = 'keyboard-type';
 | 
			
		||||
 | 
			
		||||
const A11Y_APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications';
 | 
			
		||||
const SHOW_KEYBOARD = 'screen-keyboard-enabled';
 | 
			
		||||
 | 
			
		||||
// Key constants taken from Antler
 | 
			
		||||
// FIXME: ought to be moved into libcaribou
 | 
			
		||||
const PRETTY_KEYS = {
 | 
			
		||||
    'BackSpace': '\u232b',
 | 
			
		||||
    'space': ' ',
 | 
			
		||||
    'Return': '\u23ce',
 | 
			
		||||
    'Caribou_Prefs': '\u2328',
 | 
			
		||||
    'Caribou_ShiftUp': '\u2b06',
 | 
			
		||||
    'Caribou_ShiftDown': '\u2b07',
 | 
			
		||||
    'Caribou_Emoticons': '\u263a',
 | 
			
		||||
    'Caribou_Symbols': '123',
 | 
			
		||||
    'Caribou_Symbols_More': '{#*',
 | 
			
		||||
    'Caribou_Alpha': 'Abc',
 | 
			
		||||
    'Tab': 'Tab',
 | 
			
		||||
    'Escape': 'Esc',
 | 
			
		||||
    'Control_L': 'Ctrl',
 | 
			
		||||
    'Alt_L': 'Alt'
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const CaribouKeyboardIface = <interface name='org.gnome.Caribou.Keyboard'>
 | 
			
		||||
<method name='Show'>
 | 
			
		||||
    <arg type='u' direction='in' />
 | 
			
		||||
</method>
 | 
			
		||||
<method name='Hide'>
 | 
			
		||||
    <arg type='u' direction='in' />
 | 
			
		||||
</method>
 | 
			
		||||
<method name='SetCursorLocation'>
 | 
			
		||||
    <arg type='i' direction='in' />
 | 
			
		||||
    <arg type='i' direction='in' />
 | 
			
		||||
    <arg type='i' direction='in' />
 | 
			
		||||
    <arg type='i' direction='in' />
 | 
			
		||||
</method>
 | 
			
		||||
<method name='SetEntryLocation'>
 | 
			
		||||
    <arg type='i' direction='in' />
 | 
			
		||||
    <arg type='i' direction='in' />
 | 
			
		||||
    <arg type='i' direction='in' />
 | 
			
		||||
    <arg type='i' direction='in' />
 | 
			
		||||
</method>
 | 
			
		||||
<property name='Name' access='read' type='s' />
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
const Key = new Lang.Class({
 | 
			
		||||
    Name: 'Key',
 | 
			
		||||
 | 
			
		||||
    _init : function(key) {
 | 
			
		||||
        this._key = key;
 | 
			
		||||
 | 
			
		||||
        this.actor = this._makeKey();
 | 
			
		||||
 | 
			
		||||
        this._extended_keys = this._key.get_extended_keys();
 | 
			
		||||
        this._extended_keyboard = null;
 | 
			
		||||
 | 
			
		||||
        if (this._key.name == 'Control_L' || this._key.name == 'Alt_L')
 | 
			
		||||
            this._key.latch = true;
 | 
			
		||||
 | 
			
		||||
        this._key.connect('key-pressed', Lang.bind(this, function ()
 | 
			
		||||
                                                   { this.actor.checked = true }));
 | 
			
		||||
        this._key.connect('key-released', Lang.bind(this, function ()
 | 
			
		||||
                                                    { this.actor.checked = false; }));
 | 
			
		||||
 | 
			
		||||
        if (this._extended_keys.length > 0) {
 | 
			
		||||
            this._grabbed = false;
 | 
			
		||||
            this._eventCaptureId = 0;
 | 
			
		||||
            this._key.connect('notify::show-subkeys', Lang.bind(this, this._onShowSubkeysChanged));
 | 
			
		||||
            this._boxPointer = new BoxPointer.BoxPointer(St.Side.BOTTOM,
 | 
			
		||||
                                                         { x_fill: true,
 | 
			
		||||
                                                           y_fill: true,
 | 
			
		||||
                                                           x_align: St.Align.START });
 | 
			
		||||
            // Adds style to existing keyboard style to avoid repetition
 | 
			
		||||
            this._boxPointer.actor.add_style_class_name('keyboard-subkeys');
 | 
			
		||||
            this._getExtendedKeys();
 | 
			
		||||
            this.actor._extended_keys = this._extended_keyboard;
 | 
			
		||||
            this._boxPointer.actor.hide();
 | 
			
		||||
            Main.layoutManager.addChrome(this._boxPointer.actor, { visibleInFullscreen: true });
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _makeKey: function () {
 | 
			
		||||
        let label = this._key.name;
 | 
			
		||||
 | 
			
		||||
        if (label.length > 1) {
 | 
			
		||||
            let pretty = PRETTY_KEYS[label];
 | 
			
		||||
            if (pretty)
 | 
			
		||||
                label = pretty;
 | 
			
		||||
            else
 | 
			
		||||
                label = this._getUnichar(this._key);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        label = GLib.markup_escape_text(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 () { this._key.press(); }));
 | 
			
		||||
        button.connect('button-release-event', Lang.bind(this, function () { this._key.release(); }));
 | 
			
		||||
 | 
			
		||||
        return button;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getUnichar: function(key) {
 | 
			
		||||
        let keyval = key.keyval;
 | 
			
		||||
        let unichar = Gdk.keyval_to_unicode(keyval);
 | 
			
		||||
        if (unichar) {
 | 
			
		||||
            return String.fromCharCode(unichar);
 | 
			
		||||
        } else {
 | 
			
		||||
            return key.name;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getExtendedKeys: function () {
 | 
			
		||||
        this._extended_keyboard = new St.BoxLayout({ style_class: 'keyboard-layout',
 | 
			
		||||
                                                     vertical: false });
 | 
			
		||||
        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 = 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(); }));
 | 
			
		||||
            key.connect('button-release-event', Lang.bind(this, function () { extended_key.release(); }));
 | 
			
		||||
            this._extended_keyboard.add(key);
 | 
			
		||||
        }
 | 
			
		||||
        this._boxPointer.bin.add_actor(this._extended_keyboard);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onEventCapture: function (actor, event) {
 | 
			
		||||
        let source = event.get_source();
 | 
			
		||||
        let type = event.type();
 | 
			
		||||
 | 
			
		||||
        if ((type == Clutter.EventType.BUTTON_PRESS ||
 | 
			
		||||
             type == Clutter.EventType.BUTTON_RELEASE) &&
 | 
			
		||||
            this._extended_keyboard.contains(source)) {
 | 
			
		||||
            source.extended_key.press();
 | 
			
		||||
            source.extended_key.release();
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        if (type == Clutter.EventType.BUTTON_PRESS) {
 | 
			
		||||
            this._boxPointer.actor.hide();
 | 
			
		||||
            this._ungrab();
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _ungrab: function () {
 | 
			
		||||
        global.stage.disconnect(this._eventCaptureId);
 | 
			
		||||
        this._eventCaptureId = 0;
 | 
			
		||||
        this._grabbed = false;
 | 
			
		||||
        Main.popModal(this.actor);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onShowSubkeysChanged: function () {
 | 
			
		||||
        if (this._key.show_subkeys) {
 | 
			
		||||
            this.actor.fake_release();
 | 
			
		||||
            this._boxPointer.actor.raise_top();
 | 
			
		||||
            this._boxPointer.setPosition(this.actor, 0.5);
 | 
			
		||||
            this._boxPointer.show(true);
 | 
			
		||||
            this.actor.set_hover(false);
 | 
			
		||||
            if (!this._grabbed) {
 | 
			
		||||
                 Main.pushModal(this.actor);
 | 
			
		||||
                 this._eventCaptureId = global.stage.connect('captured-event', Lang.bind(this, this._onEventCapture));
 | 
			
		||||
                 this._grabbed = true;
 | 
			
		||||
            }
 | 
			
		||||
            this._key.release();
 | 
			
		||||
        } else {
 | 
			
		||||
            if (this._grabbed)
 | 
			
		||||
                this._ungrab();
 | 
			
		||||
            this._boxPointer.hide(true);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const Keyboard = new Lang.Class({
 | 
			
		||||
    // HACK: we can't set Name, because it collides with Name dbus property
 | 
			
		||||
    // Name: 'Keyboard',
 | 
			
		||||
 | 
			
		||||
    _init: function () {
 | 
			
		||||
        this._impl = Gio.DBusExportedObject.wrapJSObject(CaribouKeyboardIface, this);
 | 
			
		||||
        this._impl.export(Gio.DBus.session, '/org/gnome/Caribou/Keyboard');
 | 
			
		||||
 | 
			
		||||
        this.actor = null;
 | 
			
		||||
 | 
			
		||||
        this._timestamp = global.get_current_time();
 | 
			
		||||
        Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._redraw));
 | 
			
		||||
 | 
			
		||||
        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();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    init: function () {
 | 
			
		||||
        this._redraw();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _settingsChanged: function (settings, key) {
 | 
			
		||||
        this._enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD);
 | 
			
		||||
        if (!this._enableKeyboard && !this._keyboard)
 | 
			
		||||
            return;
 | 
			
		||||
        if (this._enableKeyboard && this._keyboard &&
 | 
			
		||||
            this._keyboard.keyboard_type == this._keyboardSettings.get_string(KEYBOARD_TYPE))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (this._keyboard)
 | 
			
		||||
            this._destroyKeyboard();
 | 
			
		||||
 | 
			
		||||
        if (this._enableKeyboard) {
 | 
			
		||||
            // If we've been called because the setting actually just
 | 
			
		||||
            // changed to true (as opposed to being called from
 | 
			
		||||
            // this._init()), then we want to pop up the keyboard.
 | 
			
		||||
            let showKeyboard = (settings != null);
 | 
			
		||||
 | 
			
		||||
            // However, caribou-gtk-module or this._onKeyFocusChanged
 | 
			
		||||
            // will probably immediately tell us to hide it, so we
 | 
			
		||||
            // have to fake things out so we'll ignore that request.
 | 
			
		||||
            if (showKeyboard)
 | 
			
		||||
                this._timestamp = global.display.get_current_time_roundtrip() + 1;
 | 
			
		||||
            this._setupKeyboard(showKeyboard);
 | 
			
		||||
        } else
 | 
			
		||||
            Main.layoutManager.hideKeyboard(true);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _destroyKeyboard: function() {
 | 
			
		||||
        if (this._keyboardNotifyId)
 | 
			
		||||
            this._keyboard.disconnect(this._keyboardNotifyId);
 | 
			
		||||
        if (this._focusNotifyId)
 | 
			
		||||
            global.stage.disconnect(this._focusNotifyId);
 | 
			
		||||
        this._keyboard = null;
 | 
			
		||||
        this.actor.destroy();
 | 
			
		||||
        this.actor = null;
 | 
			
		||||
 | 
			
		||||
        this._destroySource();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _setupKeyboard: function(show) {
 | 
			
		||||
        this.actor = new St.BoxLayout({ name: 'keyboard', vertical: true, reactive: true });
 | 
			
		||||
        Main.layoutManager.keyboardBox.add_actor(this.actor);
 | 
			
		||||
        Main.layoutManager.trackChrome(this.actor);
 | 
			
		||||
 | 
			
		||||
        this._keyboard = new Caribou.KeyboardModel({ keyboard_type: this._keyboardSettings.get_string(KEYBOARD_TYPE) });
 | 
			
		||||
        this._groups = {};
 | 
			
		||||
        this._current_page = null;
 | 
			
		||||
 | 
			
		||||
        // Initialize keyboard key measurements
 | 
			
		||||
        this._numOfHorizKeys = 0;
 | 
			
		||||
        this._numOfVertKeys = 0;
 | 
			
		||||
 | 
			
		||||
        this._addKeys();
 | 
			
		||||
 | 
			
		||||
        // Keys should be layout according to the group, not the
 | 
			
		||||
        // locale; as Caribou already provides the expected layout,
 | 
			
		||||
        // this means enforcing LTR for all locales.
 | 
			
		||||
        this.actor.text_direction = Clutter.TextDirection.LTR;
 | 
			
		||||
 | 
			
		||||
        this._keyboardNotifyId = this._keyboard.connect('notify::active-group', Lang.bind(this, this._onGroupChanged));
 | 
			
		||||
        this._focusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged));
 | 
			
		||||
 | 
			
		||||
        if (show)
 | 
			
		||||
            this.show();
 | 
			
		||||
        else
 | 
			
		||||
            this._createSource();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onKeyFocusChanged: function () {
 | 
			
		||||
        let focus = global.stage.key_focus;
 | 
			
		||||
 | 
			
		||||
        // Showing an extended key popup and clicking a key from the extended keys
 | 
			
		||||
        // will grab focus, but ignore that
 | 
			
		||||
        if (focus && (focus._extended_keys || (focus._key && focus._key.extended_key)))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let time = global.get_current_time();
 | 
			
		||||
        if (focus instanceof Clutter.Text)
 | 
			
		||||
            this.Show(time);
 | 
			
		||||
        else
 | 
			
		||||
            this.Hide(time);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _addKeys: function () {
 | 
			
		||||
        let groups = this._keyboard.get_groups();
 | 
			
		||||
        for (let i = 0; i < groups.length; ++i) {
 | 
			
		||||
             let gname = groups[i];
 | 
			
		||||
             let group = this._keyboard.get_group(gname);
 | 
			
		||||
             group.connect('notify::active-level', Lang.bind(this, this._onLevelChanged));
 | 
			
		||||
             let layers = {};
 | 
			
		||||
             let levels = group.get_levels();
 | 
			
		||||
             for (let j = 0; j < levels.length; ++j) {
 | 
			
		||||
                 let lname = levels[j];
 | 
			
		||||
                 let level = group.get_level(lname);
 | 
			
		||||
                 let layout = new St.BoxLayout({ style_class: 'keyboard-layout',
 | 
			
		||||
                                                 vertical: true });
 | 
			
		||||
                 this._loadRows(level, layout);
 | 
			
		||||
                 layers[lname] = layout;
 | 
			
		||||
                 this.actor.add(layout, { x_fill: false });
 | 
			
		||||
 | 
			
		||||
                 layout.hide();
 | 
			
		||||
             }
 | 
			
		||||
             this._groups[gname] = layers;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._setActiveLayer();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getTrayIcon: function () {
 | 
			
		||||
        let trayButton = new St.Button ({ label: _("tray"),
 | 
			
		||||
                                          style_class: 'keyboard-key' });
 | 
			
		||||
        trayButton.key_width = 1;
 | 
			
		||||
        trayButton.connect('button-press-event', Lang.bind(this, function () {
 | 
			
		||||
            Main.messageTray.toggle();
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        Main.overview.connect('showing', Lang.bind(this, function () {
 | 
			
		||||
            trayButton.reactive = false;
 | 
			
		||||
            trayButton.add_style_pseudo_class('grayed');
 | 
			
		||||
        }));
 | 
			
		||||
        Main.overview.connect('hiding', Lang.bind(this, function () {
 | 
			
		||||
            trayButton.reactive = true;
 | 
			
		||||
            trayButton.remove_style_pseudo_class('grayed');
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        return trayButton;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _addRows : function (keys, layout) {
 | 
			
		||||
        let keyboard_row = new St.BoxLayout();
 | 
			
		||||
        for (let i = 0; i < keys.length; ++i) {
 | 
			
		||||
            let children = keys[i].get_children();
 | 
			
		||||
            let right_box = new St.BoxLayout({ style_class: 'keyboard-row' });
 | 
			
		||||
            let left_box = new St.BoxLayout({ style_class: 'keyboard-row' });
 | 
			
		||||
            for (let j = 0; j < children.length; ++j) {
 | 
			
		||||
                if (this._numOfHorizKeys == 0)
 | 
			
		||||
                    this._numOfHorizKeys = children.length;
 | 
			
		||||
                let key = children[j];
 | 
			
		||||
                let button = new Key(key);
 | 
			
		||||
 | 
			
		||||
                if (key.align == 'right')
 | 
			
		||||
                    right_box.add(button.actor);
 | 
			
		||||
                else
 | 
			
		||||
                    left_box.add(button.actor);
 | 
			
		||||
                if (key.name == 'Caribou_Prefs') {
 | 
			
		||||
                    key.connect('key-released', Lang.bind(this, this.hide));
 | 
			
		||||
 | 
			
		||||
                    // Add new key for hiding message tray
 | 
			
		||||
                    right_box.add(this._getTrayIcon());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            keyboard_row.add(left_box, { expand: true, x_fill: false, x_align: St.Align.START });
 | 
			
		||||
            keyboard_row.add(right_box, { expand: true, x_fill: false, x_align: St.Align.END });
 | 
			
		||||
        }
 | 
			
		||||
        layout.add(keyboard_row);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _loadRows : function (level, layout) {
 | 
			
		||||
        let rows = level.get_rows();
 | 
			
		||||
        for (let i = 0; i < rows.length; ++i) {
 | 
			
		||||
            let row = rows[i];
 | 
			
		||||
            if (this._numOfVertKeys == 0)
 | 
			
		||||
                this._numOfVertKeys = rows.length;
 | 
			
		||||
            this._addRows(row.get_columns(), layout);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _redraw: function () {
 | 
			
		||||
        if (!this._enableKeyboard)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let monitor = Main.layoutManager.bottomMonitor;
 | 
			
		||||
        let maxHeight = monitor.height / 3;
 | 
			
		||||
        this.actor.width = monitor.width;
 | 
			
		||||
 | 
			
		||||
        let layout = this._current_page;
 | 
			
		||||
        let verticalSpacing = layout.get_theme_node().get_length('spacing');
 | 
			
		||||
        let padding = layout.get_theme_node().get_length('padding');
 | 
			
		||||
 | 
			
		||||
        let box = layout.get_children()[0].get_children()[0];
 | 
			
		||||
        let horizontalSpacing = box.get_theme_node().get_length('spacing');
 | 
			
		||||
        let allHorizontalSpacing = (this._numOfHorizKeys - 1) * horizontalSpacing;
 | 
			
		||||
        let keyWidth = Math.floor((this.actor.width - allHorizontalSpacing - 2 * padding) / this._numOfHorizKeys);
 | 
			
		||||
 | 
			
		||||
        let allVerticalSpacing = (this._numOfVertKeys - 1) * verticalSpacing;
 | 
			
		||||
        let keyHeight = Math.floor((maxHeight - allVerticalSpacing - 2 * padding) / this._numOfVertKeys);
 | 
			
		||||
 | 
			
		||||
        let keySize = Math.min(keyWidth, keyHeight);
 | 
			
		||||
        this.actor.height = keySize * this._numOfVertKeys + allVerticalSpacing + 2 * padding;
 | 
			
		||||
 | 
			
		||||
        let rows = this._current_page.get_children();
 | 
			
		||||
        for (let i = 0; i < rows.length; ++i) {
 | 
			
		||||
            let keyboard_row = rows[i];
 | 
			
		||||
            let boxes = keyboard_row.get_children();
 | 
			
		||||
            for (let j = 0; j < boxes.length; ++j) {
 | 
			
		||||
                let keys = boxes[j].get_children();
 | 
			
		||||
                for (let k = 0; k < keys.length; ++k) {
 | 
			
		||||
                    let child = keys[k];
 | 
			
		||||
                    child.width = keySize * child.key_width;
 | 
			
		||||
                    child.height = keySize;
 | 
			
		||||
                    if (child._extended_keys) {
 | 
			
		||||
                        let extended_keys = child._extended_keys.get_children();
 | 
			
		||||
                        for (let n = 0; n < extended_keys.length; ++n) {
 | 
			
		||||
                            let extended_key = extended_keys[n];
 | 
			
		||||
                            extended_key.width = keySize;
 | 
			
		||||
                            extended_key.height = keySize;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onLevelChanged: function () {
 | 
			
		||||
        this._setActiveLayer();
 | 
			
		||||
        this._redraw();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onGroupChanged: function () {
 | 
			
		||||
        this._setActiveLayer();
 | 
			
		||||
        this._redraw();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _setActiveLayer: function () {
 | 
			
		||||
        let active_group_name = this._keyboard.active_group;
 | 
			
		||||
        let active_group = this._keyboard.get_group(active_group_name);
 | 
			
		||||
        let active_level = active_group.active_level;
 | 
			
		||||
        let layers = this._groups[active_group_name];
 | 
			
		||||
 | 
			
		||||
        if (this._current_page != null) {
 | 
			
		||||
            this._current_page.hide();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._current_page = layers[active_level];
 | 
			
		||||
        this._current_page.show();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createSource: function () {
 | 
			
		||||
        if (this._source == null) {
 | 
			
		||||
            this._source = new KeyboardSource(this);
 | 
			
		||||
            this._source.setTransient(true);
 | 
			
		||||
            Main.messageTray.add(this._source);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _destroySource: function () {
 | 
			
		||||
        if (this._source) {
 | 
			
		||||
            this._source.destroy();
 | 
			
		||||
            this._source = null;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    show: function () {
 | 
			
		||||
        this._redraw();
 | 
			
		||||
 | 
			
		||||
        Main.layoutManager.showKeyboard();
 | 
			
		||||
        this._destroySource();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hide: function () {
 | 
			
		||||
        Main.layoutManager.hideKeyboard();
 | 
			
		||||
        this._createSource();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _moveTemporarily: function () {
 | 
			
		||||
        let currentWindow = global.screen.get_display().focus_window;
 | 
			
		||||
        let rect = currentWindow.get_outer_rect();
 | 
			
		||||
 | 
			
		||||
        let newX = rect.x;
 | 
			
		||||
        let newY = 3 * this.actor.height / 2;
 | 
			
		||||
        currentWindow.move_frame(true, newX, newY);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _setLocation: function (x, y) {
 | 
			
		||||
        if (y >= 2 * this.actor.height)
 | 
			
		||||
            this._moveTemporarily();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // D-Bus methods
 | 
			
		||||
    Show: function(timestamp) {
 | 
			
		||||
        if (!this._enableKeyboard)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (timestamp - this._timestamp < 0)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._timestamp = timestamp;
 | 
			
		||||
        this.show();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    Hide: function(timestamp) {
 | 
			
		||||
        if (!this._enableKeyboard)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (timestamp - this._timestamp < 0)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._timestamp = timestamp;
 | 
			
		||||
        this.hide();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    SetCursorLocation: function(x, y, w, h) {
 | 
			
		||||
        if (!this._enableKeyboard)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
//        this._setLocation(x, y);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    SetEntryLocation: function(x, y, w, h) {
 | 
			
		||||
        if (!this._enableKeyboard)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
//        this._setLocation(x, y);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get Name() {
 | 
			
		||||
        return 'gnome-shell';
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const KeyboardSource = new Lang.Class({
 | 
			
		||||
    Name: 'KeyboardSource',
 | 
			
		||||
    Extends: MessageTray.Source,
 | 
			
		||||
 | 
			
		||||
    _init: function(keyboard) {
 | 
			
		||||
        this._keyboard = keyboard;
 | 
			
		||||
        this.parent(_("Keyboard"), 'input-keyboard', St.IconType.SYMBOLIC);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    handleSummaryClick: function() {
 | 
			
		||||
        let event = Clutter.get_current_event();
 | 
			
		||||
        if (event.type() != Clutter.EventType.BUTTON_RELEASE)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        this.open();
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    open: function() {
 | 
			
		||||
        this._keyboard.show();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
@@ -1,207 +0,0 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Pango = imports.gi.Pango;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GObject = imports.gi.GObject;
 | 
			
		||||
const Gcr = imports.gi.Gcr;
 | 
			
		||||
 | 
			
		||||
const ModalDialog = imports.ui.modalDialog;
 | 
			
		||||
const ShellEntry = imports.ui.shellEntry;
 | 
			
		||||
const CheckBox = imports.ui.checkBox;
 | 
			
		||||
 | 
			
		||||
let prompter = null;
 | 
			
		||||
 | 
			
		||||
const KeyringDialog = new Lang.Class({
 | 
			
		||||
    Name: 'KeyringDialog',
 | 
			
		||||
    Extends: ModalDialog.ModalDialog,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.parent({ styleClass: 'prompt-dialog' });
 | 
			
		||||
 | 
			
		||||
        this.prompt = new Shell.KeyringPrompt();
 | 
			
		||||
        this.prompt.connect('show-password', Lang.bind(this, this._onShowPassword));
 | 
			
		||||
        this.prompt.connect('show-confirm', Lang.bind(this, this._onShowConfirm));
 | 
			
		||||
        this.prompt.connect('hide-prompt', Lang.bind(this, this._onHidePrompt));
 | 
			
		||||
 | 
			
		||||
        let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout',
 | 
			
		||||
                                                vertical: false });
 | 
			
		||||
        this.contentLayout.add(mainContentBox);
 | 
			
		||||
 | 
			
		||||
        let icon = new St.Icon({ icon_name: 'dialog-password-symbolic' });
 | 
			
		||||
        mainContentBox.add(icon,
 | 
			
		||||
                           { x_fill:  true,
 | 
			
		||||
                             y_fill:  false,
 | 
			
		||||
                             x_align: St.Align.END,
 | 
			
		||||
                             y_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        this._messageBox = new St.BoxLayout({ style_class: 'prompt-dialog-message-layout',
 | 
			
		||||
                                              vertical: true });
 | 
			
		||||
        mainContentBox.add(this._messageBox,
 | 
			
		||||
                           { y_align: St.Align.START, expand: true, x_fill: true, y_fill: true });
 | 
			
		||||
 | 
			
		||||
        let subject = new St.Label({ style_class: 'prompt-dialog-headline' });
 | 
			
		||||
        this.prompt.bind_property('message', subject, 'text', GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
 | 
			
		||||
        this._messageBox.add(subject,
 | 
			
		||||
                             { y_fill:  false,
 | 
			
		||||
                               y_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        let description = new St.Label({ style_class: 'prompt-dialog-description' });
 | 
			
		||||
        description.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
 | 
			
		||||
        description.clutter_text.line_wrap = true;
 | 
			
		||||
        this.prompt.bind_property('description', description, 'text', GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
        this._messageBox.add(description,
 | 
			
		||||
                            { y_fill:  true,
 | 
			
		||||
                              y_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        this._controlTable = null;
 | 
			
		||||
 | 
			
		||||
        let buttons = [{ label: '',
 | 
			
		||||
                         action: Lang.bind(this, this._onCancelButton),
 | 
			
		||||
                         key:    Clutter.Escape
 | 
			
		||||
                       },
 | 
			
		||||
                       { label: '',
 | 
			
		||||
                         action: Lang.bind(this, this._onContinueButton)
 | 
			
		||||
                       }]
 | 
			
		||||
 | 
			
		||||
        this.setButtons(buttons);
 | 
			
		||||
        this._cancelButton = buttons[0].button;
 | 
			
		||||
        this._continueButton = buttons[1].button;
 | 
			
		||||
 | 
			
		||||
        this.prompt.bind_property('cancel-label', this._cancelButton, 'label', GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
        this.prompt.bind_property('continue-label', this._continueButton, 'label', GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _buildControlTable: function() {
 | 
			
		||||
        let table = new St.Table({ style_class: 'keyring-dialog-control-table' });
 | 
			
		||||
        let row = 0;
 | 
			
		||||
 | 
			
		||||
        if (this.prompt.password_visible) {
 | 
			
		||||
            let label = new St.Label(({ style_class: 'prompt-dialog-password-label' }));
 | 
			
		||||
            label.set_text(_("Password:"));
 | 
			
		||||
            table.add(label, { row: row, col: 0, x_expand: false, x_fill: true, x_align: St.Align.START });
 | 
			
		||||
            this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
 | 
			
		||||
                                                 text: '',
 | 
			
		||||
                                                 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));
 | 
			
		||||
            table.add(this._passwordEntry, { row: row, col: 1, x_expand: true, x_fill: true, x_align: St.Align.START });
 | 
			
		||||
            row++;
 | 
			
		||||
        } else {
 | 
			
		||||
            this._passwordEntry = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.prompt.confirm_visible) {
 | 
			
		||||
            var label = new St.Label(({ style_class: 'prompt-dialog-password-label' }));
 | 
			
		||||
            label.set_text(_("Type again:"));
 | 
			
		||||
            table.add(label, { row: row, col: 0, x_expand: false, x_fill: true, x_align: St.Align.START });
 | 
			
		||||
            this._confirmEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
 | 
			
		||||
                                                text: '',
 | 
			
		||||
                                                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));
 | 
			
		||||
            table.add(this._confirmEntry, { row: row, col: 1, x_expand: true, x_fill: true, x_align: St.Align.START });
 | 
			
		||||
            row++;
 | 
			
		||||
        } else {
 | 
			
		||||
            this._confirmEntry = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.prompt.set_password_actor(this._passwordEntry ? this._passwordEntry.clutter_text : null);
 | 
			
		||||
        this.prompt.set_confirm_actor(this._confirmEntry ? this._confirmEntry.clutter_text : null);
 | 
			
		||||
 | 
			
		||||
        if (this.prompt.choice_visible) {
 | 
			
		||||
            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);
 | 
			
		||||
            table.add(choice.actor, { row: row, col: 1, x_expand: false, x_fill: true, x_align: St.Align.START });
 | 
			
		||||
            row++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let warning = new St.Label({ style_class: 'prompt-dialog-error-label' });
 | 
			
		||||
        warning.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
 | 
			
		||||
        warning.clutter_text.line_wrap = true;
 | 
			
		||||
        table.add(warning, { row: row, col: 1, x_expand: false, x_fill: false, x_align: St.Align.START });
 | 
			
		||||
        this.prompt.bind_property('warning-visible', warning, 'visible', GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
        this.prompt.bind_property('warning', warning, 'text', GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
 | 
			
		||||
        if (this._controlTable) {
 | 
			
		||||
            this._controlTable.destroy_all_children();
 | 
			
		||||
            this._controlTable.destroy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._controlTable = table;
 | 
			
		||||
        this._messageBox.add(table, { x_fill: true, y_fill: true });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _ensureOpen: function() {
 | 
			
		||||
        // NOTE: ModalDialog.open() is safe to call if the dialog is
 | 
			
		||||
        // already open - it just returns true without side-effects
 | 
			
		||||
        if (this.open())
 | 
			
		||||
          return true;
 | 
			
		||||
 | 
			
		||||
        // The above fail if e.g. unable to get input grab
 | 
			
		||||
        //
 | 
			
		||||
        // In an ideal world this wouldn't happen (because the
 | 
			
		||||
        // Shell is in complete control of the session) but that's
 | 
			
		||||
        // just not how things work right now.
 | 
			
		||||
 | 
			
		||||
        log('keyringPrompt: Failed to show modal dialog.' +
 | 
			
		||||
            ' Dismissing prompt request');
 | 
			
		||||
        this.prompt.cancel()
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onShowPassword: function(prompt) {
 | 
			
		||||
        this._buildControlTable();
 | 
			
		||||
        this._ensureOpen();
 | 
			
		||||
        this._passwordEntry.grab_key_focus();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onShowConfirm: function(prompt) {
 | 
			
		||||
        this._buildControlTable();
 | 
			
		||||
        this._ensureOpen();
 | 
			
		||||
        this._continueButton.grab_key_focus();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onHidePrompt: function(prompt) {
 | 
			
		||||
        this.close();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onPasswordActivate: function() {
 | 
			
		||||
        if (this.prompt.confirm_visible)
 | 
			
		||||
            this._confirmEntry.grab_key_focus();
 | 
			
		||||
        else
 | 
			
		||||
            this._onContinueButton();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onConfirmActivate: function() {
 | 
			
		||||
        this._onContinueButton();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onContinueButton: function() {
 | 
			
		||||
        this.prompt.complete()
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onCancelButton: function() {
 | 
			
		||||
        this.prompt.cancel()
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function init() {
 | 
			
		||||
    prompter = new Gcr.SystemPrompter();
 | 
			
		||||
    prompter.connect('new-prompt', function(prompter) {
 | 
			
		||||
        let dialog = new KeyringDialog();
 | 
			
		||||
        return dialog.prompt;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    let connection = Gio.DBus.session;
 | 
			
		||||
    prompter.register(connection);
 | 
			
		||||
    Gio.bus_own_name_on_connection (connection, 'org.gnome.keyring.SystemPrompter',
 | 
			
		||||
                                    Gio.BusNameOwnerFlags.REPLACE, null, null);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										981
									
								
								js/ui/layout.js
									
									
									
									
									
								
							
							
						
						@@ -1,981 +0,0 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const DND = imports.ui.dnd;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const ScreenSaver = imports.misc.screenSaver;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
 | 
			
		||||
const HOT_CORNER_ACTIVATION_TIMEOUT = 0.5;
 | 
			
		||||
const STARTUP_ANIMATION_TIME = 0.2;
 | 
			
		||||
const KEYBOARD_ANIMATION_TIME = 0.5;
 | 
			
		||||
 | 
			
		||||
const LayoutManager = new Lang.Class({
 | 
			
		||||
    Name: 'LayoutManager',
 | 
			
		||||
 | 
			
		||||
    _init: function () {
 | 
			
		||||
        this._rtl = (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL);
 | 
			
		||||
        this.monitors = [];
 | 
			
		||||
        this.primaryMonitor = null;
 | 
			
		||||
        this.primaryIndex = -1;
 | 
			
		||||
        this._hotCorners = [];
 | 
			
		||||
        this._leftPanelBarrier = 0;
 | 
			
		||||
        this._rightPanelBarrier = 0;
 | 
			
		||||
        this._trayBarrier = 0;
 | 
			
		||||
 | 
			
		||||
        this._chrome = new Chrome(this);
 | 
			
		||||
 | 
			
		||||
        this.panelBox = new St.BoxLayout({ name: 'panelBox',
 | 
			
		||||
                                           vertical: true });
 | 
			
		||||
        this.addChrome(this.panelBox, { affectsStruts: true });
 | 
			
		||||
        this.panelBox.connect('allocation-changed',
 | 
			
		||||
                              Lang.bind(this, this._updatePanelBarriers));
 | 
			
		||||
 | 
			
		||||
        this.trayBox = new St.BoxLayout({ name: 'trayBox' }); 
 | 
			
		||||
        this.addChrome(this.trayBox, { visibleInFullscreen: true });
 | 
			
		||||
        this.trayBox.connect('allocation-changed',
 | 
			
		||||
                             Lang.bind(this, this._updateTrayBarrier));
 | 
			
		||||
 | 
			
		||||
        this.keyboardBox = new St.BoxLayout({ name: 'keyboardBox',
 | 
			
		||||
                                              reactive: true,
 | 
			
		||||
                                              track_hover: true });
 | 
			
		||||
        this.addChrome(this.keyboardBox, { visibleInFullscreen: true });
 | 
			
		||||
        this._keyboardHeightNotifyId = 0;
 | 
			
		||||
 | 
			
		||||
        global.screen.connect('monitors-changed',
 | 
			
		||||
                              Lang.bind(this, this._monitorsChanged));
 | 
			
		||||
        this._monitorsChanged();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // This is called by Main after everything else is constructed;
 | 
			
		||||
    // Chrome.init() needs access to Main.overview, which didn't exist
 | 
			
		||||
    // yet when the LayoutManager was constructed.
 | 
			
		||||
    init: function() {
 | 
			
		||||
        this._chrome.init();
 | 
			
		||||
 | 
			
		||||
        this._startupAnimation();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateMonitors: function() {
 | 
			
		||||
        let screen = global.screen;
 | 
			
		||||
 | 
			
		||||
        this.monitors = [];
 | 
			
		||||
        let nMonitors = screen.get_n_monitors();
 | 
			
		||||
        for (let i = 0; i < nMonitors; i++)
 | 
			
		||||
            this.monitors.push(screen.get_monitor_geometry(i));
 | 
			
		||||
 | 
			
		||||
        if (nMonitors == 1) {
 | 
			
		||||
            this.primaryIndex = this.bottomIndex = 0;
 | 
			
		||||
        } else {
 | 
			
		||||
            // If there are monitors below the primary, then we need
 | 
			
		||||
            // to split primary from bottom.
 | 
			
		||||
            this.primaryIndex = this.bottomIndex = screen.get_primary_monitor();
 | 
			
		||||
            for (let i = 0; i < this.monitors.length; i++) {
 | 
			
		||||
                let monitor = this.monitors[i];
 | 
			
		||||
                if (this._isAboveOrBelowPrimary(monitor)) {
 | 
			
		||||
                    if (monitor.y > this.monitors[this.bottomIndex].y)
 | 
			
		||||
                        this.bottomIndex = i;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        this.primaryMonitor = this.monitors[this.primaryIndex];
 | 
			
		||||
        this.bottomMonitor = this.monitors[this.bottomIndex];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateHotCorners: function() {
 | 
			
		||||
        // destroy old hot corners
 | 
			
		||||
        for (let i = 0; i < this._hotCorners.length; i++)
 | 
			
		||||
            this._hotCorners[i].destroy();
 | 
			
		||||
        this._hotCorners = [];
 | 
			
		||||
 | 
			
		||||
        // build new hot corners
 | 
			
		||||
        for (let i = 0; i < this.monitors.length; i++) {
 | 
			
		||||
            if (i == this.primaryIndex)
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            let monitor = this.monitors[i];
 | 
			
		||||
            let cornerX = this._rtl ? monitor.x + monitor.width : monitor.x;
 | 
			
		||||
            let cornerY = monitor.y;
 | 
			
		||||
 | 
			
		||||
            let haveTopLeftCorner = true;
 | 
			
		||||
 | 
			
		||||
            // Check if we have a top left (right for RTL) corner.
 | 
			
		||||
            // I.e. if there is no monitor directly above or to the left(right)
 | 
			
		||||
            let besideX = this._rtl ? monitor.x + 1 : cornerX - 1;
 | 
			
		||||
            let besideY = cornerY;
 | 
			
		||||
            let aboveX = cornerX;
 | 
			
		||||
            let aboveY = cornerY - 1;
 | 
			
		||||
 | 
			
		||||
            for (let j = 0; j < this.monitors.length; j++) {
 | 
			
		||||
                if (i == j)
 | 
			
		||||
                    continue;
 | 
			
		||||
                let otherMonitor = this.monitors[j];
 | 
			
		||||
                if (besideX >= otherMonitor.x &&
 | 
			
		||||
                    besideX < otherMonitor.x + otherMonitor.width &&
 | 
			
		||||
                    besideY >= otherMonitor.y &&
 | 
			
		||||
                    besideY < otherMonitor.y + otherMonitor.height) {
 | 
			
		||||
                    haveTopLeftCorner = false;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                if (aboveX >= otherMonitor.x &&
 | 
			
		||||
                    aboveX < otherMonitor.x + otherMonitor.width &&
 | 
			
		||||
                    aboveY >= otherMonitor.y &&
 | 
			
		||||
                    aboveY < otherMonitor.y + otherMonitor.height) {
 | 
			
		||||
                    haveTopLeftCorner = false;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!haveTopLeftCorner)
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            let corner = new HotCorner();
 | 
			
		||||
            this._hotCorners.push(corner);
 | 
			
		||||
            corner.actor.set_position(cornerX, cornerY);
 | 
			
		||||
            this._chrome.addActor(corner.actor);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateBoxes: function() {
 | 
			
		||||
        this.panelBox.set_position(this.primaryMonitor.x, this.primaryMonitor.y);
 | 
			
		||||
        this.panelBox.set_size(this.primaryMonitor.width, -1);
 | 
			
		||||
 | 
			
		||||
        this.keyboardBox.set_position(this.bottomMonitor.x,
 | 
			
		||||
                                      this.bottomMonitor.y + this.bottomMonitor.height);
 | 
			
		||||
        this.keyboardBox.set_size(this.bottomMonitor.width, -1);
 | 
			
		||||
 | 
			
		||||
        this.trayBox.set_position(this.bottomMonitor.x,
 | 
			
		||||
                                  this.bottomMonitor.y + this.bottomMonitor.height);
 | 
			
		||||
        this.trayBox.set_size(this.bottomMonitor.width, -1);
 | 
			
		||||
 | 
			
		||||
        // Set trayBox's clip to show things above it, but not below
 | 
			
		||||
        // it (so it's not visible behind the keyboard). The exact
 | 
			
		||||
        // height of the clip doesn't matter, as long as it's taller
 | 
			
		||||
        // than any Notification.actor.
 | 
			
		||||
        this.trayBox.set_clip(0, -this.bottomMonitor.height,
 | 
			
		||||
                              this.bottomMonitor.width, this.bottomMonitor.height);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updatePanelBarriers: function() {
 | 
			
		||||
        if (this._leftPanelBarrier)
 | 
			
		||||
            global.destroy_pointer_barrier(this._leftPanelBarrier);
 | 
			
		||||
        if (this._rightPanelBarrier)
 | 
			
		||||
            global.destroy_pointer_barrier(this._rightPanelBarrier);
 | 
			
		||||
 | 
			
		||||
        if (this.panelBox.height) {
 | 
			
		||||
            let primary = this.primaryMonitor;
 | 
			
		||||
            this._leftPanelBarrier =
 | 
			
		||||
                global.create_pointer_barrier(primary.x, primary.y,
 | 
			
		||||
                                              primary.x, primary.y + this.panelBox.height,
 | 
			
		||||
                                              1 /* BarrierPositiveX */);
 | 
			
		||||
            this._rightPanelBarrier =
 | 
			
		||||
                global.create_pointer_barrier(primary.x + primary.width, primary.y,
 | 
			
		||||
                                              primary.x + primary.width, primary.y + this.panelBox.height,
 | 
			
		||||
                                              4 /* BarrierNegativeX */);
 | 
			
		||||
        } else {
 | 
			
		||||
            this._leftPanelBarrier = 0;
 | 
			
		||||
            this._rightPanelBarrier = 0;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateTrayBarrier: function() {
 | 
			
		||||
        let monitor = this.bottomMonitor;
 | 
			
		||||
 | 
			
		||||
        if (this._trayBarrier)
 | 
			
		||||
            global.destroy_pointer_barrier(this._trayBarrier);
 | 
			
		||||
 | 
			
		||||
        if (Main.messageTray) {
 | 
			
		||||
            this._trayBarrier =
 | 
			
		||||
                global.create_pointer_barrier(monitor.x + monitor.width, monitor.y + monitor.height - Main.messageTray.actor.height,
 | 
			
		||||
                                              monitor.x + monitor.width, monitor.y + monitor.height,
 | 
			
		||||
                                              4 /* BarrierNegativeX */);
 | 
			
		||||
        } else {
 | 
			
		||||
            this._trayBarrier = 0;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _monitorsChanged: function() {
 | 
			
		||||
        this._updateMonitors();
 | 
			
		||||
        this._updateBoxes();
 | 
			
		||||
        this._updateHotCorners();
 | 
			
		||||
 | 
			
		||||
        this.emit('monitors-changed');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _isAboveOrBelowPrimary: function(monitor) {
 | 
			
		||||
        let primary = this.monitors[this.primaryIndex];
 | 
			
		||||
        let monitorLeft = monitor.x, monitorRight = monitor.x + monitor.width;
 | 
			
		||||
        let primaryLeft = primary.x, primaryRight = primary.x + primary.width;
 | 
			
		||||
 | 
			
		||||
        if ((monitorLeft >= primaryLeft && monitorLeft < primaryRight) ||
 | 
			
		||||
            (monitorRight > primaryLeft && monitorRight <= primaryRight) ||
 | 
			
		||||
            (primaryLeft >= monitorLeft && primaryLeft < monitorRight) ||
 | 
			
		||||
            (primaryRight > monitorLeft && primaryRight <= monitorRight))
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get focusIndex() {
 | 
			
		||||
        let focusWindow = global.display.focus_window;
 | 
			
		||||
 | 
			
		||||
        if (focusWindow) {
 | 
			
		||||
            let wrect = focusWindow.get_outer_rect();
 | 
			
		||||
            for (let i = 0; i < this.monitors.length; i++) {
 | 
			
		||||
                let monitor = this.monitors[i];
 | 
			
		||||
 | 
			
		||||
                if (monitor.x <= wrect.x && monitor.y <= wrect.y &&
 | 
			
		||||
                    monitor.x + monitor.width > wrect.x &&
 | 
			
		||||
                    monitor.y + monitor.height > wrect.y)
 | 
			
		||||
                    return i;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return this.primaryIndex;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get focusMonitor() {
 | 
			
		||||
        return this.monitors[this.focusIndex];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _startupAnimation: function() {
 | 
			
		||||
        // Don't animate the strut
 | 
			
		||||
        this._chrome.freezeUpdateRegions();
 | 
			
		||||
 | 
			
		||||
        this.panelBox.anchor_y = this.panelBox.height;
 | 
			
		||||
        Tweener.addTween(this.panelBox,
 | 
			
		||||
                         { anchor_y: 0,
 | 
			
		||||
                           time: STARTUP_ANIMATION_TIME,
 | 
			
		||||
                           transition: 'easeOutQuad',
 | 
			
		||||
                           onComplete: this._startupAnimationComplete,
 | 
			
		||||
                           onCompleteScope: this
 | 
			
		||||
                         });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _startupAnimationComplete: function() {
 | 
			
		||||
        this._chrome.thawUpdateRegions();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    showKeyboard: function () {
 | 
			
		||||
        Main.messageTray.hide();
 | 
			
		||||
        this.keyboardBox.raise_top();
 | 
			
		||||
        Tweener.addTween(this.keyboardBox,
 | 
			
		||||
                         { anchor_y: this.keyboardBox.height,
 | 
			
		||||
                           time: KEYBOARD_ANIMATION_TIME,
 | 
			
		||||
                           transition: 'easeOutQuad',
 | 
			
		||||
                           onComplete: this._showKeyboardComplete,
 | 
			
		||||
                           onCompleteScope: this
 | 
			
		||||
                         });
 | 
			
		||||
        Tweener.addTween(this.trayBox,
 | 
			
		||||
                         { anchor_y: this.keyboardBox.height,
 | 
			
		||||
                           time: KEYBOARD_ANIMATION_TIME,
 | 
			
		||||
                           transition: 'easeOutQuad'
 | 
			
		||||
                         });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showKeyboardComplete: function() {
 | 
			
		||||
        // Poke Chrome to update the input shape; it doesn't notice
 | 
			
		||||
        // anchor point changes
 | 
			
		||||
        this._chrome.updateRegions();
 | 
			
		||||
 | 
			
		||||
        this._keyboardHeightNotifyId = this.keyboardBox.connect('notify::height', Lang.bind(this, function () {
 | 
			
		||||
            this.keyboardBox.anchor_y = this.keyboardBox.height;
 | 
			
		||||
            this.trayBox.anchor_y = this.keyboardBox.height;
 | 
			
		||||
        }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hideKeyboard: function (immediate) {
 | 
			
		||||
        Main.messageTray.hide();
 | 
			
		||||
        if (this._keyboardHeightNotifyId) {
 | 
			
		||||
            this.keyboardBox.disconnect(this._keyboardHeightNotifyId);
 | 
			
		||||
            this._keyboardHeightNotifyId = 0;
 | 
			
		||||
        }
 | 
			
		||||
        Tweener.addTween(this.keyboardBox,
 | 
			
		||||
                         { anchor_y: 0,
 | 
			
		||||
                           time: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
 | 
			
		||||
                           transition: 'easeOutQuad',
 | 
			
		||||
                           onComplete: this._hideKeyboardComplete,
 | 
			
		||||
                           onCompleteScope: this
 | 
			
		||||
                         });
 | 
			
		||||
        Tweener.addTween(this.trayBox,
 | 
			
		||||
                         { anchor_y: 0,
 | 
			
		||||
                           time: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
 | 
			
		||||
                           transition: 'easeOutQuad'
 | 
			
		||||
                         });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _hideKeyboardComplete: function() {
 | 
			
		||||
        this._chrome.updateRegions();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // addChrome:
 | 
			
		||||
    // @actor: an actor to add to the chrome
 | 
			
		||||
    // @params: (optional) additional params
 | 
			
		||||
    //
 | 
			
		||||
    // Adds @actor to the chrome, and (unless %affectsInputRegion in
 | 
			
		||||
    // @params is %false) extends the input region to include it.
 | 
			
		||||
    // Changes in @actor's size, position, and visibility will
 | 
			
		||||
    // automatically result in appropriate changes to the input
 | 
			
		||||
    // region.
 | 
			
		||||
    //
 | 
			
		||||
    // If %affectsStruts in @params is %true (and @actor is along a
 | 
			
		||||
    // screen edge), then @actor's size and position will also affect
 | 
			
		||||
    // the window manager struts. Changes to @actor's visibility will
 | 
			
		||||
    // NOT affect whether or not the strut is present, however.
 | 
			
		||||
    //
 | 
			
		||||
    // If %visibleInFullscreen in @params is %true, the actor will be
 | 
			
		||||
    // visible even when a fullscreen window should be covering it.
 | 
			
		||||
    addChrome: function(actor, params) {
 | 
			
		||||
        this._chrome.addActor(actor, params);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // trackChrome:
 | 
			
		||||
    // @actor: a descendant of the chrome to begin tracking
 | 
			
		||||
    // @params: parameters describing how to track @actor
 | 
			
		||||
    //
 | 
			
		||||
    // Tells the chrome to track @actor, which must be a descendant
 | 
			
		||||
    // of an actor added via addChrome(). This can be used to extend the
 | 
			
		||||
    // struts or input region to cover specific children.
 | 
			
		||||
    //
 | 
			
		||||
    // @params can have any of the same values as in addChrome(),
 | 
			
		||||
    // though some possibilities don't make sense (eg, trying to have
 | 
			
		||||
    // a %visibleInFullscreen child of a non-%visibleInFullscreen
 | 
			
		||||
    // parent). By default, @actor has the same params as its chrome
 | 
			
		||||
    // ancestor.
 | 
			
		||||
    trackChrome: function(actor, params) {
 | 
			
		||||
        this._chrome.trackActor(actor, params);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // untrackChrome:
 | 
			
		||||
    // @actor: an actor previously tracked via trackChrome()
 | 
			
		||||
    //
 | 
			
		||||
    // Undoes the effect of trackChrome()
 | 
			
		||||
    untrackChrome: function(actor) {
 | 
			
		||||
        this._chrome.untrackActor(actor);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // removeChrome:
 | 
			
		||||
    // @actor: a chrome actor
 | 
			
		||||
    //
 | 
			
		||||
    // Removes @actor from the chrome
 | 
			
		||||
    removeChrome: function(actor) {
 | 
			
		||||
        this._chrome.removeActor(actor);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    findMonitorForActor: function(actor) {
 | 
			
		||||
        return this._chrome.findMonitorForActor(actor);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(LayoutManager.prototype);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// HotCorner:
 | 
			
		||||
//
 | 
			
		||||
// This class manages a "hot corner" that can toggle switching to
 | 
			
		||||
// overview.
 | 
			
		||||
const HotCorner = new Lang.Class({
 | 
			
		||||
    Name: 'HotCorner',
 | 
			
		||||
 | 
			
		||||
    _init : function() {
 | 
			
		||||
        // We use this flag to mark the case where the user has entered the
 | 
			
		||||
        // hot corner and has not left both the hot corner and a surrounding
 | 
			
		||||
        // guard area (the "environs"). This avoids triggering the hot corner
 | 
			
		||||
        // multiple times due to an accidental jitter.
 | 
			
		||||
        this._entered = false;
 | 
			
		||||
 | 
			
		||||
        this.actor = new Clutter.Group({ name: 'hot-corner-environs',
 | 
			
		||||
                                         width: 3,
 | 
			
		||||
                                         height: 3,
 | 
			
		||||
                                         reactive: true });
 | 
			
		||||
 | 
			
		||||
        this._corner = new Clutter.Rectangle({ name: 'hot-corner',
 | 
			
		||||
                                               width: 1,
 | 
			
		||||
                                               height: 1,
 | 
			
		||||
                                               opacity: 0,
 | 
			
		||||
                                               reactive: true });
 | 
			
		||||
        this._corner._delegate = this;
 | 
			
		||||
 | 
			
		||||
        this.actor.add_actor(this._corner);
 | 
			
		||||
 | 
			
		||||
        if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) {
 | 
			
		||||
            this._corner.set_position(this.actor.width - this._corner.width, 0);
 | 
			
		||||
            this.actor.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
 | 
			
		||||
        } else {
 | 
			
		||||
            this._corner.set_position(0, 0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._activationTime = 0;
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('leave-event',
 | 
			
		||||
                           Lang.bind(this, this._onEnvironsLeft));
 | 
			
		||||
 | 
			
		||||
        // Clicking on the hot corner environs should result in the
 | 
			
		||||
        // same behavior as clicking on the hot corner.
 | 
			
		||||
        this.actor.connect('button-release-event',
 | 
			
		||||
                           Lang.bind(this, this._onCornerClicked));
 | 
			
		||||
 | 
			
		||||
        // In addition to being triggered by the mouse enter event,
 | 
			
		||||
        // the hot corner can be triggered by clicking on it. This is
 | 
			
		||||
        // useful if the user wants to undo the effect of triggering
 | 
			
		||||
        // the hot corner once in the hot corner.
 | 
			
		||||
        this._corner.connect('enter-event',
 | 
			
		||||
                             Lang.bind(this, this._onCornerEntered));
 | 
			
		||||
        this._corner.connect('button-release-event',
 | 
			
		||||
                             Lang.bind(this, this._onCornerClicked));
 | 
			
		||||
        this._corner.connect('leave-event',
 | 
			
		||||
                             Lang.bind(this, this._onCornerLeft));
 | 
			
		||||
 | 
			
		||||
        // Cache the three ripples instead of dynamically creating and destroying them.
 | 
			
		||||
        this._ripple1 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0, visible: false });
 | 
			
		||||
        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 });
 | 
			
		||||
 | 
			
		||||
        Main.uiGroup.add_actor(this._ripple1);
 | 
			
		||||
        Main.uiGroup.add_actor(this._ripple2);
 | 
			
		||||
        Main.uiGroup.add_actor(this._ripple3);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    destroy: function() {
 | 
			
		||||
        this.actor.destroy();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _animRipple : function(ripple, delay, time, startScale, startOpacity, finalScale) {
 | 
			
		||||
        // We draw a ripple by using a source image and animating it scaling
 | 
			
		||||
        // outwards and fading away. We want the ripples to move linearly
 | 
			
		||||
        // or it looks unrealistic, but if the opacity of the ripple goes
 | 
			
		||||
        // linearly to zero it fades away too quickly, so we use Tweener's
 | 
			
		||||
        // 'onUpdate' to give a non-linear curve to the fade-away and make
 | 
			
		||||
        // it more visible in the middle section.
 | 
			
		||||
 | 
			
		||||
        ripple._opacity = startOpacity;
 | 
			
		||||
 | 
			
		||||
        if (ripple.get_text_direction() == Clutter.TextDirection.RTL)
 | 
			
		||||
            ripple.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
 | 
			
		||||
 | 
			
		||||
        ripple.visible = true;
 | 
			
		||||
        ripple.opacity = 255 * Math.sqrt(startOpacity);
 | 
			
		||||
        ripple.scale_x = ripple.scale_y = startScale;
 | 
			
		||||
 | 
			
		||||
        let [x, y] = this._corner.get_transformed_position();
 | 
			
		||||
        ripple.x = x;
 | 
			
		||||
        ripple.y = y;
 | 
			
		||||
 | 
			
		||||
        Tweener.addTween(ripple, { _opacity: 0,
 | 
			
		||||
                                   scale_x: finalScale,
 | 
			
		||||
                                   scale_y: finalScale,
 | 
			
		||||
                                   delay: delay,
 | 
			
		||||
                                   time: time,
 | 
			
		||||
                                   transition: 'linear',
 | 
			
		||||
                                   onUpdate: function() { ripple.opacity = 255 * Math.sqrt(ripple._opacity); },
 | 
			
		||||
                                   onComplete: function() { ripple.visible = false; } });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    rippleAnimation: function() {
 | 
			
		||||
        // Show three concentric ripples expanding outwards; the exact
 | 
			
		||||
        // parameters were found by trial and error, so don't look
 | 
			
		||||
        // for them to make perfect sense mathematically
 | 
			
		||||
 | 
			
		||||
        //                              delay  time  scale opacity => scale
 | 
			
		||||
        this._animRipple(this._ripple1, 0.0,   0.83,  0.25,  1.0,     1.5);
 | 
			
		||||
        this._animRipple(this._ripple2, 0.05,  1.0,   0.0,   0.7,     1.25);
 | 
			
		||||
        this._animRipple(this._ripple3, 0.35,  1.0,   0.0,   0.3,     1);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    handleDragOver: function(source, actor, x, y, time) {
 | 
			
		||||
        if (source != Main.xdndHandler)
 | 
			
		||||
            return DND.DragMotionResult.CONTINUE;
 | 
			
		||||
 | 
			
		||||
        if (!Main.overview.visible && !Main.overview.animationInProgress) {
 | 
			
		||||
            this.rippleAnimation();
 | 
			
		||||
            Main.overview.showTemporarily();
 | 
			
		||||
            Main.overview.beginItemDrag(actor);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return DND.DragMotionResult.CONTINUE;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onCornerEntered : function() {
 | 
			
		||||
        if (!this._entered) {
 | 
			
		||||
            this._entered = true;
 | 
			
		||||
            if (!Main.overview.animationInProgress) {
 | 
			
		||||
                this._activationTime = Date.now() / 1000;
 | 
			
		||||
 | 
			
		||||
                this.rippleAnimation();
 | 
			
		||||
                Main.overview.toggle();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onCornerClicked : function() {
 | 
			
		||||
        if (this.shouldToggleOverviewOnClick())
 | 
			
		||||
            Main.overview.toggle();
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onCornerLeft : function(actor, event) {
 | 
			
		||||
        if (event.get_related() != this.actor)
 | 
			
		||||
            this._entered = false;
 | 
			
		||||
        // Consume event, otherwise this will confuse onEnvironsLeft
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onEnvironsLeft : function(actor, event) {
 | 
			
		||||
        if (event.get_related() != this._corner)
 | 
			
		||||
            this._entered = false;
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // Checks if the Activities button is currently sensitive to
 | 
			
		||||
    // clicks. The first call to this function within the
 | 
			
		||||
    // HOT_CORNER_ACTIVATION_TIMEOUT time of the hot corner being
 | 
			
		||||
    // triggered will return false. This avoids opening and closing
 | 
			
		||||
    // the overview if the user both triggered the hot corner and
 | 
			
		||||
    // clicked the Activities button.
 | 
			
		||||
    shouldToggleOverviewOnClick: function() {
 | 
			
		||||
        if (Main.overview.animationInProgress)
 | 
			
		||||
            return false;
 | 
			
		||||
        if (this._activationTime == 0 || Date.now() / 1000 - this._activationTime > HOT_CORNER_ACTIVATION_TIMEOUT)
 | 
			
		||||
            return true;
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// This manages the shell "chrome"; the UI that's visible in the
 | 
			
		||||
// normal mode (ie, outside the Overview), that surrounds the main
 | 
			
		||||
// workspace content.
 | 
			
		||||
 | 
			
		||||
const defaultParams = {
 | 
			
		||||
    visibleInFullscreen: false,
 | 
			
		||||
    affectsStruts: false,
 | 
			
		||||
    affectsInputRegion: true
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const Chrome = new Lang.Class({
 | 
			
		||||
    Name: 'Chrome',
 | 
			
		||||
 | 
			
		||||
    _init: function(layoutManager) {
 | 
			
		||||
        this._layoutManager = layoutManager;
 | 
			
		||||
 | 
			
		||||
        this._monitors = [];
 | 
			
		||||
        this._inOverview = false;
 | 
			
		||||
        this._updateRegionIdle = 0;
 | 
			
		||||
        this._freezeUpdateCount = 0;
 | 
			
		||||
 | 
			
		||||
        this._trackedActors = [];
 | 
			
		||||
 | 
			
		||||
        this._layoutManager.connect('monitors-changed',
 | 
			
		||||
                                    Lang.bind(this, this._relayout));
 | 
			
		||||
        global.screen.connect('restacked',
 | 
			
		||||
                              Lang.bind(this, this._windowsRestacked));
 | 
			
		||||
 | 
			
		||||
        // Need to update struts on new workspaces when they are added
 | 
			
		||||
        global.screen.connect('notify::n-workspaces',
 | 
			
		||||
                              Lang.bind(this, this._queueUpdateRegions));
 | 
			
		||||
 | 
			
		||||
        this._screenSaverActive = false;
 | 
			
		||||
        this._screenSaverProxy = new ScreenSaver.ScreenSaverProxy();
 | 
			
		||||
        this._screenSaverProxy.connectSignal('ActiveChanged', Lang.bind(this, function(proxy, senderName, [isActive]) {
 | 
			
		||||
            this._onScreenSaverActiveChanged(isActive);
 | 
			
		||||
        }));
 | 
			
		||||
        this._screenSaverProxy.GetActiveRemote(Lang.bind(this, function(result, err) {
 | 
			
		||||
            if (!err)
 | 
			
		||||
                this._onScreenSaverActiveChanged(result[0]);
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        this._relayout();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    init: function() {
 | 
			
		||||
        Main.overview.connect('showing',
 | 
			
		||||
                             Lang.bind(this, this._overviewShowing));
 | 
			
		||||
        Main.overview.connect('hidden',
 | 
			
		||||
                             Lang.bind(this, this._overviewHidden));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addActor: function(actor, params) {
 | 
			
		||||
        Main.uiGroup.add_actor(actor);
 | 
			
		||||
        this._trackActor(actor, params);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    trackActor: function(actor, params) {
 | 
			
		||||
        let ancestor = actor.get_parent();
 | 
			
		||||
        let index = this._findActor(ancestor);
 | 
			
		||||
        while (ancestor && index == -1) {
 | 
			
		||||
            ancestor = ancestor.get_parent();
 | 
			
		||||
            index = this._findActor(ancestor);
 | 
			
		||||
        }
 | 
			
		||||
        if (!ancestor)
 | 
			
		||||
            throw new Error('actor is not a descendent of a chrome actor');
 | 
			
		||||
 | 
			
		||||
        let ancestorData = this._trackedActors[index];
 | 
			
		||||
        if (!params)
 | 
			
		||||
            params = {};
 | 
			
		||||
        // We can't use Params.parse here because we want to drop
 | 
			
		||||
        // the extra values like ancestorData.actor
 | 
			
		||||
        for (let prop in defaultParams) {
 | 
			
		||||
            if (!params.hasOwnProperty(prop))
 | 
			
		||||
                params[prop] = ancestorData[prop];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._trackActor(actor, params);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    untrackActor: function(actor) {
 | 
			
		||||
        this._untrackActor(actor);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    removeActor: function(actor) {
 | 
			
		||||
        Main.uiGroup.remove_actor(actor);
 | 
			
		||||
        this._untrackActor(actor);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _findActor: function(actor) {
 | 
			
		||||
        for (let i = 0; i < this._trackedActors.length; i++) {
 | 
			
		||||
            let actorData = this._trackedActors[i];
 | 
			
		||||
            if (actorData.actor == actor)
 | 
			
		||||
                return i;
 | 
			
		||||
        }
 | 
			
		||||
        return -1;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _trackActor: function(actor, params) {
 | 
			
		||||
        if (this._findActor(actor) != -1)
 | 
			
		||||
            throw new Error('trying to re-track existing chrome actor');
 | 
			
		||||
 | 
			
		||||
        let actorData = Params.parse(params, defaultParams);
 | 
			
		||||
        actorData.actor = actor;
 | 
			
		||||
        actorData.isToplevel = actor.get_parent() == Main.uiGroup;
 | 
			
		||||
        actorData.visibleId = actor.connect('notify::visible',
 | 
			
		||||
                                            Lang.bind(this, this._queueUpdateRegions));
 | 
			
		||||
        actorData.allocationId = actor.connect('notify::allocation',
 | 
			
		||||
                                               Lang.bind(this, this._queueUpdateRegions));
 | 
			
		||||
        actorData.parentSetId = actor.connect('parent-set',
 | 
			
		||||
                                              Lang.bind(this, this._actorReparented));
 | 
			
		||||
        // Note that destroying actor will unset its parent, so we don't
 | 
			
		||||
        // need to connect to 'destroy' too.
 | 
			
		||||
 | 
			
		||||
        this._trackedActors.push(actorData);
 | 
			
		||||
        this._queueUpdateRegions();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _untrackActor: function(actor) {
 | 
			
		||||
        let i = this._findActor(actor);
 | 
			
		||||
 | 
			
		||||
        if (i == -1)
 | 
			
		||||
            return;
 | 
			
		||||
        let actorData = this._trackedActors[i];
 | 
			
		||||
 | 
			
		||||
        this._trackedActors.splice(i, 1);
 | 
			
		||||
        actor.disconnect(actorData.visibleId);
 | 
			
		||||
        actor.disconnect(actorData.allocationId);
 | 
			
		||||
        actor.disconnect(actorData.parentSetId);
 | 
			
		||||
 | 
			
		||||
        this._queueUpdateRegions();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _actorReparented: function(actor, oldParent) {
 | 
			
		||||
        let newParent = actor.get_parent();
 | 
			
		||||
        if (!newParent)
 | 
			
		||||
            this._untrackActor(actor);
 | 
			
		||||
        else
 | 
			
		||||
            actorData.isToplevel = (newParent == Main.uiGroup);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateVisibility: function() {
 | 
			
		||||
        for (let i = 0; i < this._trackedActors.length; i++) {
 | 
			
		||||
            let actorData = this._trackedActors[i], visible;
 | 
			
		||||
            if (!actorData.isToplevel)
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            if (this._screenSaverActive)
 | 
			
		||||
                visible = false;
 | 
			
		||||
            else if (this._inOverview)
 | 
			
		||||
                visible = true;
 | 
			
		||||
            else if (!actorData.visibleInFullscreen &&
 | 
			
		||||
                     this.findMonitorForActor(actorData.actor).inFullscreen)
 | 
			
		||||
                visible = false;
 | 
			
		||||
            else
 | 
			
		||||
                visible = true;
 | 
			
		||||
            Main.uiGroup.set_skip_paint(actorData.actor, !visible);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _overviewShowing: function() {
 | 
			
		||||
        this._inOverview = true;
 | 
			
		||||
        this._updateVisibility();
 | 
			
		||||
        this._queueUpdateRegions();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _overviewHidden: function() {
 | 
			
		||||
        this._inOverview = false;
 | 
			
		||||
        this._updateVisibility();
 | 
			
		||||
        this._queueUpdateRegions();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _relayout: function() {
 | 
			
		||||
        this._monitors = this._layoutManager.monitors;
 | 
			
		||||
        this._primaryMonitor = this._layoutManager.primaryMonitor;
 | 
			
		||||
 | 
			
		||||
        this._updateFullscreen();
 | 
			
		||||
        this._updateVisibility();
 | 
			
		||||
        this._queueUpdateRegions();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onScreenSaverActiveChanged: function(screenSaverActive) {
 | 
			
		||||
        this._screenSaverActive = screenSaverActive;
 | 
			
		||||
        this._updateVisibility();
 | 
			
		||||
        this._queueUpdateRegions();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _findMonitorForRect: function(x, y, w, h) {
 | 
			
		||||
        // First look at what monitor the center of the rectangle is at
 | 
			
		||||
        let cx = x + w/2;
 | 
			
		||||
        let cy = y + h/2;
 | 
			
		||||
        for (let i = 0; i < this._monitors.length; i++) {
 | 
			
		||||
            let monitor = this._monitors[i];
 | 
			
		||||
            if (cx >= monitor.x && cx < monitor.x + monitor.width &&
 | 
			
		||||
                cy >= monitor.y && cy < monitor.y + monitor.height)
 | 
			
		||||
                return monitor;
 | 
			
		||||
        }
 | 
			
		||||
        // If the center is not on a monitor, return the first overlapping monitor
 | 
			
		||||
        for (let i = 0; i < this._monitors.length; i++) {
 | 
			
		||||
            let monitor = this._monitors[i];
 | 
			
		||||
            if (x + w > monitor.x && x < monitor.x + monitor.width &&
 | 
			
		||||
                y + h > monitor.y && y < monitor.y + monitor.height)
 | 
			
		||||
                return monitor;
 | 
			
		||||
        }
 | 
			
		||||
        // otherwise on no monitor
 | 
			
		||||
        return null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _findMonitorForWindow: function(window) {
 | 
			
		||||
        return this._findMonitorForRect(window.x, window.y, window.width, window.height);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // This call guarantees that we return some monitor to simplify usage of it
 | 
			
		||||
    // In practice all tracked actors should be visible on some monitor anyway
 | 
			
		||||
    findMonitorForActor: function(actor) {
 | 
			
		||||
        let [x, y] = actor.get_transformed_position();
 | 
			
		||||
        let [w, h] = actor.get_transformed_size();
 | 
			
		||||
        let monitor = this._findMonitorForRect(x, y, w, h);
 | 
			
		||||
        if (monitor)
 | 
			
		||||
            return monitor;
 | 
			
		||||
        return this._primaryMonitor; // Not on any monitor, pretend its on the primary
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _queueUpdateRegions: function() {
 | 
			
		||||
        if (!this._updateRegionIdle && !this._freezeUpdateCount)
 | 
			
		||||
            this._updateRegionIdle = Mainloop.idle_add(Lang.bind(this, this.updateRegions),
 | 
			
		||||
                                                       Meta.PRIORITY_BEFORE_REDRAW);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    freezeUpdateRegions: function() {
 | 
			
		||||
        if (this._updateRegionIdle)
 | 
			
		||||
            this.updateRegions();
 | 
			
		||||
        this._freezeUpdateCount++;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    thawUpdateRegions: function() {
 | 
			
		||||
        this._freezeUpdateCount--;
 | 
			
		||||
        this._queueUpdateRegions();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateFullscreen: function() {
 | 
			
		||||
        let windows = Main.getWindowActorsForWorkspace(global.screen.get_active_workspace_index());
 | 
			
		||||
 | 
			
		||||
        // Reset all monitors to not fullscreen
 | 
			
		||||
        for (let i = 0; i < this._monitors.length; i++)
 | 
			
		||||
            this._monitors[i].inFullscreen = false;
 | 
			
		||||
 | 
			
		||||
        // Ordinary chrome should be visible unless there is a window
 | 
			
		||||
        // with layer FULLSCREEN, or a window with layer
 | 
			
		||||
        // OVERRIDE_REDIRECT that covers the whole screen.
 | 
			
		||||
        // ('override_redirect' is not actually a layer above all
 | 
			
		||||
        // other windows, but this seems to be how mutter treats it
 | 
			
		||||
        // currently...) If we wanted to be extra clever, we could
 | 
			
		||||
        // figure out when an OVERRIDE_REDIRECT window was trying to
 | 
			
		||||
        // partially overlap us, and then adjust the input region and
 | 
			
		||||
        // our clip region accordingly...
 | 
			
		||||
 | 
			
		||||
        // @windows is sorted bottom to top.
 | 
			
		||||
 | 
			
		||||
        for (let i = windows.length - 1; i > -1; i--) {
 | 
			
		||||
            let window = windows[i];
 | 
			
		||||
            let layer = window.get_meta_window().get_layer();
 | 
			
		||||
 | 
			
		||||
            // Skip minimized windows
 | 
			
		||||
            if (!window.showing_on_its_workspace())
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            if (layer == Meta.StackLayer.FULLSCREEN) {
 | 
			
		||||
                let monitor = this._findMonitorForWindow(window);
 | 
			
		||||
                if (monitor)
 | 
			
		||||
                    monitor.inFullscreen = true;
 | 
			
		||||
            }
 | 
			
		||||
            if (layer == Meta.StackLayer.OVERRIDE_REDIRECT) {
 | 
			
		||||
                // Check whether the window is screen sized
 | 
			
		||||
                let isScreenSized =
 | 
			
		||||
                    (window.x == 0 && window.y == 0 &&
 | 
			
		||||
                    window.width == global.screen_width &&
 | 
			
		||||
                    window.height == global.screen_height);
 | 
			
		||||
 | 
			
		||||
                if (isScreenSized) {
 | 
			
		||||
                    for (let i = 0; i < this._monitors.length; i++)
 | 
			
		||||
                        this._monitors[i].inFullscreen = true;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Or whether it is monitor sized
 | 
			
		||||
                let monitor = this._findMonitorForWindow(window);
 | 
			
		||||
                if (monitor &&
 | 
			
		||||
                    window.x <= monitor.x &&
 | 
			
		||||
                    window.x + window.width >= monitor.x + monitor.width &&
 | 
			
		||||
                    window.y <= monitor.y &&
 | 
			
		||||
                    window.y + window.height >= monitor.y + monitor.height)
 | 
			
		||||
                    monitor.inFullscreen = true;
 | 
			
		||||
            } else
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _windowsRestacked: function() {
 | 
			
		||||
        let wasInFullscreen = [];
 | 
			
		||||
        for (let i = 0; i < this._monitors.length; i++)
 | 
			
		||||
            wasInFullscreen[i] = this._monitors[i].inFullscreen;
 | 
			
		||||
 | 
			
		||||
        this._updateFullscreen();
 | 
			
		||||
 | 
			
		||||
        let changed = false;
 | 
			
		||||
        for (let i = 0; i < wasInFullscreen.length; i++) {
 | 
			
		||||
            if (wasInFullscreen[i] != this._monitors[i].inFullscreen) {
 | 
			
		||||
                changed = true;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (changed) {
 | 
			
		||||
            this._updateVisibility();
 | 
			
		||||
            this._queueUpdateRegions();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    updateRegions: function() {
 | 
			
		||||
        let rects = [], struts = [], i;
 | 
			
		||||
 | 
			
		||||
        if (this._updateRegionIdle) {
 | 
			
		||||
            Mainloop.source_remove(this._updateRegionIdle);
 | 
			
		||||
            delete this._updateRegionIdle;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (i = 0; i < this._trackedActors.length; i++) {
 | 
			
		||||
            let actorData = this._trackedActors[i];
 | 
			
		||||
            if (!actorData.affectsInputRegion && !actorData.affectsStruts)
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            let [x, y] = actorData.actor.get_transformed_position();
 | 
			
		||||
            let [w, h] = actorData.actor.get_transformed_size();
 | 
			
		||||
            x = Math.round(x);
 | 
			
		||||
            y = Math.round(y);
 | 
			
		||||
            w = Math.round(w);
 | 
			
		||||
            h = Math.round(h);
 | 
			
		||||
            let rect = new Meta.Rectangle({ x: x, y: y, width: w, height: h});
 | 
			
		||||
 | 
			
		||||
            if (actorData.affectsInputRegion &&
 | 
			
		||||
                actorData.actor.get_paint_visibility() &&
 | 
			
		||||
                !Main.uiGroup.get_skip_paint(actorData.actor))
 | 
			
		||||
                rects.push(rect);
 | 
			
		||||
 | 
			
		||||
            if (!actorData.affectsStruts)
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            // Limit struts to the size of the screen
 | 
			
		||||
            let x1 = Math.max(x, 0);
 | 
			
		||||
            let x2 = Math.min(x + w, global.screen_width);
 | 
			
		||||
            let y1 = Math.max(y, 0);
 | 
			
		||||
            let y2 = Math.min(y + h, global.screen_height);
 | 
			
		||||
 | 
			
		||||
            // NetWM struts are not really powerful enought to handle
 | 
			
		||||
            // a multi-monitor scenario, they only describe what happens
 | 
			
		||||
            // around the outer sides of the full display region. However
 | 
			
		||||
            // it can describe a partial region along each side, so
 | 
			
		||||
            // we can support having the struts only affect the
 | 
			
		||||
            // primary monitor. This should be enough as we only have
 | 
			
		||||
            // chrome affecting the struts on the primary monitor so
 | 
			
		||||
            // far.
 | 
			
		||||
            //
 | 
			
		||||
            // Metacity wants to know what side of the screen the
 | 
			
		||||
            // strut is considered to be attached to. If the actor is
 | 
			
		||||
            // only touching one edge, or is touching the entire
 | 
			
		||||
            // border of the primary monitor, then it's obvious which
 | 
			
		||||
            // side to call it. If it's in a corner, we pick a side
 | 
			
		||||
            // arbitrarily. If it doesn't touch any edges, or it spans
 | 
			
		||||
            // the width/height across the middle of the screen, then
 | 
			
		||||
            // we don't create a strut for it at all.
 | 
			
		||||
            let side;
 | 
			
		||||
            let primary = this._primaryMonitor;
 | 
			
		||||
            if (x1 <= primary.x && x2 >= primary.x + primary.width) {
 | 
			
		||||
                if (y1 <= primary.y)
 | 
			
		||||
                    side = Meta.Side.TOP;
 | 
			
		||||
                else if (y2 >= primary.y + primary.height)
 | 
			
		||||
                    side = Meta.Side.BOTTOM;
 | 
			
		||||
                else
 | 
			
		||||
                    continue;
 | 
			
		||||
            } else if (y1 <= primary.y && y2 >= primary.y + primary.height) {
 | 
			
		||||
                if (x1 <= 0)
 | 
			
		||||
                    side = Meta.Side.LEFT;
 | 
			
		||||
                else if (x2 >= global.screen_width)
 | 
			
		||||
                    side = Meta.Side.RIGHT;
 | 
			
		||||
                else
 | 
			
		||||
                    continue;
 | 
			
		||||
            } else if (x1 <= 0)
 | 
			
		||||
                side = Meta.Side.LEFT;
 | 
			
		||||
            else if (y1 <= 0)
 | 
			
		||||
                side = Meta.Side.TOP;
 | 
			
		||||
            else if (x2 >= global.screen_width)
 | 
			
		||||
                side = Meta.Side.RIGHT;
 | 
			
		||||
            else if (y2 >= global.screen_height)
 | 
			
		||||
                side = Meta.Side.BOTTOM;
 | 
			
		||||
            else
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            // Ensure that the strut rects goes all the way to the screen edge,
 | 
			
		||||
            // as this really what mutter expects.
 | 
			
		||||
            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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        global.set_stage_input_region(rects);
 | 
			
		||||
 | 
			
		||||
        let screen = global.screen;
 | 
			
		||||
        for (let w = 0; w < screen.n_workspaces; w++) {
 | 
			
		||||
            let workspace = screen.get_workspace_by_index(w);
 | 
			
		||||
            workspace.set_builtin_struts(struts);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
@@ -31,9 +30,11 @@ const Tweener = imports.ui.tweener;
 | 
			
		||||
 * @container and will track any changes in its size. You can override
 | 
			
		||||
 * this by passing an explicit width and height in @params.
 | 
			
		||||
 */
 | 
			
		||||
const Lightbox = new Lang.Class({
 | 
			
		||||
    Name: 'Lightbox',
 | 
			
		||||
function Lightbox(container, params) {
 | 
			
		||||
    this._init(container, params);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Lightbox.prototype = {
 | 
			
		||||
    _init : function(container, params) {
 | 
			
		||||
        params = Params.parse(params, { inhibitEvents: false,
 | 
			
		||||
                                        width: null,
 | 
			
		||||
@@ -58,10 +59,11 @@ const Lightbox = new Lang.Class({
 | 
			
		||||
        if (params.width && params.height) {
 | 
			
		||||
            this.actor.width = params.width;
 | 
			
		||||
            this.actor.height = params.height;
 | 
			
		||||
            this._allocationChangedSignalId = 0;
 | 
			
		||||
        } else {
 | 
			
		||||
            let constraint = new Clutter.BindConstraint({ source: container,
 | 
			
		||||
                                                          coordinate: Clutter.BindCoordinate.ALL });
 | 
			
		||||
            this.actor.add_constraint(constraint);
 | 
			
		||||
            this.actor.width = container.width;
 | 
			
		||||
            this.actor.height = container.height;
 | 
			
		||||
            this._allocationChangedSignalId = container.connect('allocation-changed', Lang.bind(this, this._allocationChanged));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._actorAddedSignalId = container.connect('actor-added', Lang.bind(this, this._actorAdded));
 | 
			
		||||
@@ -70,6 +72,16 @@ const Lightbox = new Lang.Class({
 | 
			
		||||
        this._highlighted = null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _allocationChanged : function(container, box, flags) {
 | 
			
		||||
        Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
 | 
			
		||||
            this.actor.width = this.width;
 | 
			
		||||
            this.actor.height = this.height;
 | 
			
		||||
            return false;
 | 
			
		||||
        }));
 | 
			
		||||
        this.width = this._container.width;
 | 
			
		||||
        this.height = this._container.height;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _actorAdded : function(container, newChild) {
 | 
			
		||||
        let children = this._container.get_children();
 | 
			
		||||
        let myIndex = children.indexOf(this.actor);
 | 
			
		||||
@@ -177,9 +189,11 @@ const Lightbox = new Lang.Class({
 | 
			
		||||
     * by destroying its container or by explicitly calling this.destroy().
 | 
			
		||||
     */
 | 
			
		||||
    _onDestroy: function() {
 | 
			
		||||
        if (this._allocationChangedSignalId != 0)
 | 
			
		||||
            this._container.disconnect(this._allocationChangedSignalId);
 | 
			
		||||
        this._container.disconnect(this._actorAddedSignalId);
 | 
			
		||||
        this._container.disconnect(this._actorRemovedSignalId);
 | 
			
		||||
 | 
			
		||||
        this.highlight(null);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||