Compare commits
	
		
			448 Commits
		
	
	
		
			3.1.91.1
			...
			wip/menus-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					94d01bed12 | ||
| 
						 | 
					9daf358122 | ||
| 
						 | 
					b4b3f5a669 | ||
| 
						 | 
					5290a9dd08 | ||
| 
						 | 
					ab4a7c5237 | ||
| 
						 | 
					95e5c5cfb1 | ||
| 
						 | 
					757fb5796e | ||
| 
						 | 
					75e9fa9cfb | ||
| 
						 | 
					8997aa45b1 | ||
| 
						 | 
					f884dbbfb2 | ||
| 
						 | 
					d0c36bb732 | ||
| 
						 | 
					17c46c2452 | ||
| 
						 | 
					0996174b3d | ||
| 
						 | 
					d6b6f814d3 | ||
| 
						 | 
					987099ea55 | ||
| 
						 | 
					b356aa8e3b | ||
| 
						 | 
					566bdb50c2 | ||
| 
						 | 
					2b57603271 | ||
| 
						 | 
					c3528f5b6b | ||
| 
						 | 
					4c7cc94cdc | ||
| 
						 | 
					5ff2285707 | ||
| 
						 | 
					d714dfd82e | ||
| 
						 | 
					b1064cbe50 | ||
| 
						 | 
					8d3e5ea507 | ||
| 
						 | 
					001b6afc7e | ||
| 
						 | 
					55d6c5ea8f | ||
| 
						 | 
					fa2ff8158f | ||
| 
						 | 
					97e7ea0b5d | ||
| 
						 | 
					65dec2b72a | ||
| 
						 | 
					5fd3ca8d09 | ||
| 
						 | 
					dc9a8d505d | ||
| 
						 | 
					fc8d13f4bd | ||
| 
						 | 
					d1aa7de5d0 | ||
| 
						 | 
					e279ef1c7c | ||
| 
						 | 
					b88657ab83 | ||
| 
						 | 
					d20e646ed6 | ||
| 
						 | 
					8678b87120 | ||
| 
						 | 
					960571a589 | ||
| 
						 | 
					d856338f86 | ||
| 
						 | 
					2b6b2d93a9 | ||
| 
						 | 
					363bd04166 | ||
| 
						 | 
					9bc1a68fe4 | ||
| 
						 | 
					2c2729f7be | ||
| 
						 | 
					9011959356 | ||
| 
						 | 
					c79b8bbe7e | ||
| 
						 | 
					da59eebf8e | ||
| 
						 | 
					7854024326 | ||
| 
						 | 
					a9ab8784c4 | ||
| 
						 | 
					de5b00fd52 | ||
| 
						 | 
					6547f75b12 | ||
| 
						 | 
					827bf506a7 | ||
| 
						 | 
					adc187c32e | ||
| 
						 | 
					5350302b09 | ||
| 
						 | 
					167ca75388 | ||
| 
						 | 
					46cea67258 | ||
| 
						 | 
					463e0919d4 | ||
| 
						 | 
					98906c1da3 | ||
| 
						 | 
					b71e66c335 | ||
| 
						 | 
					2b6c5bb416 | ||
| 
						 | 
					628e59894b | ||
| 
						 | 
					703d2ead33 | ||
| 
						 | 
					43f53a708f | ||
| 
						 | 
					07e7331e7b | ||
| 
						 | 
					c516af3130 | ||
| 
						 | 
					39727d1156 | ||
| 
						 | 
					85cd189a69 | ||
| 
						 | 
					a8e35422f2 | ||
| 
						 | 
					3941961f8b | ||
| 
						 | 
					d9c6485cbf | ||
| 
						 | 
					c52ccc76a3 | ||
| 
						 | 
					be1c4f26b5 | ||
| 
						 | 
					a6ee6739e0 | ||
| 
						 | 
					54a8ad8bc6 | ||
| 
						 | 
					2541bfcdf2 | ||
| 
						 | 
					d7d5da0301 | ||
| 
						 | 
					d2bd9efc25 | ||
| 
						 | 
					779b18bf48 | ||
| 
						 | 
					618a53b34f | ||
| 
						 | 
					f4eaadb948 | ||
| 
						 | 
					ea061b0f46 | ||
| 
						 | 
					3652e42699 | ||
| 
						 | 
					398489f661 | ||
| 
						 | 
					70fc13500d | ||
| 
						 | 
					18541c447e | ||
| 
						 | 
					3294a6e1a7 | ||
| 
						 | 
					38563c38e8 | ||
| 
						 | 
					a465c5f996 | ||
| 
						 | 
					1760ba1279 | ||
| 
						 | 
					3d3c9546a2 | ||
| 
						 | 
					203c5db5eb | ||
| 
						 | 
					cf44234323 | ||
| 
						 | 
					cc94076ffb | ||
| 
						 | 
					8d137eae5b | ||
| 
						 | 
					51fa9ae513 | ||
| 
						 | 
					9951c92459 | ||
| 
						 | 
					ee77e5d582 | ||
| 
						 | 
					d74721f229 | ||
| 
						 | 
					1aa97b19f7 | ||
| 
						 | 
					95de48e986 | ||
| 
						 | 
					a147d0428d | ||
| 
						 | 
					90b3f7b7f6 | ||
| 
						 | 
					c80acfda08 | ||
| 
						 | 
					8a39145e3c | ||
| 
						 | 
					b62f5ef07d | ||
| 
						 | 
					bd5c6c5cd6 | ||
| 
						 | 
					f874a57439 | ||
| 
						 | 
					6a4525e554 | ||
| 
						 | 
					d553a5bdc0 | ||
| 
						 | 
					80076965a7 | ||
| 
						 | 
					84e8d38d4c | ||
| 
						 | 
					33f3f9d997 | ||
| 
						 | 
					be72b1d066 | ||
| 
						 | 
					dc5d2b83ef | ||
| 
						 | 
					3dabe645c2 | ||
| 
						 | 
					e9ede362dc | ||
| 
						 | 
					01357aca35 | ||
| 
						 | 
					c944dd6768 | ||
| 
						 | 
					ff01ed5e4b | ||
| 
						 | 
					d23c374326 | ||
| 
						 | 
					a69ebc8a68 | ||
| 
						 | 
					f4d8a35b9d | ||
| 
						 | 
					2b140f8fb7 | ||
| 
						 | 
					ab603bdbbf | ||
| 
						 | 
					44e2f7f555 | ||
| 
						 | 
					fd1b3b4fee | ||
| 
						 | 
					4ae2a0b2a5 | ||
| 
						 | 
					0cb415b3bd | ||
| 
						 | 
					c1fa9a82e6 | ||
| 
						 | 
					dde124ab5a | ||
| 
						 | 
					668920cec4 | ||
| 
						 | 
					9b38c5b304 | ||
| 
						 | 
					e63c2da433 | ||
| 
						 | 
					38c768fdb3 | ||
| 
						 | 
					0dd4584157 | ||
| 
						 | 
					b7bf712b97 | ||
| 
						 | 
					615723d8df | ||
| 
						 | 
					de352a309d | ||
| 
						 | 
					c573e7f9a1 | ||
| 
						 | 
					d59fd1a75d | ||
| 
						 | 
					18d69d7032 | ||
| 
						 | 
					5d25716cee | ||
| 
						 | 
					840e79c18c | ||
| 
						 | 
					ddf562e306 | ||
| 
						 | 
					20a6ce7003 | ||
| 
						 | 
					8c43298af0 | ||
| 
						 | 
					4bb48e56d2 | ||
| 
						 | 
					338ba10ca2 | ||
| 
						 | 
					36eb745ecc | ||
| 
						 | 
					b07e45e214 | ||
| 
						 | 
					bba5198e63 | ||
| 
						 | 
					9e2bab008a | ||
| 
						 | 
					5ea032bbf7 | ||
| 
						 | 
					897fadfb40 | ||
| 
						 | 
					b05f71eb9b | ||
| 
						 | 
					4ce0e80956 | ||
| 
						 | 
					577ccc4d56 | ||
| 
						 | 
					39d12351ba | ||
| 
						 | 
					e37bc6d7f0 | ||
| 
						 | 
					9593ff3582 | ||
| 
						 | 
					ad8dfd7b04 | ||
| 
						 | 
					ca5ab20f67 | ||
| 
						 | 
					0eab448221 | ||
| 
						 | 
					a26a77f9db | ||
| 
						 | 
					c3df6bb8bd | ||
| 
						 | 
					ce3a26cf37 | ||
| 
						 | 
					04482c23c4 | ||
| 
						 | 
					ff20fe856e | ||
| 
						 | 
					12e3921f81 | ||
| 
						 | 
					928fbee15b | ||
| 
						 | 
					a103c028f9 | ||
| 
						 | 
					775347d865 | ||
| 
						 | 
					6d0be86a4e | ||
| 
						 | 
					a4b69db8af | ||
| 
						 | 
					790b9d3371 | ||
| 
						 | 
					adef2009a5 | ||
| 
						 | 
					1721db6d8d | ||
| 
						 | 
					6d95e8b988 | ||
| 
						 | 
					b07f9932db | ||
| 
						 | 
					9439da81c4 | ||
| 
						 | 
					6257e64d03 | ||
| 
						 | 
					ba110f2d2e | ||
| 
						 | 
					6bdf621d05 | ||
| 
						 | 
					1c4db98c95 | ||
| 
						 | 
					dadac957e4 | ||
| 
						 | 
					cf3976d496 | ||
| 
						 | 
					82ed80c9c3 | ||
| 
						 | 
					67222525ad | ||
| 
						 | 
					fff0861773 | ||
| 
						 | 
					13ffe41498 | ||
| 
						 | 
					96e0528a7b | ||
| 
						 | 
					3df30fbd57 | ||
| 
						 | 
					b57d8b336b | ||
| 
						 | 
					3169b2c440 | ||
| 
						 | 
					6bc34e0f32 | ||
| 
						 | 
					cecb1a41fb | ||
| 
						 | 
					b9069df85c | ||
| 
						 | 
					aee3c6f041 | ||
| 
						 | 
					c427bba9f1 | ||
| 
						 | 
					da83ad561b | ||
| 
						 | 
					85520e34ab | ||
| 
						 | 
					d0edd970e1 | ||
| 
						 | 
					8529ca70af | ||
| 
						 | 
					1a8d78212f | ||
| 
						 | 
					4270a2806d | ||
| 
						 | 
					4333bdc709 | ||
| 
						 | 
					75b824d032 | ||
| 
						 | 
					7bc2573d85 | ||
| 
						 | 
					67b7b7a950 | ||
| 
						 | 
					786cfbd397 | ||
| 
						 | 
					9df8b583cf | ||
| 
						 | 
					8e32290dc9 | ||
| 
						 | 
					23478f3336 | ||
| 
						 | 
					2e244ecb63 | ||
| 
						 | 
					e307680206 | ||
| 
						 | 
					6bb1a3e2c4 | ||
| 
						 | 
					8a1ac6b13f | ||
| 
						 | 
					61b8af2252 | ||
| 
						 | 
					c99afed012 | ||
| 
						 | 
					2947b92148 | ||
| 
						 | 
					39c5d23a87 | ||
| 
						 | 
					d839670f54 | ||
| 
						 | 
					0d1b7e15d1 | ||
| 
						 | 
					ac678f63ee | ||
| 
						 | 
					d862c0879b | ||
| 
						 | 
					23a4d4c69e | ||
| 
						 | 
					472b20d933 | ||
| 
						 | 
					492dd718fb | ||
| 
						 | 
					0d5618fdd1 | ||
| 
						 | 
					503508af41 | ||
| 
						 | 
					4ec5e55122 | ||
| 
						 | 
					8daca865ca | ||
| 
						 | 
					f9b37a21e8 | ||
| 
						 | 
					c398f319fc | ||
| 
						 | 
					1e049f88b8 | ||
| 
						 | 
					4831d9c3a3 | ||
| 
						 | 
					f13f5bc1bb | ||
| 
						 | 
					4e114107ed | ||
| 
						 | 
					0ccb280008 | ||
| 
						 | 
					28c3e0693e | ||
| 
						 | 
					c321c8a02f | ||
| 
						 | 
					2407ec7b47 | ||
| 
						 | 
					70eeb75716 | ||
| 
						 | 
					751d250471 | ||
| 
						 | 
					c28217db80 | ||
| 
						 | 
					0968e556fa | ||
| 
						 | 
					130f2cf808 | ||
| 
						 | 
					4eec7413c7 | ||
| 
						 | 
					efc3246d26 | ||
| 
						 | 
					9930dbc0ff | ||
| 
						 | 
					754f87dac3 | ||
| 
						 | 
					51139bd096 | ||
| 
						 | 
					6e0119d620 | ||
| 
						 | 
					a3528bf973 | ||
| 
						 | 
					77c36af588 | ||
| 
						 | 
					69c0a52a33 | ||
| 
						 | 
					a7442cd0a5 | ||
| 
						 | 
					d47a013931 | ||
| 
						 | 
					745f9c0e6e | ||
| 
						 | 
					414f49fd80 | ||
| 
						 | 
					e49a595f54 | ||
| 
						 | 
					77485c2a04 | ||
| 
						 | 
					e9b28634e5 | ||
| 
						 | 
					b43dcb8876 | ||
| 
						 | 
					f0c1eeece8 | ||
| 
						 | 
					1e6b824ede | ||
| 
						 | 
					1e2d16273c | ||
| 
						 | 
					32dc24c59b | ||
| 
						 | 
					7a8a189c48 | ||
| 
						 | 
					6aa411fecc | ||
| 
						 | 
					9c76318df8 | ||
| 
						 | 
					6510904711 | ||
| 
						 | 
					a9817f4832 | ||
| 
						 | 
					9067689839 | ||
| 
						 | 
					4e9e91fdce | ||
| 
						 | 
					73cc91ba60 | ||
| 
						 | 
					0ab0d0860f | ||
| 
						 | 
					337b399a75 | ||
| 
						 | 
					46f21e81e3 | ||
| 
						 | 
					c1300ddbbc | ||
| 
						 | 
					8bd5b1e696 | ||
| 
						 | 
					40c5db397d | ||
| 
						 | 
					8b52919b4d | ||
| 
						 | 
					2859f23038 | ||
| 
						 | 
					00384ccb47 | ||
| 
						 | 
					0191cc589a | ||
| 
						 | 
					dae6db9b51 | ||
| 
						 | 
					4d912c9feb | ||
| 
						 | 
					07c4b46466 | ||
| 
						 | 
					e9cdce49a3 | ||
| 
						 | 
					84c3ce8778 | ||
| 
						 | 
					d5a32a7fe4 | ||
| 
						 | 
					cc4dfda21b | ||
| 
						 | 
					703b37aa7b | ||
| 
						 | 
					b433de9022 | ||
| 
						 | 
					0c1a22ff95 | ||
| 
						 | 
					4d526e40c3 | ||
| 
						 | 
					4586c7b36b | ||
| 
						 | 
					3d60b73b60 | ||
| 
						 | 
					4ef5cd8ef6 | ||
| 
						 | 
					6959bd19f1 | ||
| 
						 | 
					17e4ce5ea8 | ||
| 
						 | 
					33094b4988 | ||
| 
						 | 
					a8fdcffd44 | ||
| 
						 | 
					5adb5411fa | ||
| 
						 | 
					ff0d11c89c | ||
| 
						 | 
					5f6dce2b5c | ||
| 
						 | 
					a7405e8b39 | ||
| 
						 | 
					d87c520bad | ||
| 
						 | 
					24959f8d34 | ||
| 
						 | 
					6d1432e166 | ||
| 
						 | 
					2c7ba2c125 | ||
| 
						 | 
					a0ba664c64 | ||
| 
						 | 
					131da5f523 | ||
| 
						 | 
					7c6144450a | ||
| 
						 | 
					4c7369db16 | ||
| 
						 | 
					f4355de896 | ||
| 
						 | 
					4a3db9f44d | ||
| 
						 | 
					6c0a9ff9cc | ||
| 
						 | 
					57b1695fcf | ||
| 
						 | 
					045c6546cc | ||
| 
						 | 
					ce5bd954bf | ||
| 
						 | 
					6ef00a4a3b | ||
| 
						 | 
					569d9718a0 | ||
| 
						 | 
					00a3a8697f | ||
| 
						 | 
					c93444e390 | ||
| 
						 | 
					5e5788ab14 | ||
| 
						 | 
					abf57e6362 | ||
| 
						 | 
					74c2074d5a | ||
| 
						 | 
					b74606312e | ||
| 
						 | 
					0c849df4d5 | ||
| 
						 | 
					38690d4a09 | ||
| 
						 | 
					b64c237cb3 | ||
| 
						 | 
					3fbee8e027 | ||
| 
						 | 
					a68e6e3c63 | ||
| 
						 | 
					db5a72774d | ||
| 
						 | 
					966f90f24a | ||
| 
						 | 
					eaa664c023 | ||
| 
						 | 
					e9282c3987 | ||
| 
						 | 
					ed1f8ed339 | ||
| 
						 | 
					5d0d637eb8 | ||
| 
						 | 
					7e70dfdf4c | ||
| 
						 | 
					3f61f39ae3 | ||
| 
						 | 
					371f623a3e | ||
| 
						 | 
					566d566f26 | ||
| 
						 | 
					fb30822860 | ||
| 
						 | 
					526a53bdd4 | ||
| 
						 | 
					3833124d66 | ||
| 
						 | 
					e5e1b52abf | ||
| 
						 | 
					82fc66305d | ||
| 
						 | 
					05e0d5066f | ||
| 
						 | 
					ce2dc84e49 | ||
| 
						 | 
					eb14ed32ea | ||
| 
						 | 
					f97987d0d8 | ||
| 
						 | 
					d23d9c3b05 | ||
| 
						 | 
					3ebf6e3bea | ||
| 
						 | 
					9f41f5c740 | ||
| 
						 | 
					ae00f86887 | ||
| 
						 | 
					ab67c0f8b0 | ||
| 
						 | 
					ed7d4928e5 | ||
| 
						 | 
					f23239a923 | ||
| 
						 | 
					d949920e68 | ||
| 
						 | 
					a1def85c18 | ||
| 
						 | 
					dc624f65e4 | ||
| 
						 | 
					361652d028 | ||
| 
						 | 
					92024b7e54 | ||
| 
						 | 
					4e4ce0dd21 | ||
| 
						 | 
					bc0c490ec3 | ||
| 
						 | 
					6d92af17fd | ||
| 
						 | 
					2140a498a2 | ||
| 
						 | 
					28349d362c | ||
| 
						 | 
					e7af9f98e3 | ||
| 
						 | 
					dd6053c5e1 | ||
| 
						 | 
					37726a4cb6 | ||
| 
						 | 
					4352cc231e | ||
| 
						 | 
					824220356f | ||
| 
						 | 
					247ad9d7ab | ||
| 
						 | 
					09fe12d0c1 | ||
| 
						 | 
					127ef8383b | ||
| 
						 | 
					82eccb566c | ||
| 
						 | 
					543b29efe7 | ||
| 
						 | 
					0f4ce5dd4e | ||
| 
						 | 
					c23919df15 | ||
| 
						 | 
					2b2a8b4747 | ||
| 
						 | 
					2e48dbf6ee | ||
| 
						 | 
					207917ba45 | ||
| 
						 | 
					f824b97f3a | ||
| 
						 | 
					a5ff2fc68f | ||
| 
						 | 
					4906806c0b | ||
| 
						 | 
					d98336a906 | ||
| 
						 | 
					9ddd11cdb8 | ||
| 
						 | 
					554ad4ef05 | ||
| 
						 | 
					45d8550044 | ||
| 
						 | 
					f2b44c1494 | ||
| 
						 | 
					bdb28e87a9 | ||
| 
						 | 
					8b9592e53e | ||
| 
						 | 
					84f89648a6 | ||
| 
						 | 
					1174992099 | ||
| 
						 | 
					391a220dc1 | ||
| 
						 | 
					43f1d0578b | ||
| 
						 | 
					d3e35028ca | ||
| 
						 | 
					61c7d87003 | ||
| 
						 | 
					20f2fa84a4 | ||
| 
						 | 
					17e269b96c | ||
| 
						 | 
					6a57ac92ba | ||
| 
						 | 
					07ad03556f | ||
| 
						 | 
					04c33230c8 | ||
| 
						 | 
					083dac630f | ||
| 
						 | 
					6375724196 | ||
| 
						 | 
					922957c1ae | ||
| 
						 | 
					cbf7d0e738 | ||
| 
						 | 
					fb81efeecf | ||
| 
						 | 
					8466198626 | ||
| 
						 | 
					33718ef7a5 | ||
| 
						 | 
					a94a62764d | ||
| 
						 | 
					12c98df3db | ||
| 
						 | 
					81909a406f | ||
| 
						 | 
					d291aaa4f2 | ||
| 
						 | 
					da36d87e46 | ||
| 
						 | 
					42bc09a7ef | ||
| 
						 | 
					d0defc592e | ||
| 
						 | 
					700f7fbaf3 | ||
| 
						 | 
					74f2d02ac3 | ||
| 
						 | 
					c865d96f4b | ||
| 
						 | 
					cd7b9e108c | ||
| 
						 | 
					f54b82f64c | ||
| 
						 | 
					36bfe8c533 | ||
| 
						 | 
					a40d063cb8 | ||
| 
						 | 
					ac88a88bfb | ||
| 
						 | 
					d89c9b4556 | ||
| 
						 | 
					a07056f5e2 | ||
| 
						 | 
					f91bea3ea5 | ||
| 
						 | 
					9fbd79316a | ||
| 
						 | 
					6d89d0b02a | ||
| 
						 | 
					0febcbfa2a | ||
| 
						 | 
					f2f2898fe3 | ||
| 
						 | 
					f65826b3ba | ||
| 
						 | 
					a869007180 | ||
| 
						 | 
					b5fa48f485 | ||
| 
						 | 
					36d564526c | ||
| 
						 | 
					063f34b5d3 | ||
| 
						 | 
					9486ca5975 | ||
| 
						 | 
					63ead272a9 | ||
| 
						 | 
					9dfa2ad84e | ||
| 
						 | 
					523e431ece | ||
| 
						 | 
					768c4a0dd5 | ||
| 
						 | 
					fd25cf30ff | ||
| 
						 | 
					1d14488a4f | ||
| 
						 | 
					6e32c97c43 | 
							
								
								
									
										13
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -21,6 +21,19 @@ data/gnome-shell.desktop.in
 | 
			
		||||
data/gschemas.compiled
 | 
			
		||||
data/org.gnome.shell.gschema.xml
 | 
			
		||||
data/org.gnome.shell.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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
SUBDIRS = data js src browser-plugin tests po man docs
 | 
			
		||||
 | 
			
		||||
EXTRA_DIST =		\
 | 
			
		||||
	.project	\
 | 
			
		||||
@@ -19,3 +19,5 @@ 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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										222
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										222
									
								
								NEWS
									
									
									
									
									
								
							@@ -1,3 +1,225 @@
 | 
			
		||||
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 [cz], 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
 | 
			
		||||
========
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
 | 
			
		||||
mozillalibdir = $(libdir)/mozilla/plugins
 | 
			
		||||
mozillalibdir = $(BROWSER_PLUGIN_DIR)
 | 
			
		||||
 | 
			
		||||
mozillalib_LTLIBRARIES = libgnome-shell-browser-plugin.la
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -47,8 +47,6 @@ typedef struct {
 | 
			
		||||
  GDBusProxy *proxy;
 | 
			
		||||
} PluginData;
 | 
			
		||||
 | 
			
		||||
/* =============== public entry points =================== */
 | 
			
		||||
 | 
			
		||||
static NPNetscapeFuncs funcs;
 | 
			
		||||
 | 
			
		||||
static inline gchar *
 | 
			
		||||
@@ -71,10 +69,7 @@ get_string_property (NPP         instance,
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  result_str = NPVARIANT_TO_STRING (result);
 | 
			
		||||
  if (strlen (result_str.UTF8Characters) != result_str.UTF8Length)
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  result_copy = g_strdup (result_str.UTF8Characters);
 | 
			
		||||
  result_copy = g_strndup (result_str.UTF8Characters, result_str.UTF8Length);
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  funcs.releasevariantvalue (&result);
 | 
			
		||||
@@ -150,6 +145,8 @@ check_origin_and_protocol (NPP instance)
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* =============== public entry points =================== */
 | 
			
		||||
 | 
			
		||||
NPError
 | 
			
		||||
NP_Initialize(NPNetscapeFuncs *pfuncs, NPPluginFuncs *plugin)
 | 
			
		||||
{
 | 
			
		||||
@@ -816,6 +813,11 @@ NPP_GetValue(NPP          instance,
 | 
			
		||||
 | 
			
		||||
    *(NPObject**)value = funcs.createobject (instance, &plugin_class);
 | 
			
		||||
    break;
 | 
			
		||||
 | 
			
		||||
  case NPPVpluginNeedsXEmbed:
 | 
			
		||||
    *(bool *)value = TRUE;
 | 
			
		||||
    break;
 | 
			
		||||
 | 
			
		||||
  default:
 | 
			
		||||
    ;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										35
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								configure.ac
									
									
									
									
									
								
							@@ -1,5 +1,5 @@
 | 
			
		||||
AC_PREREQ(2.63)
 | 
			
		||||
AC_INIT([gnome-shell],[3.1.91.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
 | 
			
		||||
AC_INIT([gnome-shell],[3.3.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,7 +9,7 @@ AC_CONFIG_AUX_DIR([config])
 | 
			
		||||
AC_SUBST([PACKAGE_NAME], ["$PACKAGE_NAME"])
 | 
			
		||||
AC_SUBST([PACKAGE_VERSION], ["$PACKAGE_VERSION"])
 | 
			
		||||
 | 
			
		||||
AM_INIT_AUTOMAKE([1.10 dist-xz no-dist-gzip foreign])
 | 
			
		||||
AM_INIT_AUTOMAKE([1.11 no-dist-gzip dist-xz tar-ustar foreign])
 | 
			
		||||
AM_MAINTAINER_MODE([enable])
 | 
			
		||||
 | 
			
		||||
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
 | 
			
		||||
@@ -36,10 +36,6 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
@@ -66,11 +62,11 @@ AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
 | 
			
		||||
 | 
			
		||||
CLUTTER_MIN_VERSION=1.7.5
 | 
			
		||||
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
 | 
			
		||||
GJS_MIN_VERSION=1.29.15
 | 
			
		||||
MUTTER_MIN_VERSION=3.0.0
 | 
			
		||||
GJS_MIN_VERSION=1.29.18
 | 
			
		||||
MUTTER_MIN_VERSION=3.3.2
 | 
			
		||||
FOLKS_MIN_VERSION=0.5.2
 | 
			
		||||
GTK_MIN_VERSION=3.0.0
 | 
			
		||||
GIO_MIN_VERSION=2.29.10
 | 
			
		||||
GIO_MIN_VERSION=2.31.0
 | 
			
		||||
LIBECAL_MIN_VERSION=2.32.0
 | 
			
		||||
LIBEDATASERVER_MIN_VERSION=1.2.0
 | 
			
		||||
LIBEDATASERVERUI_MIN_VERSION=2.91.6
 | 
			
		||||
@@ -80,13 +76,13 @@ POLKIT_MIN_VERSION=0.100
 | 
			
		||||
STARTUP_NOTIFICATION_MIN_VERSION=0.11
 | 
			
		||||
 | 
			
		||||
# Collect more than 20 libraries for a prize!
 | 
			
		||||
PKG_CHECK_MODULES(GNOME_SHELL, gio-2.0 >= $GIO_MIN_VERSION
 | 
			
		||||
                               gio-unix-2.0 dbus-glib-1 libxml-2.0
 | 
			
		||||
PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION
 | 
			
		||||
			       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 gconf-2.0
 | 
			
		||||
			       libgnome-menu-3.0 $recorder_modules
 | 
			
		||||
                               gdk-x11-3.0 libsoup-2.4
 | 
			
		||||
			       clutter-x11-1.0 >= $CLUTTER_MIN_VERSION
 | 
			
		||||
			       clutter-glx-1.0 >= $CLUTTER_MIN_VERSION
 | 
			
		||||
@@ -121,7 +117,6 @@ CFLAGS=$saved_CFLAGS
 | 
			
		||||
LIBS=$saved_LIBS
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.2 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 >= 0.1.7)
 | 
			
		||||
@@ -131,6 +126,7 @@ 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`
 | 
			
		||||
	 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])
 | 
			
		||||
@@ -179,11 +175,13 @@ 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,
 | 
			
		||||
  AS_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],[Turn on compiler warnings]),,
 | 
			
		||||
  enable_compile_warnings=error)
 | 
			
		||||
  enable_compile_warnings=maximum)
 | 
			
		||||
 | 
			
		||||
changequote(,)dnl
 | 
			
		||||
if test "$enable_compile_warnings" != no ; then
 | 
			
		||||
@@ -235,9 +233,18 @@ else
 | 
			
		||||
fi
 | 
			
		||||
AC_SUBST(SHELL_SYSTEM_CA_FILE,["$with_ca_certificates"])
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 
 | 
			
		||||
@@ -60,23 +60,14 @@ gschemas.compiled: $(gsettings_SCHEMAS:.xml=.valid)
 | 
			
		||||
all-local: gschemas.compiled
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# 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			\
 | 
			
		||||
	$(menu_DATA)					\
 | 
			
		||||
	$(gconfschema_DATA)				\
 | 
			
		||||
	$(shaders_DATA)					\
 | 
			
		||||
	org.gnome.shell.gschema.xml.in
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,100 +0,0 @@
 | 
			
		||||
<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>
 | 
			
		||||
@@ -16,8 +16,9 @@
 | 
			
		||||
      <_summary>Uuids of extensions to enable</_summary>
 | 
			
		||||
      <_description>
 | 
			
		||||
        GNOME Shell extensions have a uuid property; this key lists extensions
 | 
			
		||||
        which should be loaded.  disabled-extensions overrides this setting for
 | 
			
		||||
        extensions that appear in both lists.
 | 
			
		||||
        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.
 | 
			
		||||
      </_description>
 | 
			
		||||
    </key>
 | 
			
		||||
    <key name="enable-app-monitoring" type="b">
 | 
			
		||||
@@ -50,6 +51,14 @@
 | 
			
		||||
      <default>[]</default>
 | 
			
		||||
      <_summary>History for the looking glass dialog</_summary>
 | 
			
		||||
    </key>
 | 
			
		||||
    <key name="saved-im-presence" type="i">
 | 
			
		||||
      <default>1</default>
 | 
			
		||||
      <_summary></_summary>
 | 
			
		||||
    </key>
 | 
			
		||||
    <key name="saved-session-presence" type="i">
 | 
			
		||||
      <default>0</default>
 | 
			
		||||
      <_summary></_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"/>
 | 
			
		||||
@@ -69,13 +78,6 @@
 | 
			
		||||
 | 
			
		||||
  <schema id="org.gnome.shell.keyboard" path="/org/gnome/shell/keyboard/"
 | 
			
		||||
          gettext-domain="@GETTEXT_PACKAGE@">
 | 
			
		||||
    <key name="show-keyboard" type="b">
 | 
			
		||||
      <default>false</default>
 | 
			
		||||
      <_summary>Show the onscreen keyboard</_summary>
 | 
			
		||||
      <_description>
 | 
			
		||||
        If true, display onscreen keyboard.
 | 
			
		||||
      </_description>
 | 
			
		||||
    </key>
 | 
			
		||||
    <key name="keyboard-type" type="s">
 | 
			
		||||
      <default>'touch'</default>
 | 
			
		||||
      <_summary>Which keyboard to use</_summary>
 | 
			
		||||
@@ -140,4 +142,40 @@
 | 
			
		||||
      </_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="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 sampler0;
 | 
			
		||||
uniform sampler2D tex;
 | 
			
		||||
uniform float fraction;
 | 
			
		||||
uniform float height;
 | 
			
		||||
const float c = -0.2;
 | 
			
		||||
@@ -12,15 +12,16 @@ 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(sampler0, gl_TexCoord[0].st);
 | 
			
		||||
  float y = height * gl_TexCoord[0][1];
 | 
			
		||||
  vec4 color = texture2D(tex, cogl_tex_coord_in[0].xy);
 | 
			
		||||
  float y = height * cogl_tex_coord_in[0].y;
 | 
			
		||||
 | 
			
		||||
  // To reduce contrast, blend with a mid gray
 | 
			
		||||
  gl_FragColor = color * contrast - off * c;
 | 
			
		||||
  cogl_color_out = color * contrast - off * c * color.a;
 | 
			
		||||
 | 
			
		||||
  // We only fully dim at a distance of BORDER_MAX_HEIGHT from the edge and
 | 
			
		||||
  // We only fully dim at a distance of BORDER_MAX_HEIGHT from the top and
 | 
			
		||||
  // when the fraction is 1.0. For other locations and fractions we linearly
 | 
			
		||||
  // 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;
 | 
			
		||||
  // 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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,10 @@
 | 
			
		||||
    min-width: 350px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-prompt-fingerprint-message {
 | 
			
		||||
    font-size: 10.5pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-user-list-view {
 | 
			
		||||
    -st-vfade-offset: 1em;
 | 
			
		||||
}
 | 
			
		||||
@@ -94,8 +98,12 @@
 | 
			
		||||
    color: #666666;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-not-listed-button:hover .login-dialog-not-listed-label {
 | 
			
		||||
    color: white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-prompt-layout {
 | 
			
		||||
    padding-bottom: 64px;
 | 
			
		||||
    padding-bottom: 32px;
 | 
			
		||||
}
 | 
			
		||||
.login-dialog-prompt-label {
 | 
			
		||||
    color: white;
 | 
			
		||||
@@ -110,7 +118,17 @@
 | 
			
		||||
    background-color: white;
 | 
			
		||||
    caret-color: black;
 | 
			
		||||
    caret-size: 1px;
 | 
			
		||||
    width: 23em;
 | 
			
		||||
    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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -36,18 +36,18 @@ stage {
 | 
			
		||||
 | 
			
		||||
StScrollBar
 | 
			
		||||
{
 | 
			
		||||
  padding: 0px;
 | 
			
		||||
    padding: 0px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
StScrollView.vfade
 | 
			
		||||
{
 | 
			
		||||
  -st-vfade-offset: 68px;
 | 
			
		||||
    -st-vfade-offset: 68px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
StScrollView StScrollBar
 | 
			
		||||
{
 | 
			
		||||
  min-width: 16px;
 | 
			
		||||
  min-height: 16px;
 | 
			
		||||
    min-width: 16px;
 | 
			
		||||
    min-height: 16px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -164,6 +164,10 @@ StTooltip StLabel {
 | 
			
		||||
    background-color: #4c4c4c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.popup-menu-item:insensitive {
 | 
			
		||||
    color: #9f9f9f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.popup-image-menu-item {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -276,12 +280,12 @@ StTooltip StLabel {
 | 
			
		||||
    background-color: black;
 | 
			
		||||
    border-image: url("panel-border.svg") 1;
 | 
			
		||||
    font-size: 10.5pt;
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    height: 1.86em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#panelLeft, #panelCenter, #panelRight {
 | 
			
		||||
#panelLeft, #panelCenter {
 | 
			
		||||
    spacing: 4px;
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#panelLeft:ltr {
 | 
			
		||||
@@ -335,7 +339,8 @@ StTooltip StLabel {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.panel-button {
 | 
			
		||||
    padding: 0px 12px;
 | 
			
		||||
    -natural-hpadding: 12px;
 | 
			
		||||
    -minimum-hpadding: 6px;
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    color: #ccc;
 | 
			
		||||
    transition-duration: 100;
 | 
			
		||||
@@ -355,9 +360,9 @@ StTooltip StLabel {
 | 
			
		||||
    text-shadow: black 0px 2px 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#statusTray > .panel-button:active,
 | 
			
		||||
#statusTray > .panel-button:checked,
 | 
			
		||||
#statusTray > .panel-button:focus {
 | 
			
		||||
.panel-status-button:active,
 | 
			
		||||
.panel-status-button:checked,
 | 
			
		||||
.panel-status-button:focus {
 | 
			
		||||
    background-image: url("panel-button-highlight-narrow.svg");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -371,19 +376,7 @@ StTooltip StLabel {
 | 
			
		||||
    -boxpointer-gap: 4px
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* The rounded panel corners we draw don't
 | 
			
		||||
 * support transitions, so disable transitions
 | 
			
		||||
 * for the buttons at the left/right edges
 | 
			
		||||
 */
 | 
			
		||||
#panelActivities {
 | 
			
		||||
    transition-duration: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#panelStatus {
 | 
			
		||||
    transition-duration: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#panelStatusMenu {
 | 
			
		||||
#panelUserMenu {
 | 
			
		||||
    spacing: 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -410,6 +403,7 @@ StTooltip StLabel {
 | 
			
		||||
.status-chooser-user-name {
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    font-size: 1.3em;
 | 
			
		||||
    min-width: 120pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.status-chooser-combo {
 | 
			
		||||
@@ -426,24 +420,10 @@ StTooltip StLabel {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.status-chooser-status-item,
 | 
			
		||||
.status-chooser-combo > .popup-combobox-item {
 | 
			
		||||
.status-chooser-combo .popup-combobox-item {
 | 
			
		||||
    spacing: .4em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#legacyTray {
 | 
			
		||||
    spacing: 14px;
 | 
			
		||||
    padding-left: 14px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#legacyTray:rtl {
 | 
			
		||||
    padding-left: 0px;
 | 
			
		||||
    padding-right: 14px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#legacyTray:compact {
 | 
			
		||||
    spacing: 8px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.system-status-icon {
 | 
			
		||||
    icon-size: 1.14em;
 | 
			
		||||
}
 | 
			
		||||
@@ -529,10 +509,9 @@ StTooltip StLabel {
 | 
			
		||||
    width: 60px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dash-placeholder {
 | 
			
		||||
.placeholder {
 | 
			
		||||
    background-image: url("dash-placeholder.svg");
 | 
			
		||||
    height: 27px;
 | 
			
		||||
    width: 48px;
 | 
			
		||||
    height: 24px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#viewSelector {
 | 
			
		||||
@@ -764,24 +743,24 @@ StTooltip StLabel {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.contact-icon {
 | 
			
		||||
  border-radius: 4px;
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.contact-details {
 | 
			
		||||
  padding: 6px 8px 11px 8px;
 | 
			
		||||
    padding: 6px 8px 11px 8px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.contact-details-alias {
 | 
			
		||||
  font-size: 16px;
 | 
			
		||||
  padding-bottom: 11px;
 | 
			
		||||
    font-size: 16px;
 | 
			
		||||
    padding-bottom: 11px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.contact-details-status {
 | 
			
		||||
  font-size: 11pt;
 | 
			
		||||
    font-size: 11pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.contact-details-status-icon {
 | 
			
		||||
  padding-right: 2px;
 | 
			
		||||
    padding-right: 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.contact:hover {
 | 
			
		||||
@@ -822,37 +801,45 @@ StTooltip StLabel {
 | 
			
		||||
 | 
			
		||||
#LookingGlassDialog
 | 
			
		||||
{
 | 
			
		||||
  background-color: rgba(0,0,0,0.85);
 | 
			
		||||
  spacing: 4px;
 | 
			
		||||
  padding: 4px;
 | 
			
		||||
  border: 2px solid grey;
 | 
			
		||||
  border-radius: 4px;
 | 
			
		||||
    background-color: rgba(0,0,0,0.80);
 | 
			
		||||
    spacing: 4px;
 | 
			
		||||
    padding: 4px;
 | 
			
		||||
    border: 2px solid grey;
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
 | 
			
		||||
  color: #88ff66;
 | 
			
		||||
    color: #ffffff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#LookingGlassDialog > #Toolbar
 | 
			
		||||
{
 | 
			
		||||
  border: 1px solid grey;
 | 
			
		||||
  border-radius: 4px;
 | 
			
		||||
    border: 1px solid grey;
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#LookingGlassDialog .labels {
 | 
			
		||||
  spacing: 4px;
 | 
			
		||||
    spacing: 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#LookingGlassDialog .notebook-tab {
 | 
			
		||||
  padding: 2px;
 | 
			
		||||
    -natural-hpadding: 12px;
 | 
			
		||||
    -minimum-hpadding: 6px;
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    color: #ccc;
 | 
			
		||||
    transition-duration: 100;
 | 
			
		||||
    padding-left: .3em;
 | 
			
		||||
    padding-right: .3em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#LookingGlassDialog .notebook-tab:hover {
 | 
			
		||||
  color: #00ff00;
 | 
			
		||||
    color: white;
 | 
			
		||||
    text-shadow: black 0px 2px 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#LookingGlassDialog .notebook-tab:selected {
 | 
			
		||||
  border: 1px solid #88ff66;
 | 
			
		||||
  border-radius: 4px;
 | 
			
		||||
  padding: 5px;
 | 
			
		||||
    border-image: url("panel-button-border.svg") 10 10 0 2;
 | 
			
		||||
    background-image: url("panel-button-highlight-wide.svg");
 | 
			
		||||
    color: white;
 | 
			
		||||
    text-shadow: black 0px 2px 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#LookingGlassDialog .lg-inspector-title {
 | 
			
		||||
@@ -862,52 +849,58 @@ StTooltip StLabel {
 | 
			
		||||
 | 
			
		||||
.lg-dialog StLabel
 | 
			
		||||
{
 | 
			
		||||
  color: #88ff66;
 | 
			
		||||
    color: #ffffff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.lg-dialog StEntry
 | 
			
		||||
{
 | 
			
		||||
  color: #88ff66;
 | 
			
		||||
  selection-background-color: #88ff66;
 | 
			
		||||
  selected-color: black;
 | 
			
		||||
    color: #ffffff;
 | 
			
		||||
    selection-background-color: #bbbbbb;
 | 
			
		||||
    selected-color: #333333;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.lg-completions-text
 | 
			
		||||
{
 | 
			
		||||
    font-size: .9em;
 | 
			
		||||
    font-style: italic;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.lg-obj-inspector-title
 | 
			
		||||
{
 | 
			
		||||
  spacing: 4px;
 | 
			
		||||
    spacing: 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.lg-obj-inspector-button
 | 
			
		||||
{
 | 
			
		||||
  border: 1px solid #88ff66;
 | 
			
		||||
  padding: 4px;
 | 
			
		||||
  border-radius: 4px;
 | 
			
		||||
    border: 1px solid gray;
 | 
			
		||||
    padding: 4px;
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.lg-obj-inspector-button:hover
 | 
			
		||||
{
 | 
			
		||||
  border: 1px solid #00ff00;
 | 
			
		||||
    border: 1px solid #ffffff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.lg-dialog .shell-link
 | 
			
		||||
{
 | 
			
		||||
  color: #88ff66;
 | 
			
		||||
    color: #999999;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.lg-dialog .shell-link:hover
 | 
			
		||||
{
 | 
			
		||||
  color: #00ff00;
 | 
			
		||||
    color: #dddddd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#LookingGlassDialog StBoxLayout#EvalBox
 | 
			
		||||
{
 | 
			
		||||
  padding: 4px;
 | 
			
		||||
  spacing: 4px;
 | 
			
		||||
    padding: 4px;
 | 
			
		||||
    spacing: 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#LookingGlassDialog StBoxLayout#ResultsArea
 | 
			
		||||
{
 | 
			
		||||
  spacing: 4px;
 | 
			
		||||
    spacing: 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#lookingGlassExtensions {
 | 
			
		||||
@@ -929,16 +922,16 @@ StTooltip StLabel {
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.lg-extension-actions {
 | 
			
		||||
.lg-extension-meta {
 | 
			
		||||
    spacing: 6px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#LookingGlassPropertyInspector {
 | 
			
		||||
    background: rgba(0, 0, 0, 0.9);
 | 
			
		||||
    background: rgba(0, 0, 0, 0.8);
 | 
			
		||||
    border: 2px solid grey;
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
    padding: 6px;
 | 
			
		||||
    color: #88ff66;
 | 
			
		||||
    color: #ffffff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Calendar popup */
 | 
			
		||||
@@ -951,7 +944,7 @@ StTooltip StLabel {
 | 
			
		||||
.calendar-vertical-separator {
 | 
			
		||||
    -stipple-width: 1px;
 | 
			
		||||
    -stipple-color: #505050;
 | 
			
		||||
    width: 1.5em;
 | 
			
		||||
    width: 0.3em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#calendarPopup {
 | 
			
		||||
@@ -974,13 +967,14 @@ StTooltip StLabel {
 | 
			
		||||
.calendar-month-label {
 | 
			
		||||
    color: #666666;
 | 
			
		||||
    font-size: 7.5pt;
 | 
			
		||||
    padding: 2px;
 | 
			
		||||
    padding-bottom: 8px;
 | 
			
		||||
    padding-top: 8px;
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.calendar-change-month-back {
 | 
			
		||||
    width: 20px;
 | 
			
		||||
    height: 20px;
 | 
			
		||||
    width: 18px;
 | 
			
		||||
    height: 12px;
 | 
			
		||||
    background-image: url("calendar-arrow-left.svg");
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
}
 | 
			
		||||
@@ -997,8 +991,8 @@ StTooltip StLabel {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.calendar-change-month-forward {
 | 
			
		||||
    width: 20px;
 | 
			
		||||
    height: 20px;
 | 
			
		||||
    width: 18px;
 | 
			
		||||
    height: 12px;
 | 
			
		||||
    background-image: url("calendar-arrow-right.svg");
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
}
 | 
			
		||||
@@ -1030,6 +1024,7 @@ StTooltip StLabel {
 | 
			
		||||
 | 
			
		||||
.calendar-day-base:hover {
 | 
			
		||||
    background-color: #777777;
 | 
			
		||||
    color: #fff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.calendar-day-base:active {
 | 
			
		||||
@@ -1038,6 +1033,7 @@ StTooltip StLabel {
 | 
			
		||||
 | 
			
		||||
.calendar-day-heading {
 | 
			
		||||
    color: #666666;
 | 
			
		||||
    padding-top: 1em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.calendar-week-number {
 | 
			
		||||
@@ -1100,7 +1096,8 @@ StTooltip StLabel {
 | 
			
		||||
    font-size: 9pt;
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    color: rgba(153, 153, 153, 1.0);
 | 
			
		||||
    padding-left: 0.3em;
 | 
			
		||||
    padding-left: 1.8em;
 | 
			
		||||
    padding-top: 0.8em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.events-day-header:rtl {
 | 
			
		||||
@@ -1227,6 +1224,7 @@ StTooltip StLabel {
 | 
			
		||||
 | 
			
		||||
#notification-scrollview {
 | 
			
		||||
    max-height: 10em;
 | 
			
		||||
    -st-vfade-offset: 24px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#notification-scrollview > .top-shadow, #notification-scrollview > .bottom-shadow {
 | 
			
		||||
@@ -1269,7 +1267,8 @@ StTooltip StLabel {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.notification-icon-button > StIcon {
 | 
			
		||||
    icon-size: 36px;
 | 
			
		||||
    icon-size: 16px;
 | 
			
		||||
    padding: 8px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hotplug-transient-box {
 | 
			
		||||
@@ -1339,9 +1338,8 @@ StTooltip StLabel {
 | 
			
		||||
    padding: 8px 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-sent {
 | 
			
		||||
.chat-received {
 | 
			
		||||
    padding-left: 4px;
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-received:rtl {
 | 
			
		||||
@@ -1351,8 +1349,7 @@ StTooltip StLabel {
 | 
			
		||||
 | 
			
		||||
.chat-sent {
 | 
			
		||||
    padding-left: 18pt;
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
    color: #7E7E7E;
 | 
			
		||||
    color: #959595;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-sent:rtl {
 | 
			
		||||
@@ -1362,7 +1359,6 @@ StTooltip StLabel {
 | 
			
		||||
 | 
			
		||||
.chat-meta-message {
 | 
			
		||||
    padding-left: 4px;
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
    font-size: 9pt;
 | 
			
		||||
    color: #bbbbbb;
 | 
			
		||||
}
 | 
			
		||||
@@ -1917,6 +1913,7 @@ StTooltip StLabel {
 | 
			
		||||
    background-gradient-end: white;
 | 
			
		||||
    background-gradient-direction: vertical;
 | 
			
		||||
    color: black;
 | 
			
		||||
    selected-color: white;
 | 
			
		||||
    border-radius: 5px;
 | 
			
		||||
    border: 2px solid #555753;
 | 
			
		||||
}
 | 
			
		||||
@@ -1925,6 +1922,12 @@ StTooltip StLabel {
 | 
			
		||||
    border: 2px solid #3465a4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.polkit-dialog-password-entry .capslock-warning {
 | 
			
		||||
    icon-size: 16px;
 | 
			
		||||
    warning-color: #999;
 | 
			
		||||
    padding: 0 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.polkit-dialog-error-label {
 | 
			
		||||
    font-size: 10pt;
 | 
			
		||||
    color: #ffff00;
 | 
			
		||||
@@ -1943,14 +1946,6 @@ StTooltip StLabel {
 | 
			
		||||
    padding-bottom: 8px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.network-dialog-show-password-checkbox {
 | 
			
		||||
    padding-top: 5px;
 | 
			
		||||
    padding-bottom: 5px;
 | 
			
		||||
    font-size: 10pt;
 | 
			
		||||
    color: white;
 | 
			
		||||
    spacing: 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.network-dialog-secret-table {
 | 
			
		||||
    spacing-rows: 15px;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								docs/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								docs/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
SUBDIRS = reference
 | 
			
		||||
							
								
								
									
										1
									
								
								docs/reference/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								docs/reference/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
SUBDIRS = shell st
 | 
			
		||||
							
								
								
									
										105
									
								
								docs/reference/shell/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								docs/reference/shell/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
			
		||||
## 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, relative to $(srcdir).
 | 
			
		||||
# gtk-doc will search all .c and .h files beneath these paths
 | 
			
		||||
# for inline comments documenting functions and macros.
 | 
			
		||||
# e.g. DOC_SOURCE_DIR=../../../gtk ../../../gdk
 | 
			
		||||
DOC_SOURCE_DIR=../../../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
 | 
			
		||||
 | 
			
		||||
# 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) $(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
 | 
			
		||||
							
								
								
									
										73
									
								
								docs/reference/shell/shell-docs.sgml.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								docs/reference/shell/shell-docs.sgml.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
<?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>
 | 
			
		||||
							
								
								
									
										105
									
								
								docs/reference/st/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								docs/reference/st/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
			
		||||
## 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, relative to $(srcdir).
 | 
			
		||||
# gtk-doc will search all .c and .h files beneath these paths
 | 
			
		||||
# for inline comments documenting functions and macros.
 | 
			
		||||
# e.g. DOC_SOURCE_DIR=../../../gtk ../../../gdk
 | 
			
		||||
DOC_SOURCE_DIR=../../../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
 | 
			
		||||
							
								
								
									
										68
									
								
								docs/reference/st/st-docs.sgml.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								docs/reference/st/st-docs.sgml.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
<?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-container.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"/>
 | 
			
		||||
      <xi:include href="xml/st-tooltip.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-group.xml"/>
 | 
			
		||||
      <xi:include href="xml/st-overflow-box.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>
 | 
			
		||||
@@ -3,13 +3,17 @@ jsdir = $(pkgdatadir)/js
 | 
			
		||||
 | 
			
		||||
nobase_dist_js_DATA = 	\
 | 
			
		||||
	gdm/batch.js		\
 | 
			
		||||
	gdm/consoleKit.js	\
 | 
			
		||||
	gdm/fingerprint.js	\
 | 
			
		||||
	gdm/loginDialog.js	\
 | 
			
		||||
	gdm/powerMenu.js	\
 | 
			
		||||
	misc/config.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     \
 | 
			
		||||
@@ -43,6 +47,7 @@ nobase_dist_js_DATA = 	\
 | 
			
		||||
	ui/messageTray.js	\
 | 
			
		||||
	ui/modalDialog.js	\
 | 
			
		||||
	ui/networkAgent.js	\
 | 
			
		||||
	ui/shellEntry.js	\
 | 
			
		||||
	ui/shellMountOperation.js \
 | 
			
		||||
	ui/notificationDaemon.js \
 | 
			
		||||
	ui/overview.js		\
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 *
 | 
			
		||||
// -*- 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
 | 
			
		||||
@@ -21,11 +21,9 @@
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
function Task() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
const Task = new Lang.Class({
 | 
			
		||||
    Name: 'Task',
 | 
			
		||||
 | 
			
		||||
Task.prototype = {
 | 
			
		||||
    _init: function(scope, handler) {
 | 
			
		||||
        if (scope)
 | 
			
		||||
            this.scope = scope;
 | 
			
		||||
@@ -41,22 +39,17 @@ Task.prototype = {
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(Task.prototype);
 | 
			
		||||
 | 
			
		||||
function Hold() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Hold.prototype = {
 | 
			
		||||
    __proto__: Task.prototype,
 | 
			
		||||
const Hold = new Lang.Class({
 | 
			
		||||
    Name: 'Hold',
 | 
			
		||||
    Extends: Task,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        Task.prototype._init.call(this,
 | 
			
		||||
                                  this,
 | 
			
		||||
                                  function () {
 | 
			
		||||
                                      return this;
 | 
			
		||||
                                  });
 | 
			
		||||
        this.parent(this, function () {
 | 
			
		||||
            return this;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._acquisitions = 1;
 | 
			
		||||
    },
 | 
			
		||||
@@ -88,18 +81,15 @@ Hold.prototype = {
 | 
			
		||||
    isAcquired: function() {
 | 
			
		||||
        return this._acquisitions > 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(Hold.prototype);
 | 
			
		||||
 | 
			
		||||
function Batch() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Batch.prototype = {
 | 
			
		||||
    __proto__: Task.prototype,
 | 
			
		||||
const Batch = new Lang.Class({
 | 
			
		||||
    Name: 'Batch',
 | 
			
		||||
    Extends: Task,
 | 
			
		||||
 | 
			
		||||
    _init: function(scope, tasks) {
 | 
			
		||||
        Task.prototype._init.call(this);
 | 
			
		||||
        this.parent();
 | 
			
		||||
 | 
			
		||||
        this.tasks = [];
 | 
			
		||||
 | 
			
		||||
@@ -166,20 +156,12 @@ Batch.prototype = {
 | 
			
		||||
    cancel: function() {
 | 
			
		||||
        this.tasks = this.tasks.splice(0, this._currentTaskIndex + 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(Batch.prototype);
 | 
			
		||||
 | 
			
		||||
function ConcurrentBatch() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ConcurrentBatch.prototype = {
 | 
			
		||||
    __proto__: Batch.prototype,
 | 
			
		||||
 | 
			
		||||
    _init: function(scope, tasks) {
 | 
			
		||||
        Batch.prototype._init.call(this, scope, tasks);
 | 
			
		||||
    },
 | 
			
		||||
const ConcurrentBatch = new Lang.Class({
 | 
			
		||||
    Name: 'ConcurrentBatch',
 | 
			
		||||
    Extends: Batch,
 | 
			
		||||
 | 
			
		||||
    process: function() {
 | 
			
		||||
       let hold = this.runTask();
 | 
			
		||||
@@ -193,19 +175,12 @@ ConcurrentBatch.prototype = {
 | 
			
		||||
       // concurrently.
 | 
			
		||||
       this.nextTask();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(ConcurrentBatch.prototype);
 | 
			
		||||
 | 
			
		||||
function ConsecutiveBatch() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ConsecutiveBatch.prototype = {
 | 
			
		||||
    __proto__: Batch.prototype,
 | 
			
		||||
 | 
			
		||||
    _init: function(scope, tasks) {
 | 
			
		||||
        Batch.prototype._init.call(this, scope, tasks);
 | 
			
		||||
    },
 | 
			
		||||
const ConsecutiveBatch = new Lang.Class({
 | 
			
		||||
    Name: 'ConsecutiveBatch',
 | 
			
		||||
    Extends: Batch,
 | 
			
		||||
 | 
			
		||||
    process: function() {
 | 
			
		||||
       let hold = this.runTask();
 | 
			
		||||
@@ -224,5 +199,5 @@ ConsecutiveBatch.prototype = {
 | 
			
		||||
           this.nextTask();
 | 
			
		||||
       }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(ConsecutiveBatch.prototype);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										22
									
								
								js/gdm/consoleKit.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								js/gdm/consoleKit.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
 | 
			
		||||
const ConsoleKitManagerIface = <interface name='org.freedesktop.ConsoleKit.Manager'>
 | 
			
		||||
<method name='CanRestart'>
 | 
			
		||||
    <arg type='b' direction='out'/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name='CanStop'>
 | 
			
		||||
    <arg type='b' direction='out'/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name='Restart' />
 | 
			
		||||
<method name='Stop' />
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
const ConsoleKitProxy = Gio.DBusProxy.makeProxyWrapper(ConsoleKitManagerIface);
 | 
			
		||||
 | 
			
		||||
function ConsoleKitManager() {
 | 
			
		||||
    return new ConsoleKitProxy(Gio.DBus.system,
 | 
			
		||||
                               'org.freedesktop.ConsoleKit',
 | 
			
		||||
                               '/org/freedesktop/ConsoleKit/Manager');
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										20
									
								
								js/gdm/fingerprint.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								js/gdm/fingerprint.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
// -*- 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 FprintManagerProxy = Gio.DBusProxy.makeProxyWrapper(FprintManagerIface);
 | 
			
		||||
 | 
			
		||||
function FprintManager() {
 | 
			
		||||
    return new FprintManagerProxy(Gio.DBus.system,
 | 
			
		||||
                           'net.reactivated.Fprint',
 | 
			
		||||
                           '/net/reactivated/Fprint/Manager');
 | 
			
		||||
};
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 *
 | 
			
		||||
// -*- 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
 | 
			
		||||
@@ -33,15 +33,24 @@ const St = imports.gi.St;
 | 
			
		||||
const GdmGreeter = imports.gi.GdmGreeter;
 | 
			
		||||
 | 
			
		||||
const Batch = imports.gdm.batch;
 | 
			
		||||
const Fprint = imports.gdm.fingerprint;
 | 
			
		||||
const Lightbox = imports.ui.lightbox;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const ModalDialog = imports.ui.modalDialog;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
 | 
			
		||||
const _PASSWORD_SERVICE_NAME = 'gdm-password';
 | 
			
		||||
const _FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
 | 
			
		||||
const _FADE_ANIMATION_TIME = 0.16;
 | 
			
		||||
const _RESIZE_ANIMATION_TIME = 0.25;
 | 
			
		||||
const _SCROLL_ANIMATION_TIME = 2.0;
 | 
			
		||||
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
 | 
			
		||||
const _LOGO_ICON_NAME_SIZE = 48;
 | 
			
		||||
 | 
			
		||||
const _LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen';
 | 
			
		||||
const _FINGERPRINT_AUTHENTICATION_KEY = 'enable-fingerprint-authentication';
 | 
			
		||||
 | 
			
		||||
const _LOGO_KEY = 'logo';
 | 
			
		||||
 | 
			
		||||
let _loginDialog = null;
 | 
			
		||||
 | 
			
		||||
@@ -131,11 +140,9 @@ function _smoothlyResizeActor(actor, width, height) {
 | 
			
		||||
    return hold;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function UserListItem(user, reason) {
 | 
			
		||||
    this._init(user, reason);
 | 
			
		||||
}
 | 
			
		||||
const UserListItem = new Lang.Class({
 | 
			
		||||
    Name: 'UserListItem',
 | 
			
		||||
 | 
			
		||||
UserListItem.prototype = {
 | 
			
		||||
    _init: function(user) {
 | 
			
		||||
        this.user = user;
 | 
			
		||||
        this._userChangedId = this.user.connect('changed',
 | 
			
		||||
@@ -246,12 +253,15 @@ UserListItem.prototype = {
 | 
			
		||||
    showFocusAnimation: function(time) {
 | 
			
		||||
        let hold = new Batch.Hold();
 | 
			
		||||
 | 
			
		||||
        let node = this.actor.get_theme_node();
 | 
			
		||||
        let padding = node.get_horizontal_padding();
 | 
			
		||||
 | 
			
		||||
        let box = this._verticalBox.get_allocation_box();
 | 
			
		||||
 | 
			
		||||
        Tweener.removeTweens(this._focusBin);
 | 
			
		||||
        this._focusBin.width = 0;
 | 
			
		||||
        Tweener.addTween(this._focusBin,
 | 
			
		||||
                         { width: box.x2 - box.x1,
 | 
			
		||||
                         { width: (box.x2 - box.x1 - padding),
 | 
			
		||||
                           time: time,
 | 
			
		||||
                           transition: 'linear',
 | 
			
		||||
                           onComplete: function() {
 | 
			
		||||
@@ -261,15 +271,12 @@ UserListItem.prototype = {
 | 
			
		||||
                         });
 | 
			
		||||
        return hold;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(UserListItem.prototype);
 | 
			
		||||
 | 
			
		||||
function UserList() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
const UserList = new Lang.Class({
 | 
			
		||||
    Name: 'UserList',
 | 
			
		||||
 | 
			
		||||
UserList.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view'});
 | 
			
		||||
        this.actor.set_policy(Gtk.PolicyType.NEVER,
 | 
			
		||||
@@ -284,6 +291,20 @@ UserList.prototype = {
 | 
			
		||||
                               x_align: St.Align.START,
 | 
			
		||||
                               y_align: St.Align.MIDDLE });
 | 
			
		||||
        this._items = {};
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('key-focus-in', Lang.bind(this, this._moveFocusToItems));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _moveFocusToItems: function() {
 | 
			
		||||
        let hasItems = Object.keys(this._items).length > 0;
 | 
			
		||||
 | 
			
		||||
        if (!hasItems)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (global.stage.get_key_focus() != this.actor)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showItem: function(item) {
 | 
			
		||||
@@ -489,6 +510,8 @@ UserList.prototype = {
 | 
			
		||||
                                         item.showFocusAnimation(0);
 | 
			
		||||
                                     }));
 | 
			
		||||
 | 
			
		||||
        this._moveFocusToItems();
 | 
			
		||||
 | 
			
		||||
        this.emit('item-added', item);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -509,14 +532,12 @@ UserList.prototype = {
 | 
			
		||||
        item.actor.destroy();
 | 
			
		||||
        delete this._items[userName];
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(UserList.prototype);
 | 
			
		||||
 | 
			
		||||
function SessionListItem(id, name) {
 | 
			
		||||
    this._init(id, name);
 | 
			
		||||
}
 | 
			
		||||
const SessionListItem = new Lang.Class({
 | 
			
		||||
    Name: 'SessionListItem',
 | 
			
		||||
 | 
			
		||||
SessionListItem.prototype = {
 | 
			
		||||
    _init: function(id, name) {
 | 
			
		||||
        this.id = id;
 | 
			
		||||
 | 
			
		||||
@@ -571,14 +592,12 @@ SessionListItem.prototype = {
 | 
			
		||||
    _onClicked: function() {
 | 
			
		||||
        this.emit('activate');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(SessionListItem.prototype);
 | 
			
		||||
 | 
			
		||||
function SessionList() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const SessionList = new Lang.Class({
 | 
			
		||||
    Name: 'SessionList',
 | 
			
		||||
 | 
			
		||||
SessionList.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.actor = new St.Bin();
 | 
			
		||||
 | 
			
		||||
@@ -681,10 +700,13 @@ SessionList.prototype = {
 | 
			
		||||
        let ids = GdmGreeter.get_session_ids();
 | 
			
		||||
        ids.sort();
 | 
			
		||||
 | 
			
		||||
        if (ids.length <= 1)
 | 
			
		||||
        if (ids.length <= 1) {
 | 
			
		||||
            this._box.hide();
 | 
			
		||||
        else
 | 
			
		||||
            this._button.hide();
 | 
			
		||||
        } else {
 | 
			
		||||
            this._button.show();
 | 
			
		||||
            this._box.show();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < ids.length; i++) {
 | 
			
		||||
            let [sessionName, sessionDescription] = GdmGreeter.get_session_name_and_description(ids[i]);
 | 
			
		||||
@@ -706,24 +728,15 @@ SessionList.prototype = {
 | 
			
		||||
                         }));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(SessionList.prototype);
 | 
			
		||||
 | 
			
		||||
function LoginDialog() {
 | 
			
		||||
    if (_loginDialog == null) {
 | 
			
		||||
        this._init();
 | 
			
		||||
        _loginDialog = this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return _loginDialog;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LoginDialog.prototype = {
 | 
			
		||||
    __proto__: ModalDialog.ModalDialog.prototype,
 | 
			
		||||
const LoginDialog = new Lang.Class({
 | 
			
		||||
    Name: 'LoginDialog',
 | 
			
		||||
    Extends: ModalDialog.ModalDialog,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        ModalDialog.ModalDialog.prototype._init.call(this, { shellReactive: true,
 | 
			
		||||
                                                             styleClass: 'login-dialog' });
 | 
			
		||||
        this.parent({ shellReactive: true, styleClass: 'login-dialog' });
 | 
			
		||||
        this.connect('destroy',
 | 
			
		||||
                     Lang.bind(this, this._onDestroy));
 | 
			
		||||
        this.connect('opened',
 | 
			
		||||
@@ -734,7 +747,7 @@ LoginDialog.prototype = {
 | 
			
		||||
 | 
			
		||||
        this._greeterClient.open_connection();
 | 
			
		||||
 | 
			
		||||
        this._greeterClient.call_start_conversation('gdm-password');
 | 
			
		||||
        this._greeterClient.call_start_conversation(_PASSWORD_SERVICE_NAME);
 | 
			
		||||
 | 
			
		||||
        this._greeterClient.connect('reset',
 | 
			
		||||
                                    Lang.bind(this, this._onReset));
 | 
			
		||||
@@ -757,6 +770,17 @@ LoginDialog.prototype = {
 | 
			
		||||
        this._greeterClient.connect('conversation-stopped',
 | 
			
		||||
                                    Lang.bind(this, this._onConversationStopped));
 | 
			
		||||
 | 
			
		||||
        this._settings = new Gio.Settings({ schema: _LOGIN_SCREEN_SCHEMA });
 | 
			
		||||
 | 
			
		||||
        this._fprintManager = new Fprint.FprintManager();
 | 
			
		||||
        this._startFingerprintConversationIfNeeded();
 | 
			
		||||
        this._settings.connect('changed::' + _LOGO_KEY,
 | 
			
		||||
                               Lang.bind(this, this._updateLogo));
 | 
			
		||||
 | 
			
		||||
        this._logoBox = new St.Bin({ style_class: 'login-dialog-logo-box' });
 | 
			
		||||
        this.contentLayout.add(this._logoBox);
 | 
			
		||||
        this._updateLogo();
 | 
			
		||||
 | 
			
		||||
        this._titleLabel = new St.Label({ style_class: 'login-dialog-title',
 | 
			
		||||
                                          text: C_("title", "Sign In") });
 | 
			
		||||
 | 
			
		||||
@@ -801,6 +825,12 @@ LoginDialog.prototype = {
 | 
			
		||||
                              x_fill: true,
 | 
			
		||||
                              y_fill: false,
 | 
			
		||||
                              x_align: St.Align.START });
 | 
			
		||||
        // Translators: this message is shown below the password entry field
 | 
			
		||||
        // to indicate the user can swipe their finger instead
 | 
			
		||||
        this._promptFingerprintMessage = new St.Label({ text: _("(or swipe finger)"),
 | 
			
		||||
                                                        style_class: 'login-dialog-prompt-fingerprint-message' });
 | 
			
		||||
        this._promptFingerprintMessage.hide();
 | 
			
		||||
        this._promptBox.add(this._promptFingerprintMessage);
 | 
			
		||||
 | 
			
		||||
        this._sessionList = new SessionList();
 | 
			
		||||
        this._sessionList.connect('session-activated',
 | 
			
		||||
@@ -815,6 +845,9 @@ LoginDialog.prototype = {
 | 
			
		||||
                              x_align: St.Align.START });
 | 
			
		||||
        this._promptBox.hide();
 | 
			
		||||
 | 
			
		||||
        // translators: this message is shown below the user list on the
 | 
			
		||||
        // login screen. It can be activated to reveal an entry for
 | 
			
		||||
        // manually entering the username.
 | 
			
		||||
        let notListedLabel = new St.Label({ text: _("Not listed?"),
 | 
			
		||||
                                            style_class: 'login-dialog-not-listed-label' });
 | 
			
		||||
        this._notListedButton = new St.Button({ style_class: 'login-dialog-not-listed-button',
 | 
			
		||||
@@ -848,18 +881,51 @@ LoginDialog.prototype = {
 | 
			
		||||
                                   this._onUserListActivated(item);
 | 
			
		||||
                               }));
 | 
			
		||||
 | 
			
		||||
   },
 | 
			
		||||
 | 
			
		||||
   _startFingerprintConversationIfNeeded: function() {
 | 
			
		||||
        this._haveFingerprintReader = false;
 | 
			
		||||
 | 
			
		||||
        if (!this._settings.get_boolean(_FINGERPRINT_AUTHENTICATION_KEY))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._fprintManager.GetDefaultDeviceRemote(Gio.DBusCallFlags.NONE, Lang.bind(this,
 | 
			
		||||
            function(device, error) {
 | 
			
		||||
                if (!error && device)
 | 
			
		||||
                    this._haveFingerprintReader = true;
 | 
			
		||||
 | 
			
		||||
                if (this._haveFingerprintReader)
 | 
			
		||||
                    this._greeterClient.call_start_conversation(_FINGERPRINT_SERVICE_NAME);
 | 
			
		||||
            }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateLogo: function() {
 | 
			
		||||
        this._logoBox.child = null;
 | 
			
		||||
        let path = this._settings.get_string(_LOGO_KEY);
 | 
			
		||||
 | 
			
		||||
        if (path) {
 | 
			
		||||
            let file = Gio.file_new_for_path(path);
 | 
			
		||||
            let uri = file.get_uri();
 | 
			
		||||
 | 
			
		||||
            let textureCache = St.TextureCache.get_default();
 | 
			
		||||
            this._logoBox.child = textureCache.load_uri_async(uri, -1, _LOGO_ICON_NAME_SIZE);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onReset: function(client, serviceName) {
 | 
			
		||||
        this._greeterClient.call_start_conversation('gdm-password');
 | 
			
		||||
        this._greeterClient.call_start_conversation(_PASSWORD_SERVICE_NAME);
 | 
			
		||||
        this._startFingerprintConversationIfNeeded();
 | 
			
		||||
 | 
			
		||||
        let tasks = [this._hidePrompt,
 | 
			
		||||
 | 
			
		||||
                     new Batch.ConcurrentBatch(this, [this._fadeInTitleLabel,
 | 
			
		||||
                                                      this._fadeInNotListedButton]),
 | 
			
		||||
                                                      this._fadeInNotListedButton,
 | 
			
		||||
                                                      this._fadeInLogo]),
 | 
			
		||||
 | 
			
		||||
                     function() {
 | 
			
		||||
                         this._sessionList.close();
 | 
			
		||||
                         this._promptFingerprintMessage.hide();
 | 
			
		||||
                         this._userList.actor.show();
 | 
			
		||||
                         this._userList.actor.opacity = 255;
 | 
			
		||||
                         return this._userList.showItems();
 | 
			
		||||
@@ -881,10 +947,28 @@ LoginDialog.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onInfo: function(client, serviceName, info) {
 | 
			
		||||
        // We don't display fingerprint messages, because they
 | 
			
		||||
        // have words like UPEK in them. Instead we use the messages
 | 
			
		||||
        // as a cue to display our own message.
 | 
			
		||||
        if (serviceName == _FINGERPRINT_SERVICE_NAME &&
 | 
			
		||||
            this._haveFingerprintReader &&
 | 
			
		||||
            (!this._promptFingerprintMessage.visible ||
 | 
			
		||||
             this._promptFingerprintMessage.opacity != 255)) {
 | 
			
		||||
 | 
			
		||||
            _fadeInActor(this._promptFingerprintMessage);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (serviceName != _PASSWORD_SERVICE_NAME)
 | 
			
		||||
            return;
 | 
			
		||||
        Main.notifyError(info);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onProblem: function(client, serviceName, problem) {
 | 
			
		||||
        // we don't want to show auth failed messages to
 | 
			
		||||
        // users who haven't enrolled their fingerprint.
 | 
			
		||||
        if (serviceName != _PASSWORD_SERVICE_NAME)
 | 
			
		||||
            return;
 | 
			
		||||
        Main.notifyError(problem);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -901,6 +985,13 @@ LoginDialog.prototype = {
 | 
			
		||||
                         return _fadeInActor(this._promptEntry);
 | 
			
		||||
                     },
 | 
			
		||||
 | 
			
		||||
                     function() {
 | 
			
		||||
                         // Show it with 0 opacity so we preallocate space for it
 | 
			
		||||
                         // in the event we need to fade in the message
 | 
			
		||||
                         this._promptFingerprintMessage.opacity = 0;
 | 
			
		||||
                         this._promptFingerprintMessage.show();
 | 
			
		||||
                     },
 | 
			
		||||
 | 
			
		||||
                     function() {
 | 
			
		||||
                         return _fadeInActor(this._promptBox);
 | 
			
		||||
                     },
 | 
			
		||||
@@ -969,6 +1060,9 @@ LoginDialog.prototype = {
 | 
			
		||||
                     },
 | 
			
		||||
 | 
			
		||||
                     function() {
 | 
			
		||||
                         this._promptFingerprintMessage.hide();
 | 
			
		||||
                         this._promptEntry.reactive = true;
 | 
			
		||||
                         this._promptEntry.remove_style_pseudo_class('insensitive');
 | 
			
		||||
                         this._promptEntry.set_text('');
 | 
			
		||||
                     }];
 | 
			
		||||
 | 
			
		||||
@@ -984,7 +1078,8 @@ LoginDialog.prototype = {
 | 
			
		||||
 | 
			
		||||
                     function() {
 | 
			
		||||
                         let _text = this._promptEntry.get_text();
 | 
			
		||||
                         this._promptEntry.set_text('');
 | 
			
		||||
                         this._promptEntry.reactive = false;
 | 
			
		||||
                         this._promptEntry.add_style_pseudo_class('insensitive');
 | 
			
		||||
                         this._greeterClient.call_answer_query(serviceName, _text);
 | 
			
		||||
                     }];
 | 
			
		||||
 | 
			
		||||
@@ -992,12 +1087,20 @@ LoginDialog.prototype = {
 | 
			
		||||
        return batch.run();
 | 
			
		||||
    },
 | 
			
		||||
    _onInfoQuery: function(client, serviceName, question) {
 | 
			
		||||
        // We only expect questions to come from the main auth service
 | 
			
		||||
        if (serviceName != _PASSWORD_SERVICE_NAME)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._promptEntry.set_text('');
 | 
			
		||||
        this._promptEntry.clutter_text.set_password_char('');
 | 
			
		||||
        this._askQuestion(serviceName, question);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onSecretInfoQuery: function(client, serviceName, secretQuestion) {
 | 
			
		||||
        // We only expect secret requests to come from the main auth service
 | 
			
		||||
        if (serviceName != _PASSWORD_SERVICE_NAME)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._promptEntry.set_text('');
 | 
			
		||||
        this._promptEntry.clutter_text.set_password_char('\u25cf');
 | 
			
		||||
        this._askQuestion(serviceName, secretQuestion);
 | 
			
		||||
@@ -1134,7 +1237,14 @@ LoginDialog.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onConversationStopped: function(client, serviceName) {
 | 
			
		||||
        this._greeterClient.call_cancel();
 | 
			
		||||
        // if the password service fails, then cancel everything.
 | 
			
		||||
        // But if, e.g., fingerprint fails, still give
 | 
			
		||||
        // password authentication a chance to succeed
 | 
			
		||||
        if (serviceName == _PASSWORD_SERVICE_NAME) {
 | 
			
		||||
            this._greeterClient.call_cancel();
 | 
			
		||||
        } else if (serviceName == _FINGERPRINT_SERVICE_NAME) {
 | 
			
		||||
            _fadeOutActor(this._promptFingerprintMessage);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onNotListedClicked: function(user) {
 | 
			
		||||
@@ -1151,16 +1261,25 @@ LoginDialog.prototype = {
 | 
			
		||||
                     },
 | 
			
		||||
 | 
			
		||||
                     new Batch.ConcurrentBatch(this, [this._fadeOutTitleLabel,
 | 
			
		||||
                                                      this._fadeOutNotListedButton]),
 | 
			
		||||
                                                      this._fadeOutNotListedButton,
 | 
			
		||||
                                                      this._fadeOutLogo]),
 | 
			
		||||
 | 
			
		||||
                     function() {
 | 
			
		||||
                         this._greeterClient.call_begin_verification('gdm-password');
 | 
			
		||||
                         this._greeterClient.call_begin_verification(_PASSWORD_SERVICE_NAME);
 | 
			
		||||
                     }];
 | 
			
		||||
 | 
			
		||||
        let batch = new Batch.ConsecutiveBatch(this, tasks);
 | 
			
		||||
        batch.run();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _fadeInLogo: function() {
 | 
			
		||||
        return _fadeInActor(this._logoBox);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _fadeOutLogo: function() {
 | 
			
		||||
        return _fadeOutActor(this._logoBox);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _fadeInTitleLabel: function() {
 | 
			
		||||
        return _fadeInActor(this._titleLabel);
 | 
			
		||||
    },
 | 
			
		||||
@@ -1196,7 +1315,8 @@ LoginDialog.prototype = {
 | 
			
		||||
                     },
 | 
			
		||||
 | 
			
		||||
                     new Batch.ConcurrentBatch(this, [this._fadeOutTitleLabel,
 | 
			
		||||
                                                      this._fadeOutNotListedButton]),
 | 
			
		||||
                                                      this._fadeOutNotListedButton,
 | 
			
		||||
                                                      this._fadeOutLogo]),
 | 
			
		||||
 | 
			
		||||
                     function() {
 | 
			
		||||
                         return this._userList.shrinkToNaturalHeight();
 | 
			
		||||
@@ -1204,8 +1324,11 @@ LoginDialog.prototype = {
 | 
			
		||||
 | 
			
		||||
                     function() {
 | 
			
		||||
                         let userName = activatedItem.user.get_user_name();
 | 
			
		||||
                         this._greeterClient.call_begin_verification_for_user('gdm-password',
 | 
			
		||||
                         this._greeterClient.call_begin_verification_for_user(_PASSWORD_SERVICE_NAME,
 | 
			
		||||
                                                                              userName);
 | 
			
		||||
 | 
			
		||||
                         if (this._haveFingerprintReader)
 | 
			
		||||
                             this._greeterClient.call_begin_verification_for_user(_FINGERPRINT_SERVICE_NAME, userName);
 | 
			
		||||
                     }];
 | 
			
		||||
 | 
			
		||||
        this._user = activatedItem.user;
 | 
			
		||||
@@ -1257,8 +1380,8 @@ LoginDialog.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    close: function() {
 | 
			
		||||
        ModalDialog.ModalDialog.prototype.close.call(this);
 | 
			
		||||
        this.parent();
 | 
			
		||||
 | 
			
		||||
        Main.ctrlAltTabManager.removeGroup(this._group);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										143
									
								
								js/gdm/powerMenu.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								js/gdm/powerMenu.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,143 @@
 | 
			
		||||
// -*- 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 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._consoleKitManager = new ConsoleKit.ConsoleKitManager();
 | 
			
		||||
        this._upClient = new UPowerGlib.Client();
 | 
			
		||||
 | 
			
		||||
        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() {
 | 
			
		||||
        if (!this._haveSuspend && !this._haveShutdown && !this._haveRestart)
 | 
			
		||||
            this.actor.hide();
 | 
			
		||||
        else
 | 
			
		||||
            this.actor.show();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateHaveShutdown: function() {
 | 
			
		||||
        this._consoleKitManager.CanStopRemote(Lang.bind(this,
 | 
			
		||||
            function(result, error) {
 | 
			
		||||
                if (!error)
 | 
			
		||||
                    this._haveShutdown = result;
 | 
			
		||||
                else
 | 
			
		||||
                    this._haveShutdown = false;
 | 
			
		||||
 | 
			
		||||
                if (this._haveShutdown) {
 | 
			
		||||
                    this._powerOffItem.actor.show();
 | 
			
		||||
                } else {
 | 
			
		||||
                    this._powerOffItem.actor.hide();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                this._updateVisibility();
 | 
			
		||||
            }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateHaveRestart: function() {
 | 
			
		||||
        this._consoleKitManager.CanRestartRemote(Lang.bind(this,
 | 
			
		||||
            function(result, error) {
 | 
			
		||||
                if (!error)
 | 
			
		||||
                    this._haveRestart = result;
 | 
			
		||||
                else
 | 
			
		||||
                    this._haveRestart = false;
 | 
			
		||||
 | 
			
		||||
                if (this._haveRestart) {
 | 
			
		||||
                    this._restartItem.actor.show();
 | 
			
		||||
                } else {
 | 
			
		||||
                    this._restartItem.actor.hide();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                this._updateVisibility();
 | 
			
		||||
            }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateHaveSuspend: function() {
 | 
			
		||||
        this._haveSuspend = this._upClient.get_can_suspend();
 | 
			
		||||
 | 
			
		||||
        if (this._haveSuspend)
 | 
			
		||||
            this._suspendItem.actor.show();
 | 
			
		||||
        else
 | 
			
		||||
            this._suspendItem.actor.hide();
 | 
			
		||||
 | 
			
		||||
        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)
 | 
			
		||||
            this._consoleKitManager.RestartRemote();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onActivatePowerOff: function() {
 | 
			
		||||
        if (this._haveShutdown)
 | 
			
		||||
            this._consoleKitManager.StopRemote();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
/* mode: js2; indent-tabs-mode: nil; tab-size: 4 */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
/* The name of this package (not localized) */
 | 
			
		||||
const PACKAGE_NAME = '@PACKAGE_NAME@';
 | 
			
		||||
/* The version of this package */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
@@ -8,11 +8,9 @@ const Search = imports.ui.search;
 | 
			
		||||
 | 
			
		||||
const THUMBNAIL_ICON_MARGIN = 2;
 | 
			
		||||
 | 
			
		||||
function DocInfo(recentInfo) {
 | 
			
		||||
    this._init(recentInfo);
 | 
			
		||||
}
 | 
			
		||||
const DocInfo = new Lang.Class({
 | 
			
		||||
    Name: 'DocInfo',
 | 
			
		||||
 | 
			
		||||
DocInfo.prototype = {
 | 
			
		||||
    _init : function(recentInfo) {
 | 
			
		||||
        this.recentInfo = recentInfo;
 | 
			
		||||
        // We actually used get_modified() instead of get_visited()
 | 
			
		||||
@@ -49,7 +47,7 @@ DocInfo.prototype = {
 | 
			
		||||
        }
 | 
			
		||||
        return mtype;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var docManagerInstance = null;
 | 
			
		||||
 | 
			
		||||
@@ -62,11 +60,9 @@ function getDocManager() {
 | 
			
		||||
/**
 | 
			
		||||
 * DocManager wraps the DocSystem, primarily to expose DocInfo objects.
 | 
			
		||||
 */
 | 
			
		||||
function DocManager() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const DocManager = new Lang.Class({
 | 
			
		||||
    Name: 'DocManager',
 | 
			
		||||
 | 
			
		||||
DocManager.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._docSystem = Shell.DocSystem.get_default();
 | 
			
		||||
        this._infosByTimestamp = [];
 | 
			
		||||
@@ -135,6 +131,6 @@ DocManager.prototype = {
 | 
			
		||||
                return this._infosByUri[url];
 | 
			
		||||
            })), terms);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Signals.addSignalMethods(DocManager.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This function is intended to extend the String object and provide
 | 
			
		||||
 
 | 
			
		||||
@@ -1,20 +1,18 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
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 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 PresenceStatus = {
 | 
			
		||||
    AVAILABLE: 0,
 | 
			
		||||
@@ -23,104 +21,41 @@ const PresenceStatus = {
 | 
			
		||||
    IDLE: 3
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function Presence() {
 | 
			
		||||
    this._init();
 | 
			
		||||
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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 = {
 | 
			
		||||
    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' }],
 | 
			
		||||
};
 | 
			
		||||
const InhibitorIface = <interface name="org.gnome.SessionManager.Inhibitor">
 | 
			
		||||
<property name="app_id" type="s" access="read" />
 | 
			
		||||
<property name="client_id" type="s" access="read" />
 | 
			
		||||
<property name="reason" type="s" access="read" />
 | 
			
		||||
<property name="flags" type="u" access="read" />
 | 
			
		||||
<property name="toplevel_xid" type="u" access="read" />
 | 
			
		||||
<property name="cookie" type="u" access="read" />
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
function Inhibitor(objectPath) {
 | 
			
		||||
    this._init(objectPath);
 | 
			
		||||
var InhibitorProxy = Gio.DBusProxy.makeProxyWrapper(InhibitorIface);
 | 
			
		||||
function Inhibitor(objectPath, initCallback, cancellable) {
 | 
			
		||||
    return new InhibitorProxy(Gio.DBus.session, 'org.gnome.SessionManager', objectPath, initCallback, cancellable);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 = {
 | 
			
		||||
    name: 'org.gnome.SessionManager',
 | 
			
		||||
    methods: [
 | 
			
		||||
        { name: 'Logout', inSignature: 'u', outSignature: '' },
 | 
			
		||||
        { name: 'Shutdown', inSignature: '', outSignature: '' },
 | 
			
		||||
        { name: 'CanShutdown', inSignature: '', outSignature: 'b' }
 | 
			
		||||
    ]
 | 
			
		||||
};
 | 
			
		||||
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>;
 | 
			
		||||
 | 
			
		||||
function SessionManager() {
 | 
			
		||||
    this._init();
 | 
			
		||||
var SessionManagerProxy = Gio.DBusProxy.makeProxyWrapper(SessionManagerIface);
 | 
			
		||||
function SessionManager(initCallback, cancellable) {
 | 
			
		||||
    return new SessionManagerProxy(Gio.DBus.session, 'org.gnome.SessionManager', '/org/gnome/SessionManager', initCallback, cancellable);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SessionManager.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        DBus.session.proxifyObject(this, 'org.gnome.SessionManager', '/org/gnome/SessionManager');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
DBus.proxifyPrototype(SessionManager.prototype, SessionManagerIface);
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
@@ -7,11 +7,9 @@ const Params = imports.misc.params;
 | 
			
		||||
 | 
			
		||||
const DEFAULT_LIMIT = 512;
 | 
			
		||||
 | 
			
		||||
function HistoryManager(params) {
 | 
			
		||||
    this._init(params);
 | 
			
		||||
}
 | 
			
		||||
const HistoryManager = new Lang.Class({
 | 
			
		||||
    Name: 'HistoryManager',
 | 
			
		||||
 | 
			
		||||
HistoryManager.prototype = {
 | 
			
		||||
    _init: function(params) {
 | 
			
		||||
        params = Params.parse(params, { gsettingsKey: null,
 | 
			
		||||
                                        limit: DEFAULT_LIMIT,
 | 
			
		||||
@@ -111,5 +109,5 @@ HistoryManager.prototype = {
 | 
			
		||||
        if (this._key)
 | 
			
		||||
            global.settings.set_strv(this._key, this._history);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(HistoryManager.prototype);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										246
									
								
								js/misc/jsParse.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										246
									
								
								js/misc/jsParse.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,246 @@
 | 
			
		||||
/* -*- 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: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
@@ -8,33 +8,43 @@ const Signals = imports.signals;
 | 
			
		||||
// The following are not the complete interfaces, just the methods we need
 | 
			
		||||
// (or may need in the future)
 | 
			
		||||
 | 
			
		||||
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 ModemGsmNetworkInterface = <interface name="org.freedesktop.ModemManager.Modem.Gsm.Network">
 | 
			
		||||
<method name="GetRegistrationInfo">
 | 
			
		||||
    <arg type="u" direction="out" />
 | 
			
		||||
    <arg type="s" direction="out" />
 | 
			
		||||
    <arg type="s" 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 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);
 | 
			
		||||
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="u" direction="out" />
 | 
			
		||||
    <arg type="s" direction="out" />
 | 
			
		||||
    <arg type="u" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<signal name="SignalQuality">
 | 
			
		||||
    <arg type="u" direction="out" />
 | 
			
		||||
</signal>
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
const ModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(ModemCdmaInterface);
 | 
			
		||||
 | 
			
		||||
let _providersTable;
 | 
			
		||||
function _getProvidersTable() {
 | 
			
		||||
@@ -44,23 +54,21 @@ function _getProvidersTable() {
 | 
			
		||||
    return _providersTable = providers;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function ModemGsm() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
const ModemGsm = new Lang.Class({
 | 
			
		||||
    Name: 'ModemGsm',
 | 
			
		||||
 | 
			
		||||
ModemGsm.prototype = {
 | 
			
		||||
    _init: function(path) {
 | 
			
		||||
        this._proxy = new ModemGsmNetworkProxy(DBus.system, 'org.freedesktop.ModemManager', path);
 | 
			
		||||
        this._proxy = new ModemGsmNetworkProxy(Gio.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.connect('SignalQuality', Lang.bind(this, function(proxy, quality) {
 | 
			
		||||
        this._proxy.connectSignal('SignalQuality', Lang.bind(this, function(proxy, sender, [quality]) {
 | 
			
		||||
            this.signal_quality = quality;
 | 
			
		||||
            this.emit('notify::signal-quality');
 | 
			
		||||
        }));
 | 
			
		||||
        this._proxy.connect('RegistrationInfo', Lang.bind(this, function(proxy, status, code, name) {
 | 
			
		||||
        this._proxy.connectSignal('RegistrationInfo', Lang.bind(this, function(proxy, sender, [status, code, name]) {
 | 
			
		||||
            this.operator_name = this._findOperatorName(name, code);
 | 
			
		||||
            this.emit('notify::operator-name');
 | 
			
		||||
        }));
 | 
			
		||||
@@ -146,21 +154,19 @@ ModemGsm.prototype = {
 | 
			
		||||
 | 
			
		||||
        return name3 || name2 || null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(ModemGsm.prototype);
 | 
			
		||||
 | 
			
		||||
function ModemCdma() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
const ModemCdma = new Lang.Class({
 | 
			
		||||
    Name: 'ModemCdma',
 | 
			
		||||
 | 
			
		||||
ModemCdma.prototype = {
 | 
			
		||||
    _init: function(path) {
 | 
			
		||||
        this._proxy = new ModemCdmaProxy(DBus.system, 'org.freedesktop.ModemManager', path);
 | 
			
		||||
        this._proxy = new ModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
 | 
			
		||||
 | 
			
		||||
        this.signal_quality = 0;
 | 
			
		||||
        this.operator_name = null;
 | 
			
		||||
        this._proxy.connect('SignalQuality', Lang.bind(this, function(proxy, quality) {
 | 
			
		||||
            this.signal_quality = quality;
 | 
			
		||||
        this._proxy.connect('SignalQuality', Lang.bind(this, function(proxy, sender, params) {
 | 
			
		||||
            this.signal_quality = params[0];
 | 
			
		||||
            this.emit('notify::signal-quality');
 | 
			
		||||
 | 
			
		||||
            // receiving this signal means the device got activated
 | 
			
		||||
@@ -221,5 +227,5 @@ ModemCdma.prototype = {
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(ModemCdma.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
// parse:
 | 
			
		||||
// @params: caller-provided parameter object, or %null
 | 
			
		||||
 
 | 
			
		||||
@@ -1,53 +1,48 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
 | 
			
		||||
const ScreenSaverIface = {
 | 
			
		||||
    name: 'org.gnome.ScreenSaver',
 | 
			
		||||
    methods: [{ name: 'GetActive',
 | 
			
		||||
                inSignature: '',
 | 
			
		||||
                outSignature: 'b' },
 | 
			
		||||
              { name: 'Lock',
 | 
			
		||||
                inSignature: '' },
 | 
			
		||||
              { name: 'SetActive',
 | 
			
		||||
                inSignature: 'b' }],
 | 
			
		||||
    signals: [{ name: 'ActiveChanged',
 | 
			
		||||
                inSignature: 'b' }]
 | 
			
		||||
};
 | 
			
		||||
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() {
 | 
			
		||||
    this._init();
 | 
			
		||||
    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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ScreenSaverProxy.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        DBus.session.proxifyObject(this,
 | 
			
		||||
                                   'org.gnome.ScreenSaver',
 | 
			
		||||
                                   '/org/gnome/ScreenSaver');
 | 
			
		||||
 | 
			
		||||
        DBus.session.watch_name('org.gnome.ScreenSaver',
 | 
			
		||||
                                false, // do not launch a name-owner if none exists
 | 
			
		||||
                                Lang.bind(this, this._onSSAppeared),
 | 
			
		||||
                                Lang.bind(this, this._onSSVanished));
 | 
			
		||||
 | 
			
		||||
        this.screenSaverActive = false;
 | 
			
		||||
        this.connect('ActiveChanged',
 | 
			
		||||
                     Lang.bind(this, this._onActiveChanged));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onSSAppeared: function(owner) {
 | 
			
		||||
        this.GetActiveRemote(Lang.bind(this, function(isActive) {
 | 
			
		||||
            this.screenSaverActive = isActive;
 | 
			
		||||
        }))
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onSSVanished: function(oldOwner) {
 | 
			
		||||
        this.screenSaverActive = false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onActiveChanged: function(object, isActive) {
 | 
			
		||||
        this.screenSaverActive = isActive;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
DBus.proxifyPrototype(ScreenSaverProxy.prototype, ScreenSaverIface);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Gdk = imports.gi.Gdk;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Scripting = imports.ui.scripting;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										166
									
								
								js/ui/altTab.js
									
									
									
									
									
								
							
							
						
						
									
										166
									
								
								js/ui/altTab.js
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gdk = imports.gi.Gdk;
 | 
			
		||||
@@ -31,11 +31,21 @@ function mod(a, b) {
 | 
			
		||||
    return (a + b) % b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function AltTabPopup() {
 | 
			
		||||
    this._init();
 | 
			
		||||
function primaryModifier(mask) {
 | 
			
		||||
    if (mask == 0)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    let primary = 1;
 | 
			
		||||
    while (mask > 1) {
 | 
			
		||||
        mask >>= 1;
 | 
			
		||||
        primary <<= 1;
 | 
			
		||||
    }
 | 
			
		||||
    return primary;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AltTabPopup.prototype = {
 | 
			
		||||
const AltTabPopup = new Lang.Class({
 | 
			
		||||
    Name: 'AltTabPopup',
 | 
			
		||||
 | 
			
		||||
    _init : function() {
 | 
			
		||||
        this.actor = new Shell.GenericContainer({ name: 'altTabPopup',
 | 
			
		||||
                                                  reactive: true,
 | 
			
		||||
@@ -48,6 +58,7 @@ AltTabPopup.prototype = {
 | 
			
		||||
        this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
 | 
			
		||||
 | 
			
		||||
        this._haveModal = false;
 | 
			
		||||
        this._modifierMask = 0;
 | 
			
		||||
 | 
			
		||||
        this._currentApp = 0;
 | 
			
		||||
        this._currentWindow = -1;
 | 
			
		||||
@@ -121,16 +132,50 @@ AltTabPopup.prototype = {
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    show : function(backward, binding) {
 | 
			
		||||
    _getAppLists: function() {
 | 
			
		||||
        let tracker = Shell.WindowTracker.get_default();
 | 
			
		||||
        let appSys = Shell.AppSystem.get_default();
 | 
			
		||||
        let apps = appSys.get_running ();
 | 
			
		||||
        let allApps = appSys.get_running ();
 | 
			
		||||
 | 
			
		||||
        if (!apps.length)
 | 
			
		||||
        let screen = global.screen;
 | 
			
		||||
        let display = screen.get_display();
 | 
			
		||||
        let windows = display.get_tab_list(Meta.TabList.NORMAL, 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)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (!Main.pushModal(this.actor))
 | 
			
		||||
            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;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        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));
 | 
			
		||||
@@ -138,7 +183,7 @@ AltTabPopup.prototype = {
 | 
			
		||||
        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(apps, this);
 | 
			
		||||
        this._appSwitcher = new AppSwitcher(localApps, otherApps, 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));
 | 
			
		||||
@@ -152,7 +197,7 @@ AltTabPopup.prototype = {
 | 
			
		||||
        this.actor.get_allocation_box();
 | 
			
		||||
 | 
			
		||||
        // Make the initial selection
 | 
			
		||||
        if (binding == 'switch_group') {
 | 
			
		||||
        if (binding == 'switch-group') {
 | 
			
		||||
            if (backward) {
 | 
			
		||||
                this._select(0, this._appIcons[0].cachedWindows.length - 1);
 | 
			
		||||
            } else {
 | 
			
		||||
@@ -161,9 +206,9 @@ AltTabPopup.prototype = {
 | 
			
		||||
                else
 | 
			
		||||
                    this._select(0, 0);
 | 
			
		||||
            }
 | 
			
		||||
        } else if (binding == 'switch_group_backward') {
 | 
			
		||||
        } else if (binding == 'switch-group-backward') {
 | 
			
		||||
            this._select(0, this._appIcons[0].cachedWindows.length - 1);
 | 
			
		||||
        } else if (binding == 'switch_windows_backward') {
 | 
			
		||||
        } else if (binding == 'switch-windows-backward') {
 | 
			
		||||
            this._select(this._appIcons.length - 1);
 | 
			
		||||
        } else if (this._appIcons.length == 1) {
 | 
			
		||||
            this._select(0);
 | 
			
		||||
@@ -179,7 +224,7 @@ AltTabPopup.prototype = {
 | 
			
		||||
        // details.) So we check now. (Have to do this after updating
 | 
			
		||||
        // selection.)
 | 
			
		||||
        let [x, y, mods] = global.get_pointer();
 | 
			
		||||
        if (!(mods & Gdk.ModifierType.MOD1_MASK)) {
 | 
			
		||||
        if (!(mods & this._modifierMask)) {
 | 
			
		||||
            this._finish();
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
@@ -256,7 +301,7 @@ AltTabPopup.prototype = {
 | 
			
		||||
 | 
			
		||||
    _keyReleaseEvent : function(actor, event) {
 | 
			
		||||
        let [x, y, mods] = global.get_pointer();
 | 
			
		||||
        let state = mods & Clutter.ModifierType.MOD1_MASK;
 | 
			
		||||
        let state = mods & this._modifierMask;
 | 
			
		||||
 | 
			
		||||
        if (state == 0)
 | 
			
		||||
            this._finish();
 | 
			
		||||
@@ -493,13 +538,11 @@ AltTabPopup.prototype = {
 | 
			
		||||
                           onComplete: Lang.bind(this, function () { this.thumbnailsVisible = true; })
 | 
			
		||||
                         });
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function SwitcherList(squareItems) {
 | 
			
		||||
    this._init(squareItems);
 | 
			
		||||
}
 | 
			
		||||
const SwitcherList = new Lang.Class({
 | 
			
		||||
    Name: 'SwitcherList',
 | 
			
		||||
 | 
			
		||||
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));
 | 
			
		||||
@@ -636,11 +679,10 @@ SwitcherList.prototype = {
 | 
			
		||||
                this._items[this._highlighted].add_style_pseudo_class('selected');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let monitor = Main.layoutManager.primaryMonitor;
 | 
			
		||||
        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)
 | 
			
		||||
        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)
 | 
			
		||||
            this._scrollToRight();
 | 
			
		||||
        else if (posX < 0)
 | 
			
		||||
            this._scrollToLeft();
 | 
			
		||||
@@ -805,15 +847,13 @@ SwitcherList.prototype = {
 | 
			
		||||
        // 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);
 | 
			
		||||
 | 
			
		||||
function AppIcon(app) {
 | 
			
		||||
    this._init(app);
 | 
			
		||||
}
 | 
			
		||||
const AppIcon = new Lang.Class({
 | 
			
		||||
    Name: 'AppIcon',
 | 
			
		||||
 | 
			
		||||
AppIcon.prototype = {
 | 
			
		||||
    _init: function(app) {
 | 
			
		||||
        this.app = app;
 | 
			
		||||
        this.actor = new St.BoxLayout({ style_class: 'alt-tab-app',
 | 
			
		||||
@@ -831,35 +871,31 @@ AppIcon.prototype = {
 | 
			
		||||
        this._iconBin.set_size(size, size);
 | 
			
		||||
        this._iconBin.child = this.icon;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function AppSwitcher(apps, altTabPopup) {
 | 
			
		||||
    this._init(apps, altTabPopup);
 | 
			
		||||
}
 | 
			
		||||
const AppSwitcher = new Lang.Class({
 | 
			
		||||
    Name: 'AppSwitcher',
 | 
			
		||||
    Extends: SwitcherList,
 | 
			
		||||
 | 
			
		||||
AppSwitcher.prototype = {
 | 
			
		||||
    __proto__ : SwitcherList.prototype,
 | 
			
		||||
    _init : function(localApps, otherApps, altTabPopup) {
 | 
			
		||||
        this.parent(true);
 | 
			
		||||
 | 
			
		||||
    _init : function(apps, altTabPopup) {
 | 
			
		||||
        SwitcherList.prototype._init.call(this, true);
 | 
			
		||||
 | 
			
		||||
        // Construct the AppIcons, sort by time, add to the popup
 | 
			
		||||
        // Construct the AppIcons, add to the popup
 | 
			
		||||
        let activeWorkspace = global.screen.get_active_workspace();
 | 
			
		||||
        let workspaceIcons = [];
 | 
			
		||||
        let otherIcons = [];
 | 
			
		||||
        for (let i = 0; i < apps.length; i++) {
 | 
			
		||||
            let appIcon = new AppIcon(apps[i]);
 | 
			
		||||
        for (let i = 0; i < localApps.length; i++) {
 | 
			
		||||
            let appIcon = new AppIcon(localApps[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();
 | 
			
		||||
            if (this._hasWindowsOnWorkspace(appIcon, activeWorkspace))
 | 
			
		||||
              workspaceIcons.push(appIcon);
 | 
			
		||||
            else
 | 
			
		||||
              otherIcons.push(appIcon);
 | 
			
		||||
            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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        workspaceIcons.sort(Lang.bind(this, this._sortAppIcon));
 | 
			
		||||
        otherIcons.sort(Lang.bind(this, this._sortAppIcon));
 | 
			
		||||
 | 
			
		||||
        this.icons = [];
 | 
			
		||||
        this._arrows = [];
 | 
			
		||||
@@ -921,7 +957,7 @@ AppSwitcher.prototype = {
 | 
			
		||||
 | 
			
		||||
    _allocate: function (actor, box, flags) {
 | 
			
		||||
        // Allocate the main list items
 | 
			
		||||
        SwitcherList.prototype._allocate.call(this, actor, box, flags);
 | 
			
		||||
        this.parent(actor, box, flags);
 | 
			
		||||
 | 
			
		||||
        let arrowHeight = Math.floor(this.actor.get_theme_node().get_padding(St.Side.BOTTOM) / 3);
 | 
			
		||||
        let arrowWidth = arrowHeight * 2;
 | 
			
		||||
@@ -976,7 +1012,7 @@ AppSwitcher.prototype = {
 | 
			
		||||
                this._arrows[this._curApp].remove_style_pseudo_class('highlighted');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SwitcherList.prototype.highlight.call(this, n, justOutline);
 | 
			
		||||
        this.parent(n, justOutline);
 | 
			
		||||
        this._curApp = n;
 | 
			
		||||
 | 
			
		||||
        if (this._curApp != -1) {
 | 
			
		||||
@@ -999,31 +1035,15 @@ AppSwitcher.prototype = {
 | 
			
		||||
 | 
			
		||||
        if (appIcon.cachedWindows.length == 1)
 | 
			
		||||
            arrow.hide();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _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,
 | 
			
		||||
const ThumbnailList = new Lang.Class({
 | 
			
		||||
    Name: 'ThumbnailList',
 | 
			
		||||
    Extends: SwitcherList,
 | 
			
		||||
 | 
			
		||||
    _init : function(windows) {
 | 
			
		||||
        SwitcherList.prototype._init.call(this);
 | 
			
		||||
        this.parent(false);
 | 
			
		||||
 | 
			
		||||
        let activeWorkspace = global.screen.get_active_workspace();
 | 
			
		||||
 | 
			
		||||
@@ -1101,7 +1121,7 @@ ThumbnailList.prototype = {
 | 
			
		||||
        // Make sure we only do this once
 | 
			
		||||
        this._thumbnailBins = new Array();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function _drawArrow(area, side) {
 | 
			
		||||
    let themeNode = area.get_theme_node();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
@@ -26,11 +26,9 @@ const MAX_APPLICATION_WORK_MILLIS = 75;
 | 
			
		||||
const MENU_POPUP_TIMEOUT = 600;
 | 
			
		||||
const SCROLL_TIME = 0.1;
 | 
			
		||||
 | 
			
		||||
function AlphabeticalView() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const AlphabeticalView = new Lang.Class({
 | 
			
		||||
    Name: 'AlphabeticalView',
 | 
			
		||||
 | 
			
		||||
AlphabeticalView.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._grid = new IconGrid.IconGrid({ xAlign: St.Align.START });
 | 
			
		||||
        this._appSystem = Shell.AppSystem.get_default();
 | 
			
		||||
@@ -130,13 +128,11 @@ AlphabeticalView.prototype = {
 | 
			
		||||
            this._addApp(app);
 | 
			
		||||
         }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function ViewByCategories() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const ViewByCategories = new Lang.Class({
 | 
			
		||||
    Name: 'ViewByCategories',
 | 
			
		||||
 | 
			
		||||
ViewByCategories.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._appSystem = Shell.AppSystem.get_default();
 | 
			
		||||
        this.actor = new St.BoxLayout({ style_class: 'all-app' });
 | 
			
		||||
@@ -281,16 +277,14 @@ ViewByCategories.prototype = {
 | 
			
		||||
                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.
 | 
			
		||||
 */
 | 
			
		||||
function AllAppDisplay() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const AllAppDisplay = new Lang.Class({
 | 
			
		||||
    Name: 'AllAppDisplay',
 | 
			
		||||
 | 
			
		||||
AllAppDisplay.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._appSystem = Shell.AppSystem.get_default();
 | 
			
		||||
        this._appSystem.connect('installed-changed', Lang.bind(this, function() {
 | 
			
		||||
@@ -306,17 +300,15 @@ AllAppDisplay.prototype = {
 | 
			
		||||
    _redisplay: function() {
 | 
			
		||||
        this._appView.refresh();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function AppSearchProvider() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AppSearchProvider.prototype = {
 | 
			
		||||
    __proto__: Search.SearchProvider.prototype,
 | 
			
		||||
const AppSearchProvider = new Lang.Class({
 | 
			
		||||
    Name: 'AppSearchProvider',
 | 
			
		||||
    Extends: Search.SearchProvider,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        Search.SearchProvider.prototype._init.call(this, _("APPLICATIONS"));
 | 
			
		||||
        this.parent(_("APPLICATIONS"));
 | 
			
		||||
 | 
			
		||||
        this._appSys = Shell.AppSystem.get_default();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -364,17 +356,15 @@ AppSearchProvider.prototype = {
 | 
			
		||||
        let icon = new AppWellIcon(app);
 | 
			
		||||
        return icon.actor;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function SettingsSearchProvider() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SettingsSearchProvider.prototype = {
 | 
			
		||||
    __proto__: Search.SearchProvider.prototype,
 | 
			
		||||
const SettingsSearchProvider = new Lang.Class({
 | 
			
		||||
    Name: 'SettingsSearchProvider',
 | 
			
		||||
    Extends: Search.SearchProvider,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        Search.SearchProvider.prototype._init.call(this, _("SETTINGS"));
 | 
			
		||||
        this.parent(_("SETTINGS"));
 | 
			
		||||
 | 
			
		||||
        this._appSys = Shell.AppSystem.get_default();
 | 
			
		||||
        this._gnomecc = this._appSys.lookup_app('gnome-control-center.desktop');
 | 
			
		||||
    },
 | 
			
		||||
@@ -412,35 +402,28 @@ SettingsSearchProvider.prototype = {
 | 
			
		||||
        let icon = new AppWellIcon(app);
 | 
			
		||||
        return icon.actor;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function AppIcon(app, params) {
 | 
			
		||||
    this._init(app, params);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AppIcon.prototype = {
 | 
			
		||||
    __proto__:  IconGrid.BaseIcon.prototype,
 | 
			
		||||
const AppIcon = new Lang.Class({
 | 
			
		||||
    Name: 'AppIcon',
 | 
			
		||||
    Extends: IconGrid.BaseIcon,
 | 
			
		||||
 | 
			
		||||
    _init : function(app, params) {
 | 
			
		||||
        this.app = app;
 | 
			
		||||
 | 
			
		||||
        let label = this.app.get_name();
 | 
			
		||||
 | 
			
		||||
        IconGrid.BaseIcon.prototype._init.call(this,
 | 
			
		||||
                                               label,
 | 
			
		||||
                                               params);
 | 
			
		||||
        this.parent(label, params);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    createIcon: function(iconSize) {
 | 
			
		||||
        return this.app.create_icon_texture(iconSize);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function AppWellIcon(app, iconParams, onActivateOverride) {
 | 
			
		||||
    this._init(app, iconParams, onActivateOverride);
 | 
			
		||||
}
 | 
			
		||||
const AppWellIcon = new Lang.Class({
 | 
			
		||||
    Name: 'AppWellIcon',
 | 
			
		||||
 | 
			
		||||
AppWellIcon.prototype = {
 | 
			
		||||
    _init : function(app, iconParams, onActivateOverride) {
 | 
			
		||||
        this.app = app;
 | 
			
		||||
        this.actor = new St.Button({ style_class: 'app-well-app',
 | 
			
		||||
@@ -559,7 +542,7 @@ AppWellIcon.prototype = {
 | 
			
		||||
            this._menu.connect('activate-window', Lang.bind(this, function (menu, window) {
 | 
			
		||||
                this.activateWindow(window);
 | 
			
		||||
            }));
 | 
			
		||||
            this._menu.connect('popup', Lang.bind(this, function (menu, isPoppedUp) {
 | 
			
		||||
            this._menu.connect('open-state-changed', Lang.bind(this, function (menu, isPoppedUp) {
 | 
			
		||||
                if (!isPoppedUp)
 | 
			
		||||
                    this._onMenuPoppedDown();
 | 
			
		||||
            }));
 | 
			
		||||
@@ -620,22 +603,19 @@ AppWellIcon.prototype = {
 | 
			
		||||
    getDragActorSource: function() {
 | 
			
		||||
        return this.icon.icon;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(AppWellIcon.prototype);
 | 
			
		||||
 | 
			
		||||
function AppIconMenu(source) {
 | 
			
		||||
    this._init(source);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AppIconMenu.prototype = {
 | 
			
		||||
    __proto__: PopupMenu.PopupMenu.prototype,
 | 
			
		||||
const AppIconMenu = new Lang.Class({
 | 
			
		||||
    Name: 'AppIconMenu',
 | 
			
		||||
    Extends: PopupMenu.PopupMenu,
 | 
			
		||||
 | 
			
		||||
    _init: function(source) {
 | 
			
		||||
        let side = St.Side.LEFT;
 | 
			
		||||
        if (St.Widget.get_default_direction() == St.TextDirection.RTL)
 | 
			
		||||
            side = St.Side.RIGHT;
 | 
			
		||||
 | 
			
		||||
        PopupMenu.PopupMenu.prototype._init.call(this, source.actor, 0.5, side);
 | 
			
		||||
        this.parent(source.actor, 0.5, side);
 | 
			
		||||
 | 
			
		||||
        // We want to keep the item hovered while the menu is up
 | 
			
		||||
        this.blockSourceEvents = true;
 | 
			
		||||
@@ -643,7 +623,6 @@ AppIconMenu.prototype = {
 | 
			
		||||
        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');
 | 
			
		||||
 | 
			
		||||
@@ -707,14 +686,6 @@ AppIconMenu.prototype = {
 | 
			
		||||
        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;
 | 
			
		||||
@@ -732,5 +703,5 @@ AppIconMenu.prototype = {
 | 
			
		||||
        }
 | 
			
		||||
        this.close();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(AppIconMenu.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
@@ -6,11 +6,9 @@ const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
 | 
			
		||||
function AppFavorites() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const AppFavorites = new Lang.Class({
 | 
			
		||||
    Name: 'AppFavorites',
 | 
			
		||||
 | 
			
		||||
AppFavorites.prototype = {
 | 
			
		||||
    FAVORITE_APPS_KEY: 'favorite-apps',
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
@@ -122,7 +120,7 @@ AppFavorites.prototype = {
 | 
			
		||||
            this._addFavorite(appId, pos);
 | 
			
		||||
        }));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(AppFavorites.prototype);
 | 
			
		||||
 | 
			
		||||
var appFavoritesInstance = null;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
@@ -16,69 +15,58 @@ const SETTING_ENABLE_AUTOMOUNT = 'automount';
 | 
			
		||||
 | 
			
		||||
const AUTORUN_EXPIRE_TIMEOUT_SECS = 10;
 | 
			
		||||
 | 
			
		||||
const ConsoleKitSessionIface = {
 | 
			
		||||
    name: 'org.freedesktop.ConsoleKit.Session',
 | 
			
		||||
    methods: [{ name: 'IsActive',
 | 
			
		||||
                inSignature: '',
 | 
			
		||||
                outSignature: 'b' }],
 | 
			
		||||
    signals: [{ name: 'ActiveChanged',
 | 
			
		||||
                inSignature: 'b' }]
 | 
			
		||||
};
 | 
			
		||||
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 = DBus.makeProxyClass(ConsoleKitSessionIface);
 | 
			
		||||
const ConsoleKitSessionProxy = Gio.DBusProxy.makeProxyWrapper(ConsoleKitSessionIface);
 | 
			
		||||
 | 
			
		||||
const ConsoleKitManagerIface = {
 | 
			
		||||
    name: 'org.freedesktop.ConsoleKit.Manager',
 | 
			
		||||
    methods: [{ name: 'GetCurrentSession',
 | 
			
		||||
                inSignature: '',
 | 
			
		||||
                outSignature: 'o' }]
 | 
			
		||||
};
 | 
			
		||||
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() {
 | 
			
		||||
    this._init();
 | 
			
		||||
};
 | 
			
		||||
    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) });
 | 
			
		||||
 | 
			
		||||
ConsoleKitManager.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.sessionActive = true;
 | 
			
		||||
    self.connect('notify::g-name-owner', function() {
 | 
			
		||||
        if (self.g_name_owner) {
 | 
			
		||||
            self.GetCurrentSessionRemote(function([session]) {
 | 
			
		||||
                self._ckSession = new ConsoleKitSessionProxy(Gio.DBus.system, 'org.freedesktop.ConsoleKit', session);
 | 
			
		||||
 | 
			
		||||
        DBus.system.proxifyObject(this,
 | 
			
		||||
                                  'org.freedesktop.ConsoleKit',
 | 
			
		||||
                                  '/org/freedesktop/ConsoleKit/Manager');
 | 
			
		||||
                self._ckSession.connectSignal('ActiveChanged', function(object, senderName, [isActive]) {
 | 
			
		||||
                    self.sessionActive = isActive;
 | 
			
		||||
                });
 | 
			
		||||
                self._ckSession.IsActiveRemote(function([isActive]) {
 | 
			
		||||
                    self.sessionActive = isActive;
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
        } else {
 | 
			
		||||
            self.sessionActive = true;
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
        DBus.system.watch_name('org.freedesktop.ConsoleKit',
 | 
			
		||||
                               false, // do not launch a name-owner if none exists
 | 
			
		||||
                               Lang.bind(this, this._onManagerAppeared),
 | 
			
		||||
                               Lang.bind(this, this._onManagerVanished));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onManagerAppeared: function(owner) {
 | 
			
		||||
        this.GetCurrentSessionRemote(Lang.bind(this, this._onCurrentSession));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onManagerVanished: function(oldOwner) {
 | 
			
		||||
        this.sessionActive = true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onCurrentSession: function(session) {
 | 
			
		||||
        this._ckSession = new ConsoleKitSessionProxy(DBus.system, 'org.freedesktop.ConsoleKit', session);
 | 
			
		||||
 | 
			
		||||
        this._ckSession.connect
 | 
			
		||||
            ('ActiveChanged', Lang.bind(this, function(object, isActive) {
 | 
			
		||||
                this.sessionActive = isActive;            
 | 
			
		||||
            }));
 | 
			
		||||
        this._ckSession.IsActiveRemote(Lang.bind(this, function(isActive) {
 | 
			
		||||
            this.sessionActive = isActive;            
 | 
			
		||||
        }));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
DBus.proxifyPrototype(ConsoleKitManager.prototype, ConsoleKitManagerIface);
 | 
			
		||||
 | 
			
		||||
function AutomountManager() {
 | 
			
		||||
    this._init();
 | 
			
		||||
    self.init(null);
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AutomountManager.prototype = {
 | 
			
		||||
const AutomountManager = new Lang.Class({
 | 
			
		||||
    Name: 'AutomountManager',
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
 | 
			
		||||
        this._volumeQueue = [];
 | 
			
		||||
@@ -86,9 +74,8 @@ AutomountManager.prototype = {
 | 
			
		||||
        this.ckListener = new ConsoleKitManager();
 | 
			
		||||
 | 
			
		||||
        this._ssProxy = new ScreenSaver.ScreenSaverProxy();
 | 
			
		||||
        this._ssProxy.connect('ActiveChanged',
 | 
			
		||||
                              Lang.bind(this,
 | 
			
		||||
                                        this._screenSaverActiveChanged));
 | 
			
		||||
        this._ssProxy.connectSignal('ActiveChanged',
 | 
			
		||||
                                    Lang.bind(this, this._screenSaverActiveChanged));
 | 
			
		||||
 | 
			
		||||
        this._volumeMonitor = Gio.VolumeMonitor.get();
 | 
			
		||||
 | 
			
		||||
@@ -111,7 +98,7 @@ AutomountManager.prototype = {
 | 
			
		||||
        Mainloop.idle_add(Lang.bind(this, this._startupMountAll));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _screenSaverActiveChanged: function(object, isActive) {
 | 
			
		||||
    _screenSaverActiveChanged: function(object, senderName, [isActive]) {
 | 
			
		||||
        if (!isActive) {
 | 
			
		||||
            this._volumeQueue.forEach(Lang.bind(this, function(volume) {
 | 
			
		||||
                this._checkAndMountVolume(volume);
 | 
			
		||||
@@ -209,10 +196,14 @@ AutomountManager.prototype = {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 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
 | 
			
		||||
            // 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.
 | 
			
		||||
@@ -275,4 +266,4 @@ AutomountManager.prototype = {
 | 
			
		||||
            return false;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
@@ -23,8 +22,6 @@ const AutorunSetting = {
 | 
			
		||||
    ASK: 3
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const HOTPLUG_ICON_SIZE = 16;
 | 
			
		||||
 | 
			
		||||
// misc utils
 | 
			
		||||
function ignoreAutorunForMount(mount) {
 | 
			
		||||
    let root = mount.get_root();
 | 
			
		||||
@@ -64,31 +61,23 @@ function startAppForMount(app, mount) {
 | 
			
		||||
 | 
			
		||||
/******************************************/
 | 
			
		||||
 | 
			
		||||
const HotplugSnifferIface = {
 | 
			
		||||
    name: 'org.gnome.Shell.HotplugSniffer',
 | 
			
		||||
    methods: [{ name: 'SniffURI',
 | 
			
		||||
                inSignature: 's',
 | 
			
		||||
                outSignature: 'as' }]
 | 
			
		||||
};
 | 
			
		||||
const HotplugSnifferIface = <interface name="org.gnome.Shell.HotplugSniffer">
 | 
			
		||||
<method name="SniffURI">
 | 
			
		||||
    <arg type="s" direction="in" />
 | 
			
		||||
    <arg type="as" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
const HotplugSniffer = function() {
 | 
			
		||||
    this._init();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
HotplugSniffer.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        DBus.session.proxifyObject(this,
 | 
			
		||||
const HotplugSnifferProxy = Gio.DBusProxy.makeProxyWrapper(HotplugSnifferIface);
 | 
			
		||||
function HotplugSniffer() {
 | 
			
		||||
    return new HotplugSnifferProxy(Gio.DBus.session,
 | 
			
		||||
                                   'org.gnome.Shell.HotplugSniffer',
 | 
			
		||||
                                   '/org/gnome/Shell/HotplugSniffer');
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
DBus.proxifyPrototype(HotplugSniffer.prototype, HotplugSnifferIface);
 | 
			
		||||
 | 
			
		||||
function ContentTypeDiscoverer(callback) {
 | 
			
		||||
    this._init(callback);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ContentTypeDiscoverer.prototype = {
 | 
			
		||||
const ContentTypeDiscoverer = new Lang.Class({
 | 
			
		||||
    Name: 'ContentTypeDiscoverer',
 | 
			
		||||
 | 
			
		||||
    _init: function(callback) {
 | 
			
		||||
        this._callback = callback;
 | 
			
		||||
    },
 | 
			
		||||
@@ -116,9 +105,8 @@ ContentTypeDiscoverer.prototype = {
 | 
			
		||||
            let root = mount.get_root();
 | 
			
		||||
 | 
			
		||||
            let hotplugSniffer = new HotplugSniffer();
 | 
			
		||||
            hotplugSniffer.SniffURIRemote
 | 
			
		||||
                (root.get_uri(), DBus.CALL_FLAG_START,
 | 
			
		||||
                 Lang.bind(this, function(contentTypes) {
 | 
			
		||||
            hotplugSniffer.SniffURIRemote(root.get_uri(),
 | 
			
		||||
                 Lang.bind(this, function([contentTypes]) {
 | 
			
		||||
                     this._emitCallback(mount, contentTypes);
 | 
			
		||||
                 }));
 | 
			
		||||
        }
 | 
			
		||||
@@ -146,13 +134,11 @@ ContentTypeDiscoverer.prototype = {
 | 
			
		||||
 | 
			
		||||
        this._callback(mount, apps, contentTypes);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function AutorunManager() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const AutorunManager = new Lang.Class({
 | 
			
		||||
    Name: 'AutorunManager',
 | 
			
		||||
 | 
			
		||||
AutorunManager.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._volumeMonitor = Gio.VolumeMonitor.get();
 | 
			
		||||
 | 
			
		||||
@@ -269,22 +255,19 @@ AutorunManager.prototype = {
 | 
			
		||||
                + ': ' + e.toString());
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function AutorunResidentSource() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AutorunResidentSource.prototype = {
 | 
			
		||||
    __proto__: MessageTray.Source.prototype,
 | 
			
		||||
const AutorunResidentSource = new Lang.Class({
 | 
			
		||||
    Name: 'AutorunResidentSource',
 | 
			
		||||
    Extends: MessageTray.Source,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        MessageTray.Source.prototype._init.call(this, _('Removable Devices'));
 | 
			
		||||
        this.parent(_("Removable Devices"));
 | 
			
		||||
 | 
			
		||||
        this._mounts = [];
 | 
			
		||||
 | 
			
		||||
        this._notification = new AutorunResidentNotification(this);
 | 
			
		||||
        this._setSummaryIcon(this.createNotificationIcon(HOTPLUG_ICON_SIZE));
 | 
			
		||||
        this._setSummaryIcon(this.createNotificationIcon());
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addMount: function(mount, apps) {
 | 
			
		||||
@@ -329,24 +312,19 @@ AutorunResidentSource.prototype = {
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    createNotificationIcon: function(iconSize) {
 | 
			
		||||
    createNotificationIcon: function() {
 | 
			
		||||
        return new St.Icon ({ icon_name: 'media-removable',
 | 
			
		||||
                              icon_type: St.IconType.FULLCOLOR,
 | 
			
		||||
                              icon_size: iconSize ? iconSize : this.ICON_SIZE });
 | 
			
		||||
                              icon_size: this.ICON_SIZE });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function AutorunResidentNotification(source) {
 | 
			
		||||
    this._init(source);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AutorunResidentNotification.prototype = {
 | 
			
		||||
    __proto__: MessageTray.Notification.prototype,
 | 
			
		||||
const AutorunResidentNotification = new Lang.Class({
 | 
			
		||||
    Name: 'AutorunResidentNotification',
 | 
			
		||||
    Extends: MessageTray.Notification,
 | 
			
		||||
 | 
			
		||||
    _init: function(source) {
 | 
			
		||||
        MessageTray.Notification.prototype._init.call(this, source,
 | 
			
		||||
                                                      source.title, null,
 | 
			
		||||
                                                      { customContent: true });
 | 
			
		||||
        this.parent(source, source.title, null, { customContent: true });
 | 
			
		||||
 | 
			
		||||
        // set the notification as resident
 | 
			
		||||
        this.setResident(true);
 | 
			
		||||
@@ -420,13 +398,11 @@ AutorunResidentNotification.prototype = {
 | 
			
		||||
 | 
			
		||||
        return item;
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function AutorunTransientDispatcher() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const AutorunTransientDispatcher = new Lang.Class({
 | 
			
		||||
    Name: 'AutorunTransientDispatcher',
 | 
			
		||||
 | 
			
		||||
AutorunTransientDispatcher.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._sources = [];
 | 
			
		||||
        this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
 | 
			
		||||
@@ -493,7 +469,7 @@ AutorunTransientDispatcher.prototype = {
 | 
			
		||||
        let app = null;
 | 
			
		||||
 | 
			
		||||
        if (setting == AutorunSetting.RUN) {
 | 
			
		||||
            app = Gio.app_info_get_default_for_type(type, false);
 | 
			
		||||
            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);
 | 
			
		||||
        }
 | 
			
		||||
@@ -517,46 +493,38 @@ AutorunTransientDispatcher.prototype = {
 | 
			
		||||
        // destroy the notification source
 | 
			
		||||
        source.destroy();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function AutorunTransientSource(mount, apps) {
 | 
			
		||||
    this._init(mount, apps);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AutorunTransientSource.prototype = {
 | 
			
		||||
    __proto__: MessageTray.Source.prototype,
 | 
			
		||||
const AutorunTransientSource = new Lang.Class({
 | 
			
		||||
    Name: 'AutorunTransientSource',
 | 
			
		||||
    Extends: MessageTray.Source,
 | 
			
		||||
 | 
			
		||||
    _init: function(mount, apps) {
 | 
			
		||||
        MessageTray.Source.prototype._init.call(this, mount.get_name());
 | 
			
		||||
        this.parent(mount.get_name());
 | 
			
		||||
 | 
			
		||||
        this.mount = mount;
 | 
			
		||||
        this.apps = apps;
 | 
			
		||||
 | 
			
		||||
        this._notification = new AutorunTransientNotification(this);
 | 
			
		||||
        this._setSummaryIcon(this.createNotificationIcon(this.ICON_SIZE));
 | 
			
		||||
        this._setSummaryIcon(this.createNotificationIcon());
 | 
			
		||||
 | 
			
		||||
        // add ourselves as a source, and popup the notification
 | 
			
		||||
        Main.messageTray.add(this);
 | 
			
		||||
        this.notify(this._notification);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    createNotificationIcon: function(iconSize) {
 | 
			
		||||
    createNotificationIcon: function() {
 | 
			
		||||
        return new St.Icon({ gicon: this.mount.get_icon(),
 | 
			
		||||
                             icon_size: iconSize ? iconSize : this.ICON_SIZE });
 | 
			
		||||
                             icon_size: this.ICON_SIZE });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function AutorunTransientNotification(source) {
 | 
			
		||||
    this._init(source);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AutorunTransientNotification.prototype = {
 | 
			
		||||
    __proto__: MessageTray.Notification.prototype,
 | 
			
		||||
const AutorunTransientNotification = new Lang.Class({
 | 
			
		||||
    Name: 'AutorunTransientNotification',
 | 
			
		||||
    Extends: MessageTray.Notification,
 | 
			
		||||
 | 
			
		||||
    _init: function(source) {
 | 
			
		||||
        MessageTray.Notification.prototype._init.call(this, source,
 | 
			
		||||
                                                      source.title, null,
 | 
			
		||||
                                                      { customContent: true });
 | 
			
		||||
        this.parent(source, source.title, null, { customContent: true });
 | 
			
		||||
 | 
			
		||||
        this._box = new St.BoxLayout({ style_class: 'hotplug-transient-box',
 | 
			
		||||
                                       vertical: true });
 | 
			
		||||
@@ -631,5 +599,5 @@ AutorunTransientNotification.prototype = {
 | 
			
		||||
 | 
			
		||||
        return button;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
@@ -21,11 +21,9 @@ const POPUP_ANIMATION_TIME = 0.15;
 | 
			
		||||
 * placed.  The arrow position may be controlled via setArrowOrigin().
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
function BoxPointer(side, binProperties) {
 | 
			
		||||
    this._init(side, binProperties);
 | 
			
		||||
}
 | 
			
		||||
const BoxPointer = new Lang.Class({
 | 
			
		||||
    Name: 'BoxPointer',
 | 
			
		||||
 | 
			
		||||
BoxPointer.prototype = {
 | 
			
		||||
    _init: function(arrowSide, binProperties) {
 | 
			
		||||
        this._arrowSide = arrowSide;
 | 
			
		||||
        this._arrowOrigin = 0;
 | 
			
		||||
@@ -46,6 +44,7 @@ BoxPointer.prototype = {
 | 
			
		||||
        this._yOffset = 0;
 | 
			
		||||
        this._xPosition = 0;
 | 
			
		||||
        this._yPosition = 0;
 | 
			
		||||
        this._sourceAlignment = 0.5;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    show: function(animate, onComplete) {
 | 
			
		||||
@@ -75,7 +74,7 @@ BoxPointer.prototype = {
 | 
			
		||||
        Tweener.addTween(this, { opacity: 255,
 | 
			
		||||
                                 xOffset: 0,
 | 
			
		||||
                                 yOffset: 0,
 | 
			
		||||
                                 transition: "linear",
 | 
			
		||||
                                 transition: 'linear',
 | 
			
		||||
                                 onComplete: onComplete,
 | 
			
		||||
                                 time: POPUP_ANIMATION_TIME });
 | 
			
		||||
    },
 | 
			
		||||
@@ -106,7 +105,7 @@ BoxPointer.prototype = {
 | 
			
		||||
        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();
 | 
			
		||||
@@ -180,7 +179,7 @@ BoxPointer.prototype = {
 | 
			
		||||
        this.bin.allocate(childBox, flags);
 | 
			
		||||
 | 
			
		||||
        if (this._sourceActor && this._sourceActor.mapped)
 | 
			
		||||
            this._reposition(this._sourceActor, this._alignment);
 | 
			
		||||
            this._reposition(this._sourceActor, this._arrowAlignment);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _drawBorder: function(area) {
 | 
			
		||||
@@ -312,24 +311,37 @@ BoxPointer.prototype = {
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
 | 
			
		||||
        this._sourceActor = sourceActor;
 | 
			
		||||
        this._alignment = alignment;
 | 
			
		||||
        this._arrowAlignment = alignment;
 | 
			
		||||
 | 
			
		||||
        this._reposition(sourceActor, 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) {
 | 
			
		||||
        // 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) / 2;
 | 
			
		||||
        let sourceCenterY = sourceAllocation.y1 + sourceContentBox.y1 + (sourceContentBox.y2 - sourceContentBox.y1) / 2;
 | 
			
		||||
        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 [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 primary = Main.layoutManager.primaryMonitor;
 | 
			
		||||
        let monitor = Main.layoutManager.findMonitorForActor(sourceActor);
 | 
			
		||||
        let themeNode = this.actor.get_theme_node();
 | 
			
		||||
        let borderWidth = themeNode.get_length('-arrow-border-width');
 | 
			
		||||
        let arrowBase = themeNode.get_length('-arrow-base');
 | 
			
		||||
@@ -364,8 +376,8 @@ BoxPointer.prototype = {
 | 
			
		||||
        case St.Side.BOTTOM:
 | 
			
		||||
            resX = sourceCenterX - (halfMargin + (natWidth - margin) * alignment);
 | 
			
		||||
 | 
			
		||||
            resX = Math.max(resX, primary.x + 10);
 | 
			
		||||
            resX = Math.min(resX, primary.x + primary.width - (10 + natWidth));
 | 
			
		||||
            resX = Math.max(resX, monitor.x + 10);
 | 
			
		||||
            resX = Math.min(resX, monitor.x + monitor.width - (10 + natWidth));
 | 
			
		||||
            this.setArrowOrigin(sourceCenterX - resX);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
@@ -373,8 +385,8 @@ BoxPointer.prototype = {
 | 
			
		||||
        case St.Side.RIGHT:
 | 
			
		||||
            resY = sourceCenterY - (halfMargin + (natHeight - margin) * alignment);
 | 
			
		||||
 | 
			
		||||
            resY = Math.max(resY, primary.y + 10);
 | 
			
		||||
            resY = Math.min(resY, primary.y + primary.height - (10 + natHeight));
 | 
			
		||||
            resY = Math.max(resY, monitor.y + 10);
 | 
			
		||||
            resY = Math.min(resY, monitor.y + monitor.height - (10 + natHeight));
 | 
			
		||||
 | 
			
		||||
            this.setArrowOrigin(sourceCenterY - resY);
 | 
			
		||||
            break;
 | 
			
		||||
@@ -438,4 +450,4 @@ BoxPointer.prototype = {
 | 
			
		||||
    get opacity() {
 | 
			
		||||
        return this.actor.opacity;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
@@ -156,28 +155,24 @@ function _getEventDayAbbreviation(dayNumber) {
 | 
			
		||||
 | 
			
		||||
// Abstraction for an appointment/event in a calendar
 | 
			
		||||
 | 
			
		||||
function CalendarEvent(date, end, summary, allDay) {
 | 
			
		||||
    this._init(date, end, summary, allDay);
 | 
			
		||||
}
 | 
			
		||||
const CalendarEvent = new Lang.Class({
 | 
			
		||||
    Name: 'CalendarEvent',
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
function EmptyEventSource() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const EmptyEventSource = new Lang.Class({
 | 
			
		||||
    Name: 'EmptyEventSource',
 | 
			
		||||
 | 
			
		||||
EmptyEventSource.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -192,33 +187,32 @@ EmptyEventSource.prototype = {
 | 
			
		||||
    hasEvents: function(day) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(EmptyEventSource.prototype);
 | 
			
		||||
 | 
			
		||||
const CalendarServerIface = {
 | 
			
		||||
    name: 'org.gnome.Shell.CalendarServer',
 | 
			
		||||
    methods: [{ name: 'GetEvents',
 | 
			
		||||
                inSignature: 'xxb',
 | 
			
		||||
                outSignature: 'a(sssbxxa{sv})' }],
 | 
			
		||||
    signals: [{ name: 'Changed',
 | 
			
		||||
                inSignature: '' }]
 | 
			
		||||
};
 | 
			
		||||
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 CalendarServer = function () {
 | 
			
		||||
    this._init();
 | 
			
		||||
};
 | 
			
		||||
const CalendarServerInfo  = Gio.DBusInterfaceInfo.new_for_xml(CalendarServerIface);
 | 
			
		||||
 | 
			
		||||
CalendarServer.prototype = {
 | 
			
		||||
     _init: function() {
 | 
			
		||||
         DBus.session.proxifyObject(this, 'org.gnome.Shell.CalendarServer', '/org/gnome/Shell/CalendarServer');
 | 
			
		||||
     }
 | 
			
		||||
};
 | 
			
		||||
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) });
 | 
			
		||||
 | 
			
		||||
DBus.proxifyPrototype(CalendarServer.prototype, CalendarServerIface);
 | 
			
		||||
 | 
			
		||||
// an implementation that reads data from a session bus service
 | 
			
		||||
function DBusEventSource(owner) {
 | 
			
		||||
    this._init(owner);
 | 
			
		||||
    self.init(null);
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function _datesEqual(a, b) {
 | 
			
		||||
@@ -239,18 +233,22 @@ 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',
 | 
			
		||||
 | 
			
		||||
DBusEventSource.prototype = {
 | 
			
		||||
    _init: function(owner) {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._resetCache();
 | 
			
		||||
 | 
			
		||||
        this._dbusProxy = new CalendarServer(owner);
 | 
			
		||||
        this._dbusProxy.connect('Changed', Lang.bind(this, this._onChanged));
 | 
			
		||||
        this._dbusProxy = new CalendarServer();
 | 
			
		||||
        this._dbusProxy.connectSignal('Changed', Lang.bind(this, this._onChanged));
 | 
			
		||||
 | 
			
		||||
        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));
 | 
			
		||||
        this._dbusProxy.connect('notify::g-name-owner', Lang.bind(this, function() {
 | 
			
		||||
            if (this._dbusProxy.g_name_owner)
 | 
			
		||||
                this._onNameAppeared();
 | 
			
		||||
            else
 | 
			
		||||
                this._onNameVanished();
 | 
			
		||||
        }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _resetCache: function() {
 | 
			
		||||
@@ -273,7 +271,7 @@ DBusEventSource.prototype = {
 | 
			
		||||
        this._loadEvents(false);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onEventsReceived: function(appointments) {
 | 
			
		||||
    _onEventsReceived: function([appointments]) {
 | 
			
		||||
        let newEvents = [];
 | 
			
		||||
        if (appointments != null) {
 | 
			
		||||
            for (let n = 0; n < appointments.length; n++) {
 | 
			
		||||
@@ -296,9 +294,9 @@ DBusEventSource.prototype = {
 | 
			
		||||
 | 
			
		||||
    _loadEvents: function(forceReload) {
 | 
			
		||||
        if (this._curRequestBegin && this._curRequestEnd){
 | 
			
		||||
            let callFlags = 0;
 | 
			
		||||
            let callFlags = Gio.DBusCallFlags.NO_AUTO_START;
 | 
			
		||||
            if (forceReload)
 | 
			
		||||
                callFlags |= DBus.CALL_FLAG_START;
 | 
			
		||||
                callFlags = Gio.DBusCallFlags.NONE;
 | 
			
		||||
            this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000,
 | 
			
		||||
                                            this._curRequestEnd.getTime() / 1000,
 | 
			
		||||
                                            forceReload,
 | 
			
		||||
@@ -339,17 +337,15 @@ DBusEventSource.prototype = {
 | 
			
		||||
 | 
			
		||||
        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.
 | 
			
		||||
function Calendar(eventSource) {
 | 
			
		||||
    this._init(eventSource);
 | 
			
		||||
}
 | 
			
		||||
const Calendar = new Lang.Class({
 | 
			
		||||
    Name: 'Calendar',
 | 
			
		||||
 | 
			
		||||
Calendar.prototype = {
 | 
			
		||||
    _init: function(eventSource) {
 | 
			
		||||
        if (eventSource) {
 | 
			
		||||
            this._eventSource = eventSource;
 | 
			
		||||
@@ -615,15 +611,13 @@ Calendar.prototype = {
 | 
			
		||||
        if (this._eventSource)
 | 
			
		||||
            this._eventSource.requestRange(beginDate, iter, forceReload);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Signals.addSignalMethods(Calendar.prototype);
 | 
			
		||||
 | 
			
		||||
function EventsList(eventSource) {
 | 
			
		||||
    this._init(eventSource);
 | 
			
		||||
}
 | 
			
		||||
const EventsList = new Lang.Class({
 | 
			
		||||
    Name: 'EventsList',
 | 
			
		||||
 | 
			
		||||
EventsList.prototype = {
 | 
			
		||||
    _init: function(eventSource) {
 | 
			
		||||
        this.actor = new St.BoxLayout({ vertical: true, style_class: 'events-header-vbox'});
 | 
			
		||||
        this._date = new Date();
 | 
			
		||||
@@ -754,4 +748,4 @@ EventsList.prototype = {
 | 
			
		||||
            this._showOtherDay(this._date);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Folks = imports.gi.Folks
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
@@ -20,13 +20,12 @@ function launchContact(id) {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* This class represents a shown contact search result in the overview */
 | 
			
		||||
function Contact(id) {
 | 
			
		||||
    this._init(id);
 | 
			
		||||
}
 | 
			
		||||
const Contact = new Lang.Class({
 | 
			
		||||
    Name: 'Contact',
 | 
			
		||||
 | 
			
		||||
Contact.prototype = {
 | 
			
		||||
    _init: function(id) {
 | 
			
		||||
        this.individual = Shell.ContactSystem.get_default().get_individual(id);
 | 
			
		||||
        this._contactSys = Shell.ContactSystem.get_default();
 | 
			
		||||
        this.individual = this._contactSys.get_individual(id);
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.Bin({ style_class: 'contact',
 | 
			
		||||
                                  reactive: true,
 | 
			
		||||
@@ -56,7 +55,12 @@ Contact.prototype = {
 | 
			
		||||
                               x_align: St.Align.START,
 | 
			
		||||
                               y_align: St.Align.MIDDLE });
 | 
			
		||||
 | 
			
		||||
        let aliasText = this.individual.alias || _("Unknown");
 | 
			
		||||
        let email = this._contactSys.get_email_for_display(this.individual);
 | 
			
		||||
        let aliasText = this.individual.alias     ||
 | 
			
		||||
                        this.individual.full_name ||
 | 
			
		||||
                        this.individual.nickname  ||
 | 
			
		||||
                        email                     ||
 | 
			
		||||
                        _("Unknown");
 | 
			
		||||
        let aliasLabel = new St.Label({ text: aliasText,
 | 
			
		||||
                                        style_class: 'contact-details-alias' });
 | 
			
		||||
        details.add(aliasLabel, { x_fill: true,
 | 
			
		||||
@@ -125,19 +129,16 @@ Contact.prototype = {
 | 
			
		||||
            return tc.load_icon_name(null, 'avatar-default', St.IconType.FULLCOLOR, size);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Searches for and returns contacts */
 | 
			
		||||
function ContactSearchProvider() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ContactSearchProvider.prototype = {
 | 
			
		||||
    __proto__: Search.SearchProvider.prototype,
 | 
			
		||||
const ContactSearchProvider = new Lang.Class({
 | 
			
		||||
    Name: 'ContactSearchProvider',
 | 
			
		||||
    Extends: Search.SearchProvider,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        Search.SearchProvider.prototype._init.call(this, _("CONTACTS"));
 | 
			
		||||
        this.parent(_("CONTACTS"));
 | 
			
		||||
        this._contactSys = Shell.ContactSystem.get_default();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -176,4 +177,4 @@ ContactSearchProvider.prototype = {
 | 
			
		||||
    activateResult: function(id, params) {
 | 
			
		||||
        launchContact(id);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gdk = imports.gi.Gdk;
 | 
			
		||||
@@ -22,11 +22,9 @@ const SortGroup = {
 | 
			
		||||
    BOTTOM: 2
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function CtrlAltTabManager() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const CtrlAltTabManager = new Lang.Class({
 | 
			
		||||
    Name: 'CtrlAltTabManager',
 | 
			
		||||
 | 
			
		||||
CtrlAltTabManager.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._items = [];
 | 
			
		||||
        this._focusManager = St.FocusManager.get_for_stage(global.stage);
 | 
			
		||||
@@ -94,7 +92,7 @@ CtrlAltTabManager.prototype = {
 | 
			
		||||
        return a.x - b.x;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    popup: function(backwards) {
 | 
			
		||||
    popup: function(backwards, mask) {
 | 
			
		||||
        // Start with the set of focus groups that are currently mapped
 | 
			
		||||
        let items = this._items.filter(function (item) { return item.proxy.mapped; });
 | 
			
		||||
 | 
			
		||||
@@ -123,19 +121,26 @@ CtrlAltTabManager.prototype = {
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        items.sort(Lang.bind(this, this._sortItems));
 | 
			
		||||
        new CtrlAltTabPopup().show(items, backwards);
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
                                      }));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function mod(a, b) {
 | 
			
		||||
    return (a + b) % b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function CtrlAltTabPopup() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const CtrlAltTabPopup = new Lang.Class({
 | 
			
		||||
    Name: 'CtrlAltTabPopup',
 | 
			
		||||
 | 
			
		||||
CtrlAltTabPopup.prototype = {
 | 
			
		||||
    _init : function() {
 | 
			
		||||
        this.actor = new Shell.GenericContainer({ name: 'ctrlAltTabPopup',
 | 
			
		||||
                                                  reactive: true });
 | 
			
		||||
@@ -147,6 +152,7 @@ CtrlAltTabPopup.prototype = {
 | 
			
		||||
        this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
 | 
			
		||||
 | 
			
		||||
        this._haveModal = false;
 | 
			
		||||
        this._modifierMask = 0;
 | 
			
		||||
        this._selection = 0;
 | 
			
		||||
 | 
			
		||||
        Main.uiGroup.add_actor(this.actor);
 | 
			
		||||
@@ -177,16 +183,17 @@ CtrlAltTabPopup.prototype = {
 | 
			
		||||
        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.width - hPadding, 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._switcher.actor.allocate(childBox, flags);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    show : function(items, startBackwards) {
 | 
			
		||||
    show : function(items, startBackwards, mask) {
 | 
			
		||||
        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));
 | 
			
		||||
@@ -200,7 +207,7 @@ CtrlAltTabPopup.prototype = {
 | 
			
		||||
        this._select(this._selection);
 | 
			
		||||
 | 
			
		||||
        let [x, y, mods] = global.get_pointer();
 | 
			
		||||
        if (!(mods & Gdk.ModifierType.MOD1_MASK)) {
 | 
			
		||||
        if (!(mods & this._modifierMask)) {
 | 
			
		||||
            this._finish();
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
@@ -246,7 +253,7 @@ CtrlAltTabPopup.prototype = {
 | 
			
		||||
 | 
			
		||||
    _keyReleaseEvent : function(actor, event) {
 | 
			
		||||
        let [x, y, mods] = global.get_pointer();
 | 
			
		||||
        let state = mods & Clutter.ModifierType.MOD1_MASK;
 | 
			
		||||
        let state = mods & this._modifierMask;
 | 
			
		||||
 | 
			
		||||
        if (state == 0)
 | 
			
		||||
            this._finish();
 | 
			
		||||
@@ -292,17 +299,14 @@ CtrlAltTabPopup.prototype = {
 | 
			
		||||
        this._selection = num;
 | 
			
		||||
        this._switcher.highlight(num);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function CtrlAltTabSwitcher(items) {
 | 
			
		||||
    this._init(items);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CtrlAltTabSwitcher.prototype = {
 | 
			
		||||
    __proto__ : AltTab.SwitcherList.prototype,
 | 
			
		||||
const CtrlAltTabSwitcher = new Lang.Class({
 | 
			
		||||
    Name: 'CtrlAltTabSwitcher',
 | 
			
		||||
    Extends: AltTab.SwitcherList,
 | 
			
		||||
 | 
			
		||||
    _init : function(items) {
 | 
			
		||||
        AltTab.SwitcherList.prototype._init.call(this, true);
 | 
			
		||||
        this.parent(true);
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < items.length; i++)
 | 
			
		||||
            this._addIcon(items[i]);
 | 
			
		||||
@@ -325,4 +329,4 @@ CtrlAltTabSwitcher.prototype = {
 | 
			
		||||
 | 
			
		||||
        this.addItem(box, text);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										158
									
								
								js/ui/dash.js
									
									
									
									
									
								
							
							
						
						
									
										158
									
								
								js/ui/dash.js
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
@@ -19,11 +19,9 @@ const DASH_ANIMATION_TIME = 0.2;
 | 
			
		||||
 | 
			
		||||
// A container like StBin, but taking the child's scale into account
 | 
			
		||||
// when requesting a size
 | 
			
		||||
function DashItemContainer() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const DashItemContainer = new Lang.Class({
 | 
			
		||||
    Name: 'DashItemContainer',
 | 
			
		||||
 | 
			
		||||
DashItemContainer.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.actor = new Shell.GenericContainer({ style_class: 'dash-item-container' });
 | 
			
		||||
        this.actor.connect('get-preferred-width',
 | 
			
		||||
@@ -37,6 +35,7 @@ DashItemContainer.prototype = {
 | 
			
		||||
        this.child = null;
 | 
			
		||||
        this._childScale = 1;
 | 
			
		||||
        this._childOpacity = 255;
 | 
			
		||||
        this.animatingOut = false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _allocate: function(actor, box, flags) {
 | 
			
		||||
@@ -115,6 +114,7 @@ DashItemContainer.prototype = {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.animatingOut = true;
 | 
			
		||||
        this.childScale = 1.0;
 | 
			
		||||
        Tweener.addTween(this,
 | 
			
		||||
                         { childScale: 0.0,
 | 
			
		||||
@@ -155,17 +155,14 @@ DashItemContainer.prototype = {
 | 
			
		||||
    get childOpacity() {
 | 
			
		||||
        return this._childOpacity;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function RemoveFavoriteIcon() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RemoveFavoriteIcon.prototype = {
 | 
			
		||||
    __proto__: DashItemContainer.prototype,
 | 
			
		||||
const RemoveFavoriteIcon = new Lang.Class({
 | 
			
		||||
    Name: 'RemoveFavoriteIcon',
 | 
			
		||||
    Extends: DashItemContainer,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        DashItemContainer.prototype._init.call(this);
 | 
			
		||||
        this.parent();
 | 
			
		||||
 | 
			
		||||
        this._iconBin = new St.Bin({ style_class: 'remove-favorite' });
 | 
			
		||||
        this._iconActor = null;
 | 
			
		||||
@@ -177,12 +174,6 @@ RemoveFavoriteIcon.prototype = {
 | 
			
		||||
        this._iconBin._delegate = this;
 | 
			
		||||
 | 
			
		||||
        this.setChild(this._iconBin);
 | 
			
		||||
        this.hiding = false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    animateOutAndDestroy: function() {
 | 
			
		||||
        DashItemContainer.prototype.animateOutAndDestroy.call(this);
 | 
			
		||||
        this.hiding = true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createIcon: function(size) {
 | 
			
		||||
@@ -223,28 +214,21 @@ RemoveFavoriteIcon.prototype = {
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function DragPlaceholderItem() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DragPlaceholderItem.prototype = {
 | 
			
		||||
    __proto__: DashItemContainer.prototype,
 | 
			
		||||
const DragPlaceholderItem = new Lang.Class({
 | 
			
		||||
    Name: 'DragPlaceholderItem',
 | 
			
		||||
    Extends: DashItemContainer,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        DashItemContainer.prototype._init.call(this);
 | 
			
		||||
        this.setChild(new St.Bin({ style_class: 'dash-placeholder' }));
 | 
			
		||||
        this.parent();
 | 
			
		||||
        this.setChild(new St.Bin({ style_class: 'placeholder' }));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const Dash = new Lang.Class({
 | 
			
		||||
    Name: 'Dash',
 | 
			
		||||
 | 
			
		||||
function Dash() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Dash.prototype = {
 | 
			
		||||
    _init : function() {
 | 
			
		||||
        this._maxHeight = -1;
 | 
			
		||||
        this.iconSize = 64;
 | 
			
		||||
@@ -314,15 +298,12 @@ Dash.prototype = {
 | 
			
		||||
    _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);
 | 
			
		||||
    },
 | 
			
		||||
@@ -401,8 +382,18 @@ Dash.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _adjustIconSize: function() {
 | 
			
		||||
        let children = this._box.get_children();
 | 
			
		||||
        if (children.length == 0) {
 | 
			
		||||
        // 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) {
 | 
			
		||||
            this._box.add_style_pseudo_class('empty');
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
@@ -412,23 +403,45 @@ Dash.prototype = {
 | 
			
		||||
        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;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // 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 themeNode = this.actor.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;
 | 
			
		||||
 | 
			
		||||
        let iconSizes = [ 16, 22, 24, 32, 48, 64 ];
 | 
			
		||||
 | 
			
		||||
        let newIconSize = 16;
 | 
			
		||||
        for (let i = 0; i < iconSizes.length; i++) {
 | 
			
		||||
            if (iconSizes[i] < this.iconSize + diff)
 | 
			
		||||
            if (iconSizes[i] < availSize)
 | 
			
		||||
                newIconSize = iconSizes[i];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -459,11 +472,15 @@ Dash.prototype = {
 | 
			
		||||
            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'
 | 
			
		||||
                               transition: 'easeOutQuad',
 | 
			
		||||
                               onComplete: function() {
 | 
			
		||||
                                   icon._animating = false;
 | 
			
		||||
                               }
 | 
			
		||||
                             });
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
@@ -566,29 +583,7 @@ Dash.prototype = {
 | 
			
		||||
            this._box.insert_actor(addedItems[i].item.actor,
 | 
			
		||||
                                   addedItems[i].pos);
 | 
			
		||||
 | 
			
		||||
        // 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();
 | 
			
		||||
 | 
			
		||||
        // ... 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) {
 | 
			
		||||
            this._shownInitially = true;
 | 
			
		||||
            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
 | 
			
		||||
@@ -598,6 +593,15 @@ Dash.prototype = {
 | 
			
		||||
                item.actor.destroy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._adjustIconSize();
 | 
			
		||||
 | 
			
		||||
        // Skip animations on first run when adding the initial set
 | 
			
		||||
        // of items, to avoid all items zooming in at once
 | 
			
		||||
        if (!this._shownInitially) {
 | 
			
		||||
            this._shownInitially = true;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Don't animate item addition when the overview is hidden
 | 
			
		||||
        if (!Main.overview.visible)
 | 
			
		||||
            return;
 | 
			
		||||
@@ -684,6 +688,8 @@ Dash.prototype = {
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this._dragPlaceholder = new DragPlaceholderItem();
 | 
			
		||||
            this._dragPlaceholder.child.set_width (this.iconSize);
 | 
			
		||||
            this._dragPlaceholder.child.set_height (this.iconSize / 2);
 | 
			
		||||
            this._box.insert_actor(this._dragPlaceholder.actor,
 | 
			
		||||
                                   this._dragPlaceholderPos);
 | 
			
		||||
            if (fadeIn)
 | 
			
		||||
@@ -744,6 +750,6 @@ Dash.prototype = {
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Signals.addSignalMethods(Dash.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
@@ -40,12 +40,9 @@ function _onVertSepRepaint (area)
 | 
			
		||||
    cr.stroke();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function DateMenuButton() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DateMenuButton.prototype = {
 | 
			
		||||
    __proto__: PanelMenu.Button.prototype,
 | 
			
		||||
const DateMenuButton = new Lang.Class({
 | 
			
		||||
    Name: 'DateMenuButton',
 | 
			
		||||
    Extends: PanelMenu.Button,
 | 
			
		||||
 | 
			
		||||
    _init: function(params) {
 | 
			
		||||
        params = Params.parse(params, { showEvents: true });
 | 
			
		||||
@@ -57,10 +54,10 @@ DateMenuButton.prototype = {
 | 
			
		||||
        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.parent(menuAlignment);
 | 
			
		||||
 | 
			
		||||
        this._clock = new St.Label();
 | 
			
		||||
        this.actor.set_child(this._clock);
 | 
			
		||||
        this.actor.add_actor(this._clock);
 | 
			
		||||
 | 
			
		||||
        hbox = new St.BoxLayout({name: 'calendarArea' });
 | 
			
		||||
        this.menu.addActor(hbox);
 | 
			
		||||
@@ -239,4 +236,4 @@ DateMenuButton.prototype = {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								js/ui/dnd.js
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								js/ui/dnd.js
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
@@ -69,11 +69,9 @@ function removeDragMonitor(monitor) {
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function _Draggable(actor, params) {
 | 
			
		||||
    this._init(actor, params);
 | 
			
		||||
}
 | 
			
		||||
const _Draggable = new Lang.Class({
 | 
			
		||||
    Name: 'Draggable',
 | 
			
		||||
 | 
			
		||||
_Draggable.prototype = {
 | 
			
		||||
    _init : function(actor, params) {
 | 
			
		||||
        params = Params.parse(params, { manualMode: false,
 | 
			
		||||
                                        restoreOnSuccess: false,
 | 
			
		||||
@@ -596,7 +594,7 @@ _Draggable.prototype = {
 | 
			
		||||
        this._dragActor = undefined;
 | 
			
		||||
        currentDraggable = null;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Signals.addSignalMethods(_Draggable.prototype);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,16 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const DocInfo = imports.misc.docInfo;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const Search = imports.ui.search;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function DocSearchProvider() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DocSearchProvider.prototype = {
 | 
			
		||||
    __proto__: Search.SearchProvider.prototype,
 | 
			
		||||
const DocSearchProvider = new Lang.Class({
 | 
			
		||||
    Name: 'DocSearchProvider',
 | 
			
		||||
    Extends: Search.SearchProvider,
 | 
			
		||||
 | 
			
		||||
    _init: function(name) {
 | 
			
		||||
        Search.SearchProvider.prototype._init.call(this, _("RECENT ITEMS"));
 | 
			
		||||
        this.parent(_("RECENT ITEMS"));
 | 
			
		||||
        this._docManager = DocInfo.getDocManager();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -44,4 +41,4 @@ DocSearchProvider.prototype = {
 | 
			
		||||
    getSubsearchResultSet: function(previousResults, terms) {
 | 
			
		||||
        return this._docManager.subsearch(previousResults, terms);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 *
 | 
			
		||||
// -*- mode: js; js-indent-level: 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,19 @@
 | 
			
		||||
 * 02111-1307, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const AccountsService = imports.gi.AccountsService;
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
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,22 +43,23 @@ const _DIALOG_ICON_SIZE = 32;
 | 
			
		||||
 | 
			
		||||
const GSM_SESSION_MANAGER_LOGOUT_FORCE = 2;
 | 
			
		||||
 | 
			
		||||
const EndSessionDialogIface = {
 | 
			
		||||
    name: 'org.gnome.SessionManager.EndSessionDialog',
 | 
			
		||||
    methods: [{ name: 'Open',
 | 
			
		||||
                inSignature: 'uuuao',
 | 
			
		||||
                outSignature: ''
 | 
			
		||||
              }
 | 
			
		||||
             ],
 | 
			
		||||
    signals: [{ name: 'Canceled',
 | 
			
		||||
                inSignature: '',
 | 
			
		||||
              }],
 | 
			
		||||
    properties: []
 | 
			
		||||
};
 | 
			
		||||
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 logoutDialogContent = {
 | 
			
		||||
    subjectWithUser: _("Log Out %s"),
 | 
			
		||||
    subject: _("Log Out"),
 | 
			
		||||
    subjectWithUser: C_("title", "Log Out %s"),
 | 
			
		||||
    subject: C_("title", "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.",
 | 
			
		||||
@@ -72,12 +73,12 @@ const logoutDialogContent = {
 | 
			
		||||
    },
 | 
			
		||||
    endDescription: _("Logging out of the system."),
 | 
			
		||||
    confirmButtons: [{ signal: 'ConfirmedLogout',
 | 
			
		||||
                       label:  _("Log Out") }],
 | 
			
		||||
                       label:  C_("button", "Log Out") }],
 | 
			
		||||
    iconStyleClass: 'end-session-dialog-logout-icon'
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const shutdownDialogContent = {
 | 
			
		||||
    subject: _("Power Off"),
 | 
			
		||||
    subject: C_("title", "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.",
 | 
			
		||||
@@ -86,15 +87,15 @@ const shutdownDialogContent = {
 | 
			
		||||
    },
 | 
			
		||||
    endDescription: _("Powering off the system."),
 | 
			
		||||
    confirmButtons: [{ signal: 'ConfirmedReboot',
 | 
			
		||||
                       label:  _("Restart") },
 | 
			
		||||
                       label:  C_("button", "Restart") },
 | 
			
		||||
                     { signal: 'ConfirmedShutdown',
 | 
			
		||||
                       label:  _("Power Off") }],
 | 
			
		||||
                       label:  C_("button", "Power Off") }],
 | 
			
		||||
    iconName: 'system-shutdown',
 | 
			
		||||
    iconStyleClass: 'end-session-dialog-shutdown-icon'
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const restartDialogContent = {
 | 
			
		||||
    subject: _("Restart"),
 | 
			
		||||
    subject: C_("title", "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.",
 | 
			
		||||
@@ -103,7 +104,7 @@ const restartDialogContent = {
 | 
			
		||||
    },
 | 
			
		||||
    endDescription: _("Restarting the system."),
 | 
			
		||||
    confirmButtons: [{ signal: 'ConfirmedReboot',
 | 
			
		||||
                       label:  _("Restart") }],
 | 
			
		||||
                       label:  C_("button", "Restart") }],
 | 
			
		||||
    iconName: 'system-shutdown',
 | 
			
		||||
    iconStyleClass: 'end-session-dialog-shutdown-icon'
 | 
			
		||||
};
 | 
			
		||||
@@ -141,11 +142,9 @@ function findAppFromInhibitor(inhibitor) {
 | 
			
		||||
    return app;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function ListItem(app, reason) {
 | 
			
		||||
    this._init(app, reason);
 | 
			
		||||
}
 | 
			
		||||
const ListItem = new Lang.Class({
 | 
			
		||||
    Name: 'ListItem',
 | 
			
		||||
 | 
			
		||||
ListItem.prototype = {
 | 
			
		||||
    _init: function(app, reason) {
 | 
			
		||||
        this._app = app;
 | 
			
		||||
        this._reason = reason;
 | 
			
		||||
@@ -191,7 +190,7 @@ ListItem.prototype = {
 | 
			
		||||
        this.emit('activate');
 | 
			
		||||
        this._app.activate();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(ListItem.prototype);
 | 
			
		||||
 | 
			
		||||
// The logout timer only shows updates every 10 seconds
 | 
			
		||||
@@ -229,29 +228,19 @@ 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.
 | 
			
		||||
    let dialog = new EndSessionDialog();
 | 
			
		||||
    _endSessionDialog = new EndSessionDialog();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EndSessionDialog.prototype = {
 | 
			
		||||
    __proto__: ModalDialog.ModalDialog.prototype,
 | 
			
		||||
const EndSessionDialog = new Lang.Class({
 | 
			
		||||
    Name: 'EndSessionDialog',
 | 
			
		||||
    Extends: ModalDialog.ModalDialog,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'end-session-dialog' });
 | 
			
		||||
        this.parent({ styleClass: 'end-session-dialog' });
 | 
			
		||||
 | 
			
		||||
        this._user = AccountsService.UserManager.get_default().get_user(GLib.get_user_name());
 | 
			
		||||
 | 
			
		||||
@@ -326,6 +315,9 @@ EndSessionDialog.prototype = {
 | 
			
		||||
                                          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() {
 | 
			
		||||
@@ -439,26 +431,20 @@ EndSessionDialog.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    close: function() {
 | 
			
		||||
        ModalDialog.ModalDialog.prototype.close.call(this);
 | 
			
		||||
        DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
 | 
			
		||||
                                 'org.gnome.SessionManager.EndSessionDialog',
 | 
			
		||||
                                 'Closed', '', []);
 | 
			
		||||
        this.parent();
 | 
			
		||||
        this._dbusImpl.emit_signal('Closed', null);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    cancel: function() {
 | 
			
		||||
        this._stopTimer();
 | 
			
		||||
        DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
 | 
			
		||||
                                 'org.gnome.SessionManager.EndSessionDialog',
 | 
			
		||||
                                 'Canceled', '', []);
 | 
			
		||||
        this._dbusImpl.emit_signal('Canceled', null);
 | 
			
		||||
        this.close(global.get_current_time());
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _confirm: function(signal) {
 | 
			
		||||
        this._fadeOutDialog();
 | 
			
		||||
        this._stopTimer();
 | 
			
		||||
        DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
 | 
			
		||||
                                 'org.gnome.SessionManager.EndSessionDialog',
 | 
			
		||||
                                 signal, '', []);
 | 
			
		||||
        this._dbusImpl.emit_signal(signal, null);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onOpened: function() {
 | 
			
		||||
@@ -510,39 +496,41 @@ EndSessionDialog.prototype = {
 | 
			
		||||
        this._updateContent();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    OpenAsync: function(type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths, callback) {
 | 
			
		||||
    OpenAsync: function(parameters, invocation) {
 | 
			
		||||
        let [type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths] = parameters;
 | 
			
		||||
        this._totalSecondsToStayOpen = totalSecondsToStayOpen;
 | 
			
		||||
        this._inhibitors = [];
 | 
			
		||||
        this._applicationList.destroy_children();
 | 
			
		||||
        this._type = type;
 | 
			
		||||
 | 
			
		||||
        if (!(this._type in DialogContent))
 | 
			
		||||
            throw new DBus.DBusError('org.gnome.Shell.ModalDialog.TypeError',
 | 
			
		||||
                                     "Unknown dialog type requested");
 | 
			
		||||
        if (!(this._type in DialogContent)) {
 | 
			
		||||
            invocation.report_dbus_error('org.gnome.Shell.ModalDialog.TypeError',
 | 
			
		||||
                                         "Unknown dialog type requested");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < inhibitorObjectPaths.length; i++) {
 | 
			
		||||
            let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i]);
 | 
			
		||||
            let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i], Lang.bind(this, function(proxy, error) {
 | 
			
		||||
                this._onInhibitorLoaded(proxy);
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
            inhibitor.connect('is-loaded',
 | 
			
		||||
                              Lang.bind(this, function() {
 | 
			
		||||
                                  this._onInhibitorLoaded(inhibitor);
 | 
			
		||||
                              }));
 | 
			
		||||
            this._inhibitors.push(inhibitor);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._updateButtons();
 | 
			
		||||
 | 
			
		||||
        if (!this.open(timestamp))
 | 
			
		||||
            throw new DBus.DBusError('org.gnome.Shell.ModalDialog.GrabError',
 | 
			
		||||
                                     "Cannot grab pointer and keyboard");
 | 
			
		||||
        if (!this.open(timestamp)) {
 | 
			
		||||
            invocation.report_dbus_error('org.gnome.Shell.ModalDialog.GrabError',
 | 
			
		||||
                                         "Cannot grab pointer and keyboard");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._updateContent();
 | 
			
		||||
 | 
			
		||||
        let signalId = this.connect('opened',
 | 
			
		||||
                                    Lang.bind(this, function() {
 | 
			
		||||
                                        callback();
 | 
			
		||||
                                        invocation.return_value(null);
 | 
			
		||||
                                        this.disconnect(signalId);
 | 
			
		||||
                                    }));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
DBus.conformExport(EndSessionDialog.prototype, EndSessionDialogIface);
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
imports.gi.versions.Clutter = '1.0';
 | 
			
		||||
imports.gi.versions.Gio = '2.0';
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
@@ -22,6 +22,7 @@ const ExtensionState = {
 | 
			
		||||
    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.
 | 
			
		||||
@@ -62,6 +63,9 @@ const extensionMeta = {};
 | 
			
		||||
const extensions = {};
 | 
			
		||||
// Maps uuid -> extension state object (returned from init())
 | 
			
		||||
const extensionStateObjs = {};
 | 
			
		||||
// Contains the order that extensions were enabled in.
 | 
			
		||||
const extensionOrder = [];
 | 
			
		||||
 | 
			
		||||
// Arrays of uuids
 | 
			
		||||
var enabledExtensions;
 | 
			
		||||
// GFile for user extensions
 | 
			
		||||
@@ -212,6 +216,27 @@ function disableExtension(uuid) {
 | 
			
		||||
 | 
			
		||||
    let extensionState = extensionStateObjs[uuid];
 | 
			
		||||
 | 
			
		||||
    // "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 {
 | 
			
		||||
            extensionStateObjs[uuid].disable();
 | 
			
		||||
        } catch(e) {
 | 
			
		||||
            logExtensionError(uuid, e.toString());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        extensionState.disable();
 | 
			
		||||
    } catch(e) {
 | 
			
		||||
@@ -219,6 +244,17 @@ function disableExtension(uuid) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (let i = 0; i < order.length; i++) {
 | 
			
		||||
        let uuid = order[i];
 | 
			
		||||
        try {
 | 
			
		||||
            extensionStateObjs[uuid].enable();
 | 
			
		||||
        } catch(e) {
 | 
			
		||||
            logExtensionError(uuid, e.toString());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    extensionOrder.splice(orderIdx, 1);
 | 
			
		||||
 | 
			
		||||
    meta.state = ExtensionState.DISABLED;
 | 
			
		||||
    _signals.emit('extension-state-changed', meta);
 | 
			
		||||
}
 | 
			
		||||
@@ -228,11 +264,18 @@ function enableExtension(uuid) {
 | 
			
		||||
    if (!meta)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (meta.state == ExtensionState.INITIALIZED) {
 | 
			
		||||
        loadExtension(meta.dir, meta.type, true);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (meta.state != ExtensionState.DISABLED)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    let extensionState = extensionStateObjs[uuid];
 | 
			
		||||
 | 
			
		||||
    extensionOrder.push(uuid);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        extensionState.enable();
 | 
			
		||||
    } catch(e) {
 | 
			
		||||
@@ -254,7 +297,7 @@ function logExtensionError(uuid, message, state) {
 | 
			
		||||
                                               state: state });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function loadExtension(dir, enabled, type) {
 | 
			
		||||
function loadExtension(dir, type, enabled) {
 | 
			
		||||
    let info;
 | 
			
		||||
    let uuid = dir.get_basename();
 | 
			
		||||
 | 
			
		||||
@@ -289,7 +332,7 @@ function loadExtension(dir, enabled, type) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (extensions[uuid] != undefined) {
 | 
			
		||||
        logExtensionError(uuid, "extension already loaded");
 | 
			
		||||
        logExtensionError(uuid, 'extension already loaded');
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -303,14 +346,9 @@ function loadExtension(dir, enabled, type) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!versionCheck(meta['shell-version'], Config.PACKAGE_VERSION) ||
 | 
			
		||||
        (meta['js-version'] && !versionCheck(meta['js-version'], Config.GJS_VERSION))) {
 | 
			
		||||
        logExtensionError(uuid, 'extension is not compatible with current GNOME Shell and/or GJS version');
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    extensionMeta[uuid] = meta;
 | 
			
		||||
    meta.type = type;
 | 
			
		||||
    meta.dir = dir;
 | 
			
		||||
    meta.path = dir.get_path();
 | 
			
		||||
    meta.error = '';
 | 
			
		||||
 | 
			
		||||
@@ -324,6 +362,11 @@ function loadExtension(dir, enabled, type) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!enabled) {
 | 
			
		||||
        meta.state = ExtensionState.INITIALIZED;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let extensionJs = dir.get_child('extension.js');
 | 
			
		||||
    if (!extensionJs.query_exists(null)) {
 | 
			
		||||
        logExtensionError(uuid, 'Missing extension.js');
 | 
			
		||||
@@ -383,8 +426,7 @@ function loadExtension(dir, enabled, type) {
 | 
			
		||||
 | 
			
		||||
    meta.state = ExtensionState.DISABLED;
 | 
			
		||||
 | 
			
		||||
    if (enabled)
 | 
			
		||||
        enableExtension(uuid);
 | 
			
		||||
    enableExtension(uuid);
 | 
			
		||||
 | 
			
		||||
    _signals.emit('extension-loaded', meta.uuid);
 | 
			
		||||
    _signals.emit('extension-state-changed', meta);
 | 
			
		||||
@@ -444,13 +486,12 @@ function _loadExtensionsIn(dir, type) {
 | 
			
		||||
        let name = info.get_name();
 | 
			
		||||
        let child = dir.get_child(name);
 | 
			
		||||
        let enabled = enabledExtensions.indexOf(name) != -1;
 | 
			
		||||
        loadExtension(child, enabled, type);
 | 
			
		||||
        loadExtension(child, type, enabled);
 | 
			
		||||
    }
 | 
			
		||||
    fileEnum.close(null);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function loadExtensions() {
 | 
			
		||||
    _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';
 | 
			
		||||
@@ -458,17 +499,15 @@ function loadExtensions() {
 | 
			
		||||
        if (dir.query_exists(null))
 | 
			
		||||
            _loadExtensionsIn(dir, ExtensionType.SYSTEM);
 | 
			
		||||
    }
 | 
			
		||||
    _loadExtensionsIn(userExtensionsDir, ExtensionType.PER_USER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function InstallExtensionDialog(uuid, version_tag, name) {
 | 
			
		||||
    this._init(uuid, version_tag, name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
InstallExtensionDialog.prototype = {
 | 
			
		||||
    __proto__: ModalDialog.ModalDialog.prototype,
 | 
			
		||||
const InstallExtensionDialog = new Lang.Class({
 | 
			
		||||
    Name: 'InstallExtensionDialog',
 | 
			
		||||
    Extends: ModalDialog.ModalDialog,
 | 
			
		||||
 | 
			
		||||
    _init: function(uuid, version_tag, name) {
 | 
			
		||||
        ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'extension-dialog' });
 | 
			
		||||
        this.parent({ styleClass: 'extension-dialog' });
 | 
			
		||||
 | 
			
		||||
        this._uuid = uuid;
 | 
			
		||||
        this._version_tag = version_tag;
 | 
			
		||||
@@ -528,4 +567,4 @@ InstallExtensionDialog.prototype = {
 | 
			
		||||
 | 
			
		||||
        this.close(global.get_current_time());
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
@@ -10,11 +10,9 @@ const Params = imports.misc.params;
 | 
			
		||||
const ICON_SIZE = 48;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function BaseIcon(label, createIcon) {
 | 
			
		||||
    this._init(label, createIcon);
 | 
			
		||||
}
 | 
			
		||||
const BaseIcon = new Lang.Class({
 | 
			
		||||
    Name: 'BaseIcon',
 | 
			
		||||
 | 
			
		||||
BaseIcon.prototype = {
 | 
			
		||||
    _init : function(label, params) {
 | 
			
		||||
        params = Params.parse(params, { createIcon: null,
 | 
			
		||||
                                        setSizeManually: false,
 | 
			
		||||
@@ -149,13 +147,11 @@ BaseIcon.prototype = {
 | 
			
		||||
 | 
			
		||||
        this._createIconTexture(size);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function IconGrid(params) {
 | 
			
		||||
    this._init(params);
 | 
			
		||||
}
 | 
			
		||||
const IconGrid = new Lang.Class({
 | 
			
		||||
    Name: 'IconGrid',
 | 
			
		||||
 | 
			
		||||
IconGrid.prototype = {
 | 
			
		||||
    _init: function(params) {
 | 
			
		||||
        params = Params.parse(params, { rowLimit: null,
 | 
			
		||||
                                        columnLimit: null,
 | 
			
		||||
@@ -324,4 +320,4 @@ IconGrid.prototype = {
 | 
			
		||||
    visibleItemsCount: function() {
 | 
			
		||||
        return this._grid.get_children().length - this._grid.get_n_skip_paint();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Caribou = imports.gi.Caribou;
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
@@ -15,9 +15,11 @@ const Main = imports.ui.main;
 | 
			
		||||
const MessageTray = imports.ui.messageTray;
 | 
			
		||||
 | 
			
		||||
const KEYBOARD_SCHEMA = 'org.gnome.shell.keyboard';
 | 
			
		||||
const SHOW_KEYBOARD = 'show-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 = {
 | 
			
		||||
@@ -37,34 +39,31 @@ const PRETTY_KEYS = {
 | 
			
		||||
    'Alt_L': 'Alt'
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const CaribouKeyboardIface = {
 | 
			
		||||
    name: 'org.gnome.Caribou.Keyboard',
 | 
			
		||||
    methods:    [ { name: 'Show',
 | 
			
		||||
                    inSignature: 'u',
 | 
			
		||||
                    outSignature: ''
 | 
			
		||||
                  },
 | 
			
		||||
                  { name: 'Hide',
 | 
			
		||||
                    inSignature: 'u',
 | 
			
		||||
                    outSignature: ''
 | 
			
		||||
                  },
 | 
			
		||||
                  { name: 'SetCursorLocation',
 | 
			
		||||
                    inSignature: 'iiii',
 | 
			
		||||
                    outSignature: ''
 | 
			
		||||
                  },
 | 
			
		||||
                  { name: 'SetEntryLocation',
 | 
			
		||||
                    inSignature: 'iiii',
 | 
			
		||||
                    outSignature: ''
 | 
			
		||||
                  } ],
 | 
			
		||||
    properties: [ { name: 'Name',
 | 
			
		||||
                    signature: 's',
 | 
			
		||||
                    access: 'read' } ]
 | 
			
		||||
};
 | 
			
		||||
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>;
 | 
			
		||||
 | 
			
		||||
function Key() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
const Key = new Lang.Class({
 | 
			
		||||
    Name: 'Key',
 | 
			
		||||
 | 
			
		||||
Key.prototype = {
 | 
			
		||||
    _init : function(key) {
 | 
			
		||||
        this._key = key;
 | 
			
		||||
 | 
			
		||||
@@ -73,7 +72,7 @@ Key.prototype = {
 | 
			
		||||
        this._extended_keys = this._key.get_extended_keys();
 | 
			
		||||
        this._extended_keyboard = null;
 | 
			
		||||
 | 
			
		||||
        if (this._key.name == "Control_L" || this._key.name == "Alt_L")
 | 
			
		||||
        if (this._key.name == 'Control_L' || this._key.name == 'Alt_L')
 | 
			
		||||
            this._key.latch = true;
 | 
			
		||||
 | 
			
		||||
        this._key.connect('key-pressed', Lang.bind(this, function ()
 | 
			
		||||
@@ -190,15 +189,15 @@ Key.prototype = {
 | 
			
		||||
            this._boxPointer.hide(true);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function Keyboard() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
const Keyboard = new Lang.Class({
 | 
			
		||||
    // HACK: we can't set Name, because it collides with Name dbus property
 | 
			
		||||
    // Name: 'Keyboard',
 | 
			
		||||
 | 
			
		||||
Keyboard.prototype = {
 | 
			
		||||
    _init: function () {
 | 
			
		||||
        DBus.session.exportObject('/org/gnome/Caribou/Keyboard', this);
 | 
			
		||||
        this._impl = Gio.DBusExportedObject.wrapJSObject(CaribouKeyboardIface, this);
 | 
			
		||||
        this._impl.export(Gio.DBus.session, '/org/gnome/Caribou/Keyboard');
 | 
			
		||||
 | 
			
		||||
        this.actor = null;
 | 
			
		||||
 | 
			
		||||
@@ -207,6 +206,8 @@ Keyboard.prototype = {
 | 
			
		||||
 | 
			
		||||
        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();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -214,8 +215,8 @@ Keyboard.prototype = {
 | 
			
		||||
        this._redraw();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _settingsChanged: function () {
 | 
			
		||||
        this._enableKeyboard = this._keyboardSettings.get_boolean(SHOW_KEYBOARD);
 | 
			
		||||
    _settingsChanged: function (settings, key) {
 | 
			
		||||
        this._enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD);
 | 
			
		||||
        if (!this._enableKeyboard && !this._keyboard)
 | 
			
		||||
            return;
 | 
			
		||||
        if (this._enableKeyboard && this._keyboard &&
 | 
			
		||||
@@ -224,9 +225,20 @@ Keyboard.prototype = {
 | 
			
		||||
 | 
			
		||||
        if (this._keyboard)
 | 
			
		||||
            this._destroyKeyboard();
 | 
			
		||||
        if (this._enableKeyboard)
 | 
			
		||||
            this._setupKeyboard();
 | 
			
		||||
        else
 | 
			
		||||
 | 
			
		||||
        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);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -242,7 +254,7 @@ Keyboard.prototype = {
 | 
			
		||||
        this._destroySource();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _setupKeyboard: function() {
 | 
			
		||||
    _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);
 | 
			
		||||
@@ -259,20 +271,26 @@ Keyboard.prototype = {
 | 
			
		||||
 | 
			
		||||
        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));
 | 
			
		||||
        this._createSource();
 | 
			
		||||
 | 
			
		||||
        if (show)
 | 
			
		||||
            this.show();
 | 
			
		||||
        else
 | 
			
		||||
            this._createSource();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onKeyFocusChanged: function () {
 | 
			
		||||
        let focus = global.stage.key_focus;
 | 
			
		||||
 | 
			
		||||
        // Showing an extended key popup will grab focus, but ignore that
 | 
			
		||||
        if (focus && focus._extended_keys)
 | 
			
		||||
        // 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();
 | 
			
		||||
            this.Show(time);
 | 
			
		||||
        else
 | 
			
		||||
            this.hide();
 | 
			
		||||
            this.Hide(time);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _addKeys: function () {
 | 
			
		||||
@@ -301,7 +319,8 @@ Keyboard.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getTrayIcon: function () {
 | 
			
		||||
        let trayButton = new St.Button ({ label: "tray", style_class: 'keyboard-key' });
 | 
			
		||||
        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();
 | 
			
		||||
@@ -335,7 +354,7 @@ Keyboard.prototype = {
 | 
			
		||||
                    right_box.add(button.actor);
 | 
			
		||||
                else
 | 
			
		||||
                    left_box.add(button.actor);
 | 
			
		||||
                if (key.name == "Caribou_Prefs") {
 | 
			
		||||
                if (key.name == 'Caribou_Prefs') {
 | 
			
		||||
                    key.connect('key-released', Lang.bind(this, this.hide));
 | 
			
		||||
 | 
			
		||||
                    // Add new key for hiding message tray
 | 
			
		||||
@@ -472,6 +491,9 @@ Keyboard.prototype = {
 | 
			
		||||
 | 
			
		||||
    // D-Bus methods
 | 
			
		||||
    Show: function(timestamp) {
 | 
			
		||||
        if (!this._enableKeyboard)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (timestamp - this._timestamp < 0)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
@@ -480,6 +502,9 @@ Keyboard.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    Hide: function(timestamp) {
 | 
			
		||||
        if (!this._enableKeyboard)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (timestamp - this._timestamp < 0)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
@@ -488,29 +513,31 @@ Keyboard.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    SetCursorLocation: function(x, y, w, h) {
 | 
			
		||||
        this._setLocation(x, y);
 | 
			
		||||
        if (!this._enableKeyboard)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
//        this._setLocation(x, y);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    SetEntryLocation: function(x, y, w, h) {
 | 
			
		||||
        this._setLocation(x, y);
 | 
			
		||||
        if (!this._enableKeyboard)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
//        this._setLocation(x, y);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get Name() {
 | 
			
		||||
        return 'gnome-shell';
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
DBus.conformExport(Keyboard.prototype, CaribouKeyboardIface);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function KeyboardSource() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
KeyboardSource.prototype = {
 | 
			
		||||
    __proto__: MessageTray.Source.prototype,
 | 
			
		||||
const KeyboardSource = new Lang.Class({
 | 
			
		||||
    Name: 'KeyboardSource',
 | 
			
		||||
    Extends: MessageTray.Source,
 | 
			
		||||
 | 
			
		||||
    _init: function(keyboard) {
 | 
			
		||||
        this.parent(_("Keyboard"));
 | 
			
		||||
        this._keyboard = keyboard;
 | 
			
		||||
        MessageTray.Source.prototype._init.call(this, _("Keyboard"));
 | 
			
		||||
 | 
			
		||||
        this._setSummaryIcon(this.createNotificationIcon());
 | 
			
		||||
    },
 | 
			
		||||
@@ -521,7 +548,7 @@ KeyboardSource.prototype = {
 | 
			
		||||
                             icon_size: this.ICON_SIZE });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
     handleSummaryClick: function() {
 | 
			
		||||
    handleSummaryClick: function() {
 | 
			
		||||
        let event = Clutter.get_current_event();
 | 
			
		||||
        if (event.type() != Clutter.EventType.BUTTON_RELEASE)
 | 
			
		||||
            return false;
 | 
			
		||||
@@ -533,4 +560,4 @@ KeyboardSource.prototype = {
 | 
			
		||||
    open: function() {
 | 
			
		||||
        this._keyboard.show();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
@@ -17,11 +17,9 @@ const HOT_CORNER_ACTIVATION_TIMEOUT = 0.5;
 | 
			
		||||
const STARTUP_ANIMATION_TIME = 0.2;
 | 
			
		||||
const KEYBOARD_ANIMATION_TIME = 0.5;
 | 
			
		||||
 | 
			
		||||
function LayoutManager() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
const LayoutManager = new Lang.Class({
 | 
			
		||||
    Name: 'LayoutManager',
 | 
			
		||||
 | 
			
		||||
LayoutManager.prototype = {
 | 
			
		||||
    _init: function () {
 | 
			
		||||
        this._rtl = (St.Widget.get_default_direction() == St.TextDirection.RTL);
 | 
			
		||||
        this.monitors = [];
 | 
			
		||||
@@ -45,7 +43,9 @@ LayoutManager.prototype = {
 | 
			
		||||
        this.trayBox.connect('allocation-changed',
 | 
			
		||||
                             Lang.bind(this, this._updateTrayBarrier));
 | 
			
		||||
 | 
			
		||||
        this.keyboardBox = new St.BoxLayout({ name: 'keyboardBox' });
 | 
			
		||||
        this.keyboardBox = new St.BoxLayout({ name: 'keyboardBox',
 | 
			
		||||
                                              reactive: true,
 | 
			
		||||
                                              track_hover: true });
 | 
			
		||||
        this.addChrome(this.keyboardBox, { visibleInFullscreen: true });
 | 
			
		||||
        this._keyboardHeightNotifyId = 0;
 | 
			
		||||
 | 
			
		||||
@@ -214,10 +214,10 @@ LayoutManager.prototype = {
 | 
			
		||||
        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))
 | 
			
		||||
        if ((monitorLeft >= primaryLeft && monitorLeft < primaryRight) ||
 | 
			
		||||
            (monitorRight > primaryLeft && monitorRight <= primaryRight) ||
 | 
			
		||||
            (primaryLeft >= monitorLeft && primaryLeft < monitorRight) ||
 | 
			
		||||
            (primaryRight > monitorLeft && primaryRight <= monitorRight))
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
@@ -367,8 +367,12 @@ LayoutManager.prototype = {
 | 
			
		||||
    // Removes @actor from the chrome
 | 
			
		||||
    removeChrome: function(actor) {
 | 
			
		||||
        this._chrome.removeActor(actor);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    findMonitorForActor: function(actor) {
 | 
			
		||||
        return this._chrome.findMonitorForActor(actor);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(LayoutManager.prototype);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -376,11 +380,9 @@ Signals.addSignalMethods(LayoutManager.prototype);
 | 
			
		||||
//
 | 
			
		||||
// This class manages a "hot corner" that can toggle switching to
 | 
			
		||||
// overview.
 | 
			
		||||
function HotCorner() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const HotCorner = new Lang.Class({
 | 
			
		||||
    Name: 'HotCorner',
 | 
			
		||||
 | 
			
		||||
HotCorner.prototype = {
 | 
			
		||||
    _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
 | 
			
		||||
@@ -542,7 +544,7 @@ HotCorner.prototype = {
 | 
			
		||||
            return true;
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// This manages the shell "chrome"; the UI that's visible in the
 | 
			
		||||
@@ -555,11 +557,9 @@ const defaultParams = {
 | 
			
		||||
    affectsInputRegion: true
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function Chrome() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
const Chrome = new Lang.Class({
 | 
			
		||||
    Name: 'Chrome',
 | 
			
		||||
 | 
			
		||||
Chrome.prototype = {
 | 
			
		||||
    _init: function(layoutManager) {
 | 
			
		||||
        this._layoutManager = layoutManager;
 | 
			
		||||
 | 
			
		||||
@@ -581,12 +581,13 @@ Chrome.prototype = {
 | 
			
		||||
 | 
			
		||||
        this._screenSaverActive = false;
 | 
			
		||||
        this._screenSaverProxy = new ScreenSaver.ScreenSaverProxy();
 | 
			
		||||
        this._screenSaverProxy.connect('ActiveChanged', Lang.bind(this, this._onScreenSaverActiveChanged));
 | 
			
		||||
        this._screenSaverProxy.GetActiveRemote(Lang.bind(this,
 | 
			
		||||
            function(result, err) {
 | 
			
		||||
                if (!err)
 | 
			
		||||
                    this._onScreenSaverActiveChanged(this._screenSaverProxy, result);
 | 
			
		||||
            }));
 | 
			
		||||
        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();
 | 
			
		||||
    },
 | 
			
		||||
@@ -619,7 +620,7 @@ Chrome.prototype = {
 | 
			
		||||
        // 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])
 | 
			
		||||
            if (!params.hasOwnProperty(prop))
 | 
			
		||||
                params[prop] = ancestorData[prop];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -698,7 +699,7 @@ Chrome.prototype = {
 | 
			
		||||
            else if (this._inOverview)
 | 
			
		||||
                visible = true;
 | 
			
		||||
            else if (!actorData.visibleInFullscreen &&
 | 
			
		||||
                     this._findMonitorForActor(actorData.actor).inFullscreen)
 | 
			
		||||
                     this.findMonitorForActor(actorData.actor).inFullscreen)
 | 
			
		||||
                visible = false;
 | 
			
		||||
            else
 | 
			
		||||
                visible = true;
 | 
			
		||||
@@ -727,7 +728,7 @@ Chrome.prototype = {
 | 
			
		||||
        this._queueUpdateRegions();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onScreenSaverActiveChanged: function(proxy, screenSaverActive) {
 | 
			
		||||
    _onScreenSaverActiveChanged: function(screenSaverActive) {
 | 
			
		||||
        this._screenSaverActive = screenSaverActive;
 | 
			
		||||
        this._updateVisibility();
 | 
			
		||||
        this._queueUpdateRegions();
 | 
			
		||||
@@ -760,7 +761,7 @@ Chrome.prototype = {
 | 
			
		||||
 | 
			
		||||
    // 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) {
 | 
			
		||||
    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);
 | 
			
		||||
@@ -819,6 +820,18 @@ Chrome.prototype = {
 | 
			
		||||
                    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 &&
 | 
			
		||||
@@ -962,4 +975,4 @@ Chrome.prototype = {
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
@@ -30,11 +30,9 @@ 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.
 | 
			
		||||
 */
 | 
			
		||||
function Lightbox(container, params) {
 | 
			
		||||
    this._init(container, params);
 | 
			
		||||
}
 | 
			
		||||
const Lightbox = new Lang.Class({
 | 
			
		||||
    Name: 'Lightbox',
 | 
			
		||||
 | 
			
		||||
Lightbox.prototype = {
 | 
			
		||||
    _init : function(container, params) {
 | 
			
		||||
        params = Params.parse(params, { inhibitEvents: false,
 | 
			
		||||
                                        width: null,
 | 
			
		||||
@@ -196,4 +194,4 @@ Lightbox.prototype = {
 | 
			
		||||
 | 
			
		||||
        this.highlight(null);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,12 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
function Link(props) {
 | 
			
		||||
    this._init(props);
 | 
			
		||||
}
 | 
			
		||||
const Link = new Lang.Class({
 | 
			
		||||
    Name: 'Link',
 | 
			
		||||
 | 
			
		||||
Link.prototype = {
 | 
			
		||||
    _init : function(props) {
 | 
			
		||||
        let realProps = { reactive: true,
 | 
			
		||||
                          track_hover: true,
 | 
			
		||||
@@ -19,6 +17,5 @@ Link.prototype = {
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.Button(realProps);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(Link.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,7 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Cogl = imports.gi.Cogl;
 | 
			
		||||
const GConf = imports.gi.GConf;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
@@ -17,8 +16,10 @@ const Mainloop = imports.mainloop;
 | 
			
		||||
const History = imports.misc.history;
 | 
			
		||||
const ExtensionSystem = imports.ui.extensionSystem;
 | 
			
		||||
const Link = imports.ui.link;
 | 
			
		||||
const ShellEntry = imports.ui.shellEntry;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const JsParse = imports.misc.jsParse;
 | 
			
		||||
 | 
			
		||||
/* Imports...feel free to add here as needed */
 | 
			
		||||
var commandHeader = 'const Clutter = imports.gi.Clutter; ' +
 | 
			
		||||
@@ -40,12 +41,88 @@ var commandHeader = 'const Clutter = imports.gi.Clutter; ' +
 | 
			
		||||
                    'const r = Lang.bind(Main.lookingGlass, Main.lookingGlass.getResult); ';
 | 
			
		||||
 | 
			
		||||
const HISTORY_KEY = 'looking-glass-history';
 | 
			
		||||
// Time between tabs for them to count as a double-tab event
 | 
			
		||||
const AUTO_COMPLETE_DOUBLE_TAB_DELAY = 500;
 | 
			
		||||
const AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION = 0.2;
 | 
			
		||||
const AUTO_COMPLETE_GLOBAL_KEYWORDS = _getAutoCompleteGlobalKeywords();
 | 
			
		||||
 | 
			
		||||
function Notebook() {
 | 
			
		||||
    this._init();
 | 
			
		||||
function _getAutoCompleteGlobalKeywords() {
 | 
			
		||||
    const keywords = ['true', 'false', 'null', 'new'];
 | 
			
		||||
    // Don't add the private properties of window (i.e., ones starting with '_')
 | 
			
		||||
    const windowProperties = Object.getOwnPropertyNames(window).filter(function(a){ return a.charAt(0) != '_' });
 | 
			
		||||
    const headerProperties = JsParse.getDeclaredConstants(commandHeader);
 | 
			
		||||
 | 
			
		||||
    return keywords.concat(windowProperties).concat(headerProperties);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Notebook.prototype = {
 | 
			
		||||
const AutoComplete = new Lang.Class({
 | 
			
		||||
    Name: 'AutoComplete',
 | 
			
		||||
 | 
			
		||||
    _init: function(entry) {
 | 
			
		||||
        this._entry = entry;
 | 
			
		||||
        this._entry.connect('key-press-event', Lang.bind(this, this._entryKeyPressEvent));
 | 
			
		||||
        this._lastTabTime = global.get_current_time();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _processCompletionRequest: function(event) {
 | 
			
		||||
        if (event.completions.length == 0) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        // Unique match = go ahead and complete; multiple matches + single tab = complete the common starting string;
 | 
			
		||||
        // multiple matches + double tab = emit a suggest event with all possible options
 | 
			
		||||
        if (event.completions.length == 1) {
 | 
			
		||||
            this.additionalCompletionText(event.completions[0], event.attrHead);
 | 
			
		||||
            this.emit('completion', { completion: event.completions[0], type: 'whole-word' });
 | 
			
		||||
        } else if (event.completions.length > 1 && event.tabType === 'single') {
 | 
			
		||||
            let commonPrefix = JsParse.getCommonPrefix(event.completions);
 | 
			
		||||
 | 
			
		||||
            if (commonPrefix.length > 0) {
 | 
			
		||||
                this.additionalCompletionText(commonPrefix, event.attrHead);
 | 
			
		||||
                this.emit('completion', { completion: commonPrefix, type: 'prefix' });
 | 
			
		||||
                this.emit('suggest', { completions: event.completions});
 | 
			
		||||
            }
 | 
			
		||||
        } else if (event.completions.length > 1 && event.tabType === 'double') {
 | 
			
		||||
            this.emit('suggest', { completions: event.completions});
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _entryKeyPressEvent: function(actor, event) {
 | 
			
		||||
        let cursorPos = this._entry.clutter_text.get_cursor_position();
 | 
			
		||||
        let text = this._entry.get_text();
 | 
			
		||||
        if (cursorPos != -1) {
 | 
			
		||||
            text = text.slice(0, cursorPos);
 | 
			
		||||
        }
 | 
			
		||||
        if (event.get_key_symbol() == Clutter.Tab) {
 | 
			
		||||
            let [completions, attrHead] = JsParse.getCompletions(text, commandHeader, AUTO_COMPLETE_GLOBAL_KEYWORDS);
 | 
			
		||||
            let currTime = global.get_current_time();
 | 
			
		||||
            if ((currTime - this._lastTabTime) < AUTO_COMPLETE_DOUBLE_TAB_DELAY) {
 | 
			
		||||
                this._processCompletionRequest({ tabType: 'double',
 | 
			
		||||
                                                 completions: completions,
 | 
			
		||||
                                                 attrHead: attrHead });
 | 
			
		||||
            } else {
 | 
			
		||||
                this._processCompletionRequest({ tabType: 'single',
 | 
			
		||||
                                                 completions: completions,
 | 
			
		||||
                                                 attrHead: attrHead });
 | 
			
		||||
            }
 | 
			
		||||
            this._lastTabTime = currTime;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // Insert characters of text not already included in head at cursor position.  i.e., if text="abc" and head="a",
 | 
			
		||||
    // the string "bc" will be appended to this._entry
 | 
			
		||||
    additionalCompletionText: function(text, head) {
 | 
			
		||||
        let additionalCompletionText = text.slice(head.length);
 | 
			
		||||
        let cursorPos = this._entry.clutter_text.get_cursor_position();
 | 
			
		||||
 | 
			
		||||
        this._entry.clutter_text.insert_text(additionalCompletionText, cursorPos);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(AutoComplete.prototype);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const Notebook = new Lang.Class({
 | 
			
		||||
    Name: 'Notebook',
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.actor = new St.BoxLayout({ vertical: true });
 | 
			
		||||
 | 
			
		||||
@@ -150,25 +227,40 @@ Notebook.prototype = {
 | 
			
		||||
            return;
 | 
			
		||||
        let vAdjust = tabData.scrollView.vscroll.adjustment;
 | 
			
		||||
        vAdjust.value = vAdjust.upper - vAdjust.page_size;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    nextTab: function() {
 | 
			
		||||
        let nextIndex = this._selectedIndex;
 | 
			
		||||
        if (nextIndex < this._tabs.length - 1) {
 | 
			
		||||
            ++nextIndex;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.selectIndex(nextIndex);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    prevTab: function() {
 | 
			
		||||
        let prevIndex = this._selectedIndex;
 | 
			
		||||
        if (prevIndex > 0) {
 | 
			
		||||
            --prevIndex;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.selectIndex(prevIndex);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(Notebook.prototype);
 | 
			
		||||
 | 
			
		||||
function objectToString(o) {
 | 
			
		||||
    if (typeof(o) == typeof(objectToString)) {
 | 
			
		||||
        // special case this since the default is way, way too verbose
 | 
			
		||||
        return "<js function>";
 | 
			
		||||
        return '<js function>';
 | 
			
		||||
    } else {
 | 
			
		||||
        return "" + o;
 | 
			
		||||
        return '' + o;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function ObjLink(o, title) {
 | 
			
		||||
    this._init(o, title);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ObjLink.prototype = {
 | 
			
		||||
    __proto__: Link.Link,
 | 
			
		||||
const ObjLink = new Lang.Class({
 | 
			
		||||
    Name: 'ObjLink',
 | 
			
		||||
    Extends: Link.Link,
 | 
			
		||||
 | 
			
		||||
    _init: function(o, title) {
 | 
			
		||||
        let text;
 | 
			
		||||
@@ -178,7 +270,8 @@ ObjLink.prototype = {
 | 
			
		||||
            text = objectToString(o);
 | 
			
		||||
        text = GLib.markup_escape_text(text, -1);
 | 
			
		||||
        this._obj = o;
 | 
			
		||||
        Link.Link.prototype._init.call(this, { label: text });
 | 
			
		||||
 | 
			
		||||
        this.parent({ label: text });
 | 
			
		||||
        this.actor.get_child().single_line_mode = true;
 | 
			
		||||
        this.actor.connect('clicked', Lang.bind(this, this._onClicked));
 | 
			
		||||
    },
 | 
			
		||||
@@ -186,13 +279,11 @@ ObjLink.prototype = {
 | 
			
		||||
    _onClicked: function (link) {
 | 
			
		||||
        Main.lookingGlass.inspectObject(this._obj, this.actor);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function Result(command, o, index) {
 | 
			
		||||
    this._init(command, o, index);
 | 
			
		||||
}
 | 
			
		||||
const Result = new Lang.Class({
 | 
			
		||||
    Name: 'Result',
 | 
			
		||||
 | 
			
		||||
Result.prototype = {
 | 
			
		||||
    _init : function(command, o, index) {
 | 
			
		||||
        this.index = index;
 | 
			
		||||
        this.o = o;
 | 
			
		||||
@@ -214,13 +305,11 @@ Result.prototype = {
 | 
			
		||||
        padBin.add_actor(line);
 | 
			
		||||
        this.actor.add(padBin);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function WindowList() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const WindowList = new Lang.Class({
 | 
			
		||||
    Name: 'WindowList',
 | 
			
		||||
 | 
			
		||||
WindowList.prototype = {
 | 
			
		||||
    _init : function () {
 | 
			
		||||
        this.actor = new St.BoxLayout({ name: 'Windows', vertical: true, style: 'spacing: 8px' });
 | 
			
		||||
        let tracker = Shell.WindowTracker.get_default();
 | 
			
		||||
@@ -261,14 +350,12 @@ WindowList.prototype = {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(WindowList.prototype);
 | 
			
		||||
 | 
			
		||||
function ObjInspector() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const ObjInspector = new Lang.Class({
 | 
			
		||||
    Name: 'ObjInspector',
 | 
			
		||||
 | 
			
		||||
ObjInspector.prototype = {
 | 
			
		||||
    _init : function () {
 | 
			
		||||
        this._obj = null;
 | 
			
		||||
        this._previousObj = null;
 | 
			
		||||
@@ -322,7 +409,7 @@ ObjInspector.prototype = {
 | 
			
		||||
                    link = new St.Label({ text: '<error>' });
 | 
			
		||||
                }
 | 
			
		||||
                let hbox = new St.BoxLayout();
 | 
			
		||||
                let propText = propName + ": " + valueStr;
 | 
			
		||||
                let propText = propName + ': ' + valueStr;
 | 
			
		||||
                hbox.add(new St.Label({ text: propName + ': ' }));
 | 
			
		||||
                hbox.add(link);
 | 
			
		||||
                this._container.add_actor(hbox);
 | 
			
		||||
@@ -343,7 +430,7 @@ ObjInspector.prototype = {
 | 
			
		||||
            this.actor.move_anchor_point(Math.floor(sourceX + sourceWidth / 2),
 | 
			
		||||
                                         Math.floor(sourceY + sourceHeight / 2));
 | 
			
		||||
            Tweener.addTween(this.actor, { scale_x: 1, scale_y: 1,
 | 
			
		||||
                                           transition: "easeOutQuad",
 | 
			
		||||
                                           transition: 'easeOutQuad',
 | 
			
		||||
                                           time: 0.2 });
 | 
			
		||||
        } else {
 | 
			
		||||
            this.actor.set_scale(1, 1);
 | 
			
		||||
@@ -368,7 +455,7 @@ ObjInspector.prototype = {
 | 
			
		||||
    _onBack: function() {
 | 
			
		||||
        this.selectObject(this._previousObj, true);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function addBorderPaintHook(actor) {
 | 
			
		||||
    let signalId = actor.connect_after('paint',
 | 
			
		||||
@@ -394,11 +481,9 @@ function addBorderPaintHook(actor) {
 | 
			
		||||
    return signalId;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function Inspector() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const Inspector = new Lang.Class({
 | 
			
		||||
    Name: 'Inspector',
 | 
			
		||||
 | 
			
		||||
Inspector.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        let container = new Shell.GenericContainer({ width: 0,
 | 
			
		||||
                                                     height: 0 });
 | 
			
		||||
@@ -537,15 +622,13 @@ Inspector.prototype = {
 | 
			
		||||
            this._borderPaintId = addBorderPaintHook(this._target);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Signals.addSignalMethods(Inspector.prototype);
 | 
			
		||||
 | 
			
		||||
function ErrorLog() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const ErrorLog = new Lang.Class({
 | 
			
		||||
    Name: 'ErrorLog',
 | 
			
		||||
 | 
			
		||||
ErrorLog.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.actor = new St.BoxLayout();
 | 
			
		||||
        this.text = new St.Label();
 | 
			
		||||
@@ -580,13 +663,11 @@ ErrorLog.prototype = {
 | 
			
		||||
        }
 | 
			
		||||
        this.text.text = text;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function Memory() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const Memory = new Lang.Class({
 | 
			
		||||
    Name: 'Memory',
 | 
			
		||||
 | 
			
		||||
Memory.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.actor = new St.BoxLayout({ vertical: true });
 | 
			
		||||
        this._glibc_uordblks = new St.Label();
 | 
			
		||||
@@ -607,6 +688,9 @@ Memory.prototype = {
 | 
			
		||||
        this._gjs_closure = new St.Label();
 | 
			
		||||
        this.actor.add(this._gjs_closure);
 | 
			
		||||
 | 
			
		||||
        this._last_gc_seconds_ago = new St.Label();
 | 
			
		||||
        this.actor.add(this._last_gc_seconds_ago);
 | 
			
		||||
 | 
			
		||||
        this._gcbutton = new St.Button({ label: 'Full GC',
 | 
			
		||||
                                         style_class: 'lg-obj-inspector-button' });
 | 
			
		||||
        this._gcbutton.connect('clicked', Lang.bind(this, function () { global.gc(); this._renderText(); }));
 | 
			
		||||
@@ -626,14 +710,13 @@ Memory.prototype = {
 | 
			
		||||
        this._gjs_gobject.text = 'gjs_gobject: ' + memInfo.gjs_gobject;
 | 
			
		||||
        this._gjs_function.text = 'gjs_function: ' + memInfo.gjs_function;
 | 
			
		||||
        this._gjs_closure.text = 'gjs_closure: ' + memInfo.gjs_closure;
 | 
			
		||||
        this._last_gc_seconds_ago.text = 'last_gc_seconds_ago: ' + memInfo.last_gc_seconds_ago;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function Extensions() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const Extensions = new Lang.Class({
 | 
			
		||||
    Name: 'Extensions',
 | 
			
		||||
 | 
			
		||||
Extensions.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.actor = new St.BoxLayout({ vertical: true,
 | 
			
		||||
                                        name: 'lookingGlassExtensions' });
 | 
			
		||||
@@ -681,11 +764,40 @@ Extensions.prototype = {
 | 
			
		||||
        Main.lookingGlass.close();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onViewErrors: function (actor) {
 | 
			
		||||
        let meta = actor._extensionMeta;
 | 
			
		||||
        let shouldShow = !actor._isShowing;
 | 
			
		||||
 | 
			
		||||
        if (shouldShow) {
 | 
			
		||||
            let errors = ExtensionSystem.errors[meta.uuid];
 | 
			
		||||
            let errorDisplay = new St.BoxLayout({ vertical: true });
 | 
			
		||||
            if (errors && errors.length) {
 | 
			
		||||
                for (let i = 0; i < errors.length; i ++)
 | 
			
		||||
                    errorDisplay.add(new St.Label({ text: errors[i] }));
 | 
			
		||||
            } else {
 | 
			
		||||
                /* Translators: argument is an extension UUID. */
 | 
			
		||||
                let message = _("%s has not emitted any errors.").format(meta.uuid);
 | 
			
		||||
                errorDisplay.add(new St.Label({ text: message }));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            actor._errorDisplay = errorDisplay;
 | 
			
		||||
            actor._parentBox.add(errorDisplay);
 | 
			
		||||
            actor.label = _("Hide Errors");
 | 
			
		||||
        } else {
 | 
			
		||||
            actor._errorDisplay.destroy();
 | 
			
		||||
            actor._errorDisplay = null;
 | 
			
		||||
            actor.label = _("Show Errors");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        actor._isShowing = shouldShow;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _stateToString: function(extensionState) {
 | 
			
		||||
        switch (extensionState) {
 | 
			
		||||
            case ExtensionSystem.ExtensionState.ENABLED:
 | 
			
		||||
                return _("Enabled");
 | 
			
		||||
            case ExtensionSystem.ExtensionState.DISABLED:
 | 
			
		||||
            case ExtensionSystem.ExtensionState.INITIALIZED:
 | 
			
		||||
                return _("Disabled");
 | 
			
		||||
            case ExtensionSystem.ExtensionState.ERROR:
 | 
			
		||||
                return _("Error");
 | 
			
		||||
@@ -706,38 +818,39 @@ Extensions.prototype = {
 | 
			
		||||
                                         text: meta.description || 'No description' });
 | 
			
		||||
        box.add(description, { expand: true });
 | 
			
		||||
 | 
			
		||||
        let metaBox = new St.BoxLayout();
 | 
			
		||||
        let metaBox = new St.BoxLayout({ style_class: 'lg-extension-meta' });
 | 
			
		||||
        box.add(metaBox);
 | 
			
		||||
        let stateString = this._stateToString(meta.state);
 | 
			
		||||
        let state = new St.Label({ style_class: 'lg-extension-state',
 | 
			
		||||
                                   text: this._stateToString(meta.state) });
 | 
			
		||||
 | 
			
		||||
        let actionsContainer = new St.Bin({ x_align: St.Align.END });
 | 
			
		||||
        metaBox.add(actionsContainer);
 | 
			
		||||
        let actionsBox = new St.BoxLayout({ style_class: 'lg-extension-actions' });
 | 
			
		||||
        actionsContainer.set_child(actionsBox);
 | 
			
		||||
        metaBox.add(state);
 | 
			
		||||
 | 
			
		||||
        let viewsource = new Link.Link({ label: _("View Source") });
 | 
			
		||||
        viewsource.actor._extensionMeta = meta;
 | 
			
		||||
        viewsource.actor.connect('clicked', Lang.bind(this, this._onViewSource));
 | 
			
		||||
        actionsBox.add(viewsource.actor);
 | 
			
		||||
        metaBox.add(viewsource.actor);
 | 
			
		||||
 | 
			
		||||
        if (meta.url) {
 | 
			
		||||
            let webpage = new Link.Link({ label: _("Web Page") });
 | 
			
		||||
            webpage.actor._extensionMeta = meta;
 | 
			
		||||
            webpage.actor.connect('clicked', Lang.bind(this, this._onWebPage));
 | 
			
		||||
            actionsBox.add(webpage.actor);
 | 
			
		||||
            metaBox.add(webpage.actor);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let viewerrors = new Link.Link({ label: _("Show Errors") });
 | 
			
		||||
        viewerrors.actor._extensionMeta = meta;
 | 
			
		||||
        viewerrors.actor._parentBox = box;
 | 
			
		||||
        viewerrors.actor._isShowing = false;
 | 
			
		||||
        viewerrors.actor.connect('clicked', Lang.bind(this, this._onViewErrors));
 | 
			
		||||
        metaBox.add(viewerrors.actor);
 | 
			
		||||
 | 
			
		||||
        return box;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function LookingGlass() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const LookingGlass = new Lang.Class({
 | 
			
		||||
    Name: 'LookingGlass',
 | 
			
		||||
 | 
			
		||||
LookingGlass.prototype = {
 | 
			
		||||
    _init : function() {
 | 
			
		||||
        this._borderPaintTarget = null;
 | 
			
		||||
        this._borderPaintId = 0;
 | 
			
		||||
@@ -754,7 +867,8 @@ LookingGlass.prototype = {
 | 
			
		||||
        this.actor = new St.BoxLayout({ name: 'LookingGlassDialog',
 | 
			
		||||
                                        style_class: 'lg-dialog',
 | 
			
		||||
                                        vertical: true,
 | 
			
		||||
                                        visible: false });
 | 
			
		||||
                                        visible: false,
 | 
			
		||||
                                        reactive: true });
 | 
			
		||||
        this.actor.connect('key-press-event', Lang.bind(this, this._globalKeyPressEvent));
 | 
			
		||||
 | 
			
		||||
        this._interfaceSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
 | 
			
		||||
@@ -809,14 +923,15 @@ LookingGlass.prototype = {
 | 
			
		||||
        this._resultsArea = new St.BoxLayout({ name: 'ResultsArea', vertical: true });
 | 
			
		||||
        this._evalBox.add(this._resultsArea, { expand: true });
 | 
			
		||||
 | 
			
		||||
        let entryArea = new St.BoxLayout({ name: 'EntryArea' });
 | 
			
		||||
        this._evalBox.add_actor(entryArea);
 | 
			
		||||
        this._entryArea = new St.BoxLayout({ name: 'EntryArea' });
 | 
			
		||||
        this._evalBox.add_actor(this._entryArea);
 | 
			
		||||
 | 
			
		||||
        let label = new St.Label({ text: 'js>>> ' });
 | 
			
		||||
        entryArea.add(label);
 | 
			
		||||
        this._entryArea.add(label);
 | 
			
		||||
 | 
			
		||||
        this._entry = new St.Entry({ can_focus: true });
 | 
			
		||||
        entryArea.add(this._entry, { expand: true });
 | 
			
		||||
        ShellEntry.addContextMenu(this._entry);
 | 
			
		||||
        this._entryArea.add(this._entry, { expand: true });
 | 
			
		||||
 | 
			
		||||
        this._windowList = new WindowList();
 | 
			
		||||
        this._windowList.connect('selected', Lang.bind(this, function(list, window) {
 | 
			
		||||
@@ -835,6 +950,9 @@ LookingGlass.prototype = {
 | 
			
		||||
        notebook.appendPage('Extensions', this._extensions.actor);
 | 
			
		||||
 | 
			
		||||
        this._entry.clutter_text.connect('activate', Lang.bind(this, function (o, e) {
 | 
			
		||||
            // Hide any completions we are currently showing
 | 
			
		||||
            this._hideCompletions();
 | 
			
		||||
 | 
			
		||||
            let text = o.get_text();
 | 
			
		||||
            // Ensure we don't get newlines in the command; the history file is
 | 
			
		||||
            // newline-separated.
 | 
			
		||||
@@ -850,6 +968,17 @@ LookingGlass.prototype = {
 | 
			
		||||
        this._history = new History.HistoryManager({ gsettingsKey: HISTORY_KEY, 
 | 
			
		||||
                                                     entry: this._entry.clutter_text });
 | 
			
		||||
 | 
			
		||||
        this._autoComplete = new AutoComplete(this._entry);
 | 
			
		||||
        this._autoComplete.connect('suggest', Lang.bind(this, function(a,e) {
 | 
			
		||||
            this._showCompletions(e.completions);
 | 
			
		||||
        }));
 | 
			
		||||
        // If a completion is completed unambiguously, the currently-displayed completion
 | 
			
		||||
        // suggestions become irrelevant.
 | 
			
		||||
        this._autoComplete.connect('completion', Lang.bind(this, function(a,e) {
 | 
			
		||||
            if (e.type == 'whole-word')
 | 
			
		||||
                this._hideCompletions();
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        this._resize();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -894,6 +1023,59 @@ LookingGlass.prototype = {
 | 
			
		||||
        this._notebook.scrollToBottom(0);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showCompletions: function(completions) {
 | 
			
		||||
        if (!this._completionActor) {
 | 
			
		||||
            let actor = new St.BoxLayout({ vertical: true });
 | 
			
		||||
 | 
			
		||||
            this._completionText = new St.Label({ name: 'LookingGlassAutoCompletionText', style_class: 'lg-completions-text' });
 | 
			
		||||
            this._completionText.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
 | 
			
		||||
            this._completionText.clutter_text.line_wrap = true;
 | 
			
		||||
            actor.add(this._completionText);
 | 
			
		||||
 | 
			
		||||
            let line = new Clutter.Rectangle();
 | 
			
		||||
            let padBin = new St.Bin({ x_fill: true, y_fill: true });
 | 
			
		||||
            padBin.add_actor(line);
 | 
			
		||||
            actor.add(padBin);
 | 
			
		||||
 | 
			
		||||
            this._completionActor = actor;
 | 
			
		||||
            this._evalBox.insert_before(this._completionActor, this._entryArea);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._completionText.set_text(completions.join(', '));
 | 
			
		||||
 | 
			
		||||
        // Setting the height to -1 allows us to get its actual preferred height rather than
 | 
			
		||||
        // whatever was last given in set_height by Tweener.
 | 
			
		||||
        this._completionActor.set_height(-1);
 | 
			
		||||
        let [minHeight, naturalHeight] = this._completionText.get_preferred_height(this._resultsArea.get_width());
 | 
			
		||||
 | 
			
		||||
        // Don't reanimate if we are already visible
 | 
			
		||||
        if (this._completionActor.visible) {
 | 
			
		||||
            this._completionActor.height = naturalHeight;
 | 
			
		||||
        } else {
 | 
			
		||||
            this._completionActor.show();
 | 
			
		||||
            Tweener.removeTweens(this._completionActor);
 | 
			
		||||
            Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / St.get_slow_down_factor(),
 | 
			
		||||
                                                      transition: 'easeOutQuad',
 | 
			
		||||
                                                      height: naturalHeight,
 | 
			
		||||
                                                      opacity: 255
 | 
			
		||||
                                                    });
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _hideCompletions: function() {
 | 
			
		||||
        if (this._completionActor) {
 | 
			
		||||
            Tweener.removeTweens(this._completionActor);
 | 
			
		||||
            Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / St.get_slow_down_factor(),
 | 
			
		||||
                                                      transition: 'easeOutQuad',
 | 
			
		||||
                                                      height: 0,
 | 
			
		||||
                                                      opacity: 0,
 | 
			
		||||
                                                      onComplete: Lang.bind(this, function () {
 | 
			
		||||
                                                          this._completionActor.hide();
 | 
			
		||||
                                                      })
 | 
			
		||||
                                                    });
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _evaluate : function(command) {
 | 
			
		||||
        this._history.addItem(command);
 | 
			
		||||
 | 
			
		||||
@@ -958,6 +1140,7 @@ LookingGlass.prototype = {
 | 
			
		||||
    // Handle key events which are relevant for all tabs of the LookingGlass
 | 
			
		||||
    _globalKeyPressEvent : function(actor, event) {
 | 
			
		||||
        let symbol = event.get_key_symbol();
 | 
			
		||||
        let modifierState = Shell.get_event_state(event);
 | 
			
		||||
        if (symbol == Clutter.Escape) {
 | 
			
		||||
            if (this._objInspector.actor.visible) {
 | 
			
		||||
                this._objInspector.close();
 | 
			
		||||
@@ -966,6 +1149,14 @@ LookingGlass.prototype = {
 | 
			
		||||
            }
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        // Ctrl+PgUp and Ctrl+PgDown switches tabs in the notebook view
 | 
			
		||||
        if (modifierState & Clutter.ModifierType.CONTROL_MASK) {
 | 
			
		||||
            if (symbol == Clutter.KEY_Page_Up) {
 | 
			
		||||
                this._notebook.prevTab();
 | 
			
		||||
            } else if (symbol == Clutter.KEY_Page_Down) {
 | 
			
		||||
                this._notebook.nextTab();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -1016,5 +1207,5 @@ LookingGlass.prototype = {
 | 
			
		||||
                                       })
 | 
			
		||||
                                     });
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(LookingGlass.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GDesktopEnums = imports.gi.GDesktopEnums;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
@@ -12,22 +13,6 @@ const Main = imports.ui.main;
 | 
			
		||||
const MagnifierDBus = imports.ui.magnifierDBus;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
 | 
			
		||||
// Keep enums in sync with GSettings schemas
 | 
			
		||||
const MouseTrackingMode = {
 | 
			
		||||
    NONE: 0,
 | 
			
		||||
    CENTERED: 1,
 | 
			
		||||
    PROPORTIONAL: 2,
 | 
			
		||||
    PUSH: 3
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const ScreenPosition = {
 | 
			
		||||
    NONE: 0,
 | 
			
		||||
    FULL_SCREEN: 1,
 | 
			
		||||
    TOP_HALF: 2,
 | 
			
		||||
    BOTTOM_HALF: 3,
 | 
			
		||||
    LEFT_HALF: 4,
 | 
			
		||||
    RIGHT_HALF: 5
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const MOUSE_POLL_FREQUENCY = 50;
 | 
			
		||||
const CROSSHAIRS_CLIP_SIZE = [100, 100];
 | 
			
		||||
@@ -51,11 +36,9 @@ const CROSS_HAIRS_CLIP_KEY      = 'cross-hairs-clip';
 | 
			
		||||
 | 
			
		||||
let magDBusService = null;
 | 
			
		||||
 | 
			
		||||
function Magnifier() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const Magnifier = new Lang.Class({
 | 
			
		||||
    Name: 'Magnifier',
 | 
			
		||||
 | 
			
		||||
Magnifier.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        // Magnifier is a manager of ZoomRegions.
 | 
			
		||||
        this._zoomRegions = [];
 | 
			
		||||
@@ -520,7 +503,7 @@ Magnifier.prototype = {
 | 
			
		||||
        if (this._zoomRegions.length) {
 | 
			
		||||
            let position = this._settings.get_enum(SCREEN_POSITION_KEY);
 | 
			
		||||
            this._zoomRegions[0].setScreenPosition(position);
 | 
			
		||||
            if (position != ScreenPosition.FULL_SCREEN)
 | 
			
		||||
            if (position != GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN)
 | 
			
		||||
                this._updateLensMode();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
@@ -558,21 +541,19 @@ Magnifier.prototype = {
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(Magnifier.prototype);
 | 
			
		||||
 | 
			
		||||
function ZoomRegion(magnifier, mouseSourceActor) {
 | 
			
		||||
    this._init(magnifier, mouseSourceActor);
 | 
			
		||||
}
 | 
			
		||||
const ZoomRegion = new Lang.Class({
 | 
			
		||||
    Name: 'ZoomRegion',
 | 
			
		||||
 | 
			
		||||
ZoomRegion.prototype = {
 | 
			
		||||
    _init: function(magnifier, mouseSourceActor) {
 | 
			
		||||
        this._magnifier = magnifier;
 | 
			
		||||
 | 
			
		||||
        this._mouseTrackingMode = MouseTrackingMode.NONE;
 | 
			
		||||
        this._mouseTrackingMode = GDesktopEnums.MagnifierMouseTrackingMode.NONE;
 | 
			
		||||
        this._clampScrollingAtEdges = false;
 | 
			
		||||
        this._lensMode = false;
 | 
			
		||||
        this._screenPosition = ScreenPosition.FULL_SCREEN;
 | 
			
		||||
        this._screenPosition = GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN;
 | 
			
		||||
 | 
			
		||||
        this._magView = null;
 | 
			
		||||
        this._uiGroupClone = null;
 | 
			
		||||
@@ -647,7 +628,8 @@ ZoomRegion.prototype = {
 | 
			
		||||
     * @mode:     One of the enum MouseTrackingMode values.
 | 
			
		||||
     */
 | 
			
		||||
    setMouseTrackingMode: function(mode) {
 | 
			
		||||
        if (mode >= MouseTrackingMode.NONE && mode <= MouseTrackingMode.PUSH)
 | 
			
		||||
        if (mode >= GDesktopEnums.MagnifierMouseTrackingMode.NONE &&
 | 
			
		||||
            mode <= GDesktopEnums.MagnifierMouseTrackingMode.PUSH)
 | 
			
		||||
            this._mouseTrackingMode = mode;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -668,7 +650,7 @@ ZoomRegion.prototype = {
 | 
			
		||||
     */
 | 
			
		||||
    setViewPort: function(viewPort) {
 | 
			
		||||
        this._setViewPort(viewPort);
 | 
			
		||||
        this._screenPosition = ScreenPosition.NONE;
 | 
			
		||||
        this._screenPosition = GDesktopEnums.MagnifierScreenPosition.NONE;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -750,7 +732,7 @@ ZoomRegion.prototype = {
 | 
			
		||||
        viewPort.width = global.screen_width;
 | 
			
		||||
        viewPort.height = global.screen_height/2;
 | 
			
		||||
        this._setViewPort(viewPort);
 | 
			
		||||
        this._screenPosition = ScreenPosition.TOP_HALF;
 | 
			
		||||
        this._screenPosition = GDesktopEnums.MagnifierScreenPosition.TOP_HALF;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -764,7 +746,7 @@ ZoomRegion.prototype = {
 | 
			
		||||
        viewPort.width = global.screen_width;
 | 
			
		||||
        viewPort.height = global.screen_height/2;
 | 
			
		||||
        this._setViewPort(viewPort);
 | 
			
		||||
        this._screenPosition = ScreenPosition.BOTTOM_HALF;
 | 
			
		||||
        this._screenPosition = GDesktopEnums.MagnifierScreenPosition.BOTTOM_HALF;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -778,7 +760,7 @@ ZoomRegion.prototype = {
 | 
			
		||||
        viewPort.width = global.screen_width/2;
 | 
			
		||||
        viewPort.height = global.screen_height;
 | 
			
		||||
        this._setViewPort(viewPort);
 | 
			
		||||
        this._screenPosition = ScreenPosition.LEFT_HALF;
 | 
			
		||||
        this._screenPosition = GDesktopEnums.MagnifierScreenPosition.LEFT_HALF;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -792,7 +774,7 @@ ZoomRegion.prototype = {
 | 
			
		||||
        viewPort.width = global.screen_width/2;
 | 
			
		||||
        viewPort.height = global.screen_height;
 | 
			
		||||
        this._setViewPort(viewPort);
 | 
			
		||||
        this._screenPosition = ScreenPosition.RIGHT_HALF;
 | 
			
		||||
        this._screenPosition = GDesktopEnums.MagnifierScreenPosition.RIGHT_HALF;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -808,7 +790,7 @@ ZoomRegion.prototype = {
 | 
			
		||||
        viewPort.height = global.screen_height;
 | 
			
		||||
        this.setViewPort(viewPort);
 | 
			
		||||
 | 
			
		||||
        this._screenPosition = ScreenPosition.FULL_SCREEN;
 | 
			
		||||
        this._screenPosition = GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -821,19 +803,19 @@ ZoomRegion.prototype = {
 | 
			
		||||
     */
 | 
			
		||||
    setScreenPosition: function(inPosition) {
 | 
			
		||||
        switch (inPosition) {
 | 
			
		||||
            case ScreenPosition.FULL_SCREEN:
 | 
			
		||||
            case GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN:
 | 
			
		||||
                this.setFullScreenMode();
 | 
			
		||||
                break;
 | 
			
		||||
            case ScreenPosition.TOP_HALF:
 | 
			
		||||
            case GDesktopEnums.MagnifierScreenPosition.TOP_HALF:
 | 
			
		||||
                this.setTopHalf();
 | 
			
		||||
                break;
 | 
			
		||||
            case ScreenPosition.BOTTOM_HALF:
 | 
			
		||||
            case GDesktopEnums.MagnifierScreenPosition.BOTTOM_HALF:
 | 
			
		||||
                this.setBottomHalf();
 | 
			
		||||
                break;
 | 
			
		||||
            case ScreenPosition.LEFT_HALF:
 | 
			
		||||
            case GDesktopEnums.MagnifierScreenPosition.LEFT_HALF:
 | 
			
		||||
                this.setLeftHalf();
 | 
			
		||||
                break;
 | 
			
		||||
            case ScreenPosition.RIGHT_HALF:
 | 
			
		||||
            case GDesktopEnums.MagnifierScreenPosition.RIGHT_HALF:
 | 
			
		||||
                this.setRightHalf();
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
@@ -856,7 +838,7 @@ ZoomRegion.prototype = {
 | 
			
		||||
     */
 | 
			
		||||
    scrollToMousePos: function() {
 | 
			
		||||
        this._followingCursor = true;
 | 
			
		||||
        if (this._mouseTrackingMode != MouseTrackingMode.NONE)
 | 
			
		||||
        if (this._mouseTrackingMode != GDesktopEnums.MagnifierMouseTrackingMode.NONE)
 | 
			
		||||
            this._changeROI({ redoCursorTracking: true });
 | 
			
		||||
        else
 | 
			
		||||
            this._updateMousePosition();
 | 
			
		||||
@@ -991,7 +973,7 @@ ZoomRegion.prototype = {
 | 
			
		||||
        this._yMagFactor = params.yMagFactor;
 | 
			
		||||
 | 
			
		||||
        if (params.redoCursorTracking &&
 | 
			
		||||
            this._mouseTrackingMode != MouseTrackingMode.NONE) {
 | 
			
		||||
            this._mouseTrackingMode != GDesktopEnums.MagnifierMouseTrackingMode.NONE) {
 | 
			
		||||
            // This depends on this.xMagFactor/yMagFactor already being updated
 | 
			
		||||
            [params.xCenter, params.yCenter] = this._centerFromMousePosition();
 | 
			
		||||
        }
 | 
			
		||||
@@ -1041,7 +1023,7 @@ ZoomRegion.prototype = {
 | 
			
		||||
    _isFullScreen: function() {
 | 
			
		||||
        // Does the magnified view occupy the whole screen? Note that this
 | 
			
		||||
        // doesn't necessarily imply
 | 
			
		||||
        // this._screenPosition = ScreenPosition.FULL_SCREEN;
 | 
			
		||||
        // this._screenPosition = GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN;
 | 
			
		||||
 | 
			
		||||
        if (this._viewPortX != 0 || this._viewPortY != 0)
 | 
			
		||||
            return false;
 | 
			
		||||
@@ -1058,13 +1040,13 @@ ZoomRegion.prototype = {
 | 
			
		||||
        let xMouse = this._magnifier.xMouse;
 | 
			
		||||
        let yMouse = this._magnifier.yMouse;
 | 
			
		||||
 | 
			
		||||
        if (this._mouseTrackingMode == MouseTrackingMode.PROPORTIONAL) {
 | 
			
		||||
        if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.PROPORTIONAL) {
 | 
			
		||||
            return this._centerFromMouseProportional(xMouse, yMouse);
 | 
			
		||||
        }
 | 
			
		||||
        else if (this._mouseTrackingMode == MouseTrackingMode.PUSH) {
 | 
			
		||||
        else if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.PUSH) {
 | 
			
		||||
            return this._centerFromMousePush(xMouse, yMouse);
 | 
			
		||||
        }
 | 
			
		||||
        else if (this._mouseTrackingMode == MouseTrackingMode.CENTERED) {
 | 
			
		||||
        else if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.CENTERED) {
 | 
			
		||||
            return this._centerFromMouseCentered(xMouse, yMouse);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -1164,13 +1146,11 @@ ZoomRegion.prototype = {
 | 
			
		||||
                                               yMagMouse - groupHeight / 2);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function Crosshairs() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const Crosshairs = new Lang.Class({
 | 
			
		||||
    Name: 'Crosshairs',
 | 
			
		||||
 | 
			
		||||
Crosshairs.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
 | 
			
		||||
        // Set the group containing the crosshairs to three times the desktop
 | 
			
		||||
@@ -1426,4 +1406,4 @@ Crosshairs.prototype = {
 | 
			
		||||
        this._vertTopHair.set_position((groupWidth - thickness) / 2, top);
 | 
			
		||||
        this._vertBottomHair.set_position((groupWidth - thickness) / 2, bottom);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
 | 
			
		||||
const MAG_SERVICE_NAME = 'org.gnome.Magnifier';
 | 
			
		||||
@@ -10,61 +11,99 @@ const ZOOM_SERVICE_PATH = '/org/gnome/Magnifier/ZoomRegion';
 | 
			
		||||
 | 
			
		||||
// Subset of gnome-mag's Magnifier dbus interface -- to be expanded.  See:
 | 
			
		||||
// http://git.gnome.org/browse/gnome-mag/tree/xml/...Magnifier.xml
 | 
			
		||||
const MagnifierIface = {
 | 
			
		||||
    name: MAG_SERVICE_NAME,
 | 
			
		||||
    methods: [
 | 
			
		||||
                { name: 'setActive', inSignature: 'b', outSignature: '' },
 | 
			
		||||
                { name: 'isActive', inSignature: '', outSignature: 'b' },
 | 
			
		||||
                { name: 'showCursor', inSignature: '', outSignature: '' },
 | 
			
		||||
                { name: 'hideCursor', inSignature: '', outSignature: ''  },
 | 
			
		||||
                { name: 'createZoomRegion', inSignature: 'ddaiai', outSignature: 'o' },
 | 
			
		||||
                { name: 'addZoomRegion', inSignature: 'o', outSignature: 'b' },
 | 
			
		||||
                { name: 'getZoomRegions', inSignature: '', outSignature: 'ao' },
 | 
			
		||||
                { name: 'clearAllZoomRegions', inSignature: '', outSignature: '' },
 | 
			
		||||
                { name: 'fullScreenCapable', inSignature: '', outSignature: 'b' },
 | 
			
		||||
 | 
			
		||||
                { name: 'setCrosswireSize', inSignature: 'i', outSignature: '' },
 | 
			
		||||
                { name: 'getCrosswireSize', inSignature: '', outSignature: 'i' },
 | 
			
		||||
                { name: 'setCrosswireLength', inSignature: 'i', outSignature: '' },
 | 
			
		||||
                { name: 'getCrosswireLength', inSignature: '', outSignature: 'i' },
 | 
			
		||||
                { name: 'setCrosswireClip', inSignature: 'b', outSignature: '' },
 | 
			
		||||
                { name: 'getCrosswireClip', inSignature: '', outSignature: 'b' },
 | 
			
		||||
                { name: 'setCrosswireColor', inSignature: 'u', outSignature: '' },
 | 
			
		||||
                { name: 'getCrosswireColor', inSignature: '', outSignature: 'u' }
 | 
			
		||||
             ],
 | 
			
		||||
    signals: [],
 | 
			
		||||
    properties: []
 | 
			
		||||
};
 | 
			
		||||
const MagnifierIface = <interface name={MAG_SERVICE_NAME}>
 | 
			
		||||
<method name="setActive">
 | 
			
		||||
    <arg type="b" direction="in" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="isActive">
 | 
			
		||||
    <arg type="b" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="showCursor" />
 | 
			
		||||
<method name="hideCursor" />
 | 
			
		||||
<method name="createZoomRegion">
 | 
			
		||||
    <arg type="d" direction="in" />
 | 
			
		||||
    <arg type="d" direction="in" />
 | 
			
		||||
    <arg type="ai" direction="in" />
 | 
			
		||||
    <arg type="ai" direction="in" />
 | 
			
		||||
    <arg type="o" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="addZoomRegion">
 | 
			
		||||
    <arg type="o" direction="in" />
 | 
			
		||||
    <arg type="b" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="getZoomRegions">
 | 
			
		||||
    <arg type="ao" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="clearAllZoomRegions" />
 | 
			
		||||
<method name="fullScreenCapable">
 | 
			
		||||
    <arg type="b" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="setCrosswireSize">
 | 
			
		||||
    <arg type="i" direction="in" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="getCrosswireSize">
 | 
			
		||||
    <arg type="i" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="setCrosswireLength">
 | 
			
		||||
    <arg type="i" direction="in" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="getCrosswireLength">
 | 
			
		||||
    <arg type="i" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="setCrosswireClip">
 | 
			
		||||
    <arg type="b" direction="in" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="getCrosswireClip">
 | 
			
		||||
    <arg type="b" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="setCrosswireColor">
 | 
			
		||||
    <arg type="u" direction="in" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="getCrosswireColor">
 | 
			
		||||
    <arg type="u" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
// Subset of gnome-mag's ZoomRegion dbus interface -- to be expanded.  See:
 | 
			
		||||
// http://git.gnome.org/browse/gnome-mag/tree/xml/...ZoomRegion.xml
 | 
			
		||||
const ZoomRegionIface = {
 | 
			
		||||
    name: ZOOM_SERVICE_NAME,
 | 
			
		||||
    methods: [
 | 
			
		||||
                { name: 'setMagFactor', inSignature: 'dd', outSignature: ''},
 | 
			
		||||
                { name: 'getMagFactor', inSignature: '', outSignature: 'dd' },
 | 
			
		||||
                { name: 'setRoi', inSignature: 'ai', outSignature: '' },
 | 
			
		||||
                { name: 'getRoi', inSignature: '', outSignature: 'ai' },
 | 
			
		||||
                { name: 'shiftContentsTo', inSignature: 'ii', outSignature: 'b' },
 | 
			
		||||
                { name: 'moveResize', inSignature: 'ai', outSignature: '' }
 | 
			
		||||
             ],
 | 
			
		||||
    signals: [],
 | 
			
		||||
    properties: []
 | 
			
		||||
};
 | 
			
		||||
const ZoomRegionIface = <interface name={ZOOM_SERVICE_NAME}>
 | 
			
		||||
<method name="setMagFactor">
 | 
			
		||||
    <arg type="d" direction="in" />
 | 
			
		||||
    <arg type="d" direction="in" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="getMagFactor">
 | 
			
		||||
    <arg type="d" direction="out" />
 | 
			
		||||
    <arg type="d" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="setRoi">
 | 
			
		||||
    <arg type="ai" direction="in" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="getRoi">
 | 
			
		||||
    <arg type="ai" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="shiftContentsTo">
 | 
			
		||||
    <arg type="i" direction="in" />
 | 
			
		||||
    <arg type="i" direction="in" />
 | 
			
		||||
    <arg type="b" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="moveResize">
 | 
			
		||||
    <arg type="ai" direction="in" />
 | 
			
		||||
</method>
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
// For making unique ZoomRegion DBus proxy object paths of the form:
 | 
			
		||||
// '/org/gnome/Magnifier/ZoomRegion/zoomer0',
 | 
			
		||||
// '/org/gnome/Magnifier/ZoomRegion/zoomer1', etc.
 | 
			
		||||
let _zoomRegionInstanceCount = 0;
 | 
			
		||||
 | 
			
		||||
function ShellMagnifier() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const ShellMagnifier = new Lang.Class({
 | 
			
		||||
    Name: 'ShellMagnifier',
 | 
			
		||||
 | 
			
		||||
ShellMagnifier.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._zoomers = {};
 | 
			
		||||
        DBus.session.exportObject(MAG_SERVICE_PATH, this);
 | 
			
		||||
 | 
			
		||||
        this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(MagnifierIface, this);
 | 
			
		||||
        this._dbusImpl.export(Gio.DBus.session, MAG_SERVICE_PATH);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -195,10 +234,10 @@ ShellMagnifier.prototype = {
 | 
			
		||||
        Main.magnifier.clearAllZoomRegions();
 | 
			
		||||
        for (let objectPath in this._zoomers) {
 | 
			
		||||
            let proxyAndZoomer = this._zoomers[objectPath];
 | 
			
		||||
            proxyAndZoomer.proxy.destroy();
 | 
			
		||||
            proxyAndZoomer.proxy = null;
 | 
			
		||||
            proxyAndZoomer.zoomRegion = null;
 | 
			
		||||
            delete this._zoomers[objectPath];
 | 
			
		||||
            DBus.session.unexportObject(proxyAndZoomer);
 | 
			
		||||
        }
 | 
			
		||||
        this._zoomers = {};
 | 
			
		||||
    },
 | 
			
		||||
@@ -285,7 +324,7 @@ ShellMagnifier.prototype = {
 | 
			
		||||
        // Drop the leading '#'.
 | 
			
		||||
        return parseInt(colorString.slice(1), 16);
 | 
			
		||||
     }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ShellMagnifierZoomRegion:
 | 
			
		||||
@@ -293,15 +332,14 @@ ShellMagnifier.prototype = {
 | 
			
		||||
 * @zoomerObjectPath:   String that is the path to a DBus ZoomRegion.
 | 
			
		||||
 * @zoomRegion:         The actual zoom region associated with the object path.
 | 
			
		||||
 */
 | 
			
		||||
function ShellMagnifierZoomRegion(zoomerObjectPath, zoomRegion) {
 | 
			
		||||
    this._init(zoomerObjectPath, zoomRegion);
 | 
			
		||||
}
 | 
			
		||||
const ShellMagnifierZoomRegion = new Lang.Class({
 | 
			
		||||
    Name: 'ShellMagnifierZoomRegion',
 | 
			
		||||
 | 
			
		||||
ShellMagnifierZoomRegion.prototype = {
 | 
			
		||||
    _init: function(zoomerObjectPath, zoomRegion) {
 | 
			
		||||
        this._zoomRegion = zoomRegion;
 | 
			
		||||
        DBus.session.proxifyObject(this, ZOOM_SERVICE_NAME, zoomerObjectPath);
 | 
			
		||||
        DBus.session.exportObject(zoomerObjectPath, this);
 | 
			
		||||
 | 
			
		||||
        this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ZoomRegionIface, this);
 | 
			
		||||
        this._dbusImpl.export(Gio.DBus.session, zoomerObjectPath);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -376,8 +414,9 @@ ShellMagnifierZoomRegion.prototype = {
 | 
			
		||||
    moveResize: function(viewPort) {
 | 
			
		||||
        let viewRect = { x: viewPort[0], y: viewPort[1], width: viewPort[2] - viewPort[0], height: viewPort[3] - viewPort[1] };
 | 
			
		||||
        this._zoomRegion.setViewPort(viewRect);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
DBus.conformExport(ShellMagnifier.prototype, MagnifierIface);
 | 
			
		||||
DBus.conformExport(ShellMagnifierZoomRegion.prototype, ZoomRegionIface);
 | 
			
		||||
    destroy: function() {
 | 
			
		||||
        this._dbusImpl.unexport();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,9 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
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 GConf = imports.gi.GConf;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
@@ -129,22 +127,16 @@ function _initRecorder() {
 | 
			
		||||
function _initUserSession() {
 | 
			
		||||
    _initRecorder();
 | 
			
		||||
 | 
			
		||||
    keyboard.init();
 | 
			
		||||
 | 
			
		||||
    global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT, false, -1, 1);
 | 
			
		||||
 | 
			
		||||
    ExtensionSystem.init();
 | 
			
		||||
    ExtensionSystem.loadExtensions();
 | 
			
		||||
 | 
			
		||||
    let shellwm = global.window_manager;
 | 
			
		||||
 | 
			
		||||
    shellwm.takeover_keybinding('panel_run_dialog');
 | 
			
		||||
    shellwm.connect('keybinding::panel_run_dialog', function () {
 | 
			
		||||
    Meta.keybindings_set_custom_handler('panel-run-dialog', function() {
 | 
			
		||||
       getRunDialog().open();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    shellwm.takeover_keybinding('panel_main_menu');
 | 
			
		||||
    shellwm.connect('keybinding::panel_main_menu', function () {
 | 
			
		||||
    Meta.keybindings_set_custom_handler('panel-main-menu', function () {
 | 
			
		||||
        overview.toggle();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -165,11 +157,6 @@ function start() {
 | 
			
		||||
    Gio.DesktopAppInfo.set_desktop_env('GNOME');
 | 
			
		||||
 | 
			
		||||
    shellDBusService = new ShellDBus.GnomeShell();
 | 
			
		||||
    // Force a connection now; dbus.js will do this internally
 | 
			
		||||
    // if we use its name acquisition stuff but we aren't right
 | 
			
		||||
    // now; to do so we'd need to convert from its async calls
 | 
			
		||||
    // back into sync ones.
 | 
			
		||||
    DBus.session.flush();
 | 
			
		||||
 | 
			
		||||
    // Ensure ShellWindowTracker and ShellAppUsage are initialized; this will
 | 
			
		||||
    // also initialize ShellAppSystem first.  ShellAppSystem
 | 
			
		||||
@@ -496,9 +483,9 @@ function notify(msg, details) {
 | 
			
		||||
function notifyError(msg, details) {
 | 
			
		||||
    // Also print to stderr so it's logged somewhere
 | 
			
		||||
    if (details)
 | 
			
		||||
        log("error: " + msg + ": " + details);
 | 
			
		||||
        log('error: ' + msg + ': ' + details);
 | 
			
		||||
    else
 | 
			
		||||
        log("error: " + msg)
 | 
			
		||||
        log('error: ' + msg);
 | 
			
		||||
 | 
			
		||||
    notify(msg, details);
 | 
			
		||||
}
 | 
			
		||||
@@ -585,19 +572,9 @@ function _globalKeyPressHandler(actor, event) {
 | 
			
		||||
    // This relies on the fact that Clutter.ModifierType is the same as Gdk.ModifierType
 | 
			
		||||
    let action = global.display.get_keybinding_action(keyCode, modifierState);
 | 
			
		||||
 | 
			
		||||
    // The screenshot action should always be available (even if a
 | 
			
		||||
    // modal dialog is present)
 | 
			
		||||
    if (action == Meta.KeyBindingAction.COMMAND_SCREENSHOT) {
 | 
			
		||||
        let gconf = GConf.Client.get_default();
 | 
			
		||||
        let command = gconf.get_string('/apps/metacity/keybinding_commands/command_screenshot');
 | 
			
		||||
        if (command != null && command != '')
 | 
			
		||||
            Util.spawnCommandLine(command);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Other bindings are only available when the overview is up and
 | 
			
		||||
    // Other bindings are only available to the user session when the overview is up and
 | 
			
		||||
    // no modal dialog is present.
 | 
			
		||||
    if (!overview.visible || modalCount > 1)
 | 
			
		||||
    if (global.session_type == Shell.SessionType.USER && (!overview.visible || modalCount > 1))
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    // This isn't a Meta.KeyBindingAction yet
 | 
			
		||||
@@ -607,7 +584,8 @@ function _globalKeyPressHandler(actor, event) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (action == Meta.KeyBindingAction.SWITCH_PANELS) {
 | 
			
		||||
        ctrlAltTabManager.popup(modifierState & Clutter.ModifierType.SHIFT_MASK);
 | 
			
		||||
        ctrlAltTabManager.popup(modifierState & Clutter.ModifierType.SHIFT_MASK,
 | 
			
		||||
                                modifierState);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -669,14 +647,17 @@ function _findModal(actor) {
 | 
			
		||||
 * initiated event.  If not provided then the value of
 | 
			
		||||
 * global.get_current_time() is assumed.
 | 
			
		||||
 *
 | 
			
		||||
 * @options: optional Meta.ModalOptions flags to indicate that the
 | 
			
		||||
 *           pointer is alrady grabbed
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: true iff we successfully acquired a grab or already had one
 | 
			
		||||
 */
 | 
			
		||||
function pushModal(actor, timestamp) {
 | 
			
		||||
function pushModal(actor, timestamp, options) {
 | 
			
		||||
    if (timestamp == undefined)
 | 
			
		||||
        timestamp = global.get_current_time();
 | 
			
		||||
 | 
			
		||||
    if (modalCount == 0) {
 | 
			
		||||
        if (!global.begin_modal(timestamp)) {
 | 
			
		||||
        if (!global.begin_modal(timestamp, options ? options : 0)) {
 | 
			
		||||
            log('pushModal: invocation of begin_modal failed');
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
@@ -83,11 +83,9 @@ function _fixMarkup(text, allowMarkup) {
 | 
			
		||||
    return GLib.markup_escape_text(text, -1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function URLHighlighter(text, lineWrap, allowMarkup) {
 | 
			
		||||
    this._init(text, lineWrap, allowMarkup);
 | 
			
		||||
}
 | 
			
		||||
const URLHighlighter = new Lang.Class({
 | 
			
		||||
    Name: 'URLHighlighter',
 | 
			
		||||
 | 
			
		||||
URLHighlighter.prototype = {
 | 
			
		||||
    _init: function(text, lineWrap, allowMarkup) {
 | 
			
		||||
        if (!text)
 | 
			
		||||
            text = '';
 | 
			
		||||
@@ -211,13 +209,11 @@ URLHighlighter.prototype = {
 | 
			
		||||
        }
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function FocusGrabber() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const FocusGrabber = new Lang.Class({
 | 
			
		||||
    Name: 'FocusGrabber',
 | 
			
		||||
 | 
			
		||||
FocusGrabber.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.actor = null;
 | 
			
		||||
 | 
			
		||||
@@ -252,7 +248,8 @@ FocusGrabber.prototype = {
 | 
			
		||||
        this._prevFocusedWindow = global.display.focus_window;
 | 
			
		||||
        this._prevKeyFocusActor = global.stage.get_key_focus();
 | 
			
		||||
 | 
			
		||||
        if (!Main.overview.visible)
 | 
			
		||||
        if (global.stage_input_mode == Shell.StageInputMode.NONREACTIVE ||
 | 
			
		||||
            global.stage_input_mode == Shell.StageInputMode.NORMAL)
 | 
			
		||||
            global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
 | 
			
		||||
 | 
			
		||||
        // Use captured-event to notice clicks outside the focused actor
 | 
			
		||||
@@ -284,7 +281,8 @@ FocusGrabber.prototype = {
 | 
			
		||||
        let source = event.get_source();
 | 
			
		||||
        switch (event.type()) {
 | 
			
		||||
            case Clutter.EventType.BUTTON_PRESS:
 | 
			
		||||
                if (!this.actor.contains(source) && !Main.keyboard.actor.contains(source))
 | 
			
		||||
                if (!this.actor.contains(source) &&
 | 
			
		||||
                    !Main.layoutManager.keyboardBox.contains(source))
 | 
			
		||||
                    this.emit('button-pressed', source);
 | 
			
		||||
                break;
 | 
			
		||||
            case Clutter.EventType.KEY_PRESS:
 | 
			
		||||
@@ -349,7 +347,7 @@ FocusGrabber.prototype = {
 | 
			
		||||
            this._togglingFocusGrabMode = false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(FocusGrabber.prototype);
 | 
			
		||||
 | 
			
		||||
// Notification:
 | 
			
		||||
@@ -406,15 +404,14 @@ Signals.addSignalMethods(FocusGrabber.prototype);
 | 
			
		||||
// the content and the action area of the notification will be cleared.
 | 
			
		||||
// The content area is also always cleared if 'customContent' is false
 | 
			
		||||
// because it might contain the @banner that didn't fit in the banner mode.
 | 
			
		||||
function Notification(source, title, banner, params) {
 | 
			
		||||
    this._init(source, title, banner, params);
 | 
			
		||||
}
 | 
			
		||||
const Notification = new Lang.Class({
 | 
			
		||||
    Name: 'Notification',
 | 
			
		||||
 | 
			
		||||
Notification.prototype = {
 | 
			
		||||
    IMAGE_SIZE: 125,
 | 
			
		||||
 | 
			
		||||
    _init: function(source, title, banner, params) {
 | 
			
		||||
        this.source = source;
 | 
			
		||||
        this.title = title;
 | 
			
		||||
        this.urgency = Urgency.NORMAL;
 | 
			
		||||
        this.resident = false;
 | 
			
		||||
        // 'transient' is a reserved keyword in JS, so we have to use an alternate variable name
 | 
			
		||||
@@ -502,8 +499,11 @@ Notification.prototype = {
 | 
			
		||||
 | 
			
		||||
        let oldFocus = global.stage.key_focus;
 | 
			
		||||
 | 
			
		||||
        if (this._icon)
 | 
			
		||||
        if (this._icon && (params.icon || params.clear)) {
 | 
			
		||||
            this._icon.destroy();
 | 
			
		||||
            this._icon = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // We always clear the content area if we don't have custom
 | 
			
		||||
        // content because it might contain the @banner that didn't
 | 
			
		||||
        // fit in the banner mode.
 | 
			
		||||
@@ -529,14 +529,17 @@ Notification.prototype = {
 | 
			
		||||
        if (!this._scrollArea && !this._actionArea && !this._imageBin)
 | 
			
		||||
            this._table.remove_style_class_name('multi-line-notification');
 | 
			
		||||
 | 
			
		||||
        this._icon = params.icon || this.source.createNotificationIcon();
 | 
			
		||||
        this._table.add(this._icon, { row: 0,
 | 
			
		||||
                                      col: 0,
 | 
			
		||||
                                      x_expand: false,
 | 
			
		||||
                                      y_expand: false,
 | 
			
		||||
                                      y_fill: false,
 | 
			
		||||
                                      y_align: St.Align.START });
 | 
			
		||||
        if (!this._icon) {
 | 
			
		||||
            this._icon = params.icon || this.source.createNotificationIcon();
 | 
			
		||||
            this._table.add(this._icon, { row: 0,
 | 
			
		||||
                                          col: 0,
 | 
			
		||||
                                          x_expand: false,
 | 
			
		||||
                                          y_expand: false,
 | 
			
		||||
                                          y_fill: false,
 | 
			
		||||
                                          y_align: St.Align.START });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.title = title;
 | 
			
		||||
        title = title ? _fixMarkup(title.replace(/\n/g, ' '), params.titleMarkup) : '';
 | 
			
		||||
        this._titleLabel.clutter_text.set_markup('<b>' + title + '</b>');
 | 
			
		||||
 | 
			
		||||
@@ -588,8 +591,7 @@ Notification.prototype = {
 | 
			
		||||
        this._table.add_style_class_name('multi-line-notification');
 | 
			
		||||
        this._scrollArea = new St.ScrollView({ name: 'notification-scrollview',
 | 
			
		||||
                                               vscrollbar_policy: this._scrollPolicy,
 | 
			
		||||
                                               hscrollbar_policy: Gtk.PolicyType.NEVER,
 | 
			
		||||
                                               style_class: 'vfade' });
 | 
			
		||||
                                               hscrollbar_policy: Gtk.PolicyType.NEVER });
 | 
			
		||||
        this._table.add(this._scrollArea, { row: 1,
 | 
			
		||||
                                            col: 2 });
 | 
			
		||||
        this._updateLastColumnSettings();
 | 
			
		||||
@@ -694,6 +696,7 @@ Notification.prototype = {
 | 
			
		||||
        this._imageBin.opacity = 230;
 | 
			
		||||
        this._table.add_style_class_name('multi-line-notification');
 | 
			
		||||
        this._table.add_style_class_name('notification-with-image');
 | 
			
		||||
        this._addBannerBody();
 | 
			
		||||
        this._updateLastColumnSettings();
 | 
			
		||||
        this._table.add(this._imageBin, { row: 1,
 | 
			
		||||
                                          col: 1,
 | 
			
		||||
@@ -791,11 +794,12 @@ Notification.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _bannerBoxAllocate: function(actor, box, flags) {
 | 
			
		||||
        let [titleMinW, titleNatW] = this._titleLabel.get_preferred_width(-1);
 | 
			
		||||
        let [titleMinH, titleNatH] = this._titleLabel.get_preferred_height(-1);
 | 
			
		||||
        let [bannerMinW, bannerNatW] = this._bannerLabel.get_preferred_width(-1);
 | 
			
		||||
        let availWidth = box.x2 - box.x1;
 | 
			
		||||
 | 
			
		||||
        let [titleMinW, titleNatW] = this._titleLabel.get_preferred_width(-1);
 | 
			
		||||
        let [titleMinH, titleNatH] = this._titleLabel.get_preferred_height(availWidth);
 | 
			
		||||
        let [bannerMinW, bannerNatW] = this._bannerLabel.get_preferred_width(availWidth);
 | 
			
		||||
 | 
			
		||||
        let titleBox = new Clutter.ActorBox();
 | 
			
		||||
        let titleBoxW = Math.min(titleNatW, availWidth);
 | 
			
		||||
        if (this._titleDirection == St.TextDirection.RTL) {
 | 
			
		||||
@@ -943,14 +947,12 @@ Notification.prototype = {
 | 
			
		||||
        this.actor.destroy();
 | 
			
		||||
        this.actor._delegate = null;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(Notification.prototype);
 | 
			
		||||
 | 
			
		||||
function Source(title) {
 | 
			
		||||
    this._init(title);
 | 
			
		||||
}
 | 
			
		||||
const Source = new Lang.Class({
 | 
			
		||||
    Name: 'MessageTraySource',
 | 
			
		||||
 | 
			
		||||
Source.prototype = {
 | 
			
		||||
    ICON_SIZE: 24,
 | 
			
		||||
 | 
			
		||||
    _init: function(title) {
 | 
			
		||||
@@ -981,6 +983,7 @@ Source.prototype = {
 | 
			
		||||
 | 
			
		||||
        this.isTransient = false;
 | 
			
		||||
        this.isChat = false;
 | 
			
		||||
        this.isMuted = false;
 | 
			
		||||
 | 
			
		||||
        this.notifications = [];
 | 
			
		||||
    },
 | 
			
		||||
@@ -1045,6 +1048,13 @@ Source.prototype = {
 | 
			
		||||
        this.emit('title-changed');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setMuted: function(muted) {
 | 
			
		||||
        if (!this.isChat || this.isMuted == muted)
 | 
			
		||||
            return;
 | 
			
		||||
        this.isMuted = muted;
 | 
			
		||||
        this.emit('muted-changed');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // Called to create a new icon actor (of size this.ICON_SIZE).
 | 
			
		||||
    // Must be overridden by the subclass if you do not pass icons
 | 
			
		||||
    // explicitly to the Notification() constructor.
 | 
			
		||||
@@ -1083,7 +1093,8 @@ Source.prototype = {
 | 
			
		||||
 | 
			
		||||
    notify: function(notification) {
 | 
			
		||||
        this.pushNotification(notification);
 | 
			
		||||
        this.emit('notify', notification);
 | 
			
		||||
        if (!this.isMuted)
 | 
			
		||||
             this.emit('notify', notification);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    destroy: function(reason) {
 | 
			
		||||
@@ -1123,14 +1134,12 @@ Source.prototype = {
 | 
			
		||||
    _lastNotificationRemoved: function() {
 | 
			
		||||
        this.destroy();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(Source.prototype);
 | 
			
		||||
 | 
			
		||||
function SummaryItem(source) {
 | 
			
		||||
    this._init(source);
 | 
			
		||||
}
 | 
			
		||||
const SummaryItem = new Lang.Class({
 | 
			
		||||
    Name: 'SummaryItem',
 | 
			
		||||
 | 
			
		||||
SummaryItem.prototype = {
 | 
			
		||||
    _init: function(source) {
 | 
			
		||||
        this.source = source;
 | 
			
		||||
        this.source.connect('notification-added', Lang.bind(this, this._notificationAddedToSource));
 | 
			
		||||
@@ -1199,6 +1208,18 @@ SummaryItem.prototype = {
 | 
			
		||||
        }));
 | 
			
		||||
        this.rightClickMenu.add(item.actor);
 | 
			
		||||
 | 
			
		||||
	if (source.isChat) {
 | 
			
		||||
            item = new PopupMenu.PopupMenuItem('');
 | 
			
		||||
            item.actor.connect('notify::mapped', Lang.bind(this, function() {
 | 
			
		||||
                item.label.set_text(source.isMuted ? _("Unmute") : _("Mute"));
 | 
			
		||||
            }));
 | 
			
		||||
            item.connect('activate', Lang.bind(this, function() {
 | 
			
		||||
                source.setMuted(!source.isMuted);
 | 
			
		||||
                this.emit('done-displaying-content');
 | 
			
		||||
            }));
 | 
			
		||||
            this.rightClickMenu.add(item.actor);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        let focusManager = St.FocusManager.get_for_stage(global.stage);
 | 
			
		||||
        focusManager.add_group(this.rightClickMenu);
 | 
			
		||||
    },
 | 
			
		||||
@@ -1309,21 +1330,22 @@ SummaryItem.prototype = {
 | 
			
		||||
        if (this.notificationStack.get_children().length > 0)
 | 
			
		||||
            this.notificationStack.get_children()[0]._delegate.setIconVisible(true);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(SummaryItem.prototype);
 | 
			
		||||
 | 
			
		||||
function MessageTray() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const MessageTray = new Lang.Class({
 | 
			
		||||
    Name: 'MessageTray',
 | 
			
		||||
 | 
			
		||||
MessageTray.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._presence = new GnomeSession.Presence();
 | 
			
		||||
        this._presence = new GnomeSession.Presence(Lang.bind(this, function(proxy, error) {
 | 
			
		||||
            this._onStatusChanged(proxy.status);
 | 
			
		||||
        }));
 | 
			
		||||
        this._userStatus = GnomeSession.PresenceStatus.AVAILABLE;
 | 
			
		||||
        this._busy = false;
 | 
			
		||||
        this._backFromAway = false;
 | 
			
		||||
        this._presence.connect('StatusChanged', Lang.bind(this, this._onStatusChanged));
 | 
			
		||||
        this._presence.getStatus(Lang.bind(this, this._onStatusChanged));
 | 
			
		||||
        this._presence.connectSignal('StatusChanged', Lang.bind(this, function(proxy, senderName, [status]) {
 | 
			
		||||
            this._onStatusChanged(status);
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.Group({ name: 'message-tray',
 | 
			
		||||
                                    reactive: true,
 | 
			
		||||
@@ -1347,6 +1369,7 @@ MessageTray.prototype = {
 | 
			
		||||
        this._summaryBin.opacity = 0;
 | 
			
		||||
 | 
			
		||||
        this._summaryMotionId = 0;
 | 
			
		||||
        this._trayMotionId = 0;
 | 
			
		||||
 | 
			
		||||
        this._summaryBoxPointer = new BoxPointer.BoxPointer(St.Side.BOTTOM,
 | 
			
		||||
                                                            { reactive: true,
 | 
			
		||||
@@ -1386,12 +1409,15 @@ MessageTray.prototype = {
 | 
			
		||||
           }));
 | 
			
		||||
        this._focusGrabber.connect('escape-pressed', Lang.bind(this, this._escapeTray));
 | 
			
		||||
 | 
			
		||||
        Main.layoutManager.keyboardBox.connect('notify::hover', Lang.bind(this, this._onKeyboardHoverChanged));
 | 
			
		||||
 | 
			
		||||
        this._trayState = State.HIDDEN;
 | 
			
		||||
        this._locked = false;
 | 
			
		||||
        this._traySummoned = false;
 | 
			
		||||
        this._useLongerTrayLeftTimeout = false;
 | 
			
		||||
        this._trayLeftTimeoutId = 0;
 | 
			
		||||
        this._pointerInTray = false;
 | 
			
		||||
        this._pointerInKeyboard = false;
 | 
			
		||||
        this._summaryState = State.HIDDEN;
 | 
			
		||||
        this._summaryTimeoutId = 0;
 | 
			
		||||
        this._pointerInSummary = false;
 | 
			
		||||
@@ -1494,12 +1520,23 @@ MessageTray.prototype = {
 | 
			
		||||
        // after notifications are done showing. However, we don't want that to happen for
 | 
			
		||||
        // transient sources, which are removed after the notification is shown, but are
 | 
			
		||||
        // not removed fast enough because of the callbacks to avoid the summary popping up.
 | 
			
		||||
        // So we just don't add transient sources to this._newSummaryItems .
 | 
			
		||||
        if (!source.isTransient)
 | 
			
		||||
        // So we just don't add transient sources to this._newSummaryItems.
 | 
			
		||||
        // We don't want that to happen for chat sources neither, because they
 | 
			
		||||
        // can be added when the user starts a chat from Empathy and they are not transient.
 | 
			
		||||
        // The notification will popup on incoming message anyway. See bug #657249.
 | 
			
		||||
        if (!source.isTransient && !source.isChat)
 | 
			
		||||
            this._newSummaryItems.push(summaryItem);
 | 
			
		||||
 | 
			
		||||
        source.connect('notify', Lang.bind(this, this._onNotify));
 | 
			
		||||
 | 
			
		||||
        source.connect('muted-changed', Lang.bind(this,
 | 
			
		||||
            function () {
 | 
			
		||||
                if (source.isMuted)
 | 
			
		||||
                    this._notificationQueue = this._notificationQueue.filter(function(notification) {
 | 
			
		||||
                        return source != notification.source;
 | 
			
		||||
                    });
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
        summaryItem.actor.connect('notify::hover', Lang.bind(this,
 | 
			
		||||
            function () {
 | 
			
		||||
                this._onSummaryItemHoverChanged(summaryItem);
 | 
			
		||||
@@ -1569,7 +1606,7 @@ MessageTray.prototype = {
 | 
			
		||||
 | 
			
		||||
        summaryItemToRemove.actor.destroy();
 | 
			
		||||
 | 
			
		||||
        if (needUpdate);
 | 
			
		||||
        if (needUpdate)
 | 
			
		||||
            this._updateState();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -1814,7 +1851,7 @@ MessageTray.prototype = {
 | 
			
		||||
                // automatically. Instead, the user is able to expand the notification by mousing away from it and then
 | 
			
		||||
                // mousing back in. Because this is an expected action, we set the boolean flag that indicates that a longer
 | 
			
		||||
                // timeout should be used before popping down the notification.
 | 
			
		||||
                if (this._notificationBin.contains(actorAtShowNotificationPosition)) {
 | 
			
		||||
                if (this.actor.contains(actorAtShowNotificationPosition)) {
 | 
			
		||||
                    this._useLongerTrayLeftTimeout = true;
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
@@ -1838,7 +1875,25 @@ MessageTray.prototype = {
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onStatusChanged: function(presence, status) {
 | 
			
		||||
    _onKeyboardHoverChanged: function(keyboard) {
 | 
			
		||||
        this._pointerInKeyboard = keyboard.hover;
 | 
			
		||||
 | 
			
		||||
        if (!keyboard.hover) {
 | 
			
		||||
            let event = Clutter.get_current_event();
 | 
			
		||||
            if (event && event.type() == Clutter.EventType.LEAVE) {
 | 
			
		||||
                let into = event.get_related();
 | 
			
		||||
                if (into && this.actor.contains(into)) {
 | 
			
		||||
                    // Don't call _updateState, because pointerInTray is
 | 
			
		||||
                    // still false
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._updateState();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onStatusChanged: function(status) {
 | 
			
		||||
        this._backFromAway = (this._userStatus == GnomeSession.PresenceStatus.IDLE && this._userStatus != status);
 | 
			
		||||
        this._userStatus = status;
 | 
			
		||||
 | 
			
		||||
@@ -1902,7 +1957,7 @@ MessageTray.prototype = {
 | 
			
		||||
        let notificationsPending = this._notificationQueue.length > 0 && (!this._busy || notificationUrgent);
 | 
			
		||||
        let notificationPinned = this._pointerInTray && !this._pointerInSummary && !this._notificationRemoved;
 | 
			
		||||
        let notificationExpanded = this._notificationBin.y < 0;
 | 
			
		||||
        let notificationExpired = (this._notificationTimeoutId == 0 && !(this._notification && this._notification.urgency == Urgency.CRITICAL) && !this._pointerInTray && !this._locked) || this._notificationRemoved;
 | 
			
		||||
        let notificationExpired = (this._notificationTimeoutId == 0 && !(this._notification && this._notification.urgency == Urgency.CRITICAL) && !this._pointerInTray && !this._locked && !(this._pointerInKeyboard && notificationExpanded)) || this._notificationRemoved;
 | 
			
		||||
        let canShowNotification = notificationsPending && this._summaryState == State.HIDDEN;
 | 
			
		||||
 | 
			
		||||
        if (this._notificationState == State.HIDDEN) {
 | 
			
		||||
@@ -2260,6 +2315,8 @@ MessageTray.prototype = {
 | 
			
		||||
        // _clickedSummaryItem.actor can change absolute position without changing allocation
 | 
			
		||||
        this._summaryMotionId = this._summary.connect('allocation-changed',
 | 
			
		||||
                                                      Lang.bind(this, this._adjustSummaryBoxPointerPosition));
 | 
			
		||||
        this._trayMotionId = Main.layoutManager.trayBox.connect('notify::anchor-y',
 | 
			
		||||
                                                                Lang.bind(this, this._adjustSummaryBoxPointerPosition));
 | 
			
		||||
 | 
			
		||||
        this._summaryBoxPointer.actor.opacity = 0;
 | 
			
		||||
        this._summaryBoxPointer.actor.show();
 | 
			
		||||
@@ -2291,8 +2348,10 @@ MessageTray.prototype = {
 | 
			
		||||
        if (this._clickedSummaryItemAllocationChangedId) {
 | 
			
		||||
            this._clickedSummaryItem.actor.disconnect(this._clickedSummaryItemAllocationChangedId);
 | 
			
		||||
            this._summary.disconnect(this._summaryMotionId);
 | 
			
		||||
            Main.layoutManager.trayBox.disconnect(this._trayMotionId);
 | 
			
		||||
            this._clickedSummaryItemAllocationChangedId = 0;
 | 
			
		||||
            this._summaryMotionId = 0;
 | 
			
		||||
            this._trayMotionId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._clickedSummaryItem)
 | 
			
		||||
@@ -2311,8 +2370,9 @@ MessageTray.prototype = {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._summaryBoxPointerState = State.HIDING;
 | 
			
		||||
        // Unset this._clickedSummaryItem if we are no longer showing the summary
 | 
			
		||||
        if (this._summaryState != State.SHOWN)
 | 
			
		||||
        // Unset this._clickedSummaryItem if we are no longer showing the summary or if
 | 
			
		||||
        // this._clickedSummaryItem is still the item associated with the currently showing box pointer
 | 
			
		||||
        if (this._summaryState != State.SHOWN || this._summaryBoxPointerItem == this._clickedSummaryItem)
 | 
			
		||||
            this._unsetClickedSummaryItem();
 | 
			
		||||
 | 
			
		||||
        this._focusGrabber.ungrabFocus();
 | 
			
		||||
@@ -2354,17 +2414,14 @@ MessageTray.prototype = {
 | 
			
		||||
        if (this._clickedSummaryItem)
 | 
			
		||||
            this._updateState();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function SystemNotificationSource() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SystemNotificationSource.prototype = {
 | 
			
		||||
    __proto__:  Source.prototype,
 | 
			
		||||
const SystemNotificationSource = new Lang.Class({
 | 
			
		||||
    Name: 'SystemNotificationSource',
 | 
			
		||||
    Extends: Source,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        Source.prototype._init.call(this, _("System Information"));
 | 
			
		||||
        this.parent(_("System Information"));
 | 
			
		||||
 | 
			
		||||
        this._setSummaryIcon(this.createNotificationIcon());
 | 
			
		||||
    },
 | 
			
		||||
@@ -2378,4 +2435,4 @@ SystemNotificationSource.prototype = {
 | 
			
		||||
    open: function() {
 | 
			
		||||
        this.destroy();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gdk = imports.gi.Gdk;
 | 
			
		||||
@@ -29,11 +29,9 @@ const State = {
 | 
			
		||||
    FADED_OUT: 4
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function ModalDialog() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const ModalDialog = new Lang.Class({
 | 
			
		||||
    Name: 'ModalDialog',
 | 
			
		||||
 | 
			
		||||
ModalDialog.prototype = {
 | 
			
		||||
    _init: function(params) {
 | 
			
		||||
        params = Params.parse(params, { shellReactive: false,
 | 
			
		||||
                                        styleClass: null });
 | 
			
		||||
@@ -110,9 +108,8 @@ ModalDialog.prototype = {
 | 
			
		||||
        this._buttonLayout.destroy_children();
 | 
			
		||||
        this._actionKeys = {};
 | 
			
		||||
 | 
			
		||||
        let i = 0;
 | 
			
		||||
        for (let index in buttons) {
 | 
			
		||||
            let buttonInfo = buttons[index];
 | 
			
		||||
        for (let i = 0; i < buttons.length; i++) {
 | 
			
		||||
            let buttonInfo = buttons[i];
 | 
			
		||||
            let label = buttonInfo['label'];
 | 
			
		||||
            let action = buttonInfo['action'];
 | 
			
		||||
            let key = buttonInfo['key'];
 | 
			
		||||
@@ -132,7 +129,9 @@ ModalDialog.prototype = {
 | 
			
		||||
            else
 | 
			
		||||
                x_alignment = St.Align.MIDDLE;
 | 
			
		||||
 | 
			
		||||
            this._initialKeyFocus = buttonInfo.button;
 | 
			
		||||
            if (this._initialKeyFocus == this._dialogLayout ||
 | 
			
		||||
                this._buttonLayout.contains(this._initialKeyFocus))
 | 
			
		||||
                this._initialKeyFocus = buttonInfo.button;
 | 
			
		||||
            this._buttonLayout.add(buttonInfo.button,
 | 
			
		||||
                                   { expand: true,
 | 
			
		||||
                                     x_fill: false,
 | 
			
		||||
@@ -144,11 +143,10 @@ ModalDialog.prototype = {
 | 
			
		||||
 | 
			
		||||
            if (key)
 | 
			
		||||
                this._actionKeys[key] = action;
 | 
			
		||||
            i++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Fade in buttons if there weren't any before
 | 
			
		||||
        if (!hadChildren && i > 0) {
 | 
			
		||||
        if (!hadChildren && buttons.length > 0) {
 | 
			
		||||
            this._buttonLayout.opacity = 0;
 | 
			
		||||
            Tweener.addTween(this._buttonLayout,
 | 
			
		||||
                             { opacity: 255,
 | 
			
		||||
@@ -303,5 +301,5 @@ ModalDialog.prototype = {
 | 
			
		||||
                               })
 | 
			
		||||
                         });
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(ModalDialog.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 *
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2011 Giovanni Campagna <scampa.giovanni@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
@@ -30,16 +30,14 @@ const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const ModalDialog = imports.ui.modalDialog;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
const ShellEntry = imports.ui.shellEntry;
 | 
			
		||||
 | 
			
		||||
function NetworkSecretDialog() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NetworkSecretDialog.prototype = {
 | 
			
		||||
    __proto__: ModalDialog.ModalDialog.prototype,
 | 
			
		||||
const NetworkSecretDialog = new Lang.Class({
 | 
			
		||||
    Name: 'NetworkSecretDialog',
 | 
			
		||||
    Extends: ModalDialog.ModalDialog,
 | 
			
		||||
 | 
			
		||||
    _init: function(agent, requestId, connection, settingName, hints) {
 | 
			
		||||
        ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'polkit-dialog' });
 | 
			
		||||
        this.parent({ styleClass: 'polkit-dialog' });
 | 
			
		||||
 | 
			
		||||
        this._agent = agent;
 | 
			
		||||
        this._requestId = requestId;
 | 
			
		||||
@@ -91,6 +89,7 @@ NetworkSecretDialog.prototype = {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let secretTable = new St.Table({ style_class: 'network-dialog-secret-table' });
 | 
			
		||||
        let initialFocusSet = false;
 | 
			
		||||
        let pos = 0;
 | 
			
		||||
        for (let i = 0; i < this._content.secrets.length; i++) {
 | 
			
		||||
            let secret = this._content.secrets[i];
 | 
			
		||||
@@ -102,6 +101,8 @@ NetworkSecretDialog.prototype = {
 | 
			
		||||
            secret.entry = new St.Entry({ style_class: 'polkit-dialog-password-entry',
 | 
			
		||||
                                          text: secret.value, can_focus: reactive,
 | 
			
		||||
                                          reactive: reactive });
 | 
			
		||||
            ShellEntry.addContextMenu(secret.entry,
 | 
			
		||||
                                      { isPassword: secret.password });
 | 
			
		||||
 | 
			
		||||
            if (secret.validate)
 | 
			
		||||
                secret.valid = secret.validate(secret);
 | 
			
		||||
@@ -109,6 +110,12 @@ NetworkSecretDialog.prototype = {
 | 
			
		||||
                secret.valid = secret.value.length > 0;
 | 
			
		||||
 | 
			
		||||
            if (reactive) {
 | 
			
		||||
                if (!initialFocusSet) {
 | 
			
		||||
                    this.setInitialKeyFocus(secret.entry);
 | 
			
		||||
                    initialFocusSet = true;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                secret.entry.clutter_text.connect('activate', Lang.bind(this, this._onOk));
 | 
			
		||||
                secret.entry.clutter_text.connect('text-changed', Lang.bind(this, function() {
 | 
			
		||||
                    secret.value = secret.entry.get_text();
 | 
			
		||||
                    if (secret.validate)
 | 
			
		||||
@@ -120,34 +127,14 @@ NetworkSecretDialog.prototype = {
 | 
			
		||||
            } else
 | 
			
		||||
                secret.valid = true;
 | 
			
		||||
 | 
			
		||||
            secretTable.add(label, { row: pos, col: 0, x_align: St.Align.START, y_align: St.Align.START });
 | 
			
		||||
            secretTable.add(label, { row: pos, col: 0, x_expand: false, x_fill: true, x_align: St.Align.START, y_align: St.Align.START });
 | 
			
		||||
            secretTable.add(secret.entry, { row: pos, col: 1, x_expand: true, x_fill: true, y_align: St.Align.END });
 | 
			
		||||
            pos++;
 | 
			
		||||
 | 
			
		||||
            if (secret.password) {
 | 
			
		||||
            if (secret.password)
 | 
			
		||||
                secret.entry.clutter_text.set_password_char('\u25cf');
 | 
			
		||||
 | 
			
		||||
                // FIXME: need a real checkbox here
 | 
			
		||||
                let button = new St.Button({ button_mask: St.ButtonMask.ONE,
 | 
			
		||||
                                             can_focus: true });
 | 
			
		||||
                let checkbox = new St.BoxLayout({ vertical: false,
 | 
			
		||||
                                                  style_class: 'network-dialog-show-password-checkbox' 
 | 
			
		||||
                                                });
 | 
			
		||||
                let _switch = new PopupMenu.Switch(false);
 | 
			
		||||
                checkbox.add(_switch.actor);
 | 
			
		||||
                checkbox.add(new St.Label({ text: _("Show password") }), { expand: true });
 | 
			
		||||
                button.connect('clicked', function() {
 | 
			
		||||
                    _switch.toggle();
 | 
			
		||||
                    if (_switch.state)
 | 
			
		||||
                        secret.entry.clutter_text.set_password_char('');
 | 
			
		||||
                    else
 | 
			
		||||
                        secret.entry.clutter_text.set_password_char('\u25cf');
 | 
			
		||||
                });
 | 
			
		||||
                button.child = checkbox;
 | 
			
		||||
                secretTable.add(button, { row: pos, col: 1, x_expand: true, x_fill: true, y_fill: true })
 | 
			
		||||
                pos++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        messageBox.add(secretTable);
 | 
			
		||||
 | 
			
		||||
        this._okButton = { label:  _("Connect"),
 | 
			
		||||
@@ -368,13 +355,11 @@ NetworkSecretDialog.prototype = {
 | 
			
		||||
 | 
			
		||||
        return content;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function NetworkAgent() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
const NetworkAgent = new Lang.Class({
 | 
			
		||||
    Name: 'NetworkAgent',
 | 
			
		||||
 | 
			
		||||
NetworkAgent.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._native = new Shell.NetworkAgent({ auto_register: true,
 | 
			
		||||
                                                identifier: 'org.gnome.Shell.NetworkAgent' });
 | 
			
		||||
@@ -397,4 +382,4 @@ NetworkAgent.prototype = {
 | 
			
		||||
        this._dialogs[requestId].close(global.get_current_time());
 | 
			
		||||
        this._dialogs[requestId].destroy();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
@@ -16,49 +16,52 @@ const Util = imports.misc.util;
 | 
			
		||||
 | 
			
		||||
let nextNotificationId = 1;
 | 
			
		||||
 | 
			
		||||
// Should really be defined in dbus.js
 | 
			
		||||
const BusIface = {
 | 
			
		||||
    name: 'org.freedesktop.DBus',
 | 
			
		||||
    methods: [{ name: 'GetConnectionUnixProcessID',
 | 
			
		||||
                inSignature: 's',
 | 
			
		||||
                outSignature: 'i' }]
 | 
			
		||||
};
 | 
			
		||||
// Should really be defined in Gio.js
 | 
			
		||||
const BusIface = <interface name="org.freedesktop.DBus">
 | 
			
		||||
<method name="GetConnectionUnixProcessID">
 | 
			
		||||
    <arg type="s" direction="in" />
 | 
			
		||||
    <arg type="u" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
const Bus = function () {
 | 
			
		||||
    this._init();
 | 
			
		||||
};
 | 
			
		||||
var BusProxy = Gio.DBusProxy.makeProxyWrapper(BusIface);
 | 
			
		||||
function Bus() {
 | 
			
		||||
    return new BusProxy(Gio.DBus.session, 'org.freedesktop.DBus', '/org/freedesktop/DBus');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Bus.prototype = {
 | 
			
		||||
     _init: function() {
 | 
			
		||||
         DBus.session.proxifyObject(this, 'org.freedesktop.DBus', '/org/freedesktop/DBus');
 | 
			
		||||
     }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
DBus.proxifyPrototype(Bus.prototype, BusIface);
 | 
			
		||||
 | 
			
		||||
const NotificationDaemonIface = {
 | 
			
		||||
    name: 'org.freedesktop.Notifications',
 | 
			
		||||
    methods: [{ name: 'Notify',
 | 
			
		||||
                inSignature: 'susssasa{sv}i',
 | 
			
		||||
                outSignature: 'u'
 | 
			
		||||
              },
 | 
			
		||||
              { name: 'CloseNotification',
 | 
			
		||||
                inSignature: 'u',
 | 
			
		||||
                outSignature: ''
 | 
			
		||||
              },
 | 
			
		||||
              { name: 'GetCapabilities',
 | 
			
		||||
                inSignature: '',
 | 
			
		||||
                outSignature: 'as'
 | 
			
		||||
              },
 | 
			
		||||
              { name: 'GetServerInformation',
 | 
			
		||||
                inSignature: '',
 | 
			
		||||
                outSignature: 'ssss'
 | 
			
		||||
              }],
 | 
			
		||||
    signals: [{ name: 'NotificationClosed',
 | 
			
		||||
                inSignature: 'uu' },
 | 
			
		||||
              { name: 'ActionInvoked',
 | 
			
		||||
                inSignature: 'us' }]
 | 
			
		||||
};
 | 
			
		||||
const NotificationDaemonIface = <interface name="org.freedesktop.Notifications">
 | 
			
		||||
<method name="Notify">
 | 
			
		||||
    <arg type="s" direction="in"/>
 | 
			
		||||
    <arg type="u" direction="in"/>
 | 
			
		||||
    <arg type="s" direction="in"/>
 | 
			
		||||
    <arg type="s" direction="in"/>
 | 
			
		||||
    <arg type="s" direction="in"/>
 | 
			
		||||
    <arg type="as" direction="in"/>
 | 
			
		||||
    <arg type="a{sv}" direction="in"/>
 | 
			
		||||
    <arg type="i" direction="in"/>
 | 
			
		||||
    <arg type="u" direction="out"/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name="CloseNotification">
 | 
			
		||||
    <arg type="u" direction="in"/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name="GetCapabilities">
 | 
			
		||||
    <arg type="as" direction="out"/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name="GetServerInformation">
 | 
			
		||||
    <arg type="s" direction="out"/>
 | 
			
		||||
    <arg type="s" direction="out"/>
 | 
			
		||||
    <arg type="s" direction="out"/>
 | 
			
		||||
    <arg type="s" direction="out"/>
 | 
			
		||||
</method>
 | 
			
		||||
<signal name="NotificationClosed">
 | 
			
		||||
    <arg type="u"/>
 | 
			
		||||
    <arg type="u"/>
 | 
			
		||||
</signal>
 | 
			
		||||
<signal name="ActionInvoked">
 | 
			
		||||
    <arg type="u"/>
 | 
			
		||||
    <arg type="s"/>
 | 
			
		||||
</signal>
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
const NotificationClosedReason = {
 | 
			
		||||
    EXPIRED: 1,
 | 
			
		||||
@@ -84,13 +87,12 @@ const rewriteRules = {
 | 
			
		||||
    ]
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function NotificationDaemon() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const NotificationDaemon = new Lang.Class({
 | 
			
		||||
    Name: 'NotificationDaemon',
 | 
			
		||||
 | 
			
		||||
NotificationDaemon.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        DBus.session.exportObject('/org/freedesktop/Notifications', this);
 | 
			
		||||
        this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(NotificationDaemonIface, this);
 | 
			
		||||
        this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/Notifications');
 | 
			
		||||
 | 
			
		||||
        this._sources = {};
 | 
			
		||||
        this._senderToPid = {};
 | 
			
		||||
@@ -109,6 +111,14 @@ NotificationDaemon.prototype = {
 | 
			
		||||
    _iconForNotificationData: function(icon, hints, size) {
 | 
			
		||||
        let textureCache = St.TextureCache.get_default();
 | 
			
		||||
 | 
			
		||||
        // If an icon is not specified, we use 'image-data' or 'image-path' hint for an icon
 | 
			
		||||
        // and don't show a large image. There are currently many applications that use
 | 
			
		||||
        // notify_notification_set_icon_from_pixbuf() from libnotify, which in turn sets
 | 
			
		||||
        // the 'image-data' hint. These applications don't typically pass in 'app_icon'
 | 
			
		||||
        // argument to Notify() and actually expect the pixbuf to be shown as an icon.
 | 
			
		||||
        // So the logic here does the right thing for this case. If both an icon and either
 | 
			
		||||
        // one of 'image-data' or 'image-path' are specified, we show both an icon and
 | 
			
		||||
        // a large image.
 | 
			
		||||
        if (icon) {
 | 
			
		||||
            if (icon.substr(0, 7) == 'file://')
 | 
			
		||||
                return textureCache.load_uri_async(icon, size, size);
 | 
			
		||||
@@ -119,6 +129,12 @@ NotificationDaemon.prototype = {
 | 
			
		||||
                return new St.Icon({ icon_name: icon,
 | 
			
		||||
                                     icon_type: St.IconType.FULLCOLOR,
 | 
			
		||||
                                     icon_size: size });
 | 
			
		||||
        } else if (hints['image-data']) {
 | 
			
		||||
            let [width, height, rowStride, hasAlpha,
 | 
			
		||||
                 bitsPerSample, nChannels, data] = hints['image-data'];
 | 
			
		||||
            return textureCache.load_from_raw(data, hasAlpha, width, height, rowStride, size);
 | 
			
		||||
        } else if (hints['image-path']) {
 | 
			
		||||
            return textureCache.load_uri_async(GLib.filename_to_uri(hints['image-path'], null), size, size);
 | 
			
		||||
        } else {
 | 
			
		||||
            let stockIcon;
 | 
			
		||||
            switch (hints.urgency) {
 | 
			
		||||
@@ -181,8 +197,8 @@ NotificationDaemon.prototype = {
 | 
			
		||||
        return source;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    Notify: function(appName, replacesId, icon, summary, body,
 | 
			
		||||
                     actions, hints, timeout) {
 | 
			
		||||
    NotifyAsync: function(params, invocation) {
 | 
			
		||||
        let [appName, replacesId, icon, summary, body, actions, hints, timeout] = params;
 | 
			
		||||
        let id;
 | 
			
		||||
 | 
			
		||||
        // Filter out chat, presence, calls and invitation notifications from
 | 
			
		||||
@@ -201,7 +217,7 @@ NotificationDaemon.prototype = {
 | 
			
		||||
                                        function () {
 | 
			
		||||
                                            this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
 | 
			
		||||
                                        }));
 | 
			
		||||
            return id;
 | 
			
		||||
            return invocation.return_value(GLib.Variant.new('(u)', [id]));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let rewrites = rewriteRules[appName];
 | 
			
		||||
@@ -213,6 +229,11 @@ NotificationDaemon.prototype = {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let hint in hints) {
 | 
			
		||||
            // unpack the variants
 | 
			
		||||
            hints[hint] = hints[hint].deep_unpack();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        hints = Params.parse(hints, { urgency: Urgency.NORMAL }, true);
 | 
			
		||||
 | 
			
		||||
        // Be compatible with the various hints for image data and image path
 | 
			
		||||
@@ -244,51 +265,55 @@ NotificationDaemon.prototype = {
 | 
			
		||||
        }
 | 
			
		||||
        this._notifications[id] = ndata;
 | 
			
		||||
 | 
			
		||||
        let sender = DBus.getCurrentMessageContext().sender;
 | 
			
		||||
        let sender = invocation.get_sender();
 | 
			
		||||
        let pid = this._senderToPid[sender];
 | 
			
		||||
 | 
			
		||||
        let source = this._getSource(appName, pid, ndata, sender);
 | 
			
		||||
 | 
			
		||||
        if (source) {
 | 
			
		||||
            this._notifyForSource(source, ndata);
 | 
			
		||||
            return id;
 | 
			
		||||
            return invocation.return_value(GLib.Variant.new('(u)', [id]));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (replacesId) {
 | 
			
		||||
            // There's already a pending call to GetConnectionUnixProcessID,
 | 
			
		||||
            // which will see the new notification data when it finishes,
 | 
			
		||||
            // so we don't have to do anything.
 | 
			
		||||
            return id;
 | 
			
		||||
            return invocation.return_value(GLib.Variant.new('(u)', [id]));;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._busProxy.GetConnectionUnixProcessIDRemote(sender, Lang.bind(this,
 | 
			
		||||
            function (pid, ex) {
 | 
			
		||||
                // The app may have updated or removed the notification
 | 
			
		||||
                ndata = this._notifications[id];
 | 
			
		||||
                if (!ndata)
 | 
			
		||||
                    return;
 | 
			
		||||
        this._busProxy.GetConnectionUnixProcessIDRemote(sender, Lang.bind(this, function (result, excp) {
 | 
			
		||||
            // The app may have updated or removed the notification
 | 
			
		||||
            ndata = this._notifications[id];
 | 
			
		||||
            if (!ndata)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
                source = this._getSource(appName, pid, ndata, sender);
 | 
			
		||||
            if (excp) {
 | 
			
		||||
                logError(excp, 'Call to GetConnectionUnixProcessID failed');
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
                // We only store sender-pid entries for persistent sources.
 | 
			
		||||
                // Removing the entries once the source is destroyed
 | 
			
		||||
                // would result in the entries associated with transient
 | 
			
		||||
                // sources removed once the notification is shown anyway.
 | 
			
		||||
                // However, keeping these pairs would mean that we would
 | 
			
		||||
                // possibly remove an entry associated with a persistent
 | 
			
		||||
                // source when a transient source for the same sender is
 | 
			
		||||
                // distroyed.
 | 
			
		||||
                if (!source.isTransient) {
 | 
			
		||||
                    this._senderToPid[sender] = pid;
 | 
			
		||||
                    source.connect('destroy', Lang.bind(this,
 | 
			
		||||
                        function() {
 | 
			
		||||
                            delete this._senderToPid[sender];
 | 
			
		||||
                        }));
 | 
			
		||||
                }
 | 
			
		||||
                this._notifyForSource(source, ndata);
 | 
			
		||||
            }));
 | 
			
		||||
            let [pid] = result;
 | 
			
		||||
            source = this._getSource(appName, pid, ndata, sender);
 | 
			
		||||
 | 
			
		||||
        return id;
 | 
			
		||||
            // We only store sender-pid entries for persistent sources.
 | 
			
		||||
            // Removing the entries once the source is destroyed
 | 
			
		||||
            // would result in the entries associated with transient
 | 
			
		||||
            // sources removed once the notification is shown anyway.
 | 
			
		||||
            // However, keeping these pairs would mean that we would
 | 
			
		||||
            // possibly remove an entry associated with a persistent
 | 
			
		||||
            // source when a transient source for the same sender is
 | 
			
		||||
            // distroyed.
 | 
			
		||||
            if (!source.isTransient) {
 | 
			
		||||
                this._senderToPid[sender] = pid;
 | 
			
		||||
                source.connect('destroy', Lang.bind(this, function() {
 | 
			
		||||
                    delete this._senderToPid[sender];
 | 
			
		||||
                }));
 | 
			
		||||
            }
 | 
			
		||||
            this._notifyForSource(source, ndata);
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        return invocation.return_value(GLib.Variant.new('(u)', [id]));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _notifyForSource: function(source, ndata) {
 | 
			
		||||
@@ -330,7 +355,8 @@ NotificationDaemon.prototype = {
 | 
			
		||||
                                                 clear: true });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (hints['image-data'] || hints['image-path']) {
 | 
			
		||||
        // We only display a large image if an icon is also specified.
 | 
			
		||||
        if (icon && (hints['image-data'] || hints['image-path'])) {
 | 
			
		||||
            let image = null;
 | 
			
		||||
            if (hints['image-data']) {
 | 
			
		||||
                let [width, height, rowStride, hasAlpha,
 | 
			
		||||
@@ -427,17 +453,13 @@ NotificationDaemon.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _emitNotificationClosed: function(id, reason) {
 | 
			
		||||
        DBus.session.emit_signal('/org/freedesktop/Notifications',
 | 
			
		||||
                                 'org.freedesktop.Notifications',
 | 
			
		||||
                                 'NotificationClosed', 'uu',
 | 
			
		||||
                                 [id, reason]);
 | 
			
		||||
        this._dbusImpl.emit_signal('NotificationClosed',
 | 
			
		||||
                                   GLib.Variant.new('(uu)', [id, reason]));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _emitActionInvoked: function(id, action) {
 | 
			
		||||
        DBus.session.emit_signal('/org/freedesktop/Notifications',
 | 
			
		||||
                                 'org.freedesktop.Notifications',
 | 
			
		||||
                                 'ActionInvoked', 'us',
 | 
			
		||||
                                 [id, action]);
 | 
			
		||||
        this._dbusImpl.emit_signal('ActionInvoked',
 | 
			
		||||
                                   GLib.Variant.new('(us)', [id, action]));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onTrayIconAdded: function(o, icon) {
 | 
			
		||||
@@ -450,31 +472,23 @@ NotificationDaemon.prototype = {
 | 
			
		||||
        if (source)
 | 
			
		||||
            source.destroy();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
DBus.conformExport(NotificationDaemon.prototype, NotificationDaemonIface);
 | 
			
		||||
 | 
			
		||||
function Source(title, pid, sender) {
 | 
			
		||||
    this._init(title, pid, sender);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Source.prototype = {
 | 
			
		||||
    __proto__:  MessageTray.Source.prototype,
 | 
			
		||||
const Source = new Lang.Class({
 | 
			
		||||
    Name: 'NotificationDaemonSource',
 | 
			
		||||
    Extends: MessageTray.Source,
 | 
			
		||||
 | 
			
		||||
    _init: function(title, pid, sender) {
 | 
			
		||||
        MessageTray.Source.prototype._init.call(this, title);
 | 
			
		||||
        this.parent(title);
 | 
			
		||||
 | 
			
		||||
        this._pid = pid;
 | 
			
		||||
        if (sender)
 | 
			
		||||
            // TODO: dbus-glib implementation of watch_name() doesn’t return an id to be used for
 | 
			
		||||
            // unwatch_name() or implement unwatch_name(), however when we move to using GDBus implementation,
 | 
			
		||||
            // we should save the id here and call unwatch_name() with it in destroy().
 | 
			
		||||
            // Moving to GDBus is the work in progress: https://bugzilla.gnome.org/show_bug.cgi?id=648651
 | 
			
		||||
            // and https://bugzilla.gnome.org/show_bug.cgi?id=622921 .
 | 
			
		||||
            DBus.session.watch_name(sender,
 | 
			
		||||
                                    false,
 | 
			
		||||
                                    null,
 | 
			
		||||
                                    Lang.bind(this, this._onNameVanished));
 | 
			
		||||
            this._nameWatcherId = Gio.DBus.session.watch_name(sender,
 | 
			
		||||
                                                              Gio.BusNameWatcherFlags.NONE,
 | 
			
		||||
                                                              null,
 | 
			
		||||
                                                              Lang.bind(this, this._onNameVanished));
 | 
			
		||||
        else
 | 
			
		||||
            this._nameWatcherId = 0;
 | 
			
		||||
 | 
			
		||||
        this._setApp();
 | 
			
		||||
        if (this.app)
 | 
			
		||||
@@ -582,6 +596,11 @@ Source.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    destroy: function() {
 | 
			
		||||
        MessageTray.Source.prototype.destroy.call(this);
 | 
			
		||||
        if (this._nameWatcherId) {
 | 
			
		||||
            Gio.DBus.session.unwatch_name(this._nameWatcherId);
 | 
			
		||||
            this._nameWatcherId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.parent();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
@@ -46,11 +46,9 @@ const SwipeScrollResult = {
 | 
			
		||||
    CLICK: 2
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function ShellInfo() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const ShellInfo = new Lang.Class({
 | 
			
		||||
    Name: 'ShellInfo',
 | 
			
		||||
 | 
			
		||||
ShellInfo.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._source = null;
 | 
			
		||||
        this._undoCallback = null;
 | 
			
		||||
@@ -95,13 +93,11 @@ ShellInfo.prototype = {
 | 
			
		||||
 | 
			
		||||
        this._source.notify(notification);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function Overview() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
const Overview = new Lang.Class({
 | 
			
		||||
    Name: 'Overview',
 | 
			
		||||
 | 
			
		||||
Overview.prototype = {
 | 
			
		||||
    _init : function(params) {
 | 
			
		||||
        params = Params.parse(params, { isDummy: false });
 | 
			
		||||
 | 
			
		||||
@@ -811,5 +807,5 @@ Overview.prototype = {
 | 
			
		||||
            this._needsFakePointerEvent = false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(Overview.prototype);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										256
									
								
								js/ui/panel.js
									
									
									
									
									
								
							
							
						
						
									
										256
									
								
								js/ui/panel.js
									
									
									
									
									
								
							@@ -1,8 +1,9 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Cairo = imports.cairo;
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Pango = imports.gi.Pango;
 | 
			
		||||
@@ -16,7 +17,6 @@ const Layout = imports.ui.layout;
 | 
			
		||||
const Overview = imports.ui.overview;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
const PanelMenu = imports.ui.panelMenu;
 | 
			
		||||
const UserMenu = imports.ui.userMenu;
 | 
			
		||||
const DateMenu = imports.ui.dateMenu;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
@@ -28,29 +28,31 @@ const BUTTON_DND_ACTIVATION_TIMEOUT = 250;
 | 
			
		||||
const ANIMATED_ICON_UPDATE_TIMEOUT = 100;
 | 
			
		||||
const SPINNER_ANIMATION_TIME = 0.2;
 | 
			
		||||
 | 
			
		||||
const STANDARD_TRAY_ICON_ORDER = ['a11y', 'keyboard', 'volume', 'bluetooth', 'network', 'battery'];
 | 
			
		||||
const STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION = {
 | 
			
		||||
const STANDARD_STATUS_AREA_ORDER = ['a11y', 'keyboard', 'volume', 'bluetooth', 'network', 'battery', 'userMenu'];
 | 
			
		||||
const STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION = {
 | 
			
		||||
    'a11y': imports.ui.status.accessibility.ATIndicator,
 | 
			
		||||
    'volume': imports.ui.status.volume.Indicator,
 | 
			
		||||
    'battery': imports.ui.status.power.Indicator,
 | 
			
		||||
    'keyboard': imports.ui.status.keyboard.XKBIndicator
 | 
			
		||||
    'keyboard': imports.ui.status.keyboard.XKBIndicator,
 | 
			
		||||
    'userMenu': imports.ui.userMenu.UserMenuButton
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
if (Config.HAVE_BLUETOOTH)
 | 
			
		||||
    STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION['bluetooth'] = imports.ui.status.bluetooth.Indicator;
 | 
			
		||||
    STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION['bluetooth'] = imports.ui.status.bluetooth.Indicator;
 | 
			
		||||
 | 
			
		||||
try {
 | 
			
		||||
    STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION['network'] = imports.ui.status.network.NMApplet;
 | 
			
		||||
    STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION['network'] = imports.ui.status.network.NMApplet;
 | 
			
		||||
} catch(e) {
 | 
			
		||||
    log('NMApplet is not supported. It is possible that your NetworkManager version is too old');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const GDM_TRAY_ICON_ORDER = ['a11y', 'display', 'keyboard', 'volume', 'battery'];
 | 
			
		||||
const GDM_TRAY_ICON_SHELL_IMPLEMENTATION = {
 | 
			
		||||
const GDM_STATUS_AREA_ORDER = ['a11y', 'display', 'keyboard', 'volume', 'battery', 'powerMenu'];
 | 
			
		||||
const GDM_STATUS_AREA_SHELL_IMPLEMENTATION = {
 | 
			
		||||
    'a11y': imports.ui.status.accessibility.ATIndicator,
 | 
			
		||||
    'volume': imports.ui.status.volume.Indicator,
 | 
			
		||||
    'battery': imports.ui.status.power.Indicator,
 | 
			
		||||
    'keyboard': imports.ui.status.keyboard.XKBIndicator
 | 
			
		||||
    'keyboard': imports.ui.status.keyboard.XKBIndicator,
 | 
			
		||||
    'powerMenu': imports.gdm.powerMenu.PowerMenuButton
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// To make sure the panel corners blend nicely with the panel,
 | 
			
		||||
@@ -97,11 +99,9 @@ function _unpremultiply(color) {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function AnimatedIcon(name, size) {
 | 
			
		||||
    this._init(name, size);
 | 
			
		||||
}
 | 
			
		||||
const AnimatedIcon = new Lang.Class({
 | 
			
		||||
    Name: 'AnimatedIcon',
 | 
			
		||||
 | 
			
		||||
AnimatedIcon.prototype = {
 | 
			
		||||
    _init: function(name, size) {
 | 
			
		||||
        this.actor = new St.Bin({ visible: false });
 | 
			
		||||
        this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
 | 
			
		||||
@@ -138,13 +138,11 @@ AnimatedIcon.prototype = {
 | 
			
		||||
        if (this._timeoutId)
 | 
			
		||||
            Mainloop.source_remove(this._timeoutId);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function TextShadower() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const TextShadower = new Lang.Class({
 | 
			
		||||
    Name: 'TextShadower',
 | 
			
		||||
 | 
			
		||||
TextShadower.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.actor = new Shell.GenericContainer();
 | 
			
		||||
        this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
 | 
			
		||||
@@ -224,7 +222,7 @@ TextShadower.prototype = {
 | 
			
		||||
            child.allocate(childBox, flags);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * AppMenuButton:
 | 
			
		||||
@@ -234,21 +232,22 @@ TextShadower.prototype = {
 | 
			
		||||
 * this menu also handles startup notification for it.  So when we
 | 
			
		||||
 * have an active startup notification, we switch modes to display that.
 | 
			
		||||
 */
 | 
			
		||||
function AppMenuButton() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const AppMenuButton = new Lang.Class({
 | 
			
		||||
    Name: 'AppMenuButton',
 | 
			
		||||
    Extends: PanelMenu.Button,
 | 
			
		||||
 | 
			
		||||
AppMenuButton.prototype = {
 | 
			
		||||
    __proto__: PanelMenu.Button.prototype,
 | 
			
		||||
    _init: function(menuManager) {
 | 
			
		||||
        this.parent(0.0, true);
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        PanelMenu.Button.prototype._init.call(this, 0.0);
 | 
			
		||||
        this._startingApps = [];
 | 
			
		||||
 | 
			
		||||
        this._menuManager = menuManager;
 | 
			
		||||
        this._targetApp = null;
 | 
			
		||||
        this._appMenuNotifyId = 0;
 | 
			
		||||
        this._actionGroupNotifyId = 0;
 | 
			
		||||
 | 
			
		||||
        let bin = new St.Bin({ name: 'appMenu' });
 | 
			
		||||
        this.actor.set_child(bin);
 | 
			
		||||
        this.actor.add_actor(bin);
 | 
			
		||||
 | 
			
		||||
        this.actor.reactive = false;
 | 
			
		||||
        this._targetIsCurrent = false;
 | 
			
		||||
@@ -270,10 +269,6 @@ AppMenuButton.prototype = {
 | 
			
		||||
 | 
			
		||||
        this._iconBottomClip = 0;
 | 
			
		||||
 | 
			
		||||
        this._quitMenu = new PopupMenu.PopupMenuItem('');
 | 
			
		||||
        this.menu.addMenuItem(this._quitMenu);
 | 
			
		||||
        this._quitMenu.connect('activate', Lang.bind(this, this._onQuit));
 | 
			
		||||
 | 
			
		||||
        this._visible = !Main.overview.visible;
 | 
			
		||||
        if (!this._visible)
 | 
			
		||||
            this.actor.hide();
 | 
			
		||||
@@ -452,12 +447,6 @@ AppMenuButton.prototype = {
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onQuit: function() {
 | 
			
		||||
        if (this._targetApp == null)
 | 
			
		||||
            return;
 | 
			
		||||
        this._targetApp.request_quit();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onAppStateChanged: function(appSys, app) {
 | 
			
		||||
        let state = app.state;
 | 
			
		||||
        if (state != Shell.AppState.STARTING) {
 | 
			
		||||
@@ -519,8 +508,10 @@ AppMenuButton.prototype = {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (targetApp == this._targetApp) {
 | 
			
		||||
            if (targetApp && targetApp.get_state() != Shell.AppState.STARTING)
 | 
			
		||||
            if (targetApp && targetApp.get_state() != Shell.AppState.STARTING) {
 | 
			
		||||
                this.stopAnimation();
 | 
			
		||||
                this._maybeSetMenu();
 | 
			
		||||
            }
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -530,43 +521,73 @@ AppMenuButton.prototype = {
 | 
			
		||||
        this._iconBox.hide();
 | 
			
		||||
        this._label.setText('');
 | 
			
		||||
 | 
			
		||||
        if (this._appMenuNotifyId)
 | 
			
		||||
            this._targetApp.disconnect(this._appMenuNotifyId);
 | 
			
		||||
        if (this._actionGroupNotifyId)
 | 
			
		||||
            this._targetApp.disconnect(this._actionGroupNotifyId);
 | 
			
		||||
        if (targetApp) {
 | 
			
		||||
            this._appMenuNotifyId = targetApp.connect('notify::menu', Lang.bind(this, this._sync));
 | 
			
		||||
            this._actionGroupNotifyId = targetApp.connect('notify::action-group', Lang.bind(this, this._sync));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._targetApp = targetApp;
 | 
			
		||||
        let icon = targetApp.get_faded_icon(2 * PANEL_ICON_SIZE);
 | 
			
		||||
 | 
			
		||||
        this._label.setText(targetApp.get_name());
 | 
			
		||||
        // TODO - _quit() doesn't really work on apps in state STARTING yet
 | 
			
		||||
        this._quitMenu.label.set_text(_("Quit %s").format(targetApp.get_name()));
 | 
			
		||||
 | 
			
		||||
        this._iconBox.set_child(icon);
 | 
			
		||||
        this._iconBox.show();
 | 
			
		||||
 | 
			
		||||
        if (targetApp.get_state() == Shell.AppState.STARTING)
 | 
			
		||||
            this.startAnimation();
 | 
			
		||||
        else
 | 
			
		||||
            this._maybeSetMenu();
 | 
			
		||||
 | 
			
		||||
        this.emit('changed');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _maybeSetMenu: function() {
 | 
			
		||||
        let menu;
 | 
			
		||||
 | 
			
		||||
        if (this._targetApp.action_group) {
 | 
			
		||||
            if (this.menu instanceof PopupMenu.RemoteMenu &&
 | 
			
		||||
                this.menu.actionGroup == this._targetApp.action_group)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            menu = new PopupMenu.RemoteMenu(this.actor, this._targetApp.menu, this._targetApp.action_group);
 | 
			
		||||
        } else {
 | 
			
		||||
            if (this.menu && !(this.menu instanceof PopupMenu.RemoteMenu))
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            // fallback to older menu
 | 
			
		||||
            menu = new PopupMenu.PopupMenu(this.actor, 0.0, St.Side.TOP, 0);
 | 
			
		||||
            menu.addAction(_("Quit"), Lang.bind(this, function() {
 | 
			
		||||
                this._targetApp.request_quit();
 | 
			
		||||
            }));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.setMenu(menu);
 | 
			
		||||
        this._menuManager.addMenu(menu);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Signals.addSignalMethods(AppMenuButton.prototype);
 | 
			
		||||
 | 
			
		||||
// Activities button. Because everything else in the top bar is a
 | 
			
		||||
// PanelMenu.Button, it simplifies some things to make this be one too.
 | 
			
		||||
// We just hack it up to not actually have a menu attached to it.
 | 
			
		||||
function ActivitiesButton() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ActivitiesButton.prototype = {
 | 
			
		||||
    __proto__: PanelMenu.Button.prototype,
 | 
			
		||||
const ActivitiesButton = new Lang.Class({
 | 
			
		||||
    Name: 'ActivitiesButton',
 | 
			
		||||
    Extends: PanelMenu.Button,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        PanelMenu.Button.prototype._init.call(this, 0.0);
 | 
			
		||||
        this.parent(0.0);
 | 
			
		||||
 | 
			
		||||
        let container = new Shell.GenericContainer();
 | 
			
		||||
        container.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
 | 
			
		||||
        container.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
 | 
			
		||||
        container.connect('allocate', Lang.bind(this, this._allocate));
 | 
			
		||||
        this.actor.child = container;
 | 
			
		||||
        container.connect('get-preferred-width', Lang.bind(this, this._containerGetPreferredWidth));
 | 
			
		||||
        container.connect('get-preferred-height', Lang.bind(this, this._containerGetPreferredHeight));
 | 
			
		||||
        container.connect('allocate', Lang.bind(this, this._containerAllocate));
 | 
			
		||||
        this.actor.add_actor(container);
 | 
			
		||||
        this.actor.name = 'panelActivities';
 | 
			
		||||
 | 
			
		||||
        /* Translators: If there is no suitable word for "Activities"
 | 
			
		||||
@@ -598,15 +619,15 @@ ActivitiesButton.prototype = {
 | 
			
		||||
        this._xdndTimeOut = 0;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getPreferredWidth: function(actor, forHeight, alloc) {
 | 
			
		||||
    _containerGetPreferredWidth: function(actor, forHeight, alloc) {
 | 
			
		||||
        [alloc.min_size, alloc.natural_size] = this._label.get_preferred_width(forHeight);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getPreferredHeight: function(actor, forWidth, alloc) {
 | 
			
		||||
    _containerGetPreferredHeight: function(actor, forWidth, alloc) {
 | 
			
		||||
        [alloc.min_size, alloc.natural_size] = this._label.get_preferred_height(forWidth);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _allocate: function(actor, box, flags) {
 | 
			
		||||
    _containerAllocate: function(actor, box, flags) {
 | 
			
		||||
        this._label.allocate(box, flags);
 | 
			
		||||
 | 
			
		||||
        // The hot corner needs to be outside any padding/alignment
 | 
			
		||||
@@ -697,13 +718,11 @@ ActivitiesButton.prototype = {
 | 
			
		||||
        Mainloop.source_remove(this._xdndTimeOut);
 | 
			
		||||
        this._xdndTimeOut = 0;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function PanelCorner(panel, side) {
 | 
			
		||||
    this._init(panel, side);
 | 
			
		||||
}
 | 
			
		||||
const PanelCorner = new Lang.Class({
 | 
			
		||||
    Name: 'PanelCorner',
 | 
			
		||||
 | 
			
		||||
PanelCorner.prototype = {
 | 
			
		||||
    _init: function(box, side) {
 | 
			
		||||
        this._side = side;
 | 
			
		||||
 | 
			
		||||
@@ -782,8 +801,10 @@ PanelCorner.prototype = {
 | 
			
		||||
            button = this._findRightmostButton(this._box);
 | 
			
		||||
 | 
			
		||||
        if (button) {
 | 
			
		||||
            if (this._button && this._buttonStyleChangedSignalId)
 | 
			
		||||
            if (this._button && this._buttonStyleChangedSignalId) {
 | 
			
		||||
                this._button.disconnect(this._buttonStyleChangedSignalId);
 | 
			
		||||
                this._button.style = null;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this._button = button;
 | 
			
		||||
 | 
			
		||||
@@ -801,6 +822,10 @@ PanelCorner.prototype = {
 | 
			
		||||
                    let pseudoClass = button.get_style_pseudo_class();
 | 
			
		||||
                    this.actor.set_style_pseudo_class(pseudoClass);
 | 
			
		||||
                }));
 | 
			
		||||
 | 
			
		||||
            // The corner doesn't support theme transitions, so override
 | 
			
		||||
            // the .panel-button default
 | 
			
		||||
            button.style = 'transition-duration: 0';
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -873,14 +898,12 @@ PanelCorner.prototype = {
 | 
			
		||||
        this.actor.set_size(cornerRadius, innerBorderWidth + cornerRadius);
 | 
			
		||||
        this.actor.set_anchor_point(0, innerBorderWidth);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function Panel() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const Panel = new Lang.Class({
 | 
			
		||||
    Name: 'Panel',
 | 
			
		||||
 | 
			
		||||
Panel.prototype = {
 | 
			
		||||
    _init : function() {
 | 
			
		||||
        this.actor = new Shell.GenericContainer({ name: 'panel',
 | 
			
		||||
                                                  reactive: true });
 | 
			
		||||
@@ -895,14 +918,6 @@ Panel.prototype = {
 | 
			
		||||
            this.actor.remove_style_class_name('in-overview');
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        if (global.session_type == Shell.SessionType.GDM) {
 | 
			
		||||
            this._tray_icon_order = GDM_TRAY_ICON_ORDER;
 | 
			
		||||
            this._tray_icon_shell_implementation = GDM_TRAY_ICON_SHELL_IMPLEMENTATION;
 | 
			
		||||
        } else {
 | 
			
		||||
            this._tray_icon_order = STANDARD_TRAY_ICON_ORDER;
 | 
			
		||||
            this._tray_icon_shell_implementation = STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._menus = new PopupMenu.PopupMenuManager(this);
 | 
			
		||||
 | 
			
		||||
        this._leftBox = new St.BoxLayout({ name: 'panelLeft' });
 | 
			
		||||
@@ -939,9 +954,8 @@ Panel.prototype = {
 | 
			
		||||
            // more cleanly with the rest of the panel
 | 
			
		||||
            this._menus.addMenu(this._activitiesButton.menu);
 | 
			
		||||
 | 
			
		||||
            this._appMenu = new AppMenuButton();
 | 
			
		||||
            this._appMenu = new AppMenuButton(this._menus);
 | 
			
		||||
            this._leftBox.add(this._appMenu.actor);
 | 
			
		||||
            this._menus.addMenu(this._appMenu.menu);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* center */
 | 
			
		||||
@@ -953,21 +967,12 @@ Panel.prototype = {
 | 
			
		||||
        this._menus.addMenu(this._dateMenu.menu);
 | 
			
		||||
 | 
			
		||||
        /* right */
 | 
			
		||||
 | 
			
		||||
        // System status applets live in statusBox, while legacy tray icons
 | 
			
		||||
        // live in trayBox
 | 
			
		||||
        // The trayBox is hidden when there are no tray icons.
 | 
			
		||||
        this._trayBox = new St.BoxLayout({ name: 'legacyTray' });
 | 
			
		||||
        this._statusBox = new St.BoxLayout({ name: 'statusTray' });
 | 
			
		||||
 | 
			
		||||
        this._trayBox.hide();
 | 
			
		||||
        this._rightBox.add(this._trayBox);
 | 
			
		||||
        this._rightBox.add(this._statusBox);
 | 
			
		||||
 | 
			
		||||
        if (global.session_type == Shell.SessionType.USER) {
 | 
			
		||||
            this._userMenu = new UserMenu.UserMenuButton();
 | 
			
		||||
            this._userMenu.actor.name = 'panelStatus';
 | 
			
		||||
            this._rightBox.add(this._userMenu.actor);
 | 
			
		||||
        if (global.session_type == Shell.SessionType.GDM) {
 | 
			
		||||
            this._status_area_order = GDM_STATUS_AREA_ORDER;
 | 
			
		||||
            this._status_area_shell_implementation = GDM_STATUS_AREA_SHELL_IMPLEMENTATION;
 | 
			
		||||
        } else {
 | 
			
		||||
            this._status_area_order = STANDARD_STATUS_AREA_ORDER;
 | 
			
		||||
            this._status_area_shell_implementation = STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Main.statusIconDispatcher.connect('status-icon-added', Lang.bind(this, this._onTrayIconAdded));
 | 
			
		||||
@@ -1053,9 +1058,9 @@ Panel.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    startStatusArea: function() {
 | 
			
		||||
        for (let i = 0; i < this._tray_icon_order.length; i++) {
 | 
			
		||||
            let role = this._tray_icon_order[i];
 | 
			
		||||
            let constructor = this._tray_icon_shell_implementation[role];
 | 
			
		||||
        for (let i = 0; i < this._status_area_order.length; i++) {
 | 
			
		||||
            let role = this._status_area_order[i];
 | 
			
		||||
            let constructor = this._status_area_shell_implementation[role];
 | 
			
		||||
            if (!constructor) {
 | 
			
		||||
                // This icon is not implemented (this is a bug)
 | 
			
		||||
                continue;
 | 
			
		||||
@@ -1064,11 +1069,23 @@ Panel.prototype = {
 | 
			
		||||
            let indicator = new constructor();
 | 
			
		||||
            this.addToStatusArea(role, indicator, i);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
        // PopupMenuManager depends on menus being added in order for
 | 
			
		||||
        // keyboard navigation
 | 
			
		||||
        if (this._userMenu)
 | 
			
		||||
            this._menus.addMenu(this._userMenu.menu);
 | 
			
		||||
    _insertStatusItem: function(actor, position) {
 | 
			
		||||
        let children = this._rightBox.get_children();
 | 
			
		||||
        let i;
 | 
			
		||||
        for (i = children.length - 1; i >= 0; i--) {
 | 
			
		||||
            let rolePosition = children[i]._rolePosition;
 | 
			
		||||
            if (position > rolePosition) {
 | 
			
		||||
                this._rightBox.insert_actor(actor, i + 1);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (i == -1) {
 | 
			
		||||
            // If we didn't find a position, we must be first
 | 
			
		||||
            this._rightBox.insert_actor(actor, 0);
 | 
			
		||||
        }
 | 
			
		||||
        actor._rolePosition = position;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addToStatusArea: function(role, indicator, position) {
 | 
			
		||||
@@ -1080,8 +1097,7 @@ Panel.prototype = {
 | 
			
		||||
 | 
			
		||||
        if (!position)
 | 
			
		||||
            position = 0;
 | 
			
		||||
 | 
			
		||||
        this._statusBox.insert_actor(indicator.actor, position);
 | 
			
		||||
        this._insertStatusItem(indicator.actor, position);
 | 
			
		||||
        this._menus.addMenu(indicator.menu);
 | 
			
		||||
 | 
			
		||||
        this._statusArea[role] = indicator;
 | 
			
		||||
@@ -1094,39 +1110,23 @@ Panel.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onTrayIconAdded: function(o, icon, role) {
 | 
			
		||||
        icon.height = PANEL_ICON_SIZE;
 | 
			
		||||
 | 
			
		||||
        if (this._tray_icon_shell_implementation[role]) {
 | 
			
		||||
        if (this._status_area_shell_implementation[role]) {
 | 
			
		||||
            // This icon is legacy, and replaced by a Shell version
 | 
			
		||||
            // Hide it
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        // Figure out the index in our well-known order for this icon
 | 
			
		||||
        let position = this._tray_icon_order.indexOf(role);
 | 
			
		||||
        icon._rolePosition = position;
 | 
			
		||||
        let children = this._trayBox.get_children();
 | 
			
		||||
        let i;
 | 
			
		||||
        // Walk children backwards, until we find one that isn't
 | 
			
		||||
        // well-known, or one where we should follow
 | 
			
		||||
        for (i = children.length - 1; i >= 0; i--) {
 | 
			
		||||
            let rolePosition = children[i]._rolePosition;
 | 
			
		||||
            if (!rolePosition || position > rolePosition) {
 | 
			
		||||
                this._trayBox.insert_actor(icon, i + 1);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (i == -1) {
 | 
			
		||||
            // If we didn't find a position, we must be first
 | 
			
		||||
            this._trayBox.insert_actor(icon, 0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Make sure the trayBox is shown.
 | 
			
		||||
        this._trayBox.show();
 | 
			
		||||
        icon.height = PANEL_ICON_SIZE;
 | 
			
		||||
        let buttonBox = new PanelMenu.ButtonBox();
 | 
			
		||||
        let box = buttonBox.actor;
 | 
			
		||||
        box.add_actor(icon);
 | 
			
		||||
 | 
			
		||||
        this._insertStatusItem(box, this._status_area_order.indexOf(role));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onTrayIconRemoved: function(o, icon) {
 | 
			
		||||
        if (icon.get_parent() != null)
 | 
			
		||||
            this._trayBox.remove_actor(icon);
 | 
			
		||||
        let box = icon.get_parent();
 | 
			
		||||
        if (box && box._delegate instanceof PanelMenu.ButtonBox)
 | 
			
		||||
            box.destroy();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,38 +1,134 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
 | 
			
		||||
function Button(menuAlignment) {
 | 
			
		||||
    this._init(menuAlignment);
 | 
			
		||||
}
 | 
			
		||||
const ButtonBox = new Lang.Class({
 | 
			
		||||
    Name: 'ButtonBox',
 | 
			
		||||
 | 
			
		||||
Button.prototype = {
 | 
			
		||||
    _init: function(menuAlignment) {
 | 
			
		||||
        this.actor = new St.Bin({ style_class: 'panel-button',
 | 
			
		||||
                                  reactive: true,
 | 
			
		||||
                                  can_focus: true,
 | 
			
		||||
                                  x_fill: true,
 | 
			
		||||
                                  y_fill: false,
 | 
			
		||||
                                  track_hover: true });
 | 
			
		||||
    _init: function(params) {
 | 
			
		||||
        params = Params.parse(params, { style_class: 'panel-button' }, true);
 | 
			
		||||
        this.actor = new Shell.GenericContainer(params);
 | 
			
		||||
        this.actor._delegate = this;
 | 
			
		||||
 | 
			
		||||
        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, this._onStyleChanged));
 | 
			
		||||
        this._minHPadding = this._natHPadding = 0.0;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onStyleChanged: function(actor) {
 | 
			
		||||
        let themeNode = actor.get_theme_node();
 | 
			
		||||
 | 
			
		||||
        this._minHPadding = themeNode.get_length('-minimum-hpadding');
 | 
			
		||||
        this._natHPadding = themeNode.get_length('-natural-hpadding');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getPreferredWidth: function(actor, forHeight, alloc) {
 | 
			
		||||
        let children = actor.get_children();
 | 
			
		||||
        let child = children.length > 0 ? children[0] : null;
 | 
			
		||||
 | 
			
		||||
        if (child) {
 | 
			
		||||
            [alloc.min_size, alloc.natural_size] = child.get_preferred_width(-1);
 | 
			
		||||
        } else {
 | 
			
		||||
            alloc.min_size = alloc.natural_size = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        alloc.min_size += 2 * this._minHPadding;
 | 
			
		||||
        alloc.natural_size += 2 * this._natHPadding;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getPreferredHeight: function(actor, forWidth, alloc) {
 | 
			
		||||
        let children = actor.get_children();
 | 
			
		||||
        let child = children.length > 0 ? children[0] : null;
 | 
			
		||||
 | 
			
		||||
        if (child) {
 | 
			
		||||
            [alloc.min_size, alloc.natural_size] = child.get_preferred_height(-1);
 | 
			
		||||
        } else {
 | 
			
		||||
            alloc.min_size = alloc.natural_size = 0;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _allocate: function(actor, box, flags) {
 | 
			
		||||
        let children = actor.get_children();
 | 
			
		||||
        if (children.length == 0)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let child = children[0];
 | 
			
		||||
        let [minWidth, natWidth] = child.get_preferred_width(-1);
 | 
			
		||||
        let [minHeight, natHeight] = child.get_preferred_height(-1);
 | 
			
		||||
 | 
			
		||||
        let availWidth = box.x2 - box.x1;
 | 
			
		||||
        let availHeight = box.y2 - box.y1;
 | 
			
		||||
 | 
			
		||||
        let childBox = new Clutter.ActorBox();
 | 
			
		||||
        if (natWidth + 2 * this._natHPadding <= availWidth) {
 | 
			
		||||
            childBox.x1 = this._natHPadding;
 | 
			
		||||
            childBox.x2 = availWidth - this._natHPadding;
 | 
			
		||||
        } else {
 | 
			
		||||
            childBox.x1 = this._minHPadding;
 | 
			
		||||
            childBox.x2 = availWidth - this._minHPadding;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (natHeight <= availHeight) {
 | 
			
		||||
            childBox.y1 = Math.floor((availHeight - natHeight) / 2);
 | 
			
		||||
            childBox.y2 = childBox.y1 + natHeight;
 | 
			
		||||
        } else {
 | 
			
		||||
            childBox.y1 = 0;
 | 
			
		||||
            childBox.y2 = availHeight;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        child.allocate(childBox, flags);
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const Button = new Lang.Class({
 | 
			
		||||
    Name: 'PanelMenuButton',
 | 
			
		||||
    Extends: ButtonBox,
 | 
			
		||||
 | 
			
		||||
    _init: function(menuAlignment, dontCreateMenu) {
 | 
			
		||||
        this.parent({ reactive: true,
 | 
			
		||||
                      can_focus: true,
 | 
			
		||||
                      track_hover: true });
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
 | 
			
		||||
        this.actor.connect('key-press-event', Lang.bind(this, this._onSourceKeyPress));
 | 
			
		||||
        this.menu = new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP);
 | 
			
		||||
        this.menu.actor.add_style_class_name('panel-menu');
 | 
			
		||||
        this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
 | 
			
		||||
        this.menu.actor.connect('key-press-event', Lang.bind(this, this._onMenuKeyPress));
 | 
			
		||||
        Main.uiGroup.add_actor(this.menu.actor);
 | 
			
		||||
        this.menu.actor.hide();
 | 
			
		||||
 | 
			
		||||
        if (dontCreateMenu)
 | 
			
		||||
            this.menu = null;
 | 
			
		||||
        else
 | 
			
		||||
            this.setMenu(new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP, 0));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setMenu: function(menu) {
 | 
			
		||||
        if (this.menu)
 | 
			
		||||
            this.menu.destroy();
 | 
			
		||||
 | 
			
		||||
        this.menu = menu;
 | 
			
		||||
        if (this.menu) {
 | 
			
		||||
            this.menu.actor.add_style_class_name('panel-menu');
 | 
			
		||||
            this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
 | 
			
		||||
            this.menu.actor.connect('key-press-event', Lang.bind(this, this._onMenuKeyPress));
 | 
			
		||||
 | 
			
		||||
            Main.uiGroup.add_actor(this.menu.actor);
 | 
			
		||||
            this.menu.actor.hide();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onButtonPress: function(actor, event) {
 | 
			
		||||
        if (!this.menu)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (!this.menu.isOpen) {
 | 
			
		||||
            // Setting the max-height won't do any good if the minimum height of the
 | 
			
		||||
            // menu is higher then the screen; it's useful if part of the menu is
 | 
			
		||||
@@ -46,6 +142,9 @@ Button.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onSourceKeyPress: function(actor, event) {
 | 
			
		||||
        if (!this.menu)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        let symbol = event.get_key_symbol();
 | 
			
		||||
        if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) {
 | 
			
		||||
            this.menu.toggle();
 | 
			
		||||
@@ -91,7 +190,7 @@ Button.prototype = {
 | 
			
		||||
 | 
			
		||||
        this.emit('destroy');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(Button.prototype);
 | 
			
		||||
 | 
			
		||||
/* SystemStatusButton:
 | 
			
		||||
@@ -100,19 +199,18 @@ Signals.addSignalMethods(Button.prototype);
 | 
			
		||||
 * volume, bluetooth...), which is just a PanelMenuButton with an
 | 
			
		||||
 * icon and a tooltip
 | 
			
		||||
 */
 | 
			
		||||
function SystemStatusButton() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SystemStatusButton.prototype = {
 | 
			
		||||
    __proto__: Button.prototype,
 | 
			
		||||
const SystemStatusButton = new Lang.Class({
 | 
			
		||||
    Name: 'SystemStatusButton',
 | 
			
		||||
    Extends: Button,
 | 
			
		||||
 | 
			
		||||
    _init: function(iconName,tooltipText) {
 | 
			
		||||
        Button.prototype._init.call(this, 0.0);
 | 
			
		||||
        this.parent(0.0);
 | 
			
		||||
 | 
			
		||||
        this._iconActor = new St.Icon({ icon_name: iconName,
 | 
			
		||||
                                        icon_type: St.IconType.SYMBOLIC,
 | 
			
		||||
                                        style_class: 'system-status-icon' });
 | 
			
		||||
        this.actor.set_child(this._iconActor);
 | 
			
		||||
        this.actor.add_actor(this._iconActor);
 | 
			
		||||
        this.actor.add_style_class_name('panel-status-button');
 | 
			
		||||
        this.setTooltip(tooltipText);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -134,4 +232,4 @@ SystemStatusButton.prototype = {
 | 
			
		||||
            this.tooltip = null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
@@ -22,11 +22,9 @@ const Util = imports.misc.util;
 | 
			
		||||
 * @iconFactory: A JavaScript callback which will create an icon texture given a size parameter
 | 
			
		||||
 * @launch: A JavaScript callback to launch the entry
 | 
			
		||||
 */
 | 
			
		||||
function PlaceInfo(id, name, iconFactory, launch) {
 | 
			
		||||
    this._init(id, name, iconFactory, launch);
 | 
			
		||||
}
 | 
			
		||||
const PlaceInfo = new Lang.Class({
 | 
			
		||||
    Name: 'PlaceInfo',
 | 
			
		||||
 | 
			
		||||
PlaceInfo.prototype = {
 | 
			
		||||
    _init: function(id, name, iconFactory, launch) {
 | 
			
		||||
        this.id = id;
 | 
			
		||||
        this.name = name;
 | 
			
		||||
@@ -55,7 +53,7 @@ PlaceInfo.prototype = {
 | 
			
		||||
    isRemovable: function() {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// Helper function to translate launch parameters into a GAppLaunchContext
 | 
			
		||||
function _makeLaunchContext(params)
 | 
			
		||||
@@ -72,12 +70,9 @@ function _makeLaunchContext(params)
 | 
			
		||||
    return launchContext;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function PlaceDeviceInfo(mount) {
 | 
			
		||||
    this._init(mount);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PlaceDeviceInfo.prototype = {
 | 
			
		||||
    __proto__: PlaceInfo.prototype,
 | 
			
		||||
const PlaceDeviceInfo = new Lang.Class({
 | 
			
		||||
    Name: 'PlaceDeviceInfo',
 | 
			
		||||
    Extends: PlaceInfo,
 | 
			
		||||
 | 
			
		||||
    _init: function(mount) {
 | 
			
		||||
        this._mount = mount;
 | 
			
		||||
@@ -123,13 +118,11 @@ PlaceDeviceInfo.prototype = {
 | 
			
		||||
                                     _("Retry"));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function PlacesManager() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const PlacesManager = new Lang.Class({
 | 
			
		||||
    Name: 'PlacesManager',
 | 
			
		||||
 | 
			
		||||
PlacesManager.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._defaultPlaces = [];
 | 
			
		||||
        this._mounts = [];
 | 
			
		||||
@@ -195,9 +188,9 @@ PlacesManager.prototype = {
 | 
			
		||||
 | 
			
		||||
        this._bookmarksPath = GLib.build_filenamev([GLib.get_home_dir(), '.gtk-bookmarks']);
 | 
			
		||||
        this._bookmarksFile = Gio.file_new_for_path(this._bookmarksPath);
 | 
			
		||||
        let monitor = this._bookmarksFile.monitor_file(Gio.FileMonitorFlags.NONE, null);
 | 
			
		||||
        this._monitor = this._bookmarksFile.monitor_file(Gio.FileMonitorFlags.NONE, null);
 | 
			
		||||
        this._bookmarkTimeoutId = 0;
 | 
			
		||||
        monitor.connect('changed', Lang.bind(this, function () {
 | 
			
		||||
        this._monitor.connect('changed', Lang.bind(this, function () {
 | 
			
		||||
            if (this._bookmarkTimeoutId > 0)
 | 
			
		||||
                return;
 | 
			
		||||
            /* Defensive event compression */
 | 
			
		||||
@@ -360,19 +353,15 @@ PlacesManager.prototype = {
 | 
			
		||||
    _removeById: function(sourceArray, id) {
 | 
			
		||||
        sourceArray.splice(this._lookupIndexById(sourceArray, id), 1);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(PlacesManager.prototype);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function PlaceSearchProvider() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PlaceSearchProvider.prototype = {
 | 
			
		||||
    __proto__: Search.SearchProvider.prototype,
 | 
			
		||||
const PlaceSearchProvider = new Lang.Class({
 | 
			
		||||
    Name: 'PlaceSearchProvider',
 | 
			
		||||
    Extends: Search.SearchProvider,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        Search.SearchProvider.prototype._init.call(this, _("PLACES & DEVICES"));
 | 
			
		||||
        this.parent(_("PLACES & DEVICES"));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getResultMeta: function(resultId) {
 | 
			
		||||
@@ -434,4 +423,4 @@ PlaceSearchProvider.prototype = {
 | 
			
		||||
        let places = previousResults.map(function (id) { return Main.placesManager.lookupPlaceById(id); });
 | 
			
		||||
        return this._searchPlaces(places, terms);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 *
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2010 Red Hat, Inc
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
@@ -27,22 +27,21 @@ const AccountsService = imports.gi.AccountsService;
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Pango = imports.gi.Pango;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Polkit = imports.gi.Polkit;
 | 
			
		||||
const PolkitAgent = imports.gi.PolkitAgent;
 | 
			
		||||
 | 
			
		||||
const ModalDialog = imports.ui.modalDialog;
 | 
			
		||||
const ShellEntry = imports.ui.shellEntry;
 | 
			
		||||
 | 
			
		||||
function AuthenticationDialog(actionId, message, cookie, userNames) {
 | 
			
		||||
    this._init(actionId, message, cookie, userNames);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AuthenticationDialog.prototype = {
 | 
			
		||||
    __proto__: ModalDialog.ModalDialog.prototype,
 | 
			
		||||
const AuthenticationDialog = new Lang.Class({
 | 
			
		||||
    Name: 'AuthenticationDialog',
 | 
			
		||||
    Extends: ModalDialog.ModalDialog,
 | 
			
		||||
 | 
			
		||||
    _init: function(actionId, message, cookie, userNames) {
 | 
			
		||||
        ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'polkit-dialog' });
 | 
			
		||||
        this.parent({ styleClass: 'polkit-dialog' });
 | 
			
		||||
 | 
			
		||||
        this.actionId = actionId;
 | 
			
		||||
        this.message = message;
 | 
			
		||||
@@ -87,10 +86,14 @@ AuthenticationDialog.prototype = {
 | 
			
		||||
        if (userNames.length > 1) {
 | 
			
		||||
            log('polkitAuthenticationAgent: Received ' + userNames.length +
 | 
			
		||||
                ' identities that can be used for authentication. Only ' +
 | 
			
		||||
                'considering the first one.');
 | 
			
		||||
                'considering one.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let userName = userNames[0];
 | 
			
		||||
        let userName = GLib.get_user_name();
 | 
			
		||||
        if (userNames.indexOf(userName) < 0)
 | 
			
		||||
            userName = 'root';
 | 
			
		||||
        if (userNames.indexOf(userName) < 0)
 | 
			
		||||
            userName = userNames[0];
 | 
			
		||||
 | 
			
		||||
        this._user = AccountsService.UserManager.get_default().get_user(userName);
 | 
			
		||||
        let userRealName = this._user.get_real_name()
 | 
			
		||||
@@ -139,9 +142,11 @@ AuthenticationDialog.prototype = {
 | 
			
		||||
        this._passwordEntry = new St.Entry({ style_class: 'polkit-dialog-password-entry',
 | 
			
		||||
                                             text: "",
 | 
			
		||||
                                             can_focus: true});
 | 
			
		||||
        ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
 | 
			
		||||
        this._passwordEntry.clutter_text.connect('activate', Lang.bind(this, this._onEntryActivate));
 | 
			
		||||
        this._passwordBox.add(this._passwordEntry,
 | 
			
		||||
                              {expand: true });
 | 
			
		||||
        this.setInitialKeyFocus(this._passwordEntry);
 | 
			
		||||
        this._passwordBox.hide();
 | 
			
		||||
 | 
			
		||||
        this._errorMessageLabel = new St.Label({ style_class: 'polkit-dialog-error-label' });
 | 
			
		||||
@@ -186,13 +191,6 @@ AuthenticationDialog.prototype = {
 | 
			
		||||
        this._session.connect('request', Lang.bind(this, this._onSessionRequest));
 | 
			
		||||
        this._session.connect('show-error', Lang.bind(this, this._onSessionShowError));
 | 
			
		||||
        this._session.connect('show-info', Lang.bind(this, this._onSessionShowInfo));
 | 
			
		||||
 | 
			
		||||
        // Delay focus grab to avoid ModalDialog stealing focus with
 | 
			
		||||
        // its buttons
 | 
			
		||||
        this.connect('opened',
 | 
			
		||||
                     Lang.bind(this, function() {
 | 
			
		||||
                         this._passwordEntry.grab_key_focus();
 | 
			
		||||
                     }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    startAuthentication: function() {
 | 
			
		||||
@@ -334,15 +332,12 @@ AuthenticationDialog.prototype = {
 | 
			
		||||
        this.close(global.get_current_time());
 | 
			
		||||
        this._emitDone(false, true);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(AuthenticationDialog.prototype);
 | 
			
		||||
 | 
			
		||||
function AuthenticationAgent() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const AuthenticationAgent = new Lang.Class({
 | 
			
		||||
    Name: 'AuthenticationAgent',
 | 
			
		||||
 | 
			
		||||
AuthenticationAgent.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._native = new Shell.PolkitAuthenticationAgent();
 | 
			
		||||
        this._native.connect('initiate', Lang.bind(this, this._onInitiate));
 | 
			
		||||
@@ -403,7 +398,7 @@ AuthenticationAgent.prototype = {
 | 
			
		||||
            this._reallyCompleteRequest(wasDismissed);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function init() {
 | 
			
		||||
    let agent = new AuthenticationAgent();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,10 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Cairo = imports.cairo;
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
@@ -26,15 +28,14 @@ function _ensureStyle(actor) {
 | 
			
		||||
        actor.ensure_style();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function PopupBaseMenuItem(params) {
 | 
			
		||||
    this._init(params);
 | 
			
		||||
}
 | 
			
		||||
const PopupBaseMenuItem = new Lang.Class({
 | 
			
		||||
    Name: 'PopupBaseMenuItem',
 | 
			
		||||
 | 
			
		||||
PopupBaseMenuItem.prototype = {
 | 
			
		||||
    _init: function (params) {
 | 
			
		||||
        params = Params.parse (params, { reactive: true,
 | 
			
		||||
                                         activate: true,
 | 
			
		||||
                                         hover: true,
 | 
			
		||||
                                         sensitive: true,
 | 
			
		||||
                                         style_class: null
 | 
			
		||||
                                       });
 | 
			
		||||
        this.actor = new Shell.GenericContainer({ style_class: 'popup-menu-item',
 | 
			
		||||
@@ -52,11 +53,15 @@ PopupBaseMenuItem.prototype = {
 | 
			
		||||
        this._columnWidths = null;
 | 
			
		||||
        this._spacing = 0;
 | 
			
		||||
        this.active = false;
 | 
			
		||||
        this._activatable = params.reactive && params.activate;
 | 
			
		||||
        this.sensitive = this._activatable && params.sensitive;
 | 
			
		||||
 | 
			
		||||
        this.setSensitive(this.sensitive);
 | 
			
		||||
 | 
			
		||||
        if (params.style_class)
 | 
			
		||||
            this.actor.add_style_class_name(params.style_class);
 | 
			
		||||
 | 
			
		||||
        if (params.reactive && params.activate) {
 | 
			
		||||
        if (this._activatable) {
 | 
			
		||||
            this.actor.connect('button-release-event', Lang.bind(this, this._onButtonReleaseEvent));
 | 
			
		||||
            this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
 | 
			
		||||
        }
 | 
			
		||||
@@ -103,20 +108,39 @@ PopupBaseMenuItem.prototype = {
 | 
			
		||||
        this.emit('activate', event);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setActive: function (active) {
 | 
			
		||||
    setActive: function (active, params) {
 | 
			
		||||
        let activeChanged = active != this.active;
 | 
			
		||||
        params = Params.parse (params, { grabKeyboard: true });
 | 
			
		||||
 | 
			
		||||
        if (activeChanged) {
 | 
			
		||||
            this.active = active;
 | 
			
		||||
            if (active) {
 | 
			
		||||
                this.actor.add_style_pseudo_class('active');
 | 
			
		||||
                this.actor.grab_key_focus();
 | 
			
		||||
                if (params.grabKeyboard)
 | 
			
		||||
                    this.actor.grab_key_focus();
 | 
			
		||||
            } else
 | 
			
		||||
                this.actor.remove_style_pseudo_class('active');
 | 
			
		||||
            this.emit('active-changed', active);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setSensitive: function(sensitive) {
 | 
			
		||||
        if (!this._activatable)
 | 
			
		||||
            return;
 | 
			
		||||
        if (this.sensitive == sensitive)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this.sensitive = sensitive;
 | 
			
		||||
        this.actor.reactive = sensitive;
 | 
			
		||||
        this.actor.can_focus = sensitive;
 | 
			
		||||
 | 
			
		||||
        if (sensitive)
 | 
			
		||||
            this.actor.remove_style_pseudo_class('insensitive');
 | 
			
		||||
        else
 | 
			
		||||
            this.actor.add_style_pseudo_class('insensitive');
 | 
			
		||||
        this.emit('sensitive-changed', sensitive);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    destroy: function() {
 | 
			
		||||
        this.actor.destroy();
 | 
			
		||||
        this.emit('destroy');
 | 
			
		||||
@@ -222,10 +246,25 @@ PopupBaseMenuItem.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getPreferredHeight: function(actor, forWidth, alloc) {
 | 
			
		||||
        let height = 0;
 | 
			
		||||
        let height = 0, x = 0, minWidth, childWidth;
 | 
			
		||||
        for (let i = 0; i < this._children.length; i++) {
 | 
			
		||||
            let child = this._children[i];
 | 
			
		||||
            let [min, natural] = child.actor.get_preferred_height(forWidth);
 | 
			
		||||
            if (this._columnWidths) {
 | 
			
		||||
                if (child.span == -1) {
 | 
			
		||||
                    childWidth = 0;
 | 
			
		||||
                    for (let j = i; j < this._columnWidths.length; j++)
 | 
			
		||||
                        childWidth += this._columnWidths[j]
 | 
			
		||||
                } else
 | 
			
		||||
                    childWidth = this._columnWidths[i];
 | 
			
		||||
            } else {
 | 
			
		||||
                if (child.span == -1)
 | 
			
		||||
                    childWidth = forWidth - x;
 | 
			
		||||
                else
 | 
			
		||||
                    [minWidth, childWidth] = child.actor.get_preferred_width(-1);
 | 
			
		||||
            }
 | 
			
		||||
            x += childWidth;
 | 
			
		||||
 | 
			
		||||
            let [min, natural] = child.actor.get_preferred_height(childWidth);
 | 
			
		||||
            if (natural > height)
 | 
			
		||||
                height = natural;
 | 
			
		||||
        }
 | 
			
		||||
@@ -283,7 +322,14 @@ PopupBaseMenuItem.prototype = {
 | 
			
		||||
                }
 | 
			
		||||
                extraWidth = availWidth - naturalWidth;
 | 
			
		||||
            } else {
 | 
			
		||||
                availWidth = naturalWidth;
 | 
			
		||||
                if (child.span == -1) {
 | 
			
		||||
                    if (direction == St.TextDirection.LTR)
 | 
			
		||||
                        availWidth = box.x2 - x;
 | 
			
		||||
                    else
 | 
			
		||||
                        availWidth = x - box.x1;
 | 
			
		||||
                } else {
 | 
			
		||||
                    availWidth = naturalWidth;
 | 
			
		||||
                }
 | 
			
		||||
                extraWidth = 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -291,7 +337,7 @@ PopupBaseMenuItem.prototype = {
 | 
			
		||||
                if (child.expand) {
 | 
			
		||||
                    childBox.x1 = x;
 | 
			
		||||
                    childBox.x2 = x + availWidth;
 | 
			
		||||
                } else if (child.align === St.Align.CENTER) {
 | 
			
		||||
                } else if (child.align === St.Align.MIDDLE) {
 | 
			
		||||
                    childBox.x1 = x + Math.round(extraWidth / 2);
 | 
			
		||||
                    childBox.x2 = childBox.x1 + naturalWidth;
 | 
			
		||||
                } else if (child.align === St.Align.END) {
 | 
			
		||||
@@ -305,7 +351,7 @@ PopupBaseMenuItem.prototype = {
 | 
			
		||||
                if (child.expand) {
 | 
			
		||||
                    childBox.x1 = x - availWidth;
 | 
			
		||||
                    childBox.x2 = x;
 | 
			
		||||
                } else if (child.align === St.Align.CENTER) {
 | 
			
		||||
                } else if (child.align === St.Align.MIDDLE) {
 | 
			
		||||
                    childBox.x1 = x - Math.round(extraWidth / 2);
 | 
			
		||||
                    childBox.x2 = childBox.x1 + naturalWidth;
 | 
			
		||||
                } else if (child.align === St.Align.END) {
 | 
			
		||||
@@ -331,33 +377,27 @@ PopupBaseMenuItem.prototype = {
 | 
			
		||||
                x -= availWidth + this._spacing;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(PopupBaseMenuItem.prototype);
 | 
			
		||||
 | 
			
		||||
function PopupMenuItem() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PopupMenuItem.prototype = {
 | 
			
		||||
    __proto__: PopupBaseMenuItem.prototype,
 | 
			
		||||
const PopupMenuItem = new Lang.Class({
 | 
			
		||||
    Name: 'PopupMenuItem',
 | 
			
		||||
    Extends: PopupBaseMenuItem,
 | 
			
		||||
 | 
			
		||||
    _init: function (text, params) {
 | 
			
		||||
        PopupBaseMenuItem.prototype._init.call(this, params);
 | 
			
		||||
        this.parent(params);
 | 
			
		||||
 | 
			
		||||
        this.label = new St.Label({ text: text });
 | 
			
		||||
        this.addActor(this.label);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function PopupSeparatorMenuItem() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PopupSeparatorMenuItem.prototype = {
 | 
			
		||||
    __proto__: PopupBaseMenuItem.prototype,
 | 
			
		||||
const PopupSeparatorMenuItem = new Lang.Class({
 | 
			
		||||
    Name: 'PopupSeparatorMenuItem',
 | 
			
		||||
    Extends: PopupBaseMenuItem,
 | 
			
		||||
 | 
			
		||||
    _init: function () {
 | 
			
		||||
        PopupBaseMenuItem.prototype._init.call(this, { reactive: false });
 | 
			
		||||
        this.parent({ reactive: false });
 | 
			
		||||
 | 
			
		||||
        this._drawingArea = new St.DrawingArea({ style_class: 'popup-separator-menu-item' });
 | 
			
		||||
        this.addActor(this._drawingArea, { span: -1, expand: true });
 | 
			
		||||
@@ -383,22 +423,19 @@ PopupSeparatorMenuItem.prototype = {
 | 
			
		||||
        cr.rectangle(margin, gradientOffset, gradientWidth, gradientHeight);
 | 
			
		||||
        cr.fill();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const PopupAlternatingMenuItemState = {
 | 
			
		||||
    DEFAULT: 0,
 | 
			
		||||
    ALTERNATIVE: 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function PopupAlternatingMenuItem() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PopupAlternatingMenuItem.prototype = {
 | 
			
		||||
    __proto__: PopupBaseMenuItem.prototype,
 | 
			
		||||
const PopupAlternatingMenuItem = new Lang.Class({
 | 
			
		||||
    Name: 'PopupAlternatingMenuItem',
 | 
			
		||||
    Extends: PopupBaseMenuItem,
 | 
			
		||||
 | 
			
		||||
    _init: function(text, alternateText, params) {
 | 
			
		||||
        PopupBaseMenuItem.prototype._init.call(this, params);
 | 
			
		||||
        this.parent(params);
 | 
			
		||||
        this.actor.add_style_class_name('popup-alternating-menu-item');
 | 
			
		||||
 | 
			
		||||
        this._text = text;
 | 
			
		||||
@@ -484,17 +521,14 @@ PopupAlternatingMenuItem.prototype = {
 | 
			
		||||
 | 
			
		||||
        this._updateLabel();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function PopupSliderMenuItem() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PopupSliderMenuItem.prototype = {
 | 
			
		||||
    __proto__: PopupBaseMenuItem.prototype,
 | 
			
		||||
const PopupSliderMenuItem = new Lang.Class({
 | 
			
		||||
    Name: 'PopupSliderMenuItem',
 | 
			
		||||
    Extends: PopupBaseMenuItem,
 | 
			
		||||
 | 
			
		||||
    _init: function(value) {
 | 
			
		||||
        PopupBaseMenuItem.prototype._init.call(this, { activate: false });
 | 
			
		||||
        this.parent({ activate: false });
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
 | 
			
		||||
 | 
			
		||||
@@ -670,13 +704,11 @@ PopupSliderMenuItem.prototype = {
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function Switch() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
const Switch = new Lang.Class({
 | 
			
		||||
    Name: 'Switch',
 | 
			
		||||
 | 
			
		||||
Switch.prototype = {
 | 
			
		||||
    _init: function(state) {
 | 
			
		||||
        this.actor = new St.Bin({ style_class: 'toggle-switch' });
 | 
			
		||||
        // Translators: this MUST be either "toggle-switch-us"
 | 
			
		||||
@@ -699,17 +731,14 @@ Switch.prototype = {
 | 
			
		||||
    toggle: function() {
 | 
			
		||||
        this.setToggleState(!this.state);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function PopupSwitchMenuItem() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PopupSwitchMenuItem.prototype = {
 | 
			
		||||
    __proto__: PopupBaseMenuItem.prototype,
 | 
			
		||||
const PopupSwitchMenuItem = new Lang.Class({
 | 
			
		||||
    Name: 'PopupSwitchMenuItem',
 | 
			
		||||
    Extends: PopupBaseMenuItem,
 | 
			
		||||
 | 
			
		||||
    _init: function(text, active, params) {
 | 
			
		||||
        PopupBaseMenuItem.prototype._init.call(this, params);
 | 
			
		||||
        this.parent(params);
 | 
			
		||||
 | 
			
		||||
        this.label = new St.Label({ text: text });
 | 
			
		||||
        this._switch = new Switch(active);
 | 
			
		||||
@@ -744,7 +773,7 @@ PopupSwitchMenuItem.prototype = {
 | 
			
		||||
            this.toggle();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        PopupBaseMenuItem.prototype.activate.call(this, event);
 | 
			
		||||
        this.parent(event);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    toggle: function() {
 | 
			
		||||
@@ -759,17 +788,14 @@ PopupSwitchMenuItem.prototype = {
 | 
			
		||||
    setToggleState: function(state) {
 | 
			
		||||
        this._switch.setToggleState(state);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function PopupImageMenuItem() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PopupImageMenuItem.prototype = {
 | 
			
		||||
    __proto__: PopupBaseMenuItem.prototype,
 | 
			
		||||
const PopupImageMenuItem = new Lang.Class({
 | 
			
		||||
    Name: 'PopupImageMenuItem',
 | 
			
		||||
    Extends: PopupBaseMenuItem,
 | 
			
		||||
 | 
			
		||||
    _init: function (text, iconName, params) {
 | 
			
		||||
        PopupBaseMenuItem.prototype._init.call(this, params);
 | 
			
		||||
        this.parent(params);
 | 
			
		||||
 | 
			
		||||
        this.label = new St.Label({ text: text });
 | 
			
		||||
        this.addActor(this.label);
 | 
			
		||||
@@ -782,13 +808,12 @@ PopupImageMenuItem.prototype = {
 | 
			
		||||
    setIcon: function(name) {
 | 
			
		||||
        this._icon.icon_name = name;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function PopupMenuBase() {
 | 
			
		||||
    throw new TypeError('Trying to instantiate abstract class PopupMenuBase');
 | 
			
		||||
}
 | 
			
		||||
const PopupMenuBase = new Lang.Class({
 | 
			
		||||
    Name: 'PopupMenuBase',
 | 
			
		||||
    Abstract: true,
 | 
			
		||||
 | 
			
		||||
PopupMenuBase.prototype = {
 | 
			
		||||
    _init: function(sourceActor, styleClass) {
 | 
			
		||||
        this.sourceActor = sourceActor;
 | 
			
		||||
 | 
			
		||||
@@ -899,6 +924,17 @@ PopupMenuBase.prototype = {
 | 
			
		||||
                this.emit('active-changed', null);
 | 
			
		||||
            }
 | 
			
		||||
        }));
 | 
			
		||||
        menuItem._sensitiveChangeId = menuItem.connect('sensitive-changed', Lang.bind(this, function(menuItem, sensitive) {
 | 
			
		||||
            if (!sensitive && this._activeMenuItem == menuItem) {
 | 
			
		||||
                if (!this.actor.navigate_focus(menuItem.actor,
 | 
			
		||||
                                               Gtk.DirectionType.TAB_FORWARD,
 | 
			
		||||
                                               true))
 | 
			
		||||
                    this.actor.grab_key_focus();
 | 
			
		||||
            } else if (sensitive && this._activeMenuItem == null) {
 | 
			
		||||
                if (global.stage.get_key_focus() == this.actor)
 | 
			
		||||
                    menuItem.actor.grab_key_focus();
 | 
			
		||||
            }
 | 
			
		||||
        }));
 | 
			
		||||
        menuItem._activateId = menuItem.connect('activate', Lang.bind(this, function (menuItem, event) {
 | 
			
		||||
            this.emit('activate', menuItem);
 | 
			
		||||
            this.close(true);
 | 
			
		||||
@@ -906,6 +942,7 @@ PopupMenuBase.prototype = {
 | 
			
		||||
        menuItem.connect('destroy', Lang.bind(this, function(emitter) {
 | 
			
		||||
            menuItem.disconnect(menuItem._activateId);
 | 
			
		||||
            menuItem.disconnect(menuItem._activeChangeId);
 | 
			
		||||
            menuItem.disconnect(menuItem._sensitiveChangeId);
 | 
			
		||||
            if (menuItem.menu) {
 | 
			
		||||
                menuItem.menu.disconnect(menuItem._subMenuActivateId);
 | 
			
		||||
                menuItem.menu.disconnect(menuItem._subMenuActiveChangeId);
 | 
			
		||||
@@ -963,6 +1000,11 @@ PopupMenuBase.prototype = {
 | 
			
		||||
        }
 | 
			
		||||
        if (menuItem instanceof PopupMenuSection) {
 | 
			
		||||
            this._connectSubMenuSignals(menuItem, menuItem);
 | 
			
		||||
            menuItem._closingId = this.connect('open-state-changed',
 | 
			
		||||
                function(self, open) {
 | 
			
		||||
                    if (!open)
 | 
			
		||||
                        menuItem.close(false);
 | 
			
		||||
                });
 | 
			
		||||
            menuItem.connect('destroy', Lang.bind(this, function() {
 | 
			
		||||
                menuItem.disconnect(menuItem._subMenuActivateId);
 | 
			
		||||
                menuItem.disconnect(menuItem._subMenuActiveChangeId);
 | 
			
		||||
@@ -1076,20 +1118,17 @@ PopupMenuBase.prototype = {
 | 
			
		||||
 | 
			
		||||
        this.emit('destroy');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(PopupMenuBase.prototype);
 | 
			
		||||
 | 
			
		||||
function PopupMenu() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
const PopupMenu = new Lang.Class({
 | 
			
		||||
    Name: 'PopupMenu',
 | 
			
		||||
    Extends: PopupMenuBase,
 | 
			
		||||
 | 
			
		||||
PopupMenu.prototype = {
 | 
			
		||||
    __proto__: PopupMenuBase.prototype,
 | 
			
		||||
    _init: function(sourceActor, arrowAlignment, arrowSide) {
 | 
			
		||||
        this.parent(sourceActor, 'popup-menu-content');
 | 
			
		||||
 | 
			
		||||
    _init: function(sourceActor, alignment, arrowSide) {
 | 
			
		||||
        PopupMenuBase.prototype._init.call (this, sourceActor, 'popup-menu-content');
 | 
			
		||||
 | 
			
		||||
        this._alignment = alignment;
 | 
			
		||||
        this._arrowAlignment = arrowAlignment;
 | 
			
		||||
        this._arrowSide = arrowSide;
 | 
			
		||||
 | 
			
		||||
        this._boxPointer = new BoxPointer.BoxPointer(arrowSide,
 | 
			
		||||
@@ -1142,13 +1181,17 @@ PopupMenu.prototype = {
 | 
			
		||||
        this._boxPointer.setArrowOrigin(origin);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setSourceAlignment: function(alignment) {
 | 
			
		||||
        this._boxPointer.setSourceAlignment(alignment);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    open: function(animate) {
 | 
			
		||||
        if (this.isOpen)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this.isOpen = true;
 | 
			
		||||
 | 
			
		||||
        this._boxPointer.setPosition(this.sourceActor, this._alignment);
 | 
			
		||||
        this._boxPointer.setPosition(this.sourceActor, this._arrowAlignment);
 | 
			
		||||
        this._boxPointer.show(animate);
 | 
			
		||||
 | 
			
		||||
        this.actor.raise_top();
 | 
			
		||||
@@ -1168,17 +1211,14 @@ PopupMenu.prototype = {
 | 
			
		||||
        this.isOpen = false;
 | 
			
		||||
        this.emit('open-state-changed', false);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function PopupSubMenu() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PopupSubMenu.prototype = {
 | 
			
		||||
    __proto__: PopupMenuBase.prototype,
 | 
			
		||||
const PopupSubMenu = new Lang.Class({
 | 
			
		||||
    Name: 'PopupSubMenu',
 | 
			
		||||
    Extends: PopupMenuBase,
 | 
			
		||||
 | 
			
		||||
    _init: function(sourceActor, sourceArrow) {
 | 
			
		||||
        PopupMenuBase.prototype._init.call(this, sourceActor);
 | 
			
		||||
        this.parent(sourceActor);
 | 
			
		||||
 | 
			
		||||
        this._arrow = sourceArrow;
 | 
			
		||||
        this._arrow.rotation_center_z_gravity = Clutter.Gravity.CENTER;
 | 
			
		||||
@@ -1333,7 +1373,7 @@ PopupSubMenu.prototype = {
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * PopupMenuSection:
 | 
			
		||||
@@ -1343,35 +1383,30 @@ PopupSubMenu.prototype = {
 | 
			
		||||
 * can add it to another menu), but is completely transparent
 | 
			
		||||
 * to the user
 | 
			
		||||
 */
 | 
			
		||||
function PopupMenuSection() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PopupMenuSection.prototype = {
 | 
			
		||||
    __proto__: PopupMenuBase.prototype,
 | 
			
		||||
const PopupMenuSection = new Lang.Class({
 | 
			
		||||
    Name: 'PopupMenuSection',
 | 
			
		||||
    Extends: PopupMenuBase,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        PopupMenuBase.prototype._init.call(this);
 | 
			
		||||
        this.parent();
 | 
			
		||||
 | 
			
		||||
        this.actor = this.box;
 | 
			
		||||
        this.actor._delegate = this;
 | 
			
		||||
        this.isOpen = true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // deliberately ignore any attempt to open() or close()
 | 
			
		||||
    open: function(animate) { },
 | 
			
		||||
    close: function() { },
 | 
			
		||||
}
 | 
			
		||||
    // deliberately ignore any attempt to open() or close(), but emit the
 | 
			
		||||
    // corresponding signal so children can still pick it up
 | 
			
		||||
    open: function(animate) { this.emit('open-state-changed', true); },
 | 
			
		||||
    close: function() { this.emit('open-state-changed', false); },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function PopupSubMenuMenuItem() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PopupSubMenuMenuItem.prototype = {
 | 
			
		||||
    __proto__: PopupBaseMenuItem.prototype,
 | 
			
		||||
const PopupSubMenuMenuItem = new Lang.Class({
 | 
			
		||||
    Name: 'PopupSubMenuMenuItem',
 | 
			
		||||
    Extends: PopupBaseMenuItem,
 | 
			
		||||
 | 
			
		||||
    _init: function(text) {
 | 
			
		||||
        PopupBaseMenuItem.prototype._init.call(this);
 | 
			
		||||
        this.parent();
 | 
			
		||||
 | 
			
		||||
        this.actor.add_style_class_name('popup-submenu-menu-item');
 | 
			
		||||
 | 
			
		||||
@@ -1393,7 +1428,8 @@ PopupSubMenuMenuItem.prototype = {
 | 
			
		||||
 | 
			
		||||
    destroy: function() {
 | 
			
		||||
        this.menu.destroy();
 | 
			
		||||
        PopupBaseMenuItem.prototype.destroy.call(this);
 | 
			
		||||
 | 
			
		||||
        this.parent();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onKeyPressEvent: function(actor, event) {
 | 
			
		||||
@@ -1408,7 +1444,7 @@ PopupSubMenuMenuItem.prototype = {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return PopupBaseMenuItem.prototype._onKeyPressEvent.call(this, actor, event);
 | 
			
		||||
        return this.parent(actor, event);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    activate: function(event) {
 | 
			
		||||
@@ -1418,22 +1454,21 @@ PopupSubMenuMenuItem.prototype = {
 | 
			
		||||
    _onButtonReleaseEvent: function(actor) {
 | 
			
		||||
        this.menu.toggle();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function PopupComboMenu() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PopupComboMenu.prototype = {
 | 
			
		||||
    __proto__: PopupMenuBase.prototype,
 | 
			
		||||
const PopupComboMenu = new Lang.Class({
 | 
			
		||||
    Name: 'PopupComboMenu',
 | 
			
		||||
    Extends: PopupMenuBase,
 | 
			
		||||
 | 
			
		||||
    _init: function(sourceActor) {
 | 
			
		||||
        PopupMenuBase.prototype._init.call(this,
 | 
			
		||||
                                           sourceActor, 'popup-combo-menu');
 | 
			
		||||
        this.parent(sourceActor, 'popup-combo-menu');
 | 
			
		||||
 | 
			
		||||
        this.actor = this.box;
 | 
			
		||||
        this.actor._delegate = this;
 | 
			
		||||
        this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
 | 
			
		||||
        this.actor.connect('key-focus-in', Lang.bind(this, this._onKeyFocusIn));
 | 
			
		||||
        sourceActor.connect('style-changed',
 | 
			
		||||
                            Lang.bind(this, this._onSourceActorStyleChanged));
 | 
			
		||||
        this._activeItemPos = -1;
 | 
			
		||||
        global.focus_manager.add_group(this.actor);
 | 
			
		||||
    },
 | 
			
		||||
@@ -1453,6 +1488,26 @@ PopupComboMenu.prototype = {
 | 
			
		||||
        activeItem.actor.grab_key_focus();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onSourceActorStyleChanged: function() {
 | 
			
		||||
        // PopupComboBoxMenuItem clones the active item's actors
 | 
			
		||||
        // to work with arbitrary items in the menu; this means
 | 
			
		||||
        // that we need to propagate some style information and
 | 
			
		||||
        // enforce style updates even when the menu is closed
 | 
			
		||||
        let activeItem = this._getMenuItems()[this._activeItemPos];
 | 
			
		||||
        if (this.sourceActor.has_style_pseudo_class('insensitive'))
 | 
			
		||||
            activeItem.actor.add_style_pseudo_class('insensitive');
 | 
			
		||||
        else
 | 
			
		||||
            activeItem.actor.remove_style_pseudo_class('insensitive');
 | 
			
		||||
 | 
			
		||||
        // To propagate the :active style, we need to make sure that the
 | 
			
		||||
        // internal state of the PopupComboMenu is updated as well, but
 | 
			
		||||
        // we must not move the keyboard grab
 | 
			
		||||
        activeItem.setActive(this.sourceActor.has_style_pseudo_class('active'),
 | 
			
		||||
                             { grabKeyboard: false });
 | 
			
		||||
 | 
			
		||||
        _ensureStyle(this.actor);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    open: function() {
 | 
			
		||||
        if (this.isOpen)
 | 
			
		||||
            return;
 | 
			
		||||
@@ -1512,23 +1567,21 @@ PopupComboMenu.prototype = {
 | 
			
		||||
    getItemVisible: function(position) {
 | 
			
		||||
        return this._getMenuItems()[position].actor.visible;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function PopupComboBoxMenuItem() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PopupComboBoxMenuItem.prototype = {
 | 
			
		||||
    __proto__: PopupBaseMenuItem.prototype,
 | 
			
		||||
const PopupComboBoxMenuItem = new Lang.Class({
 | 
			
		||||
    Name: 'PopupComboBoxMenuItem',
 | 
			
		||||
    Extends: PopupBaseMenuItem,
 | 
			
		||||
 | 
			
		||||
    _init: function (params) {
 | 
			
		||||
        PopupBaseMenuItem.prototype._init.call(this, params);
 | 
			
		||||
        this.parent(params);
 | 
			
		||||
 | 
			
		||||
        this._itemBox = new Shell.Stack();
 | 
			
		||||
        this.addActor(this._itemBox);
 | 
			
		||||
 | 
			
		||||
        let expander = new St.Label({ text: '\u2304' });
 | 
			
		||||
        this.addActor(expander, { align: St.Align.END });
 | 
			
		||||
        this.addActor(expander, { align: St.Align.END,
 | 
			
		||||
                                  span: -1 });
 | 
			
		||||
 | 
			
		||||
        this._menu = new PopupComboMenu(this.actor);
 | 
			
		||||
        Main.uiGroup.add_actor(this._menu.actor);
 | 
			
		||||
@@ -1639,16 +1692,254 @@ PopupComboBoxMenuItem.prototype = {
 | 
			
		||||
        this.setActiveItem(position);
 | 
			
		||||
        this.emit('active-item-changed', position);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * RemoteMenu:
 | 
			
		||||
 *
 | 
			
		||||
 * A PopupMenu that tracks a GMenuModel and shows its actions
 | 
			
		||||
 * (exposed by GApplication/GActionGroup)
 | 
			
		||||
 */
 | 
			
		||||
const RemoteMenu = new Lang.Class({
 | 
			
		||||
    Name: 'RemoteMenu',
 | 
			
		||||
    Extends: PopupMenu,
 | 
			
		||||
 | 
			
		||||
    _init: function(sourceActor, model, actionGroup) {
 | 
			
		||||
        this.parent(sourceActor, 0.0, St.Side.TOP);
 | 
			
		||||
 | 
			
		||||
        this.model = model;
 | 
			
		||||
        this.actionGroup = actionGroup;
 | 
			
		||||
 | 
			
		||||
        this._actions = { };
 | 
			
		||||
        this._modelChanged(this.model, 0, 0, this.model.get_n_items(), this);
 | 
			
		||||
 | 
			
		||||
        this._actionStateChangeId = this.actionGroup.connect('action-state-changed', Lang.bind(this, this._actionStateChanged));
 | 
			
		||||
        this._actionEnableChangeId = this.actionGroup.connect('action-enabled-changed', Lang.bind(this, this._actionEnabledChanged));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    destroy: function() {
 | 
			
		||||
        if (this._actionStateChangeId) {
 | 
			
		||||
            this.actionGroup.disconnect(this._actionStateChangeId);
 | 
			
		||||
            this._actionStateChangeId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._actionEnableChangeId) {
 | 
			
		||||
            this.actionGroup.disconnect(this._actionEnableChangeId);
 | 
			
		||||
            this._actionEnableChangeId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.parent();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createMenuItem: function(model, index) {
 | 
			
		||||
        let section_link = model.get_item_link(index, Gio.MENU_LINK_SECTION);
 | 
			
		||||
        if (section_link) {
 | 
			
		||||
            let item = new PopupMenuSection();
 | 
			
		||||
            this._modelChanged(section_link, 0, 0, section_link.get_n_items(), item);
 | 
			
		||||
            return [item, true, ''];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // labels are not checked for existance, as they're required for all items
 | 
			
		||||
        let label = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_LABEL, null).deep_unpack();
 | 
			
		||||
        // remove all underscores that are not followed by another underscore
 | 
			
		||||
        label = label.replace(/_([^_])/, '$1');
 | 
			
		||||
        let submenu_link = model.get_item_link(index, Gio.MENU_LINK_SUBMENU);
 | 
			
		||||
 | 
			
		||||
        if (submenu_link) {
 | 
			
		||||
            let item = new PopupSubMenuMenuItem(label);
 | 
			
		||||
            this._modelChanged(submenu_link, 0, 0, submenu_link.get_n_items(), item.menu);
 | 
			
		||||
            return [item, false, ''];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let action_id = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_ACTION, null).deep_unpack();
 | 
			
		||||
        if (!this.actionGroup.has_action(action_id)) {
 | 
			
		||||
            // the action may not be there yet, wait for action-added
 | 
			
		||||
            return [null, false, 'action-added'];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!this._actions[action_id])
 | 
			
		||||
            this._actions[action_id] = { enabled: this.actionGroup.get_action_enabled(action_id),
 | 
			
		||||
                                         state: this.actionGroup.get_action_state(action_id),
 | 
			
		||||
                                         items: [ ],
 | 
			
		||||
                                       };
 | 
			
		||||
        let action = this._actions[action_id];
 | 
			
		||||
        let item, target, destroyId, specificSignalId;
 | 
			
		||||
 | 
			
		||||
        if (action.state) {
 | 
			
		||||
            // Docs have get_state_hint(), except that the DBus protocol
 | 
			
		||||
            // has no provision for it (so ShellApp does not implement it,
 | 
			
		||||
            // and neither GApplication), and g_action_get_state_hint()
 | 
			
		||||
            // always returns null
 | 
			
		||||
            // Funny :)
 | 
			
		||||
 | 
			
		||||
            switch (String.fromCharCode(action.state.classify())) {
 | 
			
		||||
            case 'b':
 | 
			
		||||
                item = new PopupSwitchMenuItem(label, action.state.get_boolean());
 | 
			
		||||
                action.items.push(item);
 | 
			
		||||
                specificSignalId = item.connect('toggled', Lang.bind(this, function(item) {
 | 
			
		||||
                    this.actionGroup.activate_action(action_id, null);
 | 
			
		||||
                }));
 | 
			
		||||
                break;
 | 
			
		||||
            case 's':
 | 
			
		||||
                item = new PopupMenuItem(label);
 | 
			
		||||
                item._remoteTarget = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_TARGET, null).deep_unpack();
 | 
			
		||||
                action.items.push(item);
 | 
			
		||||
                item.setShowDot(action.state.deep_unpack() == item._remoteTarget);
 | 
			
		||||
                specificSignalId = item.connect('activate', Lang.bind(this, function(item) {
 | 
			
		||||
                    this.actionGroup.activate_action(action_id, GLib.Variant.new_string(item._remoteTarget));
 | 
			
		||||
                }));
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                log('Action "%s" has state of type %s, which is not supported'.format(action_id, action.state.get_type_string()));
 | 
			
		||||
                return [null, false, 'action-state-changed'];
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            target = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_TARGET, null);
 | 
			
		||||
            item = new PopupMenuItem(label);
 | 
			
		||||
            action.items.push(item);
 | 
			
		||||
            specificSignalId = item.connect('activate', Lang.bind(this, function() {
 | 
			
		||||
                this.actionGroup.activate_action(action_id, target);
 | 
			
		||||
            }));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        item.actor.reactive = item.actor.can_focus = action.enabled;
 | 
			
		||||
        if (action.enabled)
 | 
			
		||||
            item.actor.remove_style_pseudo_class('insensitive');
 | 
			
		||||
        else
 | 
			
		||||
            item.actor.add_style_pseudo_class('insensitive');
 | 
			
		||||
 | 
			
		||||
        destroyId = item.connect('destroy', Lang.bind(this, function() {
 | 
			
		||||
            item.disconnect(destroyId);
 | 
			
		||||
            item.disconnect(specificSignalId);
 | 
			
		||||
 | 
			
		||||
            let pos = action.items.indexOf(item);
 | 
			
		||||
            if (pos != -1)
 | 
			
		||||
                action.items.splice(pos, 1);
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        return [item, false, ''];
 | 
			
		||||
    }, 
 | 
			
		||||
 | 
			
		||||
    _modelChanged: function(model, position, removed, added, target) {
 | 
			
		||||
        let j, k;
 | 
			
		||||
        let j0, k0;
 | 
			
		||||
 | 
			
		||||
        let currentItems = target._getMenuItems();
 | 
			
		||||
 | 
			
		||||
        for (j0 = 0, k0 = 0; j0 < position; j0++, k0++) {
 | 
			
		||||
            if (currentItems[k0] instanceof PopupSeparatorMenuItem)
 | 
			
		||||
                k0++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (removed == -1) {
 | 
			
		||||
            // special flag to indicate we should destroy everything
 | 
			
		||||
            for (k = k0; k < currentItems.length; k++)
 | 
			
		||||
                currentItems[k].destroy();
 | 
			
		||||
        } else {
 | 
			
		||||
            for (j = j0, k = k0; j < j0 + removed; j++, k++) {
 | 
			
		||||
                currentItems[k].destroy();
 | 
			
		||||
 | 
			
		||||
                if (currentItems[k] instanceof PopupSeparatorMenuItem)
 | 
			
		||||
                    j--;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (j = j0, k = k0; j < j0 + added; j++, k++) {
 | 
			
		||||
            let [item, addSeparator, changeSignal] = this._createMenuItem(model, j);
 | 
			
		||||
 | 
			
		||||
            if (item) {
 | 
			
		||||
                // separators must be added in the parent to make autohiding work
 | 
			
		||||
                if (addSeparator) {
 | 
			
		||||
                    target.addMenuItem(new PopupSeparatorMenuItem(), k+1);
 | 
			
		||||
                    k++;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                target.addMenuItem(item, k);
 | 
			
		||||
 | 
			
		||||
                if (addSeparator) {
 | 
			
		||||
                    target.addMenuItem(new PopupSeparatorMenuItem(), k+1);
 | 
			
		||||
                    k++;
 | 
			
		||||
                }
 | 
			
		||||
            } else if (changeSignal) {
 | 
			
		||||
                let signalId = this.actionGroup.connect(changeSignal, Lang.bind(this, function() {
 | 
			
		||||
                    this.actionGroup.disconnect(signalId);
 | 
			
		||||
 | 
			
		||||
                    // force a full update
 | 
			
		||||
                    this._modelChanged(model, 0, -1, model.get_n_items(), target);
 | 
			
		||||
                }));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!model._changedId) {
 | 
			
		||||
            model._changedId = model.connect('items-changed', Lang.bind(this, this._modelChanged, target));
 | 
			
		||||
            model._destroyId = target.connect('destroy', function() {
 | 
			
		||||
                if (model._changedId)
 | 
			
		||||
                    model.disconnect(model._changedId);
 | 
			
		||||
                if (model._destroyId)
 | 
			
		||||
                    target.disconnect(model._destroyId);
 | 
			
		||||
                model._changedId = 0;
 | 
			
		||||
                model._destroyId = 0;
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (target instanceof PopupMenuSection) {
 | 
			
		||||
            target.actor.visible = target.numMenuItems != 0;
 | 
			
		||||
        } else {
 | 
			
		||||
            let sourceItem = target.sourceActor._delegate;
 | 
			
		||||
            if (sourceItem instanceof PopupSubMenuMenuItem)
 | 
			
		||||
                sourceItem.actor.visible = target.numMenuItems != 0;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _actionStateChanged: function(actionGroup, action_id) {
 | 
			
		||||
        let action = this._actions[action_id];
 | 
			
		||||
        if (!action)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        action.state = actionGroup.get_action_state(action_id);
 | 
			
		||||
        if (action.items.length) {
 | 
			
		||||
            switch (String.fromCharCode(action.state.classify())) {
 | 
			
		||||
            case 'b':
 | 
			
		||||
                for (let i = 0; i < action.items.length; i++)
 | 
			
		||||
                    action.items[i].setToggleState(action.state.get_boolean());
 | 
			
		||||
                break;
 | 
			
		||||
            case 'd':
 | 
			
		||||
                for (let i = 0; i < action.items.length; i++)
 | 
			
		||||
                    action.items[i].setValue(action.state.get_double());
 | 
			
		||||
                break;
 | 
			
		||||
            case 's':
 | 
			
		||||
                for (let i = 0; i < action.items.length; i++)
 | 
			
		||||
                    action.items[i].setShowDot(action.items[i]._remoteTarget == action.state.deep_unpack());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _actionEnabledChanged: function(actionGroup, action_id) {
 | 
			
		||||
        let action = this._actions[action_id];
 | 
			
		||||
        if (!action)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        action.enabled = actionGroup.get_action_enabled(action_id);
 | 
			
		||||
        if (action.items.length) {
 | 
			
		||||
            for (let i = 0; i < action.items.length; i++) {
 | 
			
		||||
                let item = action.items[i];
 | 
			
		||||
                item.actor.reactive = item.actor.can_focus = action.enabled;
 | 
			
		||||
 | 
			
		||||
                if (action.enabled)
 | 
			
		||||
                    item.actor.remove_style_pseudo_class('insensitive');
 | 
			
		||||
                else
 | 
			
		||||
                    item.actor.add_style_pseudo_class('insensitive');
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/* Basic implementation of a menu manager.
 | 
			
		||||
 * Call addMenu to add menus
 | 
			
		||||
 */
 | 
			
		||||
function PopupMenuManager(owner) {
 | 
			
		||||
    this._init(owner);
 | 
			
		||||
}
 | 
			
		||||
const PopupMenuManager = new Lang.Class({
 | 
			
		||||
    Name: 'PopupMenuManager',
 | 
			
		||||
 | 
			
		||||
PopupMenuManager.prototype = {
 | 
			
		||||
    _init: function(owner) {
 | 
			
		||||
        this._owner = owner;
 | 
			
		||||
        this.grabbed = false;
 | 
			
		||||
@@ -1920,4 +2211,4 @@ PopupMenuManager.prototype = {
 | 
			
		||||
        if (this._activeMenu != null)
 | 
			
		||||
            this._activeMenu.close(true);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
@@ -12,6 +12,7 @@ const Signals = imports.signals;
 | 
			
		||||
const FileUtils = imports.misc.fileUtils;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const ModalDialog = imports.ui.modalDialog;
 | 
			
		||||
const ShellEntry = imports.ui.shellEntry;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
const Util = imports.misc.util;
 | 
			
		||||
const History = imports.misc.history;
 | 
			
		||||
@@ -29,11 +30,9 @@ const EXEC_ARG_KEY = 'exec-arg';
 | 
			
		||||
 | 
			
		||||
const DIALOG_GROW_TIME = 0.1;
 | 
			
		||||
 | 
			
		||||
function CommandCompleter() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const CommandCompleter = new Lang.Class({
 | 
			
		||||
    Name: 'CommandCompleter',
 | 
			
		||||
 | 
			
		||||
CommandCompleter.prototype = {
 | 
			
		||||
    _init : function() {
 | 
			
		||||
        this._changedCount = 0;
 | 
			
		||||
        this._paths = GLib.getenv('PATH').split(':');
 | 
			
		||||
@@ -161,16 +160,14 @@ CommandCompleter.prototype = {
 | 
			
		||||
            return common.substr(text.length);
 | 
			
		||||
        return common;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function RunDialog() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const RunDialog = new Lang.Class({
 | 
			
		||||
    Name: 'RunDialog',
 | 
			
		||||
    Extends: ModalDialog.ModalDialog,
 | 
			
		||||
 | 
			
		||||
RunDialog.prototype = {
 | 
			
		||||
__proto__: ModalDialog.ModalDialog.prototype,
 | 
			
		||||
    _init : function() {
 | 
			
		||||
        ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'run-dialog' });
 | 
			
		||||
        this.parent({ styleClass: 'run-dialog' });
 | 
			
		||||
 | 
			
		||||
        this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA });
 | 
			
		||||
        this._terminalSettings = new Gio.Settings({ schema: TERMINAL_SCHEMA });
 | 
			
		||||
@@ -210,6 +207,7 @@ __proto__: ModalDialog.ModalDialog.prototype,
 | 
			
		||||
        this.contentLayout.add(label, { y_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        let entry = new St.Entry({ style_class: 'run-dialog-entry' });
 | 
			
		||||
        ShellEntry.addContextMenu(entry);
 | 
			
		||||
 | 
			
		||||
        this._entryText = entry.clutter_text;
 | 
			
		||||
        this.contentLayout.add(entry, { y_align: St.Align.START });
 | 
			
		||||
@@ -382,8 +380,7 @@ __proto__: ModalDialog.ModalDialog.prototype,
 | 
			
		||||
        if (this._lockdownSettings.get_boolean(DISABLE_COMMAND_LINE_KEY))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        ModalDialog.ModalDialog.prototype.open.call(this);
 | 
			
		||||
        this.parent();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(RunDialog.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
@@ -70,24 +69,21 @@ function waitLeisure() {
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const PerfHelperIface = {
 | 
			
		||||
    name: 'org.gnome.Shell.PerfHelper',
 | 
			
		||||
    methods: [{ name: 'CreateWindow', inSignature: 'iibb', outSignature: '' },
 | 
			
		||||
              { name: 'WaitWindows', inSignature: '', outSignature: '' },
 | 
			
		||||
              { name: 'DestroyWindows', inSignature: '', outSignature: ''}]
 | 
			
		||||
};
 | 
			
		||||
const PerfHelperIface = <interface name="org.gnome.Shell.PerfHelper">
 | 
			
		||||
<method name="CreateWindow">
 | 
			
		||||
    <arg type="i" direction="in" />
 | 
			
		||||
    <arg type="i" direction="in" />
 | 
			
		||||
    <arg type="b" direction="in" />
 | 
			
		||||
    <arg type="b" direction="in" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="WaitWindows" />
 | 
			
		||||
<method name="DestroyWindows" />
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
const PerfHelper = function () {
 | 
			
		||||
    this._init();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
PerfHelper.prototype = {
 | 
			
		||||
     _init: function() {
 | 
			
		||||
         DBus.session.proxifyObject(this, 'org.gnome.Shell.PerfHelper', '/org/gnome/Shell/PerfHelper');
 | 
			
		||||
     }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
DBus.proxifyPrototype(PerfHelper.prototype, PerfHelperIface);
 | 
			
		||||
var PerfHelperProxy = Gio.DBusProxy.makeProxyWrapper(PerfHelperIface);
 | 
			
		||||
function PerfHelper() {
 | 
			
		||||
    return new PerfHelperProxy(Gio.DBus.session, 'org.gnome.Shell.PerfHelper', '/org/gnome/Shell/PerfHelper');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
let _perfHelper = null;
 | 
			
		||||
function _getPerfHelper() {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
@@ -23,11 +23,9 @@ const MatchType = {
 | 
			
		||||
    MULTIPLE_PREFIX: 4
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function SearchResultDisplay(provider) {
 | 
			
		||||
    this._init(provider);
 | 
			
		||||
}
 | 
			
		||||
const SearchResultDisplay = new Lang.Class({
 | 
			
		||||
    Name: 'SearchResultDisplay',
 | 
			
		||||
 | 
			
		||||
SearchResultDisplay.prototype = {
 | 
			
		||||
    _init: function(provider) {
 | 
			
		||||
        this.provider = provider;
 | 
			
		||||
        this.actor = null;
 | 
			
		||||
@@ -96,7 +94,7 @@ SearchResultDisplay.prototype = {
 | 
			
		||||
    activateSelected: function() {
 | 
			
		||||
        throw new Error('Not implemented');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SearchProvider:
 | 
			
		||||
@@ -105,11 +103,9 @@ SearchResultDisplay.prototype = {
 | 
			
		||||
 * to the search system, then call registerProvider()
 | 
			
		||||
 * in SearchSystem with an instance.
 | 
			
		||||
 */
 | 
			
		||||
function SearchProvider(title) {
 | 
			
		||||
    this._init(title);
 | 
			
		||||
}
 | 
			
		||||
const SearchProvider = new Lang.Class({
 | 
			
		||||
    Name: 'SearchProvider',
 | 
			
		||||
 | 
			
		||||
SearchProvider.prototype = {
 | 
			
		||||
    _init: function(title) {
 | 
			
		||||
        this.title = title;
 | 
			
		||||
        this.searchSystem = null;
 | 
			
		||||
@@ -243,14 +239,12 @@ SearchProvider.prototype = {
 | 
			
		||||
    activateResult: function(id) {
 | 
			
		||||
        throw new Error('Not implemented');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(SearchProvider.prototype);
 | 
			
		||||
 | 
			
		||||
function OpenSearchSystem() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const OpenSearchSystem = new Lang.Class({
 | 
			
		||||
    Name: 'OpenSearchSystem',
 | 
			
		||||
 | 
			
		||||
OpenSearchSystem.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._providers = [];
 | 
			
		||||
        global.settings.connect('changed::' + DISABLED_OPEN_SEARCH_PROVIDERS_KEY, Lang.bind(this, this._refresh));
 | 
			
		||||
@@ -338,14 +332,12 @@ OpenSearchSystem.prototype = {
 | 
			
		||||
            }
 | 
			
		||||
        }));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(OpenSearchSystem.prototype);
 | 
			
		||||
 | 
			
		||||
function SearchSystem() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const SearchSystem = new Lang.Class({
 | 
			
		||||
    Name: 'SearchSystem',
 | 
			
		||||
 | 
			
		||||
SearchSystem.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._providers = [];
 | 
			
		||||
        this.reset();
 | 
			
		||||
@@ -433,5 +425,5 @@ SearchSystem.prototype = {
 | 
			
		||||
        this._previousResults = results;
 | 
			
		||||
        this.emit('search-completed', results);
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(SearchSystem.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
@@ -15,11 +15,9 @@ const Search = imports.ui.search;
 | 
			
		||||
const MAX_SEARCH_RESULTS_ROWS = 1;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function SearchResult(provider, metaInfo, terms) {
 | 
			
		||||
    this._init(provider, metaInfo, terms);
 | 
			
		||||
}
 | 
			
		||||
const SearchResult = new Lang.Class({
 | 
			
		||||
    Name: 'SearchResult',
 | 
			
		||||
 | 
			
		||||
SearchResult.prototype = {
 | 
			
		||||
    _init: function(provider, metaInfo, terms) {
 | 
			
		||||
        this.provider = provider;
 | 
			
		||||
        this.metaInfo = metaInfo;
 | 
			
		||||
@@ -97,18 +95,16 @@ SearchResult.prototype = {
 | 
			
		||||
        else
 | 
			
		||||
            this.provider.activateResult(this.metaInfo.id, params);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function GridSearchResults(provider, grid) {
 | 
			
		||||
    this._init(provider, grid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GridSearchResults.prototype = {
 | 
			
		||||
    __proto__: Search.SearchResultDisplay.prototype,
 | 
			
		||||
const GridSearchResults = new Lang.Class({
 | 
			
		||||
    Name: 'GridSearchResults',
 | 
			
		||||
    Extends: Search.SearchResultDisplay,
 | 
			
		||||
 | 
			
		||||
    _init: function(provider, grid) {
 | 
			
		||||
        Search.SearchResultDisplay.prototype._init.call(this, provider);
 | 
			
		||||
        this.parent(provider);
 | 
			
		||||
 | 
			
		||||
        this._grid = grid || new IconGrid.IconGrid({ rowLimit: MAX_SEARCH_RESULTS_ROWS,
 | 
			
		||||
                                                     xAlign: St.Align.START });
 | 
			
		||||
        this.actor = new St.Bin({ x_align: St.Align.START });
 | 
			
		||||
@@ -179,14 +175,11 @@ GridSearchResults.prototype = {
 | 
			
		||||
        let targetActor = this._grid.getItemAtIndex(this.selectionIndex);
 | 
			
		||||
        targetActor._delegate.activate();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const SearchResults = new Lang.Class({
 | 
			
		||||
    Name: 'SearchResults',
 | 
			
		||||
 | 
			
		||||
function SearchResults(searchSystem, openSearchSystem) {
 | 
			
		||||
    this._init(searchSystem, openSearchSystem);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SearchResults.prototype = {
 | 
			
		||||
    _init: function(searchSystem, openSearchSystem) {
 | 
			
		||||
        this._searchSystem = searchSystem;
 | 
			
		||||
        this._searchSystem.connect('search-updated', Lang.bind(this, this._updateCurrentResults));
 | 
			
		||||
@@ -486,4 +479,4 @@ SearchResults.prototype = {
 | 
			
		||||
        resultDisplay.activateSelected();
 | 
			
		||||
        Main.overview.hide();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,79 +1,77 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
 | 
			
		||||
const Config = imports.misc.config;
 | 
			
		||||
const ExtensionSystem = imports.ui.extensionSystem;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
 | 
			
		||||
const GnomeShellIface = {
 | 
			
		||||
    name: 'org.gnome.Shell',
 | 
			
		||||
    methods: [{ name: 'Eval',
 | 
			
		||||
                inSignature: 's',
 | 
			
		||||
                outSignature: 'bs'
 | 
			
		||||
              },
 | 
			
		||||
              { name: 'ListExtensions',
 | 
			
		||||
                inSignature: '',
 | 
			
		||||
                outSignature: 'a{sa{sv}}'
 | 
			
		||||
              },
 | 
			
		||||
              { name: 'GetExtensionInfo',
 | 
			
		||||
                inSignature: 's',
 | 
			
		||||
                outSignature: 'a{sv}'
 | 
			
		||||
              },
 | 
			
		||||
              { name: 'GetExtensionErrors',
 | 
			
		||||
                inSignature: 's',
 | 
			
		||||
                outSignature: 'as'
 | 
			
		||||
              },
 | 
			
		||||
              { name: 'ScreenshotArea',
 | 
			
		||||
                inSignature: 'iiiis',
 | 
			
		||||
                outSignature: 'b'
 | 
			
		||||
              },
 | 
			
		||||
              { name: 'ScreenshotWindow',
 | 
			
		||||
                inSignature: 'bs',
 | 
			
		||||
                outSignature: 'b'
 | 
			
		||||
              },
 | 
			
		||||
              { name: 'Screenshot',
 | 
			
		||||
                inSignature: 's',
 | 
			
		||||
                outSignature: 'b'
 | 
			
		||||
              },
 | 
			
		||||
              { name: 'EnableExtension',
 | 
			
		||||
                inSignature: 's',
 | 
			
		||||
                outSignature: ''
 | 
			
		||||
              },
 | 
			
		||||
              { name: 'DisableExtension',
 | 
			
		||||
                inSignature: 's',
 | 
			
		||||
                outSignature: ''
 | 
			
		||||
              },
 | 
			
		||||
              { name: 'InstallRemoteExtension',
 | 
			
		||||
                inSignature: 'ss',
 | 
			
		||||
                outSignature: ''
 | 
			
		||||
              },
 | 
			
		||||
              { name: 'UninstallExtension',
 | 
			
		||||
                inSignature: 's',
 | 
			
		||||
                outSignature: 'b'
 | 
			
		||||
              }
 | 
			
		||||
             ],
 | 
			
		||||
    signals: [{ name: 'ExtensionStatusChanged',
 | 
			
		||||
                inSignature: 'sis' }],
 | 
			
		||||
    properties: [{ name: 'OverviewActive',
 | 
			
		||||
                   signature: 'b',
 | 
			
		||||
                   access: 'readwrite' },
 | 
			
		||||
                 { name: 'ApiVersion',
 | 
			
		||||
                   signature: 'i',
 | 
			
		||||
                   access: 'read' },
 | 
			
		||||
                 { name: 'ShellVersion',
 | 
			
		||||
                   signature: 's',
 | 
			
		||||
                   access: 'read' }]
 | 
			
		||||
};
 | 
			
		||||
const GnomeShellIface = <interface name="org.gnome.Shell">
 | 
			
		||||
<method name="Eval">
 | 
			
		||||
    <arg type="s" direction="in" name="script" />
 | 
			
		||||
    <arg type="b" direction="out" name="success" />
 | 
			
		||||
    <arg type="s" direction="out" name="result" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="ListExtensions">
 | 
			
		||||
    <arg type="a{sa{sv}}" direction="out" name="extensions" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="GetExtensionInfo">
 | 
			
		||||
    <arg type="s" direction="in" name="extension" />
 | 
			
		||||
    <arg type="a{sv}" direction="out" name="info" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="GetExtensionErrors">
 | 
			
		||||
    <arg type="s" direction="in" name="extension" />
 | 
			
		||||
    <arg type="as" direction="out" name="errors" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="ScreenshotArea">
 | 
			
		||||
    <arg type="i" direction="in" name="x"/>
 | 
			
		||||
    <arg type="i" direction="in" name="y"/>
 | 
			
		||||
    <arg type="i" direction="in" name="width"/>
 | 
			
		||||
    <arg type="i" direction="in" name="height"/>
 | 
			
		||||
    <arg type="s" direction="in" name="filename"/>
 | 
			
		||||
    <arg type="b" direction="out" name="success"/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name="ScreenshotWindow">
 | 
			
		||||
    <arg type="b" direction="in" name="include_frame"/>
 | 
			
		||||
    <arg type="s" direction="in" name="filename"/>
 | 
			
		||||
    <arg type="b" direction="out" name="success"/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name="Screenshot">
 | 
			
		||||
    <arg type="s" direction="in" name="filename"/>
 | 
			
		||||
    <arg type="b" direction="out" name="success"/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name="EnableExtension">
 | 
			
		||||
    <arg type="s" direction="in" name="uuid"/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name="DisableExtension">
 | 
			
		||||
    <arg type="s" direction="in" name="uuid"/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name="InstallRemoteExtension">
 | 
			
		||||
    <arg type="s" direction="in" name="uuid"/>
 | 
			
		||||
    <arg type="s" direction="in" name="version"/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name="UninstallExtension">
 | 
			
		||||
    <arg type="s" direction="in" name="uuid"/>
 | 
			
		||||
    <arg type="b" direction="out" name="success"/>
 | 
			
		||||
</method>
 | 
			
		||||
<property name="OverviewActive" type="b" access="readwrite" />
 | 
			
		||||
<property name="ApiVersion" type="i" access="read" />
 | 
			
		||||
<property name="ShellVersion" type="s" access="read" />
 | 
			
		||||
<signal name="ExtensionStatusChanged">
 | 
			
		||||
    <arg type="s" name="uuid"/>
 | 
			
		||||
    <arg type="i" name="state"/>
 | 
			
		||||
    <arg type="s" name="error"/>
 | 
			
		||||
</signal>
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
function GnomeShell() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const GnomeShell = new Lang.Class({
 | 
			
		||||
    Name: 'GnomeShellDBus',
 | 
			
		||||
 | 
			
		||||
GnomeShell.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        DBus.session.exportObject('/org/gnome/Shell', this);
 | 
			
		||||
        this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellIface, this);
 | 
			
		||||
        this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell');
 | 
			
		||||
        ExtensionSystem.connect('extension-state-changed',
 | 
			
		||||
                                Lang.bind(this, this._extensionStateChanged));
 | 
			
		||||
    },
 | 
			
		||||
@@ -93,6 +91,9 @@ GnomeShell.prototype = {
 | 
			
		||||
     *
 | 
			
		||||
     */
 | 
			
		||||
    Eval: function(code) {
 | 
			
		||||
        if (!global.settings.get_boolean('development-tools'))
 | 
			
		||||
            return [false, null];
 | 
			
		||||
 | 
			
		||||
        let returnValue;
 | 
			
		||||
        let success;
 | 
			
		||||
        try {
 | 
			
		||||
@@ -153,11 +154,33 @@ GnomeShell.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    ListExtensions: function() {
 | 
			
		||||
        return ExtensionSystem.extensionMeta;
 | 
			
		||||
        let out = {};
 | 
			
		||||
        for (let uuid in ExtensionSystem.extensionMeta) {
 | 
			
		||||
            let dbusObj = this.GetExtensionInfo(uuid);
 | 
			
		||||
            out[uuid] = dbusObj;
 | 
			
		||||
        }
 | 
			
		||||
        return out;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    GetExtensionInfo: function(uuid) {
 | 
			
		||||
        return ExtensionSystem.extensionMeta[uuid] || {};
 | 
			
		||||
        let meta = ExtensionSystem.extensionMeta[uuid] || {};
 | 
			
		||||
        let out = {};
 | 
			
		||||
        for (let key in meta) {
 | 
			
		||||
            let val = meta[key];
 | 
			
		||||
            let type;
 | 
			
		||||
            switch (typeof val) {
 | 
			
		||||
            case 'string':
 | 
			
		||||
                type = 's';
 | 
			
		||||
                break;
 | 
			
		||||
            case 'number':
 | 
			
		||||
                type = 'd';
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            out[key] = GLib.Variant.new(type, val);
 | 
			
		||||
        }
 | 
			
		||||
        return out;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    GetExtensionErrors: function(uuid) {
 | 
			
		||||
@@ -202,12 +225,7 @@ GnomeShell.prototype = {
 | 
			
		||||
    ShellVersion: Config.PACKAGE_VERSION,
 | 
			
		||||
 | 
			
		||||
    _extensionStateChanged: function(_, newState) {
 | 
			
		||||
        DBus.session.emit_signal('/org/gnome/Shell',
 | 
			
		||||
                                 'org.gnome.Shell',
 | 
			
		||||
                                 'ExtensionStatusChanged', 'sis',
 | 
			
		||||
                                 [newState.uuid, newState.state, newState.error]);
 | 
			
		||||
        this._dbusImpl.emit_signal('ExtensionStatusChanged',
 | 
			
		||||
                                   GLib.Variant.new('(sis)', [newState.uuid, newState.state, newState.error]));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
DBus.conformExport(GnomeShell.prototype, GnomeShellIface);
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										168
									
								
								js/ui/shellEntry.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								js/ui/shellEntry.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,168 @@
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
 | 
			
		||||
const _EntryMenu = new Lang.Class({
 | 
			
		||||
    Name: 'ShellEntryMenu',
 | 
			
		||||
    Extends: PopupMenu.PopupMenu,
 | 
			
		||||
 | 
			
		||||
    _init: function(entry, params) {
 | 
			
		||||
        params = Params.parse (params, { isPassword: false });
 | 
			
		||||
 | 
			
		||||
        this.parent(entry, 0, St.Side.TOP);
 | 
			
		||||
 | 
			
		||||
        this.actor.add_style_class_name('entry-context-menu');
 | 
			
		||||
 | 
			
		||||
        this._entry = entry;
 | 
			
		||||
        this._clipboard = St.Clipboard.get_default();
 | 
			
		||||
 | 
			
		||||
        // Populate menu
 | 
			
		||||
        let item;
 | 
			
		||||
        item = new PopupMenu.PopupMenuItem(_("Copy"));
 | 
			
		||||
        item.connect('activate', Lang.bind(this, this._onCopyActivated));
 | 
			
		||||
        this.addMenuItem(item);
 | 
			
		||||
        this._copyItem = item;
 | 
			
		||||
 | 
			
		||||
        item = new PopupMenu.PopupMenuItem(_("Paste"));
 | 
			
		||||
        item.connect('activate', Lang.bind(this, this._onPasteActivated));
 | 
			
		||||
        this.addMenuItem(item);
 | 
			
		||||
        this._pasteItem = item;
 | 
			
		||||
 | 
			
		||||
        this._passwordItem = null;
 | 
			
		||||
        if (params.isPassword) {
 | 
			
		||||
            item = new PopupMenu.PopupMenuItem('');
 | 
			
		||||
            item.connect('activate', Lang.bind(this,
 | 
			
		||||
                                               this._onPasswordActivated));
 | 
			
		||||
            this.addMenuItem(item);
 | 
			
		||||
            this._passwordItem = item;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Main.uiGroup.add_actor(this.actor);
 | 
			
		||||
        this.actor.hide();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    open: function() {
 | 
			
		||||
        this._updatePasteItem();
 | 
			
		||||
        this._updateCopyItem();
 | 
			
		||||
        if (this._passwordItem)
 | 
			
		||||
            this._updatePasswordItem();
 | 
			
		||||
 | 
			
		||||
        let direction = Gtk.DirectionType.TAB_FORWARD;
 | 
			
		||||
        if (!this.actor.navigate_focus(null, direction, false))
 | 
			
		||||
            this.actor.grab_key_focus();
 | 
			
		||||
 | 
			
		||||
        this.parent();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateCopyItem: function() {
 | 
			
		||||
        let selection = this._entry.clutter_text.get_selection();
 | 
			
		||||
        this._copyItem.setSensitive(selection && selection != '');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updatePasteItem: function() {
 | 
			
		||||
        this._clipboard.get_text(Lang.bind(this,
 | 
			
		||||
            function(clipboard, text) {
 | 
			
		||||
                this._pasteItem.setSensitive(text && text != '');
 | 
			
		||||
            }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updatePasswordItem: function() {
 | 
			
		||||
        let textHidden = (this._entry.clutter_text.password_char);
 | 
			
		||||
        if (textHidden)
 | 
			
		||||
            this._passwordItem.label.set_text(_("Show Text"));
 | 
			
		||||
        else
 | 
			
		||||
            this._passwordItem.label.set_text(_("Hide Text"));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onCopyActivated: function() {
 | 
			
		||||
        let selection = this._entry.clutter_text.get_selection();
 | 
			
		||||
        this._clipboard.set_text(selection);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onPasteActivated: function() {
 | 
			
		||||
        this._clipboard.get_text(Lang.bind(this,
 | 
			
		||||
            function(clipboard, text) {
 | 
			
		||||
                if (!text)
 | 
			
		||||
                    return;
 | 
			
		||||
                this._entry.clutter_text.delete_selection();
 | 
			
		||||
                let pos = this._entry.clutter_text.get_cursor_position();
 | 
			
		||||
                this._entry.clutter_text.insert_text(text, pos);
 | 
			
		||||
            }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onPasswordActivated: function() {
 | 
			
		||||
        let visible = !!(this._entry.clutter_text.password_char);
 | 
			
		||||
        this._entry.clutter_text.set_password_char(visible ? '' : '\u25cf');
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function _setMenuAlignment(entry, stageX) {
 | 
			
		||||
    let [success, entryX, entryY] = entry.transform_stage_point(stageX, 0);
 | 
			
		||||
    if (success)
 | 
			
		||||
        entry._menu.setSourceAlignment(entryX / entry.width);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function _onClicked(action, actor) {
 | 
			
		||||
    let entry = actor._menu ? actor : actor.get_parent();
 | 
			
		||||
 | 
			
		||||
    if (entry._menu.isOpen) {
 | 
			
		||||
        entry._menu.close();
 | 
			
		||||
    } else if (action.get_button() == 3) {
 | 
			
		||||
        let [stageX, stageY] = action.get_coords();
 | 
			
		||||
        _setMenuAlignment(entry, stageX);
 | 
			
		||||
        entry._menu.open();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function _onLongPress(action, actor, state) {
 | 
			
		||||
    let entry = actor._menu ? actor : actor.get_parent();
 | 
			
		||||
 | 
			
		||||
    if (state == Clutter.LongPressState.QUERY)
 | 
			
		||||
        return action.get_button() == 1 && !entry._menu.isOpen;
 | 
			
		||||
 | 
			
		||||
    if (state == Clutter.LongPressState.ACTIVATE) {
 | 
			
		||||
        let [stageX, stageY] = action.get_coords();
 | 
			
		||||
        _setMenuAlignment(entry, stageX);
 | 
			
		||||
        entry._menu.open();
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function _onPopup(actor) {
 | 
			
		||||
    let entry = actor._menu ? actor : actor.get_parent();
 | 
			
		||||
    let [success, textX, textY, lineHeight] = entry.clutter_text.position_to_coords(-1);
 | 
			
		||||
    if (success)
 | 
			
		||||
        entry._menu.setSourceAlignment(textX / entry.width);
 | 
			
		||||
    entry._menu.open();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function addContextMenu(entry, params) {
 | 
			
		||||
    if (entry._menu)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    entry._menu = new _EntryMenu(entry, params);
 | 
			
		||||
    entry._menuManager = new PopupMenu.PopupMenuManager({ actor: entry });
 | 
			
		||||
    entry._menuManager.addMenu(entry._menu);
 | 
			
		||||
 | 
			
		||||
    let clickAction;
 | 
			
		||||
 | 
			
		||||
    // Add a click action to both the entry and its clutter_text; the former
 | 
			
		||||
    // so padding is included in the clickable area, the latter because the
 | 
			
		||||
    // event processing of ClutterText prevents event-bubbling.
 | 
			
		||||
    clickAction = new Clutter.ClickAction();
 | 
			
		||||
    clickAction.connect('clicked', _onClicked);
 | 
			
		||||
    clickAction.connect('long-press', _onLongPress);
 | 
			
		||||
    entry.clutter_text.add_action(clickAction);
 | 
			
		||||
 | 
			
		||||
    clickAction = new Clutter.ClickAction();
 | 
			
		||||
    clickAction.connect('clicked', _onClicked);
 | 
			
		||||
    clickAction.connect('long-press', _onLongPress);
 | 
			
		||||
    entry.add_action(clickAction);
 | 
			
		||||
 | 
			
		||||
    entry.connect('popup-menu', _onPopup);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
@@ -50,11 +50,9 @@ function _setLabelsForMessage(dialog, message) {
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
function ListItem(app) {
 | 
			
		||||
    this._init(app);
 | 
			
		||||
}
 | 
			
		||||
const ListItem = new Lang.Class({
 | 
			
		||||
    Name: 'ListItem',
 | 
			
		||||
 | 
			
		||||
ListItem.prototype = {
 | 
			
		||||
    _init: function(app) {
 | 
			
		||||
        this._app = app;
 | 
			
		||||
 | 
			
		||||
@@ -86,14 +84,12 @@ ListItem.prototype = {
 | 
			
		||||
        this.emit('activate');
 | 
			
		||||
        this._app.activate();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(ListItem.prototype);
 | 
			
		||||
 | 
			
		||||
function ShellMountOperation(source, params) {
 | 
			
		||||
    this._init(source, params);
 | 
			
		||||
}
 | 
			
		||||
const ShellMountOperation = new Lang.Class({
 | 
			
		||||
    Name: 'ShellMountOperation',
 | 
			
		||||
 | 
			
		||||
ShellMountOperation.prototype = {
 | 
			
		||||
    _init: function(source, params) {
 | 
			
		||||
        params = Params.parse(params, { reaskPassword: false });
 | 
			
		||||
 | 
			
		||||
@@ -190,17 +186,14 @@ ShellMountOperation.prototype = {
 | 
			
		||||
 | 
			
		||||
        this._processesDialog.update(message, processes, choices);
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function ShellMountQuestionDialog(icon) {
 | 
			
		||||
    this._init(icon);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ShellMountQuestionDialog.prototype = {
 | 
			
		||||
    __proto__: ModalDialog.ModalDialog.prototype,
 | 
			
		||||
const ShellMountQuestionDialog = new Lang.Class({
 | 
			
		||||
    Name: 'ShellMountQuestionDialog',
 | 
			
		||||
    Extends: ModalDialog.ModalDialog,
 | 
			
		||||
 | 
			
		||||
    _init: function(icon) {
 | 
			
		||||
        ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'mount-question-dialog' });
 | 
			
		||||
        this.parent({ styleClass: 'mount-question-dialog' });
 | 
			
		||||
 | 
			
		||||
        let mainContentLayout = new St.BoxLayout();
 | 
			
		||||
        this.contentLayout.add(mainContentLayout, { x_fill: true,
 | 
			
		||||
@@ -236,19 +229,16 @@ ShellMountQuestionDialog.prototype = {
 | 
			
		||||
        _setLabelsForMessage(this, message);
 | 
			
		||||
        _setButtonsForChoices(this, choices);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(ShellMountQuestionDialog.prototype);
 | 
			
		||||
 | 
			
		||||
function ShellMountPasswordSource(message, icon, reaskPassword) {
 | 
			
		||||
    this._init(message, icon, reaskPassword);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ShellMountPasswordSource.prototype = {
 | 
			
		||||
    __proto__: MessageTray.Source.prototype,
 | 
			
		||||
const ShellMountPasswordSource = new Lang.Class({
 | 
			
		||||
    Name: 'ShellMountPasswordSource',
 | 
			
		||||
    Extends: MessageTray.Source,
 | 
			
		||||
 | 
			
		||||
    _init: function(message, icon, reaskPassword) {
 | 
			
		||||
        let strings = message.split('\n');
 | 
			
		||||
        MessageTray.Source.prototype._init.call(this, strings[0]);
 | 
			
		||||
        this.parent(strings[0]);
 | 
			
		||||
 | 
			
		||||
        this._notification = new ShellMountPasswordNotification(this, strings, icon, reaskPassword);
 | 
			
		||||
 | 
			
		||||
@@ -256,21 +246,15 @@ ShellMountPasswordSource.prototype = {
 | 
			
		||||
        Main.messageTray.add(this);
 | 
			
		||||
        this.notify(this._notification);
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(ShellMountPasswordSource.prototype);
 | 
			
		||||
 | 
			
		||||
function ShellMountPasswordNotification(source, strings, icon, reaskPassword) {
 | 
			
		||||
    this._init(source, strings, icon, reaskPassword);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ShellMountPasswordNotification.prototype = {
 | 
			
		||||
    __proto__: MessageTray.Notification.prototype,
 | 
			
		||||
const ShellMountPasswordNotification = new Lang.Class({
 | 
			
		||||
    Name: 'ShellMountPasswordNotification',
 | 
			
		||||
    Extends: MessageTray.Notification,
 | 
			
		||||
 | 
			
		||||
    _init: function(source, strings, icon, reaskPassword) {
 | 
			
		||||
        MessageTray.Notification.prototype._init.call(this, source,
 | 
			
		||||
                                                      strings[0], null,
 | 
			
		||||
                                                      { customContent: true,
 | 
			
		||||
                                                        icon: icon });
 | 
			
		||||
        this.parent(source, strings[0], null, { customContent: true, icon: icon });
 | 
			
		||||
 | 
			
		||||
        // set the notification to transient and urgent, so that it
 | 
			
		||||
        // expands out
 | 
			
		||||
@@ -305,17 +289,14 @@ ShellMountPasswordNotification.prototype = {
 | 
			
		||||
 | 
			
		||||
        this.source.emit('password-ready', text);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function ShellProcessesDialog(icon) {
 | 
			
		||||
    this._init(icon);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ShellProcessesDialog.prototype = {
 | 
			
		||||
    __proto__: ModalDialog.ModalDialog.prototype,
 | 
			
		||||
const ShellProcessesDialog = new Lang.Class({
 | 
			
		||||
    Name: 'ShellProcessesDialog',
 | 
			
		||||
    Extends: ModalDialog.ModalDialog,
 | 
			
		||||
 | 
			
		||||
    _init: function(icon) {
 | 
			
		||||
        ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'show-processes-dialog' });
 | 
			
		||||
        this.parent({ styleClass: 'show-processes-dialog' });
 | 
			
		||||
 | 
			
		||||
        let mainContentLayout = new St.BoxLayout();
 | 
			
		||||
        this.contentLayout.add(mainContentLayout, { x_fill: true,
 | 
			
		||||
@@ -401,5 +382,5 @@ ShellProcessesDialog.prototype = {
 | 
			
		||||
        _setLabelsForMessage(this, message);
 | 
			
		||||
        _setButtonsForChoices(this, choices);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(ShellProcessesDialog.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const GConf = imports.gi.GConf;
 | 
			
		||||
const GDesktopEnums = imports.gi.GDesktopEnums;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
@@ -30,8 +29,8 @@ const DPI_FACTOR_LARGE   = 1.25;
 | 
			
		||||
const DPI_FACTOR_LARGER  = 1.5;
 | 
			
		||||
const DPI_FACTOR_LARGEST = 2.0;
 | 
			
		||||
 | 
			
		||||
const KEY_META_DIR       = '/apps/metacity/general';
 | 
			
		||||
const KEY_VISUAL_BELL = KEY_META_DIR + '/visual_bell';
 | 
			
		||||
const WM_SCHEMA            = 'org.gnome.desktop.wm.preferences';
 | 
			
		||||
const KEY_VISUAL_BELL      = 'visual-bell';
 | 
			
		||||
 | 
			
		||||
const DESKTOP_INTERFACE_SCHEMA = 'org.gnome.desktop.interface';
 | 
			
		||||
const KEY_GTK_THEME      = 'gtk-theme';
 | 
			
		||||
@@ -40,19 +39,12 @@ const KEY_TEXT_SCALING_FACTOR = 'text-scaling-factor';
 | 
			
		||||
 | 
			
		||||
const HIGH_CONTRAST_THEME = 'HighContrast';
 | 
			
		||||
 | 
			
		||||
function ATIndicator() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ATIndicator.prototype = {
 | 
			
		||||
    __proto__: PanelMenu.SystemStatusButton.prototype,
 | 
			
		||||
const ATIndicator = new Lang.Class({
 | 
			
		||||
    Name: 'ATIndicator',
 | 
			
		||||
    Extends: PanelMenu.SystemStatusButton,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        PanelMenu.SystemStatusButton.prototype._init.call(this, 'preferences-desktop-accessibility', null);
 | 
			
		||||
 | 
			
		||||
        let client = GConf.Client.get_default();
 | 
			
		||||
        client.add_dir(KEY_META_DIR, GConf.ClientPreloadType.PRELOAD_ONELEVEL, null);
 | 
			
		||||
        client.notify_add(KEY_META_DIR, Lang.bind(this, this._keyChanged), null, null);
 | 
			
		||||
        this.parent('preferences-desktop-accessibility', null);
 | 
			
		||||
 | 
			
		||||
        let highContrast = this._buildHCItem();
 | 
			
		||||
        this.menu.addMenuItem(highContrast);
 | 
			
		||||
@@ -68,11 +60,11 @@ ATIndicator.prototype = {
 | 
			
		||||
//                                                               'screen-reader-enabled');
 | 
			
		||||
//        this.menu.addMenuItem(screenReader);
 | 
			
		||||
 | 
			
		||||
//        let screenKeyboard = this._buildItem(_("Screen Keyboard"), APPLICATIONS_SCHEMA,
 | 
			
		||||
//                                                                   'screen-keyboard-enabled');
 | 
			
		||||
//        this.menu.addMenuItem(screenKeyboard);
 | 
			
		||||
        let screenKeyboard = this._buildItem(_("Screen Keyboard"), APPLICATIONS_SCHEMA,
 | 
			
		||||
                                                                   'screen-keyboard-enabled');
 | 
			
		||||
        this.menu.addMenuItem(screenKeyboard);
 | 
			
		||||
 | 
			
		||||
        let visualBell = this._buildItemGConf(_("Visual Alerts"), client, KEY_VISUAL_BELL);
 | 
			
		||||
        let visualBell = this._buildItem(_("Visual Alerts"), WM_SCHEMA, KEY_VISUAL_BELL);
 | 
			
		||||
        this.menu.addMenuItem(visualBell);
 | 
			
		||||
 | 
			
		||||
        let stickyKeys = this._buildItem(_("Sticky Keys"), A11Y_SCHEMA, KEY_STICKY_KEYS_ENABLED);
 | 
			
		||||
@@ -102,22 +94,6 @@ ATIndicator.prototype = {
 | 
			
		||||
        return widget;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _buildItemGConf: function(string, client, key) {
 | 
			
		||||
        function on_get() {
 | 
			
		||||
            return client.get_bool(key);
 | 
			
		||||
        }
 | 
			
		||||
        let widget = this._buildItemExtended(string,
 | 
			
		||||
            client.get_bool(key),
 | 
			
		||||
            client.key_is_writable(key),
 | 
			
		||||
            function(enabled) {
 | 
			
		||||
                client.set_bool(key, enabled);
 | 
			
		||||
            });
 | 
			
		||||
        this.connect('gconf-changed', function() {
 | 
			
		||||
            widget.setToggleState(client.get_bool(key));
 | 
			
		||||
        });
 | 
			
		||||
        return widget;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _buildItem: function(string, schema, key) {
 | 
			
		||||
        let settings = new Gio.Settings({ schema: schema });
 | 
			
		||||
        let widget = this._buildItemExtended(string,
 | 
			
		||||
@@ -191,10 +167,5 @@ ATIndicator.prototype = {
 | 
			
		||||
            widget.setToggleState(active);
 | 
			
		||||
        });
 | 
			
		||||
        return widget;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _keyChanged: function() {
 | 
			
		||||
        this.emit('gconf-changed');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(ATIndicator.prototype);
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gdk = imports.gi.Gdk;
 | 
			
		||||
@@ -23,15 +23,12 @@ const ConnectionState = {
 | 
			
		||||
    CONNECTING: 3
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function Indicator() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Indicator.prototype = {
 | 
			
		||||
    __proto__: PanelMenu.SystemStatusButton.prototype,
 | 
			
		||||
const Indicator = new Lang.Class({
 | 
			
		||||
    Name: 'BTIndicator',
 | 
			
		||||
    Extends: PanelMenu.SystemStatusButton,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        PanelMenu.SystemStatusButton.prototype._init.call(this, 'bluetooth-disabled', null);
 | 
			
		||||
        this.parent('bluetooth-disabled', null);
 | 
			
		||||
 | 
			
		||||
        GLib.spawn_command_line_sync ('pkill -f "^bluetooth-applet$"');
 | 
			
		||||
        this._applet = new GnomeBluetoothApplet.Applet();
 | 
			
		||||
@@ -204,9 +201,10 @@ Indicator.prototype = {
 | 
			
		||||
 | 
			
		||||
    _buildDeviceSubMenu: function(item, device) {
 | 
			
		||||
        if (device.can_connect) {
 | 
			
		||||
            let menuitem = new PopupMenu.PopupSwitchMenuItem(_("Connection"), device.connected);
 | 
			
		||||
            item._connected = device.connected;
 | 
			
		||||
            item._connectedMenuitem = new PopupMenu.PopupSwitchMenuItem(_("Connection"), device.connected);
 | 
			
		||||
            item._connectedMenuitem.connect('toggled', Lang.bind(this, function() {
 | 
			
		||||
            item._connectedMenuItem = menuitem;
 | 
			
		||||
            menuitem.connect('toggled', Lang.bind(this, function() {
 | 
			
		||||
                if (item._connected > ConnectionState.CONNECTED) {
 | 
			
		||||
                    // operation already in progress, revert
 | 
			
		||||
                    // (should not happen anyway)
 | 
			
		||||
@@ -241,7 +239,7 @@ Indicator.prototype = {
 | 
			
		||||
                }
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
            item.menu.addMenuItem(item._connectedMenuitem);
 | 
			
		||||
            item.menu.addMenuItem(menuitem);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (device.capabilities & GnomeBluetoothApplet.Capabilities.OBEX_PUSH) {
 | 
			
		||||
@@ -334,17 +332,14 @@ Indicator.prototype = {
 | 
			
		||||
    _cancelRequest: function() {
 | 
			
		||||
        this._source.destroy();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function Source() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Source.prototype = {
 | 
			
		||||
    __proto__: MessageTray.Source.prototype,
 | 
			
		||||
const Source = new Lang.Class({
 | 
			
		||||
    Name: 'BluetoothSource',
 | 
			
		||||
    Extends: MessageTray.Source,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        MessageTray.Source.prototype._init.call(this, _("Bluetooth"));
 | 
			
		||||
        this.parent(_("Bluetooth"));
 | 
			
		||||
 | 
			
		||||
        this._setSummaryIcon(this.createNotificationIcon());
 | 
			
		||||
    },
 | 
			
		||||
@@ -358,7 +353,7 @@ Source.prototype = {
 | 
			
		||||
            }
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        MessageTray.Source.prototype.notify.call(this, notification);
 | 
			
		||||
        this.parent(notification);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    createNotificationIcon: function() {
 | 
			
		||||
@@ -366,21 +361,17 @@ Source.prototype = {
 | 
			
		||||
                             icon_type: St.IconType.SYMBOLIC,
 | 
			
		||||
                             icon_size: this.ICON_SIZE });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function AuthNotification() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AuthNotification.prototype = {
 | 
			
		||||
    __proto__: MessageTray.Notification.prototype,
 | 
			
		||||
const AuthNotification = new Lang.Class({
 | 
			
		||||
    Name: 'AuthNotification',
 | 
			
		||||
    Extends: MessageTray.Notification,
 | 
			
		||||
 | 
			
		||||
    _init: function(source, applet, device_path, name, long_name, uuid) {
 | 
			
		||||
        MessageTray.Notification.prototype._init.call(this,
 | 
			
		||||
                                                      source,
 | 
			
		||||
                                                      _("Bluetooth"),
 | 
			
		||||
                                                      _("Authorization request from %s").format(name),
 | 
			
		||||
                                                      { customContent: true });
 | 
			
		||||
        this.parent(source,
 | 
			
		||||
                    _("Bluetooth"),
 | 
			
		||||
                    _("Authorization request from %s").format(name),
 | 
			
		||||
                    { customContent: true });
 | 
			
		||||
        this.setResident(true);
 | 
			
		||||
 | 
			
		||||
        this._applet = applet;
 | 
			
		||||
@@ -406,21 +397,17 @@ AuthNotification.prototype = {
 | 
			
		||||
            this.destroy();
 | 
			
		||||
        }));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function ConfirmNotification() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ConfirmNotification.prototype = {
 | 
			
		||||
    __proto__: MessageTray.Notification.prototype,
 | 
			
		||||
const ConfirmNotification = new Lang.Class({
 | 
			
		||||
    Name: 'ConfirmNotification',
 | 
			
		||||
    Extends: MessageTray.Notification,
 | 
			
		||||
 | 
			
		||||
    _init: function(source, applet, device_path, name, long_name, pin) {
 | 
			
		||||
        MessageTray.Notification.prototype._init.call(this,
 | 
			
		||||
                                                      source,
 | 
			
		||||
                                                      _("Bluetooth"),
 | 
			
		||||
                                                      _("Pairing confirmation for %s").format(name),
 | 
			
		||||
                                                      { customContent: true });
 | 
			
		||||
        this.parent(source,
 | 
			
		||||
                    _("Bluetooth"),
 | 
			
		||||
                    _("Pairing confirmation for %s").format(name),
 | 
			
		||||
                    { customContent: true });
 | 
			
		||||
        this.setResident(true);
 | 
			
		||||
 | 
			
		||||
        this._applet = applet;
 | 
			
		||||
@@ -439,21 +426,17 @@ ConfirmNotification.prototype = {
 | 
			
		||||
            this.destroy();
 | 
			
		||||
        }));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function PinNotification() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PinNotification.prototype = {
 | 
			
		||||
    __proto__: MessageTray.Notification.prototype,
 | 
			
		||||
const PinNotification = new Lang.Class({
 | 
			
		||||
    Name: 'PinNotification',
 | 
			
		||||
    Extends: MessageTray.Notification,
 | 
			
		||||
 | 
			
		||||
    _init: function(source, applet, device_path, name, long_name, numeric) {
 | 
			
		||||
        MessageTray.Notification.prototype._init.call(this,
 | 
			
		||||
                                                      source,
 | 
			
		||||
                                                      _("Bluetooth"),
 | 
			
		||||
                                                      _("Pairing request for %s").format(name),
 | 
			
		||||
                                                      { customContent: true });
 | 
			
		||||
        this.parent(source,
 | 
			
		||||
                    _("Bluetooth"),
 | 
			
		||||
                    _("Pairing request for %s").format(name),
 | 
			
		||||
                    { customContent: true });
 | 
			
		||||
        this.setResident(true);
 | 
			
		||||
 | 
			
		||||
        this._applet = applet;
 | 
			
		||||
@@ -502,7 +485,7 @@ PinNotification.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    grabFocus: function(lockTray) {
 | 
			
		||||
        MessageTray.Notification.prototype.grabFocus.call(this, lockTray);
 | 
			
		||||
        this.parent(lockTray);
 | 
			
		||||
        global.stage.set_key_focus(this._entry);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GdkPixbuf = imports.gi.GdkPixbuf;
 | 
			
		||||
@@ -14,15 +14,12 @@ const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
const PanelMenu = imports.ui.panelMenu;
 | 
			
		||||
const Util = imports.misc.util;
 | 
			
		||||
 | 
			
		||||
function LayoutMenuItem() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LayoutMenuItem.prototype = {
 | 
			
		||||
    __proto__: PopupMenu.PopupBaseMenuItem.prototype,
 | 
			
		||||
const LayoutMenuItem = new Lang.Class({
 | 
			
		||||
    Name: 'LayoutMenuItem',
 | 
			
		||||
    Extends: PopupMenu.PopupBaseMenuItem,
 | 
			
		||||
 | 
			
		||||
    _init: function(config, id, indicator, long_name) {
 | 
			
		||||
        PopupMenu.PopupBaseMenuItem.prototype._init.call(this);
 | 
			
		||||
        this.parent();
 | 
			
		||||
 | 
			
		||||
        this._config = config;
 | 
			
		||||
        this._id = id;
 | 
			
		||||
@@ -33,26 +30,25 @@ LayoutMenuItem.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    activate: function(event) {
 | 
			
		||||
        PopupMenu.PopupBaseMenuItem.prototype.activate.call(this);
 | 
			
		||||
        this.parent(event);
 | 
			
		||||
 | 
			
		||||
        this._config.lock_group(this._id);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function XKBIndicator() {
 | 
			
		||||
    this._init.call(this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
XKBIndicator.prototype = {
 | 
			
		||||
    __proto__: PanelMenu.Button.prototype,
 | 
			
		||||
const XKBIndicator = new Lang.Class({
 | 
			
		||||
    Name: 'XKBIndicator',
 | 
			
		||||
    Extends: PanelMenu.Button,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        PanelMenu.Button.prototype._init.call(this, St.Align.START);
 | 
			
		||||
        this.parent(0.0);
 | 
			
		||||
 | 
			
		||||
        this._container = new Shell.GenericContainer();
 | 
			
		||||
        this._container.connect('get-preferred-width', Lang.bind(this, this._get_preferred_width));
 | 
			
		||||
        this._container.connect('get-preferred-height', Lang.bind(this, this._get_preferred_height));
 | 
			
		||||
        this._container.connect('allocate', Lang.bind(this, this._allocate));
 | 
			
		||||
        this.actor.set_child(this._container);
 | 
			
		||||
        this._container.connect('get-preferred-width', Lang.bind(this, this._containerGetPreferredWidth));
 | 
			
		||||
        this._container.connect('get-preferred-height', Lang.bind(this, this._containerGetPreferredHeight));
 | 
			
		||||
        this._container.connect('allocate', Lang.bind(this, this._containerAllocate));
 | 
			
		||||
        this.actor.add_actor(this._container);
 | 
			
		||||
        this.actor.add_style_class_name('panel-status-button');
 | 
			
		||||
 | 
			
		||||
        this._iconActor = new St.Icon({ icon_name: 'keyboard', icon_type: St.IconType.SYMBOLIC, style_class: 'system-status-icon' });
 | 
			
		||||
        this._container.add_actor(this._iconActor);
 | 
			
		||||
@@ -61,21 +57,23 @@ XKBIndicator.prototype = {
 | 
			
		||||
 | 
			
		||||
        this._showFlags = false;
 | 
			
		||||
        this._config = Gkbd.Configuration.get();
 | 
			
		||||
        this._config.connect('changed', Lang.bind(this, this._sync_config));
 | 
			
		||||
        this._config.connect('group-changed', Lang.bind(this, this._sync_group));
 | 
			
		||||
        this._config.connect('changed', Lang.bind(this, this._syncConfig));
 | 
			
		||||
        this._config.connect('group-changed', Lang.bind(this, this._syncGroup));
 | 
			
		||||
        this._config.start_listen();
 | 
			
		||||
 | 
			
		||||
        this._sync_config();
 | 
			
		||||
        this._syncConfig();
 | 
			
		||||
 | 
			
		||||
        this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
 | 
			
		||||
        this.menu.addAction(_("Show Keyboard Layout"), Lang.bind(this, function() {
 | 
			
		||||
            Main.overview.hide();
 | 
			
		||||
            Util.spawn(['gkbd-keyboard-display', '-g', String(this._config.get_current_group() + 1)]);
 | 
			
		||||
        }));
 | 
			
		||||
        if (global.session_type == Shell.SessionType.USER) {
 | 
			
		||||
            this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
 | 
			
		||||
            this.menu.addAction(_("Show Keyboard Layout"), Lang.bind(this, function() {
 | 
			
		||||
                Main.overview.hide();
 | 
			
		||||
                Util.spawn(['gkbd-keyboard-display', '-g', String(this._config.get_current_group() + 1)]);
 | 
			
		||||
            }));
 | 
			
		||||
        }
 | 
			
		||||
        this.menu.addSettingsAction(_("Region and Language Settings"), 'gnome-region-panel.desktop');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _adjust_group_names: function(names) {
 | 
			
		||||
    _adjustGroupNames: function(names) {
 | 
			
		||||
        // Disambiguate duplicate names with a subscript
 | 
			
		||||
        // This is O(N^2) to avoid sorting names
 | 
			
		||||
        // but N <= 4 so who cares?
 | 
			
		||||
@@ -97,7 +95,7 @@ XKBIndicator.prototype = {
 | 
			
		||||
        return names;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _sync_config: function() {
 | 
			
		||||
    _syncConfig: function() {
 | 
			
		||||
        this._showFlags = this._config.if_flags_shown();
 | 
			
		||||
        if (this._showFlags) {
 | 
			
		||||
            this._container.set_skip_paint(this._iconActor, false);
 | 
			
		||||
@@ -119,7 +117,7 @@ XKBIndicator.prototype = {
 | 
			
		||||
        for (let i = 0; i < this._labelActors.length; i++)
 | 
			
		||||
            this._labelActors[i].destroy();
 | 
			
		||||
 | 
			
		||||
        let short_names = this._adjust_group_names(this._config.get_short_group_names());
 | 
			
		||||
        let short_names = this._adjustGroupNames(this._config.get_short_group_names());
 | 
			
		||||
 | 
			
		||||
        this._selectedLayout = null;
 | 
			
		||||
        this._layoutItems = [ ];
 | 
			
		||||
@@ -144,10 +142,10 @@ XKBIndicator.prototype = {
 | 
			
		||||
            this._container.set_skip_paint(shortLabel, true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._sync_group();
 | 
			
		||||
        this._syncGroup();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _sync_group: function() {
 | 
			
		||||
    _syncGroup: function() {
 | 
			
		||||
        let selected = this._config.get_current_group();
 | 
			
		||||
 | 
			
		||||
        if (this._selectedLayout) {
 | 
			
		||||
@@ -170,10 +168,10 @@ XKBIndicator.prototype = {
 | 
			
		||||
        this._selectedLayout = item;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _get_preferred_width: function(container, for_height, alloc) {
 | 
			
		||||
        /* Here, and in _get_preferred_height, we need to query for the
 | 
			
		||||
           height of all children, but we ignore the results for those
 | 
			
		||||
           we don't actually display. */
 | 
			
		||||
    _containerGetPreferredWidth: function(container, for_height, alloc) {
 | 
			
		||||
        // Here, and in _containerGetPreferredHeight, we need to query
 | 
			
		||||
        // for the height of all children, but we ignore the results
 | 
			
		||||
        // for those we don't actually display.
 | 
			
		||||
        let max_min_width = 0, max_natural_width = 0;
 | 
			
		||||
        if (this._showFlags)
 | 
			
		||||
            [max_min_width, max_natural_width] = this._iconActor.get_preferred_width(for_height);
 | 
			
		||||
@@ -190,7 +188,7 @@ XKBIndicator.prototype = {
 | 
			
		||||
        alloc.natural_size = max_natural_width;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _get_preferred_height: function(container, for_width, alloc) {
 | 
			
		||||
    _containerGetPreferredHeight: function(container, for_width, alloc) {
 | 
			
		||||
        let max_min_height = 0, max_natural_height = 0;
 | 
			
		||||
        if (this._showFlags)
 | 
			
		||||
            [max_min_height, max_natural_height] = this._iconActor.get_preferred_height(for_width);
 | 
			
		||||
@@ -207,7 +205,7 @@ XKBIndicator.prototype = {
 | 
			
		||||
        alloc.natural_size = max_natural_height;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _allocate: function(container, box, flags) {
 | 
			
		||||
    _containerAllocate: function(container, box, flags) {
 | 
			
		||||
        // translate box to (0, 0)
 | 
			
		||||
        box.x2 -= box.x1;
 | 
			
		||||
        box.x1 = 0;
 | 
			
		||||
@@ -218,4 +216,4 @@ XKBIndicator.prototype = {
 | 
			
		||||
        for (let i = 0; i < this._labelActors.length; i++)
 | 
			
		||||
            this._labelActors[i].allocate_align_fill(box, 0.5, 0, false, false, flags);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
const ByteArray = imports.byteArray;
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const GObject = imports.gi.GObject;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
@@ -98,15 +97,12 @@ function ssidToLabel(ssid) {
 | 
			
		||||
    return label;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function NMNetworkMenuItem() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NMNetworkMenuItem.prototype = {
 | 
			
		||||
    __proto__: PopupMenu.PopupBaseMenuItem.prototype,
 | 
			
		||||
const NMNetworkMenuItem = new Lang.Class({
 | 
			
		||||
    Name: 'NMNetworkMenuItem',
 | 
			
		||||
    Extends: PopupMenu.PopupBaseMenuItem,
 | 
			
		||||
 | 
			
		||||
    _init: function(accessPoints, title, params) {
 | 
			
		||||
        PopupMenu.PopupBaseMenuItem.prototype._init.call(this, params);
 | 
			
		||||
        this.parent(params);
 | 
			
		||||
 | 
			
		||||
        accessPoints = sortAccessPoints(accessPoints);
 | 
			
		||||
        this.bestAP = accessPoints[0];
 | 
			
		||||
@@ -185,21 +181,18 @@ NMNetworkMenuItem.prototype = {
 | 
			
		||||
            apObj.updateId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        PopupMenu.PopupBaseMenuItem.prototype.destroy.call(this);
 | 
			
		||||
        this.parent();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function NMWiredSectionTitleMenuItem() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NMWiredSectionTitleMenuItem.prototype = {
 | 
			
		||||
    __proto__: PopupMenu.PopupSwitchMenuItem.prototype,
 | 
			
		||||
const NMWiredSectionTitleMenuItem = new Lang.Class({
 | 
			
		||||
    Name: 'NMWiredSectionTitleMenuItem',
 | 
			
		||||
    Extends: PopupMenu.PopupSwitchMenuItem,
 | 
			
		||||
 | 
			
		||||
    _init: function(label, params) {
 | 
			
		||||
        params = params || { };
 | 
			
		||||
        params.style_class = 'popup-subtitle-menu-item';
 | 
			
		||||
        PopupMenu.PopupSwitchMenuItem.prototype._init.call(this, label, false, params);
 | 
			
		||||
        this.parent(label, false, params);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    updateForDevice: function(device) {
 | 
			
		||||
@@ -212,7 +205,7 @@ NMWiredSectionTitleMenuItem.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    activate: function(event) {
 | 
			
		||||
        PopupMenu.PopupSwitchMenuItem.prototype.activate.call(this, event);
 | 
			
		||||
        this.parent(event);
 | 
			
		||||
 | 
			
		||||
        if (!this._device) {
 | 
			
		||||
            log('Section title activated when there is more than one device, should be non reactive');
 | 
			
		||||
@@ -231,19 +224,16 @@ NMWiredSectionTitleMenuItem.prototype = {
 | 
			
		||||
        else
 | 
			
		||||
            this._device.deactivate();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function NMWirelessSectionTitleMenuItem() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NMWirelessSectionTitleMenuItem.prototype = {
 | 
			
		||||
    __proto__: PopupMenu.PopupSwitchMenuItem.prototype,
 | 
			
		||||
const NMWirelessSectionTitleMenuItem = new Lang.Class({
 | 
			
		||||
    Name: 'NMWirelessSectionTitleMenuItem',
 | 
			
		||||
    Extends: PopupMenu.PopupSwitchMenuItem,
 | 
			
		||||
 | 
			
		||||
    _init: function(client, property, title, params) {
 | 
			
		||||
        params = params || { };
 | 
			
		||||
        params.style_class = 'popup-subtitle-menu-item';
 | 
			
		||||
        PopupMenu.PopupSwitchMenuItem.prototype._init.call(this, title, false, params);
 | 
			
		||||
        this.parent(title, false, params);
 | 
			
		||||
 | 
			
		||||
        this._client = client;
 | 
			
		||||
        this._property = property + '_enabled';
 | 
			
		||||
@@ -269,7 +259,7 @@ NMWirelessSectionTitleMenuItem.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    activate: function(event) {
 | 
			
		||||
        PopupMenu.PopupSwitchMenuItem.prototype.activate.call(this, event);
 | 
			
		||||
        this.parent(event);
 | 
			
		||||
 | 
			
		||||
        this._client[this._setEnabledFunc](this._switch.state);
 | 
			
		||||
    },
 | 
			
		||||
@@ -286,13 +276,12 @@ NMWirelessSectionTitleMenuItem.prototype = {
 | 
			
		||||
 | 
			
		||||
        this.emit('enabled-changed', enabled);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function NMDevice() {
 | 
			
		||||
    throw new TypeError('Instantanting abstract class NMDevice');
 | 
			
		||||
}
 | 
			
		||||
const NMDevice = new Lang.Class({
 | 
			
		||||
    Name: 'NMDevice',
 | 
			
		||||
    Abstract: true,
 | 
			
		||||
 | 
			
		||||
NMDevice.prototype = {
 | 
			
		||||
    _init: function(client, device, connections) {
 | 
			
		||||
        this.device = device;
 | 
			
		||||
        if (device) {
 | 
			
		||||
@@ -674,26 +663,23 @@ NMDevice.prototype = {
 | 
			
		||||
 | 
			
		||||
        return out;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(NMDevice.prototype);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function NMDeviceWired() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NMDeviceWired.prototype = {
 | 
			
		||||
    __proto__: NMDevice.prototype,
 | 
			
		||||
const NMDeviceWired = new Lang.Class({
 | 
			
		||||
    Name: 'NMDeviceWired',
 | 
			
		||||
    Extends: NMDevice,
 | 
			
		||||
 | 
			
		||||
    _init: function(client, device, connections) {
 | 
			
		||||
        this._autoConnectionName = _("Auto Ethernet");
 | 
			
		||||
        this.category = NMConnectionCategory.WIRED;
 | 
			
		||||
 | 
			
		||||
        NMDevice.prototype._init.call(this, client, device, connections);
 | 
			
		||||
        this.parent(client, device, connections);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createSection: function() {
 | 
			
		||||
        NMDevice.prototype._createSection.call(this);
 | 
			
		||||
        this.parent();
 | 
			
		||||
 | 
			
		||||
        // if we have only one connection (normal or automatic)
 | 
			
		||||
        // we hide the connection list, and use the switch to control
 | 
			
		||||
@@ -718,14 +704,11 @@ NMDeviceWired.prototype = {
 | 
			
		||||
        }));
 | 
			
		||||
        return connection;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function NMDeviceModem() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NMDeviceModem.prototype = {
 | 
			
		||||
    __proto__: NMDevice.prototype,
 | 
			
		||||
const NMDeviceModem = new Lang.Class({
 | 
			
		||||
    Name: 'NMDeviceModem',
 | 
			
		||||
    Extends: NMDevice,
 | 
			
		||||
 | 
			
		||||
    _init: function(client, device, connections) {
 | 
			
		||||
        let is_wwan = false;
 | 
			
		||||
@@ -774,7 +757,7 @@ NMDeviceModem.prototype = {
 | 
			
		||||
            }));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        NMDevice.prototype._init.call(this, client, device, connections);
 | 
			
		||||
        this.parent(client, device, connections);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setEnabled: function(enabled) {
 | 
			
		||||
@@ -787,7 +770,7 @@ NMDeviceModem.prototype = {
 | 
			
		||||
                this.statusItem.setStatus(this.getStatusLabel());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        NMDevice.prototype.setEnabled.call(this, enabled);
 | 
			
		||||
        this.parent(enabled);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get connected() {
 | 
			
		||||
@@ -804,7 +787,7 @@ NMDeviceModem.prototype = {
 | 
			
		||||
            this._signalQualityId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        NMDevice.prototype.destroy.call(this);
 | 
			
		||||
        this.parent();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getSignalIcon: function() {
 | 
			
		||||
@@ -825,13 +808,13 @@ NMDeviceModem.prototype = {
 | 
			
		||||
            this.section.addMenuItem(this._operatorItem);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        NMDevice.prototype._createSection.call(this);
 | 
			
		||||
        this.parent();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _clearSection: function() {
 | 
			
		||||
        this._operatorItem = null;
 | 
			
		||||
 | 
			
		||||
        NMDevice.prototype._clearSection.call(this);
 | 
			
		||||
        this.parent();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createAutomaticConnection: function() {
 | 
			
		||||
@@ -841,14 +824,11 @@ NMDeviceModem.prototype = {
 | 
			
		||||
                    'connect-3g', this.device.get_path()]);
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function NMDeviceBluetooth() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NMDeviceBluetooth.prototype = {
 | 
			
		||||
    __proto__: NMDevice.prototype,
 | 
			
		||||
const NMDeviceBluetooth = new Lang.Class({
 | 
			
		||||
    Name: 'NMDeviceBluetooth',
 | 
			
		||||
    Extends: NMDevice,
 | 
			
		||||
 | 
			
		||||
    _init: function(client, device, connections) {
 | 
			
		||||
        this._autoConnectionName = this._makeConnectionName(device);
 | 
			
		||||
@@ -856,7 +836,7 @@ NMDeviceBluetooth.prototype = {
 | 
			
		||||
 | 
			
		||||
        this.category = NMConnectionCategory.WWAN;
 | 
			
		||||
 | 
			
		||||
        NMDevice.prototype._init.call(this, client, device, connections);
 | 
			
		||||
        this.parent(client, device, connections);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createAutomaticConnection: function() {
 | 
			
		||||
@@ -886,23 +866,20 @@ NMDeviceBluetooth.prototype = {
 | 
			
		||||
        this._clearSection();
 | 
			
		||||
        this._createSection();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Not a real device, but I save a lot code this way
 | 
			
		||||
function NMDeviceVPN() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NMDeviceVPN.prototype = {
 | 
			
		||||
    __proto__: NMDevice.prototype,
 | 
			
		||||
const NMDeviceVPN = new Lang.Class({
 | 
			
		||||
    Name: 'NMDeviceVPN',
 | 
			
		||||
    Extends: NMDevice,
 | 
			
		||||
 | 
			
		||||
    _init: function(client) {
 | 
			
		||||
        // Disable autoconnections
 | 
			
		||||
        this._autoConnectionName = null;
 | 
			
		||||
        this.category = NMConnectionCategory.VPN;
 | 
			
		||||
 | 
			
		||||
        NMDevice.prototype._init.call(this, client, null, [ ]);
 | 
			
		||||
        this.parent(client, null, [ ]);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    connectionValid: function(connection) {
 | 
			
		||||
@@ -918,7 +895,7 @@ NMDeviceVPN.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setActiveConnection: function(activeConnection) {
 | 
			
		||||
        NMDevice.prototype.setActiveConnection.call(this, activeConnection);
 | 
			
		||||
        this.parent(activeConnection);
 | 
			
		||||
 | 
			
		||||
        this.emit('active-connection-changed');
 | 
			
		||||
    },
 | 
			
		||||
@@ -935,14 +912,11 @@ NMDeviceVPN.prototype = {
 | 
			
		||||
    getStatusLabel: function() {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function NMDeviceWireless() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NMDeviceWireless.prototype = {
 | 
			
		||||
    __proto__: NMDevice.prototype,
 | 
			
		||||
const NMDeviceWireless = new Lang.Class({
 | 
			
		||||
    Name: 'NMDeviceWireless',
 | 
			
		||||
    Extends: NMDevice,
 | 
			
		||||
 | 
			
		||||
    _init: function(client, device, connections) {
 | 
			
		||||
        this.category = NMConnectionCategory.WIRELESS;
 | 
			
		||||
@@ -1014,7 +988,7 @@ NMDeviceWireless.prototype = {
 | 
			
		||||
        this._apAddedId = device.connect('access-point-added', Lang.bind(this, this._accessPointAdded));
 | 
			
		||||
        this._apRemovedId = device.connect('access-point-removed', Lang.bind(this, this._accessPointRemoved));
 | 
			
		||||
 | 
			
		||||
        NMDevice.prototype._init.call(this, client, device, validConnections);
 | 
			
		||||
        this.parent(client, device, validConnections);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    destroy: function() {
 | 
			
		||||
@@ -1034,7 +1008,7 @@ NMDeviceWireless.prototype = {
 | 
			
		||||
            this._apRemovedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        NMDevice.prototype.destroy.call(this);
 | 
			
		||||
        this.parent();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setEnabled: function(enabled) {
 | 
			
		||||
@@ -1104,10 +1078,10 @@ NMDeviceWireless.prototype = {
 | 
			
		||||
        let activeAp = this.device.active_access_point;
 | 
			
		||||
 | 
			
		||||
        if (activeAp) {
 | 
			
		||||
            let pos = this._findNetwork(activeAp);
 | 
			
		||||
            let res = this._findExistingNetwork(activeAp);
 | 
			
		||||
 | 
			
		||||
            if (pos != -1)
 | 
			
		||||
                this._activeNetwork = this._networks[pos];
 | 
			
		||||
            if (res != null)
 | 
			
		||||
                this._activeNetwork = this._networks[res.network];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // we don't refresh the view here, setActiveConnection will
 | 
			
		||||
@@ -1181,6 +1155,18 @@ NMDeviceWireless.prototype = {
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _findExistingNetwork: function(accessPoint) {
 | 
			
		||||
        for (let i = 0; i < this._networks.length; i++) {
 | 
			
		||||
            let apObj = this._networks[i];
 | 
			
		||||
            for (let j = 0; j < apObj.accessPoints.length; j++) {
 | 
			
		||||
                if (apObj.accessPoints[j] == accessPoint)
 | 
			
		||||
                    return { network: i, ap: j };
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _findNetwork: function(accessPoint) {
 | 
			
		||||
        if (accessPoint.get_ssid() == null)
 | 
			
		||||
            return -1;
 | 
			
		||||
@@ -1273,24 +1259,20 @@ NMDeviceWireless.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _accessPointRemoved: function(device, accessPoint) {
 | 
			
		||||
        let pos = this._findNetwork(accessPoint);
 | 
			
		||||
        let res = this._findExistingNetwork(accessPoint);
 | 
			
		||||
 | 
			
		||||
        if (pos == -1) {
 | 
			
		||||
        if (res == null) {
 | 
			
		||||
            log('Removing an access point that was never added');
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let apObj = this._networks[pos];
 | 
			
		||||
        let i = apObj.accessPoints.indexOf(accessPoint);
 | 
			
		||||
 | 
			
		||||
        if (i == -1) {
 | 
			
		||||
            log('Removing an access point that was never added');
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        apObj.accessPoints.splice(i, 1);
 | 
			
		||||
        let apObj = this._networks[res.network];
 | 
			
		||||
        apObj.accessPoints.splice(res.ap, 1);
 | 
			
		||||
 | 
			
		||||
        if (apObj.accessPoints.length == 0) {
 | 
			
		||||
            if (this._activeNetwork == apObj)
 | 
			
		||||
                this._activeNetwork = null;
 | 
			
		||||
 | 
			
		||||
            if (apObj.item)
 | 
			
		||||
                apObj.item.destroy();
 | 
			
		||||
 | 
			
		||||
@@ -1299,22 +1281,26 @@ NMDeviceWireless.prototype = {
 | 
			
		||||
                    // we removed an item in the main menu, and we have a more submenu
 | 
			
		||||
                    // we need to extract the first item in more and move it to the submenu
 | 
			
		||||
 | 
			
		||||
                    let apObj = this._overflowItem.menu.firstMenuItem;
 | 
			
		||||
                    if (apObj.item) {
 | 
			
		||||
                        apObj.item.destroy();
 | 
			
		||||
                    let item = this._overflowItem.menu.firstMenuItem;
 | 
			
		||||
                    if (item && item._apObj) {
 | 
			
		||||
                        item.destroy();
 | 
			
		||||
                        // clear the cycle, and allow the construction of the new item
 | 
			
		||||
                        item._apObj.item = null;
 | 
			
		||||
 | 
			
		||||
                        this._createNetworkItem(apObj, NUM_VISIBLE_NETWORKS-1);
 | 
			
		||||
                        this._createNetworkItem(item._apObj, NUM_VISIBLE_NETWORKS-1);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        log('The more... menu was existing and empty! This should not happen');
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // This can happen if the removed connection is from the overflow
 | 
			
		||||
                // menu, or if we just moved the last connection out from the menu
 | 
			
		||||
                if (this._overflowItem.menu.length == 0) {
 | 
			
		||||
                if (this._overflowItem.menu.numMenuItems == 0) {
 | 
			
		||||
                    this._overflowItem.destroy();
 | 
			
		||||
                    this._overflowItem = null;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            this._networks.splice(pos, 1);
 | 
			
		||||
            this._networks.splice(res.network, 1);
 | 
			
		||||
 | 
			
		||||
        } else if (apObj.item)
 | 
			
		||||
            apObj.item.updateAccessPoints(apObj.accessPoints);
 | 
			
		||||
@@ -1336,7 +1322,7 @@ NMDeviceWireless.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _clearSection: function() {
 | 
			
		||||
        NMDevice.prototype._clearSection.call(this);
 | 
			
		||||
        this.parent();
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < this._networks.length; i++)
 | 
			
		||||
            this._networks[i].item = null;
 | 
			
		||||
@@ -1480,19 +1466,22 @@ NMDeviceWireless.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createNetworkItem: function(apObj, position) {
 | 
			
		||||
        if(!apObj.accessPoints || apObj.accessPoints.length == 0) {
 | 
			
		||||
            // this should not happen, but I have no idea why it happens
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(apObj.connections.length > 0) {
 | 
			
		||||
            if (apObj.connections.length == 1)
 | 
			
		||||
            if (apObj.connections.length == 1) {
 | 
			
		||||
                apObj.item = this._createAPItem(apObj.connections[0], apObj, false);
 | 
			
		||||
            else {
 | 
			
		||||
            } else {
 | 
			
		||||
                let title = apObj.ssidText;
 | 
			
		||||
                apObj.item = new PopupMenu.PopupSubMenuMenuItem(title);
 | 
			
		||||
                apObj.item._apObj = apObj;
 | 
			
		||||
                for (let i = 0; i < apObj.connections.length; i++)
 | 
			
		||||
                    apObj.item.menu.addMenuItem(this._createAPItem(apObj.connections[i], apObj, true));
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            apObj.item = new NMNetworkMenuItem(apObj.accessPoints);
 | 
			
		||||
            apObj.item._apObj = apObj;
 | 
			
		||||
            apObj.item.connect('activate', Lang.bind(this, function() {
 | 
			
		||||
                let accessPoints = sortAccessPoints(apObj.accessPoints);
 | 
			
		||||
                if (   (accessPoints[0]._secType == NMAccessPointSecurity.WPA2_ENT)
 | 
			
		||||
@@ -1507,6 +1496,8 @@ NMDeviceWireless.prototype = {
 | 
			
		||||
                }
 | 
			
		||||
            }));
 | 
			
		||||
        }
 | 
			
		||||
        apObj.item._apObj = apObj;
 | 
			
		||||
 | 
			
		||||
        if (position < NUM_VISIBLE_NETWORKS) {
 | 
			
		||||
            apObj.isMore = false;
 | 
			
		||||
            this.section.addMenuItem(apObj.item, position);
 | 
			
		||||
@@ -1539,16 +1530,14 @@ NMDeviceWireless.prototype = {
 | 
			
		||||
            this._createNetworkItem(apObj, j + activeOffset);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function NMApplet() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
NMApplet.prototype = {
 | 
			
		||||
    __proto__: PanelMenu.SystemStatusButton.prototype,
 | 
			
		||||
const NMApplet = new Lang.Class({
 | 
			
		||||
    Name: 'NMApplet',
 | 
			
		||||
    Extends: PanelMenu.SystemStatusButton,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        PanelMenu.SystemStatusButton.prototype._init.call(this, 'network-error');
 | 
			
		||||
        this.parent('network-error', null);
 | 
			
		||||
 | 
			
		||||
        this._client = NMClient.Client.new();
 | 
			
		||||
 | 
			
		||||
@@ -1742,13 +1731,6 @@ NMApplet.prototype = {
 | 
			
		||||
        if (wrapperClass) {
 | 
			
		||||
            let wrapper = new wrapperClass(this._client, device, this._connections);
 | 
			
		||||
 | 
			
		||||
            wrapper._networkLostId = wrapper.connect('network-lost', Lang.bind(this, function(device) {
 | 
			
		||||
                this._notifyForDevice(device, 'network-offline',
 | 
			
		||||
                                      _("Connectivity lost"),
 | 
			
		||||
                                      _("You are no longer connected to the network"),
 | 
			
		||||
                                      // set critical urgency to popup the notification automatically
 | 
			
		||||
                                      MessageTray.Urgency.CRITICAL);
 | 
			
		||||
            }));
 | 
			
		||||
            wrapper._activationFailedId = wrapper.connect('activation-failed', Lang.bind(this, function(device, reason) {
 | 
			
		||||
                // XXX: nm-applet has no special text depending on reason
 | 
			
		||||
                // but I'm not sure of this generic message
 | 
			
		||||
@@ -1761,7 +1743,6 @@ NMApplet.prototype = {
 | 
			
		||||
                this._syncSectionTitle(dev.category);
 | 
			
		||||
            }));
 | 
			
		||||
            wrapper._destroyId = wrapper.connect('destroy', function(wrapper) {
 | 
			
		||||
                wrapper.disconnect(wrapper._networkLostId);
 | 
			
		||||
                wrapper.disconnect(wrapper._activationFailedId);
 | 
			
		||||
                wrapper.disconnect(wrapper._deviceStateChangedId);
 | 
			
		||||
                wrapper.disconnect(wrapper._destroyId);
 | 
			
		||||
@@ -2056,10 +2037,11 @@ NMApplet.prototype = {
 | 
			
		||||
                        }
 | 
			
		||||
                        this.setIcon('network-wireless-connected');
 | 
			
		||||
                    } else {
 | 
			
		||||
                        if (this._accessPointUpdateId && this._activeAccessPoint != ap) {
 | 
			
		||||
                            this._activeAccessPoint.disconnect(this._accessPointUpdateId);
 | 
			
		||||
                        if (this._activeAccessPoint != ap) {
 | 
			
		||||
                            if (this._accessPointUpdateId)
 | 
			
		||||
                                this._activeAccessPoint.disconnect(this._accessPointUpdateId);
 | 
			
		||||
                            this._activeAccessPoint = ap;
 | 
			
		||||
                            this._activeAccessPointUpdateId = ap.connect('notify::strength', Lang.bind(function() {
 | 
			
		||||
                            this._activeAccessPointUpdateId = ap.connect('notify::strength', Lang.bind(this, function() {
 | 
			
		||||
                                this.setIcon('network-wireless-signal-' + signalToIcon(ap.strength));
 | 
			
		||||
                            }));
 | 
			
		||||
                        }
 | 
			
		||||
@@ -2086,8 +2068,9 @@ NMApplet.prototype = {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (this._mobileUpdateId && this._mobileUpdateDevice != dev) {
 | 
			
		||||
                    this._mobileUpdateDevice.disconnect(this._mobileUpdateId);
 | 
			
		||||
                if (dev.mobileDevice != this._mobileUpdateDevice) {
 | 
			
		||||
                    if (this._mobileUpdateId)
 | 
			
		||||
                        this._mobileUpdateDevice.disconnect(this._mobileUpdateId);
 | 
			
		||||
                    this._mobileUpdateDevice = dev.mobileDevice;
 | 
			
		||||
                    this._mobileUpdateId = dev.mobileDevice.connect('notify::signal-quality', Lang.bind(this, function() {
 | 
			
		||||
                        this.setIcon('network-cellular-signal-' + signalToIcon(dev.mobileDevice.signal_quality));
 | 
			
		||||
@@ -2120,17 +2103,14 @@ NMApplet.prototype = {
 | 
			
		||||
            this._mobileUpdateId = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function NMMessageTraySource() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NMMessageTraySource.prototype = {
 | 
			
		||||
    __proto__: MessageTray.Source.prototype,
 | 
			
		||||
const NMMessageTraySource = new Lang.Class({
 | 
			
		||||
    Name: 'NMMessageTraySource',
 | 
			
		||||
    Extends: MessageTray.Source,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        MessageTray.Source.prototype._init.call(this, _("Network Manager"));
 | 
			
		||||
        this.parent(_("Network Manager"));
 | 
			
		||||
 | 
			
		||||
        let icon = new St.Icon({ icon_name: 'network-transmit-receive',
 | 
			
		||||
                                 icon_type: St.IconType.SYMBOLIC,
 | 
			
		||||
@@ -2138,4 +2118,4 @@ NMMessageTraySource.prototype = {
 | 
			
		||||
                               });
 | 
			
		||||
        this._setSummaryIcon(icon);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
@@ -40,31 +39,27 @@ const UPDeviceState = {
 | 
			
		||||
    PENDING_DISCHARGE: 6
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const PowerManagerInterface = {
 | 
			
		||||
    name: 'org.gnome.SettingsDaemon.Power',
 | 
			
		||||
    methods: [
 | 
			
		||||
        { name: 'GetDevices', inSignature: '', outSignature: 'a(susbut)' },
 | 
			
		||||
        { name: 'GetPrimaryDevice', inSignature: '', outSignature: '(susbut)' },
 | 
			
		||||
        ],
 | 
			
		||||
    signals: [
 | 
			
		||||
        { name: 'Changed', inSignature: '' },
 | 
			
		||||
        ],
 | 
			
		||||
    properties: [
 | 
			
		||||
        { name: 'Icon', signature: 's', access: 'read' },
 | 
			
		||||
        ]
 | 
			
		||||
};
 | 
			
		||||
let PowerManagerProxy = DBus.makeProxyClass(PowerManagerInterface);
 | 
			
		||||
const PowerManagerInterface = <interface name="org.gnome.SettingsDaemon.Power">
 | 
			
		||||
<method name="GetDevices">
 | 
			
		||||
    <arg type="a(susdut)" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="GetPrimaryDevice">
 | 
			
		||||
    <arg type="(susdut)" direction="out" />
 | 
			
		||||
</method>
 | 
			
		||||
<signal name="Changed" />
 | 
			
		||||
<property name="Icon" type="s" access="read" />
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
function Indicator() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(PowerManagerInterface);
 | 
			
		||||
 | 
			
		||||
Indicator.prototype = {
 | 
			
		||||
    __proto__: PanelMenu.SystemStatusButton.prototype,
 | 
			
		||||
const Indicator = new Lang.Class({
 | 
			
		||||
    Name: 'PowerIndicator',
 | 
			
		||||
    Extends: PanelMenu.SystemStatusButton,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        PanelMenu.SystemStatusButton.prototype._init.call(this, 'battery-missing');
 | 
			
		||||
        this._proxy = new PowerManagerProxy(DBus.session, BUS_NAME, OBJECT_PATH);
 | 
			
		||||
        this.parent('battery-missing', null);
 | 
			
		||||
 | 
			
		||||
        this._proxy = new PowerManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH);
 | 
			
		||||
 | 
			
		||||
        this._deviceItems = [ ];
 | 
			
		||||
        this._hasPrimary = false;
 | 
			
		||||
@@ -81,19 +76,19 @@ Indicator.prototype = {
 | 
			
		||||
        this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
 | 
			
		||||
        this.menu.addSettingsAction(_("Power Settings"), 'gnome-power-panel.desktop');
 | 
			
		||||
 | 
			
		||||
        this._proxy.connect('Changed', Lang.bind(this, this._devicesChanged));
 | 
			
		||||
        this._proxy.connectSignal('Changed', Lang.bind(this, this._devicesChanged));
 | 
			
		||||
        this._devicesChanged();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _readPrimaryDevice: function() {
 | 
			
		||||
        this._proxy.GetPrimaryDeviceRemote(Lang.bind(this, function(device, error) {
 | 
			
		||||
        this._proxy.GetPrimaryDeviceRemote(Lang.bind(this, function(result, error) {
 | 
			
		||||
            if (error) {
 | 
			
		||||
                this._hasPrimary = false;
 | 
			
		||||
                this._primaryDeviceId = null;
 | 
			
		||||
                this._batteryItem.actor.hide();
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            let [device_id, device_type, icon, percentage, state, seconds] = device;
 | 
			
		||||
            let [[device_id, device_type, icon, percentage, state, seconds]] = result;
 | 
			
		||||
            if (device_type == UPDeviceType.BATTERY) {
 | 
			
		||||
                this._hasPrimary = true;
 | 
			
		||||
                let time = Math.round(seconds / 60);
 | 
			
		||||
@@ -130,7 +125,7 @@ Indicator.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _readOtherDevices: function() {
 | 
			
		||||
        this._proxy.GetDevicesRemote(Lang.bind(this, function(devices, error) {
 | 
			
		||||
        this._proxy.GetDevicesRemote(Lang.bind(this, function(result, error) {
 | 
			
		||||
            this._deviceItems.forEach(function(i) { i.destroy(); });
 | 
			
		||||
            this._deviceItems = [];
 | 
			
		||||
 | 
			
		||||
@@ -139,6 +134,7 @@ Indicator.prototype = {
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let position = 0;
 | 
			
		||||
            let [devices] = result;
 | 
			
		||||
            for (let i = 0; i < devices.length; i++) {
 | 
			
		||||
                let [device_id, device_type] = devices[i];
 | 
			
		||||
                if (device_type == UPDeviceType.AC_POWER || device_id == this._primaryDeviceId)
 | 
			
		||||
@@ -153,37 +149,33 @@ Indicator.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _devicesChanged: function() {
 | 
			
		||||
        this._proxy.GetRemote('Icon', Lang.bind(this, function(icon, error) {
 | 
			
		||||
            if (icon) {
 | 
			
		||||
                let gicon = Shell.util_icon_from_string (icon);
 | 
			
		||||
                this.setGIcon(gicon);
 | 
			
		||||
                this.actor.show();
 | 
			
		||||
            } else {
 | 
			
		||||
                this.menu.close();
 | 
			
		||||
                this.actor.hide();
 | 
			
		||||
            }
 | 
			
		||||
        }));
 | 
			
		||||
        let icon = this._proxy.Icon;
 | 
			
		||||
        if (icon) {
 | 
			
		||||
            let gicon = Gio.icon_new_for_string(icon);
 | 
			
		||||
            this.setGIcon(gicon);
 | 
			
		||||
            this.actor.show();
 | 
			
		||||
        } else {
 | 
			
		||||
            this.menu.close();
 | 
			
		||||
            this.actor.hide();
 | 
			
		||||
        }
 | 
			
		||||
        this._readPrimaryDevice();
 | 
			
		||||
        this._readOtherDevices();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function DeviceItem() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DeviceItem.prototype = {
 | 
			
		||||
    __proto__: PopupMenu.PopupBaseMenuItem.prototype,
 | 
			
		||||
const DeviceItem = new Lang.Class({
 | 
			
		||||
    Name: 'DeviceItem',
 | 
			
		||||
    Extends: PopupMenu.PopupBaseMenuItem,
 | 
			
		||||
 | 
			
		||||
    _init: function(device) {
 | 
			
		||||
        PopupMenu.PopupBaseMenuItem.prototype._init.call(this, { reactive: false });
 | 
			
		||||
        this.parent({ reactive: false });
 | 
			
		||||
 | 
			
		||||
        let [device_id, device_type, icon, percentage, state, time] = device;
 | 
			
		||||
 | 
			
		||||
        this._box = new St.BoxLayout({ style_class: 'popup-device-menu-item' });
 | 
			
		||||
        this._label = new St.Label({ text: this._deviceTypeToString(device_type) });
 | 
			
		||||
 | 
			
		||||
        this._icon = new St.Icon({ gicon: Shell.util_icon_from_string(icon),
 | 
			
		||||
        this._icon = new St.Icon({ gicon: Gio.icon_new_for_string(icon),
 | 
			
		||||
                                   icon_type: St.IconType.SYMBOLIC,
 | 
			
		||||
                                   style_class: 'popup-menu-icon' });
 | 
			
		||||
 | 
			
		||||
@@ -223,4 +215,4 @@ DeviceItem.prototype = {
 | 
			
		||||
            return _("Unknown");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
@@ -18,15 +17,12 @@ const VOLUME_ADJUSTMENT_STEP = 0.05; /* Volume adjustment step in % */
 | 
			
		||||
 | 
			
		||||
const VOLUME_NOTIFY_ID = 1;
 | 
			
		||||
 | 
			
		||||
function Indicator() {
 | 
			
		||||
    this._init.apply(this, arguments);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Indicator.prototype = {
 | 
			
		||||
    __proto__: PanelMenu.SystemStatusButton.prototype,
 | 
			
		||||
const Indicator = new Lang.Class({
 | 
			
		||||
    Name: 'VolumeIndicator',
 | 
			
		||||
    Extends: PanelMenu.SystemStatusButton,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        PanelMenu.SystemStatusButton.prototype._init.call(this, 'audio-volume-muted', null);
 | 
			
		||||
        this.parent('audio-volume-muted', null);
 | 
			
		||||
 | 
			
		||||
        this._control = new Gvc.MixerControl({ name: 'GNOME Shell Volume Control' });
 | 
			
		||||
        this._control.connect('state-changed', Lang.bind(this, this._onControlStateChanged));
 | 
			
		||||
@@ -215,4 +211,4 @@ Indicator.prototype = {
 | 
			
		||||
        if (property == '_output' && !this._output.is_muted)
 | 
			
		||||
            this.setIcon(this._volumeToIcon(this._output.volume));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
@@ -23,11 +23,9 @@ const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
 | 
			
		||||
    'ibus-ui-gtk': 'input-method'
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function StatusIconDispatcher() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const StatusIconDispatcher = new Lang.Class({
 | 
			
		||||
    Name: 'StatusIconDispatcher',
 | 
			
		||||
 | 
			
		||||
StatusIconDispatcher.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._traymanager = new Shell.TrayManager();
 | 
			
		||||
        this._traymanager.connect('tray-icon-added', Lang.bind(this, this._onTrayIconAdded));
 | 
			
		||||
@@ -61,5 +59,5 @@ StatusIconDispatcher.prototype = {
 | 
			
		||||
        else
 | 
			
		||||
            this.emit('message-icon-removed', icon);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(StatusIconDispatcher.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
@@ -73,16 +72,17 @@ function makeMessageFromTplEvent(event) {
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function Client() {
 | 
			
		||||
    this._init();
 | 
			
		||||
};
 | 
			
		||||
const Client = new Lang.Class({
 | 
			
		||||
    Name: 'Client',
 | 
			
		||||
 | 
			
		||||
Client.prototype = {
 | 
			
		||||
    _init : function() {
 | 
			
		||||
        // channel path -> ChatSource
 | 
			
		||||
        this._chatSources = {};
 | 
			
		||||
        this._chatState = Tp.ChannelChatState.ACTIVE;
 | 
			
		||||
 | 
			
		||||
        // account path -> AccountNotification
 | 
			
		||||
        this._accountNotifications = {};
 | 
			
		||||
 | 
			
		||||
        // Set up a SimpleObserver, which will call _observeChannels whenever a
 | 
			
		||||
        // channel matching its filters is detected.
 | 
			
		||||
        // The second argument, recover, means _observeChannels will be run
 | 
			
		||||
@@ -254,7 +254,7 @@ Client.prototype = {
 | 
			
		||||
        // FIXME: We don't have a 'chat room' icon (bgo #653737) use
 | 
			
		||||
        // system-users for now as Empathy does.
 | 
			
		||||
        let source = new ApproverSource(dispatchOp, _("Invitation"),
 | 
			
		||||
                                        Shell.util_icon_from_string('system-users'));
 | 
			
		||||
                                        Gio.icon_new_for_string('system-users'));
 | 
			
		||||
        Main.messageTray.add(source);
 | 
			
		||||
 | 
			
		||||
        let notif = new RoomInviteNotification(source, dispatchOp, channel, contacts[0]);
 | 
			
		||||
@@ -302,6 +302,8 @@ Client.prototype = {
 | 
			
		||||
        Shell.get_tp_contacts(conn, [targetHandle],
 | 
			
		||||
                contactFeatures,
 | 
			
		||||
                Lang.bind(this, this._createAudioVideoSource, channel, context, dispatchOp));
 | 
			
		||||
 | 
			
		||||
        context.delay();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createAudioVideoSource: function(connection, contacts, failed, channel, context, dispatchOp) {
 | 
			
		||||
@@ -320,8 +322,8 @@ Client.prototype = {
 | 
			
		||||
 | 
			
		||||
        // We got the TpContact
 | 
			
		||||
        let source = new ApproverSource(dispatchOp, _("Call"), isVideo ?
 | 
			
		||||
                                        Shell.util_icon_from_string('camera-web') :
 | 
			
		||||
                                        Shell.util_icon_from_string('audio-input-microphone'));
 | 
			
		||||
                                        Gio.icon_new_for_string('camera-web') :
 | 
			
		||||
                                        Gio.icon_new_for_string('audio-input-microphone'));
 | 
			
		||||
        Main.messageTray.add(source);
 | 
			
		||||
 | 
			
		||||
        let notif = new AudioVideoNotification(source, dispatchOp, channel, contacts[0], isVideo);
 | 
			
		||||
@@ -335,6 +337,8 @@ Client.prototype = {
 | 
			
		||||
        Shell.get_tp_contacts(conn, [targetHandle],
 | 
			
		||||
                contactFeatures,
 | 
			
		||||
                Lang.bind(this, this._createFileTransferSource, channel, context, dispatchOp));
 | 
			
		||||
 | 
			
		||||
        context.delay();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createFileTransferSource: function(connection, contacts, failed, channel, context, dispatchOp) {
 | 
			
		||||
@@ -420,7 +424,6 @@ Client.prototype = {
 | 
			
		||||
 | 
			
		||||
        /* Display notification to ask user to accept/reject request */
 | 
			
		||||
        let source = this._ensureSubscriptionSource();
 | 
			
		||||
        Main.messageTray.add(source);
 | 
			
		||||
 | 
			
		||||
        let notif = new SubscriptionRequestNotification(source, contact);
 | 
			
		||||
        source.notify(notif);
 | 
			
		||||
@@ -430,6 +433,7 @@ Client.prototype = {
 | 
			
		||||
        if (this._subscriptionSource == null) {
 | 
			
		||||
            this._subscriptionSource = new MultiNotificationSource(
 | 
			
		||||
                _("Subscription request"), 'gtk-dialog-question');
 | 
			
		||||
            Main.messageTray.add(this._subscriptionSource);
 | 
			
		||||
            this._subscriptionSource.connect('destroy', Lang.bind(this, function () {
 | 
			
		||||
                this._subscriptionSource = null;
 | 
			
		||||
            }));
 | 
			
		||||
@@ -446,11 +450,18 @@ Client.prototype = {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let notif = this._accountNotifications[account.get_object_path()];
 | 
			
		||||
        if (notif)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        /* Display notification that account failed to connect */
 | 
			
		||||
        let source = this._ensureAccountSource();
 | 
			
		||||
        Main.messageTray.add(source);
 | 
			
		||||
 | 
			
		||||
        let notif = new AccountNotification(source, account, connectionError);
 | 
			
		||||
        notif = new AccountNotification(source, account, connectionError);
 | 
			
		||||
        this._accountNotifications[account.get_object_path()] = notif;
 | 
			
		||||
        notif.connect('destroy', Lang.bind(this, function() {
 | 
			
		||||
            delete this._accountNotifications[account.get_object_path()];
 | 
			
		||||
        }));
 | 
			
		||||
        source.notify(notif);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -458,6 +469,7 @@ Client.prototype = {
 | 
			
		||||
        if (this._accountSource == null) {
 | 
			
		||||
            this._accountSource = new MultiNotificationSource(
 | 
			
		||||
                _("Connection error"), 'gtk-dialog-error');
 | 
			
		||||
            Main.messageTray.add(this._accountSource);
 | 
			
		||||
            this._accountSource.connect('destroy', Lang.bind(this, function () {
 | 
			
		||||
                this._accountSource = null;
 | 
			
		||||
            }));
 | 
			
		||||
@@ -465,17 +477,14 @@ Client.prototype = {
 | 
			
		||||
 | 
			
		||||
        return this._accountSource;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function ChatSource(account, conn, channel, contact, client) {
 | 
			
		||||
    this._init(account, conn, channel, contact, client);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ChatSource.prototype = {
 | 
			
		||||
    __proto__:  MessageTray.Source.prototype,
 | 
			
		||||
const ChatSource = new Lang.Class({
 | 
			
		||||
    Name: 'ChatSource',
 | 
			
		||||
    Extends: MessageTray.Source,
 | 
			
		||||
 | 
			
		||||
    _init: function(account, conn, channel, contact, client) {
 | 
			
		||||
        MessageTray.Source.prototype._init.call(this, contact.get_alias());
 | 
			
		||||
        this.parent(contact.get_alias());
 | 
			
		||||
 | 
			
		||||
        this.isChat = true;
 | 
			
		||||
 | 
			
		||||
@@ -524,21 +533,18 @@ ChatSource.prototype = {
 | 
			
		||||
 | 
			
		||||
    _updateAlias: function() {
 | 
			
		||||
        let oldAlias = this.title;
 | 
			
		||||
        this.setTitle(this._contact.get_alias());
 | 
			
		||||
        this._notification.appendAliasChange(oldAlias, this.title);
 | 
			
		||||
        this.pushNotification(this._notification);
 | 
			
		||||
        let newAlias = this._contact.get_alias();
 | 
			
		||||
 | 
			
		||||
        if (oldAlias == newAlias)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this.setTitle(newAlias);
 | 
			
		||||
        this._notification.appendAliasChange(oldAlias, newAlias);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    createNotificationIcon: function() {
 | 
			
		||||
        this._iconBox = new St.Bin({ style_class: 'avatar-box' });
 | 
			
		||||
        this._iconBox._size = this.ICON_SIZE;
 | 
			
		||||
 | 
			
		||||
        this._updateAvatarIcon();
 | 
			
		||||
 | 
			
		||||
        return this._iconBox;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateAvatarIcon: function() {
 | 
			
		||||
        let textureCache = St.TextureCache.get_default();
 | 
			
		||||
        let file = this._contact.get_avatar_file();
 | 
			
		||||
 | 
			
		||||
@@ -550,12 +556,19 @@ ChatSource.prototype = {
 | 
			
		||||
                                                icon_type: St.IconType.FULLCOLOR,
 | 
			
		||||
                                                icon_size: this._iconBox._size });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return this._iconBox;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateAvatarIcon: function() {
 | 
			
		||||
        this._setSummaryIcon(this.createNotificationIcon());
 | 
			
		||||
        this._notification.update(this._notification.title, null, { customContent: true, icon: this.createNotificationIcon() });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    open: function(notification) {
 | 
			
		||||
          if (this._client.is_handling_channel(this._channel)) {
 | 
			
		||||
              // We are handling the channel, try to pass it to Empathy
 | 
			
		||||
              this._client.delegate_channels_async([this._channel], global.get_current_time(), "", null);
 | 
			
		||||
              this._client.delegate_channels_async([this._channel], global.get_current_time(), '', null);
 | 
			
		||||
          }
 | 
			
		||||
          else {
 | 
			
		||||
              // We are not the handler, just ask to present the channel
 | 
			
		||||
@@ -679,7 +692,7 @@ ChatSource.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    notify: function() {
 | 
			
		||||
        MessageTray.Source.prototype.notify.call(this, this._notification);
 | 
			
		||||
        this.parent(this._notification);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    respond: function(text) {
 | 
			
		||||
@@ -780,17 +793,14 @@ ChatSource.prototype = {
 | 
			
		||||
 | 
			
		||||
        this._shouldAck = false;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function ChatNotification(source) {
 | 
			
		||||
    this._init(source);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ChatNotification.prototype = {
 | 
			
		||||
    __proto__:  MessageTray.Notification.prototype,
 | 
			
		||||
const ChatNotification = new Lang.Class({
 | 
			
		||||
    Name: 'ChatNotification',
 | 
			
		||||
    Extends: MessageTray.Notification,
 | 
			
		||||
 | 
			
		||||
    _init: function(source) {
 | 
			
		||||
        MessageTray.Notification.prototype._init.call(this, source, source.title, null, { customContent: true });
 | 
			
		||||
        this.parent(source, source.title, null, { customContent: true });
 | 
			
		||||
        this.setResident(true);
 | 
			
		||||
 | 
			
		||||
        this._responseEntry = new St.Entry({ style_class: 'chat-response',
 | 
			
		||||
@@ -881,7 +891,7 @@ ChatNotification.prototype = {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let groups = this._contentArea.get_children();
 | 
			
		||||
        for (let i = 0; i < groups.length; i ++) {
 | 
			
		||||
        for (let i = 0; i < groups.length; i++) {
 | 
			
		||||
            let group = groups[i];
 | 
			
		||||
            if (group.get_children().length == 0)
 | 
			
		||||
                group.destroy();
 | 
			
		||||
@@ -919,7 +929,7 @@ ChatNotification.prototype = {
 | 
			
		||||
        let body = highlighter.actor;
 | 
			
		||||
 | 
			
		||||
        let styles = props.styles;
 | 
			
		||||
        for (let i = 0; i < styles.length; i ++)
 | 
			
		||||
        for (let i = 0; i < styles.length; i++)
 | 
			
		||||
            body.add_style_class_name(styles[i]);
 | 
			
		||||
 | 
			
		||||
        let group = props.group;
 | 
			
		||||
@@ -1073,17 +1083,14 @@ ChatNotification.prototype = {
 | 
			
		||||
            this.source.setChatState(Tp.ChannelChatState.ACTIVE);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function ApproverSource(dispatchOp, text, gicon) {
 | 
			
		||||
    this._init(dispatchOp, text, gicon);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ApproverSource.prototype = {
 | 
			
		||||
    __proto__: MessageTray.Source.prototype,
 | 
			
		||||
const ApproverSource = new Lang.Class({
 | 
			
		||||
    Name: 'ApproverSource',
 | 
			
		||||
    Extends: MessageTray.Source,
 | 
			
		||||
 | 
			
		||||
    _init: function(dispatchOp, text, gicon) {
 | 
			
		||||
        MessageTray.Source.prototype._init.call(this, text);
 | 
			
		||||
        this.parent(text);
 | 
			
		||||
 | 
			
		||||
        this._gicon = gicon;
 | 
			
		||||
        this._setSummaryIcon(this.createNotificationIcon());
 | 
			
		||||
@@ -1104,7 +1111,7 @@ ApproverSource.prototype = {
 | 
			
		||||
            this._invalidId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        MessageTray.Source.prototype.destroy.call(this);
 | 
			
		||||
        this.parent();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    createNotificationIcon: function() {
 | 
			
		||||
@@ -1112,23 +1119,19 @@ ApproverSource.prototype = {
 | 
			
		||||
                             icon_type: St.IconType.FULLCOLOR,
 | 
			
		||||
                             icon_size: this.ICON_SIZE });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function RoomInviteNotification(source, dispatchOp, channel, inviter) {
 | 
			
		||||
    this._init(source, dispatchOp, channel, inviter);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RoomInviteNotification.prototype = {
 | 
			
		||||
    __proto__: MessageTray.Notification.prototype,
 | 
			
		||||
const RoomInviteNotification = new Lang.Class({
 | 
			
		||||
    Name: 'RoomInviteNotification',
 | 
			
		||||
    Extends: MessageTray.Notification,
 | 
			
		||||
 | 
			
		||||
    _init: function(source, dispatchOp, channel, inviter) {
 | 
			
		||||
        MessageTray.Notification.prototype._init.call(this,
 | 
			
		||||
                                                      source,
 | 
			
		||||
                                                      /* translators: argument is a room name like
 | 
			
		||||
                                                       * room@jabber.org for example. */
 | 
			
		||||
                                                      _("Invitation to %s").format(channel.get_identifier()),
 | 
			
		||||
                                                      null,
 | 
			
		||||
                                                      { customContent: true });
 | 
			
		||||
        this.parent(source,
 | 
			
		||||
                    /* translators: argument is a room name like
 | 
			
		||||
                     * room@jabber.org for example. */
 | 
			
		||||
                    _("Invitation to %s").format(channel.get_identifier()),
 | 
			
		||||
                    null,
 | 
			
		||||
                    { customContent: true });
 | 
			
		||||
        this.setResident(true);
 | 
			
		||||
 | 
			
		||||
        /* translators: first argument is the name of a contact and the second
 | 
			
		||||
@@ -1155,15 +1158,12 @@ RoomInviteNotification.prototype = {
 | 
			
		||||
            this.destroy();
 | 
			
		||||
        }));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// Audio Video
 | 
			
		||||
function AudioVideoNotification(source, dispatchOp, channel, contact, isVideo) {
 | 
			
		||||
    this._init(source, dispatchOp, channel, contact, isVideo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AudioVideoNotification.prototype = {
 | 
			
		||||
    __proto__: MessageTray.Notification.prototype,
 | 
			
		||||
const AudioVideoNotification = new Lang.Class({
 | 
			
		||||
    Name: 'AudioVideoNotification',
 | 
			
		||||
    Extends: MessageTray.Notification,
 | 
			
		||||
 | 
			
		||||
    _init: function(source, dispatchOp, channel, contact, isVideo) {
 | 
			
		||||
        let title = '';
 | 
			
		||||
@@ -1175,14 +1175,11 @@ AudioVideoNotification.prototype = {
 | 
			
		||||
             /* translators: argument is a contact name like Alice for example. */
 | 
			
		||||
            title = _("Call from %s").format(contact.get_alias());
 | 
			
		||||
 | 
			
		||||
        MessageTray.Notification.prototype._init.call(this,
 | 
			
		||||
                                                      source,
 | 
			
		||||
                                                      title,
 | 
			
		||||
                                                      null,
 | 
			
		||||
                                                      { customContent: true });
 | 
			
		||||
        this.parent(this, source, title, null, { customContent: true });
 | 
			
		||||
        this.setResident(true);
 | 
			
		||||
 | 
			
		||||
        this.addButton('reject', _("Reject"));
 | 
			
		||||
        /* translators: this is a button label (verb), not a noun */
 | 
			
		||||
        this.addButton('answer', _("Answer"));
 | 
			
		||||
 | 
			
		||||
        this.connect('action-invoked', Lang.bind(this, function(self, action) {
 | 
			
		||||
@@ -1201,28 +1198,25 @@ AudioVideoNotification.prototype = {
 | 
			
		||||
            this.destroy();
 | 
			
		||||
        }));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// File Transfer
 | 
			
		||||
function FileTransferNotification(source, dispatchOp, channel, contact) {
 | 
			
		||||
    this._init(source, dispatchOp, channel, contact);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FileTransferNotification.prototype = {
 | 
			
		||||
    __proto__: MessageTray.Notification.prototype,
 | 
			
		||||
const FileTransferNotification = new Lang.Class({
 | 
			
		||||
    Name: 'FileTransferNotification',
 | 
			
		||||
    Extends: MessageTray.Notification,
 | 
			
		||||
 | 
			
		||||
    _init: function(source, dispatchOp, channel, contact) {
 | 
			
		||||
        MessageTray.Notification.prototype._init.call(this,
 | 
			
		||||
                                                      source,
 | 
			
		||||
                                                      /* To translators: The first parameter is
 | 
			
		||||
                                                       * the contact's alias and the second one is the
 | 
			
		||||
                                                       * file name. The string will be something
 | 
			
		||||
                                                       * like: "Alice is sending you test.ogg"
 | 
			
		||||
                                                       */
 | 
			
		||||
                                                      _("%s is sending you %s").format(contact.get_alias(),
 | 
			
		||||
                                                                                       channel.get_filename()),
 | 
			
		||||
                                                      null,
 | 
			
		||||
                                                      { customContent: true });
 | 
			
		||||
        this.parent(this,
 | 
			
		||||
                    source,
 | 
			
		||||
                    /* To translators: The first parameter is
 | 
			
		||||
                     * the contact's alias and the second one is the
 | 
			
		||||
                     * file name. The string will be something
 | 
			
		||||
                     * like: "Alice is sending you test.ogg"
 | 
			
		||||
                     */
 | 
			
		||||
                    _("%s is sending you %s").format(contact.get_alias(),
 | 
			
		||||
                                                     channel.get_filename()),
 | 
			
		||||
                    null,
 | 
			
		||||
                    { customContent: true });
 | 
			
		||||
        this.setResident(true);
 | 
			
		||||
 | 
			
		||||
        this.addButton('decline', _("Decline"));
 | 
			
		||||
@@ -1244,18 +1238,15 @@ FileTransferNotification.prototype = {
 | 
			
		||||
            this.destroy();
 | 
			
		||||
        }));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// A notification source that can embed multiple notifications
 | 
			
		||||
function MultiNotificationSource(title, icon) {
 | 
			
		||||
    this._init(title, icon);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MultiNotificationSource.prototype = {
 | 
			
		||||
    __proto__: MessageTray.Source.prototype,
 | 
			
		||||
const MultiNotificationSource = new Lang.Class({
 | 
			
		||||
    Name: 'MultiNotificationSource',
 | 
			
		||||
    Extends: MessageTray.Source,
 | 
			
		||||
 | 
			
		||||
    _init: function(title, icon) {
 | 
			
		||||
        MessageTray.Source.prototype._init.call(this, title);
 | 
			
		||||
        this.parent(title);
 | 
			
		||||
 | 
			
		||||
        this._icon = icon;
 | 
			
		||||
        this._setSummaryIcon(this.createNotificationIcon());
 | 
			
		||||
@@ -1263,7 +1254,7 @@ MultiNotificationSource.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    notify: function(notification) {
 | 
			
		||||
        MessageTray.Source.prototype.notify.call(this, notification);
 | 
			
		||||
        this.parent(notification);
 | 
			
		||||
 | 
			
		||||
        this._nbNotifications += 1;
 | 
			
		||||
 | 
			
		||||
@@ -1277,25 +1268,22 @@ MultiNotificationSource.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    createNotificationIcon: function() {
 | 
			
		||||
        return new St.Icon({ gicon: Shell.util_icon_from_string(this._icon),
 | 
			
		||||
        return new St.Icon({ gicon: Gio.icon_new_for_string(this._icon),
 | 
			
		||||
                             icon_type: St.IconType.FULLCOLOR,
 | 
			
		||||
                             icon_size: this.ICON_SIZE });
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// Subscription request
 | 
			
		||||
function SubscriptionRequestNotification(source, contact) {
 | 
			
		||||
    this._init(source, contact);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SubscriptionRequestNotification.prototype = {
 | 
			
		||||
    __proto__: MessageTray.Notification.prototype,
 | 
			
		||||
const SubscriptionRequestNotification = new Lang.Class({
 | 
			
		||||
    Name: 'SubscriptionRequestNotification',
 | 
			
		||||
    Extends: MessageTray.Notification,
 | 
			
		||||
 | 
			
		||||
    _init: function(source, contact) {
 | 
			
		||||
        MessageTray.Notification.prototype._init.call(this, source,
 | 
			
		||||
            /* To translators: The parameter is the contact's alias */
 | 
			
		||||
            _("%s would like permission to see when you are online").format(contact.get_alias()),
 | 
			
		||||
            null, { customContent: true });
 | 
			
		||||
        this.parent(this, source,
 | 
			
		||||
                    /* To translators: The parameter is the contact's alias */
 | 
			
		||||
                    _("%s would like permission to see when you are online").format(contact.get_alias()),
 | 
			
		||||
                    null, { customContent: true });
 | 
			
		||||
 | 
			
		||||
        this._contact = contact;
 | 
			
		||||
        this._connection = contact.get_connection();
 | 
			
		||||
@@ -1369,7 +1357,7 @@ SubscriptionRequestNotification.prototype = {
 | 
			
		||||
            this._invalidatedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        MessageTray.Notification.prototype.destroy.call(this);
 | 
			
		||||
        this.parent();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _subscriptionStatesChangedCb: function(contact, subscribe, publish, msg) {
 | 
			
		||||
@@ -1378,12 +1366,7 @@ SubscriptionRequestNotification.prototype = {
 | 
			
		||||
        if (publish != Tp.SubscriptionState.ASK)
 | 
			
		||||
            this.destroy();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function AccountNotification(source, account, connectionError) {
 | 
			
		||||
    this._init(source, account, connectionError);
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// Messages from empathy/libempathy/empathy-utils.c
 | 
			
		||||
// create_errors_to_message_hash()
 | 
			
		||||
@@ -1438,27 +1421,23 @@ _connectionErrorMessages[Tp.error_get_dbus_name(Tp.Error.CERT_INSECURE)]
 | 
			
		||||
_connectionErrorMessages[Tp.error_get_dbus_name(Tp.Error.CERT_LIMIT_EXCEEDED)]
 | 
			
		||||
  = _("The length of the server certificate, or the depth of the server certificate chain, exceed the limits imposed by the cryptography library");
 | 
			
		||||
 | 
			
		||||
AccountNotification.prototype = {
 | 
			
		||||
    __proto__: MessageTray.Notification.prototype,
 | 
			
		||||
const AccountNotification = new Lang.Class({
 | 
			
		||||
    Name: 'AccountNotification',
 | 
			
		||||
    Extends: MessageTray.Notification,
 | 
			
		||||
 | 
			
		||||
    _init: function(source, account, connectionError) {
 | 
			
		||||
        MessageTray.Notification.prototype._init.call(this, source,
 | 
			
		||||
            /* translators: argument is the account name, like
 | 
			
		||||
             * name@jabber.org for example. */
 | 
			
		||||
            _("Connection to %s failed").format(account.get_display_name()),
 | 
			
		||||
            null, { customContent: true });
 | 
			
		||||
        this.parent(source,
 | 
			
		||||
                    /* translators: argument is the account name, like
 | 
			
		||||
                     * name@jabber.org for example. */
 | 
			
		||||
                    _("Connection to %s failed").format(account.get_display_name()),
 | 
			
		||||
                    null, { customContent: true });
 | 
			
		||||
 | 
			
		||||
        let message;
 | 
			
		||||
        if (connectionError in _connectionErrorMessages) {
 | 
			
		||||
            message = _connectionErrorMessages[connectionError];
 | 
			
		||||
        } else {
 | 
			
		||||
            message = _("Unknown reason");
 | 
			
		||||
        }
 | 
			
		||||
        this._label = new St.Label();
 | 
			
		||||
        this.addActor(this._label);
 | 
			
		||||
        this._updateMessage(connectionError);
 | 
			
		||||
 | 
			
		||||
        this._account = account;
 | 
			
		||||
 | 
			
		||||
        this.addBody(message);
 | 
			
		||||
 | 
			
		||||
        this.addButton('reconnect', _("Reconnect"));
 | 
			
		||||
        this.addButton('edit', _("Edit account"));
 | 
			
		||||
 | 
			
		||||
@@ -1492,11 +1471,25 @@ AccountNotification.prototype = {
 | 
			
		||||
 | 
			
		||||
        this._connectionStatusId = account.connect('notify::connection-status',
 | 
			
		||||
            Lang.bind(this, function() {
 | 
			
		||||
                if (account.connection_status != Tp.ConnectionStatus.DISCONNECTED)
 | 
			
		||||
                let status = account.connection_status;
 | 
			
		||||
                if (status == Tp.ConnectionStatus.CONNECTED) {
 | 
			
		||||
                    this.destroy();
 | 
			
		||||
                } else if (status == Tp.ConnectionStatus.DISCONNECTED) {
 | 
			
		||||
                    this._updateMessage(account.connection_error);
 | 
			
		||||
                }
 | 
			
		||||
            }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateMessage: function(connectionError) {
 | 
			
		||||
        let message;
 | 
			
		||||
        if (connectionError in _connectionErrorMessages) {
 | 
			
		||||
            message = _connectionErrorMessages[connectionError];
 | 
			
		||||
        } else {
 | 
			
		||||
            message = _("Unknown reason");
 | 
			
		||||
        }
 | 
			
		||||
        this._label.set_text(message);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    destroy: function() {
 | 
			
		||||
        if (this._enabledId != 0) {
 | 
			
		||||
            this._account.disconnect(this._enabledId);
 | 
			
		||||
@@ -1513,6 +1506,6 @@ AccountNotification.prototype = {
 | 
			
		||||
            this._connectionStatusId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        MessageTray.Notification.prototype.destroy.call(this);
 | 
			
		||||
        this.parent();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
@@ -202,11 +202,9 @@ function registerSpecialPropertySplitter(name, splitFunction, parameters) {
 | 
			
		||||
// time updates; even better is to pay attention to the vertical
 | 
			
		||||
// vblank and sync to that when possible.)
 | 
			
		||||
//
 | 
			
		||||
function ClutterFrameTicker() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const ClutterFrameTicker = new Lang.Class({
 | 
			
		||||
    Name: 'ClutterFrameTicker',
 | 
			
		||||
 | 
			
		||||
ClutterFrameTicker.prototype = {
 | 
			
		||||
    FRAME_RATE : 60,
 | 
			
		||||
 | 
			
		||||
    _init : function() {
 | 
			
		||||
@@ -261,6 +259,6 @@ ClutterFrameTicker.prototype = {
 | 
			
		||||
        this._startTime = -1;
 | 
			
		||||
        global.end_work();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Signals.addSignalMethods(ClutterFrameTicker.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,10 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const AccountsService = imports.gi.AccountsService;
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Pango = imports.gi.Pango;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Tp = imports.gi.TelepathyGLib;
 | 
			
		||||
@@ -22,7 +22,6 @@ const DISABLE_USER_SWITCH_KEY = 'disable-user-switching';
 | 
			
		||||
const DISABLE_LOCK_SCREEN_KEY = 'disable-lock-screen';
 | 
			
		||||
const DISABLE_LOG_OUT_KEY = 'disable-log-out';
 | 
			
		||||
 | 
			
		||||
const WRAP_WIDTH = 150;
 | 
			
		||||
const DIALOG_ICON_SIZE = 64;
 | 
			
		||||
 | 
			
		||||
const IMStatus = {
 | 
			
		||||
@@ -41,15 +40,12 @@ const IMStatus = {
 | 
			
		||||
// Copyright (C) 2008,2009 Red Hat, Inc.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function IMStatusItem(label, iconName) {
 | 
			
		||||
    this._init(label, iconName);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IMStatusItem.prototype = {
 | 
			
		||||
    __proto__: PopupMenu.PopupBaseMenuItem.prototype,
 | 
			
		||||
const IMStatusItem = new Lang.Class({
 | 
			
		||||
    Name: 'IMStatusItem',
 | 
			
		||||
    Extends: PopupMenu.PopupBaseMenuItem,
 | 
			
		||||
 | 
			
		||||
    _init: function(label, iconName) {
 | 
			
		||||
        PopupMenu.PopupBaseMenuItem.prototype._init.call(this);
 | 
			
		||||
        this.parent();
 | 
			
		||||
 | 
			
		||||
        this.actor.add_style_class_name('status-chooser-status-item');
 | 
			
		||||
 | 
			
		||||
@@ -62,19 +58,15 @@ IMStatusItem.prototype = {
 | 
			
		||||
        this.label = new St.Label({ text: label });
 | 
			
		||||
        this.addActor(this.label);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function IMUserNameItem() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IMUserNameItem.prototype = {
 | 
			
		||||
    __proto__: PopupMenu.PopupBaseMenuItem.prototype,
 | 
			
		||||
const IMUserNameItem = new Lang.Class({
 | 
			
		||||
    Name: 'IMUserNameItem',
 | 
			
		||||
    Extends: PopupMenu.PopupBaseMenuItem,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        PopupMenu.PopupBaseMenuItem.prototype._init.call(this,
 | 
			
		||||
                                                         { reactive: false,
 | 
			
		||||
                                                           style_class: 'status-chooser-user-name' });
 | 
			
		||||
        this.parent({ reactive: false,
 | 
			
		||||
                      style_class: 'status-chooser-user-name' });
 | 
			
		||||
 | 
			
		||||
        this._wrapper = new Shell.GenericContainer();
 | 
			
		||||
        this._wrapper.connect('get-preferred-width',
 | 
			
		||||
@@ -87,43 +79,31 @@ IMUserNameItem.prototype = {
 | 
			
		||||
 | 
			
		||||
        this.label = new St.Label();
 | 
			
		||||
        this.label.clutter_text.set_line_wrap(true);
 | 
			
		||||
        this.label.clutter_text.set_ellipsize(Pango.EllipsizeMode.NONE);
 | 
			
		||||
        this._wrapper.add_actor(this.label);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _wrapperGetPreferredWidth: function(actor, forHeight, alloc) {
 | 
			
		||||
        [alloc.min_size, alloc.natural_size] = this.label.get_preferred_width(-1);
 | 
			
		||||
        if (alloc.natural_size > WRAP_WIDTH)
 | 
			
		||||
            alloc.natural_size = WRAP_WIDTH;
 | 
			
		||||
        alloc.min_size = 1;
 | 
			
		||||
        alloc.natural_size = 1;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _wrapperGetPreferredHeight: function(actor, forWidth, alloc) {
 | 
			
		||||
        let minWidth, natWidth;
 | 
			
		||||
        [alloc.min_size, alloc.natural_size] = this.label.get_preferred_height(forWidth);
 | 
			
		||||
        [minWidth, natWidth] = this.label.get_preferred_width(-1);
 | 
			
		||||
        if (natWidth > WRAP_WIDTH) {
 | 
			
		||||
            alloc.min_size *= 2;
 | 
			
		||||
            alloc.natural_size *= 2;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _wrapperAllocate: function(actor, box, flags) {
 | 
			
		||||
        let availWidth = box.x2 - box.x1;
 | 
			
		||||
        let availHeight = box.y2 - box.y1;
 | 
			
		||||
        this.label.allocate(box, flags);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function IMStatusChooserItem() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IMStatusChooserItem.prototype = {
 | 
			
		||||
    __proto__: PopupMenu.PopupBaseMenuItem.prototype,
 | 
			
		||||
const IMStatusChooserItem = new Lang.Class({
 | 
			
		||||
    Name: 'IMStatusChooserItem',
 | 
			
		||||
    Extends: PopupMenu.PopupBaseMenuItem,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        PopupMenu.PopupBaseMenuItem.prototype._init.call (this,
 | 
			
		||||
                                                          { reactive: false,
 | 
			
		||||
                                                            style_class: 'status-chooser' });
 | 
			
		||||
        this.parent({ reactive: false,
 | 
			
		||||
                      style_class: 'status-chooser' });
 | 
			
		||||
 | 
			
		||||
        this._iconBin = new St.Button({ style_class: 'status-chooser-user-icon' });
 | 
			
		||||
        this.addActor(this._iconBin);
 | 
			
		||||
@@ -166,22 +146,39 @@ IMStatusChooserItem.prototype = {
 | 
			
		||||
                            Lang.bind(this, this._changeIMStatus));
 | 
			
		||||
 | 
			
		||||
        this._presence = new GnomeSession.Presence();
 | 
			
		||||
        this._presence.getStatus(Lang.bind(this, this._sessionStatusChanged));
 | 
			
		||||
        this._presence.connect('StatusChanged',
 | 
			
		||||
                               Lang.bind(this, this._sessionStatusChanged));
 | 
			
		||||
        this._presence.connectSignal('StatusChanged', Lang.bind(this, function(proxy, senderName, [status]) {
 | 
			
		||||
            this._sessionStatusChanged(status);
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        this._sessionPresenceRestored = false;
 | 
			
		||||
        this._imPresenceRestored = false;
 | 
			
		||||
        this._currentPresence = undefined;
 | 
			
		||||
        this._previousPresence = undefined;
 | 
			
		||||
 | 
			
		||||
        this._accountMgr = Tp.AccountManager.dup()
 | 
			
		||||
        this._accountMgr = Tp.AccountManager.dup();
 | 
			
		||||
        this._accountMgr.connect('most-available-presence-changed',
 | 
			
		||||
                                 Lang.bind(this, this._IMStatusChanged));
 | 
			
		||||
        this._accountMgr.connect('account-enabled',
 | 
			
		||||
                                 Lang.bind(this, this._IMAccountsChanged));
 | 
			
		||||
        this._accountMgr.connect('account-disabled',
 | 
			
		||||
                                 Lang.bind(this, this._IMAccountsChanged));
 | 
			
		||||
        this._accountMgr.connect('account-removed',
 | 
			
		||||
                                 Lang.bind(this, this._IMAccountsChanged));
 | 
			
		||||
        this._accountMgr.prepare_async(null, Lang.bind(this,
 | 
			
		||||
            function(mgr) {
 | 
			
		||||
                let [presence, s, msg] = mgr.get_most_available_presence();
 | 
			
		||||
                let [presence, status, msg] = mgr.get_most_available_presence();
 | 
			
		||||
 | 
			
		||||
                this._previousPresence = presence;
 | 
			
		||||
                this._IMStatusChanged(mgr, presence, s, msg);
 | 
			
		||||
                let savedPresence = global.settings.get_int('saved-im-presence');
 | 
			
		||||
 | 
			
		||||
                this._IMAccountsChanged(mgr);
 | 
			
		||||
 | 
			
		||||
                if (savedPresence == presence) {
 | 
			
		||||
                    this._IMStatusChanged(mgr, presence, status, msg);
 | 
			
		||||
                } else {
 | 
			
		||||
                    this._setComboboxPresence(savedPresence);
 | 
			
		||||
                    status = this._statusForPresence(savedPresence);
 | 
			
		||||
                    msg = msg ? msg : '';
 | 
			
		||||
                    mgr.set_all_requested_presences(savedPresence, status, msg);
 | 
			
		||||
                }
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
        this._userManager = AccountsService.UserManager.get_default();
 | 
			
		||||
@@ -194,6 +191,25 @@ IMStatusChooserItem.prototype = {
 | 
			
		||||
        this._userChangedId = this._user.connect('changed',
 | 
			
		||||
                                                 Lang.bind(this,
 | 
			
		||||
                                                           this._updateUser));
 | 
			
		||||
        this.actor.connect('notify::mapped', Lang.bind(this, function() {
 | 
			
		||||
            if (this.actor.mapped)
 | 
			
		||||
                this._updateUser();
 | 
			
		||||
        }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    destroy: function() {
 | 
			
		||||
        // clean up signal handlers
 | 
			
		||||
        if (this._userLoadedId != 0) {
 | 
			
		||||
            this._user.disconnect(this._userLoadedId);
 | 
			
		||||
            this._userLoadedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._userChangedId != 0) {
 | 
			
		||||
            this._user.disconnect(this._userChangedId);
 | 
			
		||||
            this._userChangedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.parent();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // Override getColumnWidths()/setColumnWidths() to make the item
 | 
			
		||||
@@ -203,9 +219,6 @@ IMStatusChooserItem.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setColumnWidths: function(widths) {
 | 
			
		||||
        this._columnWidths = PopupMenu.PopupBaseMenuItem.prototype.getColumnWidths.call(this);
 | 
			
		||||
        let sectionWidths = this._section.getColumnWidths();
 | 
			
		||||
        this._section.setColumnWidths(sectionWidths);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateUser: function() {
 | 
			
		||||
@@ -267,20 +280,43 @@ IMStatusChooserItem.prototype = {
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _IMAccountsChanged: function(mgr) {
 | 
			
		||||
        let accounts = mgr.get_valid_accounts().filter(function(account) {
 | 
			
		||||
            return account.enabled;
 | 
			
		||||
        });
 | 
			
		||||
        this._combo.setSensitive(accounts.length > 0);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _IMStatusChanged: function(accountMgr, presence, status, message) {
 | 
			
		||||
        if (!this._imPresenceRestored)
 | 
			
		||||
            this._imPresenceRestored = true;
 | 
			
		||||
 | 
			
		||||
        if (presence == this._currentPresence)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._currentPresence = presence;
 | 
			
		||||
        this._setComboboxPresence(presence);
 | 
			
		||||
 | 
			
		||||
        if (!this._sessionPresenceRestored) {
 | 
			
		||||
            this._sessionStatusChanged(this._presence.status);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (presence == Tp.ConnectionPresenceType.AVAILABLE)
 | 
			
		||||
            this._presence.setStatus(GnomeSession.PresenceStatus.AVAILABLE);
 | 
			
		||||
            this._presence.status = GnomeSession.PresenceStatus.AVAILABLE;
 | 
			
		||||
 | 
			
		||||
        if (!this._expectedPresence || presence != this._expectedPresence)
 | 
			
		||||
            this._previousPresence = presence;
 | 
			
		||||
        // We ignore the actual value of _expectedPresence and never safe
 | 
			
		||||
        // the first presence change after an "automatic" change, assuming
 | 
			
		||||
        // that it is the response to our request; this is to account for
 | 
			
		||||
        // mission control falling back to "similar" presences if an account
 | 
			
		||||
        // type does not implement the requested presence.
 | 
			
		||||
        if (!this._expectedPresence)
 | 
			
		||||
            global.settings.set_int('saved-im-presence', presence);
 | 
			
		||||
        else
 | 
			
		||||
            this._expectedPresence = undefined;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _setComboboxPresence: function(presence) {
 | 
			
		||||
        let activatedItem;
 | 
			
		||||
 | 
			
		||||
        if (presence == Tp.ConnectionPresenceType.AVAILABLE)
 | 
			
		||||
@@ -317,59 +353,76 @@ IMStatusChooserItem.prototype = {
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        status = this._statusForPresence(newPresence);
 | 
			
		||||
        msg = msg ? msg : "";
 | 
			
		||||
        msg = msg ? msg : '';
 | 
			
		||||
        this._accountMgr.set_all_requested_presences(newPresence, status, msg);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _sessionStatusChanged: function(sessionPresence, sessionStatus) {
 | 
			
		||||
    getIMPresenceForSessionStatus: function(sessionStatus) {
 | 
			
		||||
        // Restore the last user-set presence when coming back from
 | 
			
		||||
        // BUSY/IDLE (otherwise the last user-set presence matches
 | 
			
		||||
        // the current one)
 | 
			
		||||
        if (sessionStatus == GnomeSession.PresenceStatus.AVAILABLE)
 | 
			
		||||
            return global.settings.get_int('saved-im-presence');
 | 
			
		||||
 | 
			
		||||
        if (sessionStatus == GnomeSession.PresenceStatus.BUSY) {
 | 
			
		||||
            // Only change presence if the current one is "more present" than
 | 
			
		||||
            // busy, or if coming back from idle
 | 
			
		||||
            if (this._currentPresence == Tp.ConnectionPresenceType.AVAILABLE ||
 | 
			
		||||
                this._currentPresence == Tp.ConnectionPresenceType.EXTENDED_AWAY)
 | 
			
		||||
                return Tp.ConnectionPresenceType.BUSY;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (sessionStatus == GnomeSession.PresenceStatus.IDLE) {
 | 
			
		||||
            // Only change presence if the current one is "more present" than
 | 
			
		||||
            // idle
 | 
			
		||||
            if (this._currentPresence != Tp.ConnectionPresenceType.OFFLINE)
 | 
			
		||||
                return Tp.ConnectionPresenceType.EXTENDED_AWAY;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return this._currentPresence;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _sessionStatusChanged: function(sessionStatus) {
 | 
			
		||||
        if (!this._imPresenceRestored)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (!this._sessionPresenceRestored) {
 | 
			
		||||
            let savedStatus = global.settings.get_int('saved-session-presence');
 | 
			
		||||
            if (sessionStatus != savedStatus) {
 | 
			
		||||
                this._presence.status = savedStatus;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            this._sessionPresenceRestored = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        global.settings.set_int('saved-session-presence', sessionStatus);
 | 
			
		||||
 | 
			
		||||
        let [presence, s, msg] = this._accountMgr.get_most_available_presence();
 | 
			
		||||
        let newPresence, status;
 | 
			
		||||
 | 
			
		||||
        if (sessionStatus == GnomeSession.PresenceStatus.AVAILABLE) {
 | 
			
		||||
            newPresence = this._previousPresence;
 | 
			
		||||
        } else if (sessionStatus == GnomeSession.PresenceStatus.BUSY) {
 | 
			
		||||
            // Only change presence if the current one is "more present" than
 | 
			
		||||
            // busy, or if coming back from idle
 | 
			
		||||
            if (presence == Tp.ConnectionPresenceType.AVAILABLE ||
 | 
			
		||||
                presence == Tp.ConnectionPresenceType.EXTENDED_AWAY) {
 | 
			
		||||
                newPresence = Tp.ConnectionPresenceType.BUSY;
 | 
			
		||||
            } else {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        } else if (sessionStatus == GnomeSession.PresenceStatus.IDLE) {
 | 
			
		||||
            // Only change presence if the current one is "more present" than
 | 
			
		||||
            // idle
 | 
			
		||||
            if (presence != Tp.ConnectionPresenceType.OFFLINE)
 | 
			
		||||
                newPresence = Tp.ConnectionPresenceType.EXTENDED_AWAY;
 | 
			
		||||
            else
 | 
			
		||||
                return;
 | 
			
		||||
        } else {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        let newPresence = this.getIMPresenceForSessionStatus(sessionStatus);
 | 
			
		||||
 | 
			
		||||
        if (newPresence == undefined)
 | 
			
		||||
        if (!newPresence || newPresence == presence)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        status = this._statusForPresence(newPresence);
 | 
			
		||||
        msg = msg ? msg : "";
 | 
			
		||||
        msg = msg ? msg : '';
 | 
			
		||||
 | 
			
		||||
        this._expectedPresence = newPresence;
 | 
			
		||||
        this._accountMgr.set_all_requested_presences(newPresence, status, msg);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function UserMenuButton() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UserMenuButton.prototype = {
 | 
			
		||||
    __proto__: PanelMenu.Button.prototype,
 | 
			
		||||
const UserMenuButton = new Lang.Class({
 | 
			
		||||
    Name: 'UserMenuButton',
 | 
			
		||||
    Extends: PanelMenu.Button,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        PanelMenu.Button.prototype._init.call(this, 0.0);
 | 
			
		||||
        let box = new St.BoxLayout({ name: 'panelStatusMenu' });
 | 
			
		||||
        this.actor.set_child(box);
 | 
			
		||||
        this.parent(0.0);
 | 
			
		||||
 | 
			
		||||
        let box = new St.BoxLayout({ name: 'panelUserMenu' });
 | 
			
		||||
        this.actor.add_actor(box);
 | 
			
		||||
 | 
			
		||||
        this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA });
 | 
			
		||||
 | 
			
		||||
@@ -380,7 +433,7 @@ UserMenuButton.prototype = {
 | 
			
		||||
        this._session = new GnomeSession.SessionManager();
 | 
			
		||||
        this._haveShutdown = true;
 | 
			
		||||
 | 
			
		||||
        this._account_mgr = Tp.AccountManager.dup()
 | 
			
		||||
        this._accountMgr = Tp.AccountManager.dup();
 | 
			
		||||
 | 
			
		||||
        this._upClient = new UPowerGlib.Client();
 | 
			
		||||
        this._screenSaverProxy = new ScreenSaver.ScreenSaverProxy();
 | 
			
		||||
@@ -403,13 +456,9 @@ UserMenuButton.prototype = {
 | 
			
		||||
        this._idleIcon = new St.Icon({ icon_name: 'user-idle',
 | 
			
		||||
                                       style_class: 'popup-menu-icon' });
 | 
			
		||||
 | 
			
		||||
        this._presence.connect('StatusChanged',
 | 
			
		||||
                               Lang.bind(this, this._updateSwitch));
 | 
			
		||||
        this._presence.getStatus(Lang.bind(this, this._updateSwitch));
 | 
			
		||||
 | 
			
		||||
        this._account_mgr.connect('most-available-presence-changed',
 | 
			
		||||
        this._accountMgr.connect('most-available-presence-changed',
 | 
			
		||||
                                  Lang.bind(this, this._updatePresenceIcon));
 | 
			
		||||
        this._account_mgr.prepare_async(null, Lang.bind(this,
 | 
			
		||||
        this._accountMgr.prepare_async(null, Lang.bind(this,
 | 
			
		||||
            function(mgr) {
 | 
			
		||||
                let [presence, s, msg] = mgr.get_most_available_presence();
 | 
			
		||||
                this._updatePresenceIcon(mgr, presence, s, msg);
 | 
			
		||||
@@ -419,10 +468,19 @@ UserMenuButton.prototype = {
 | 
			
		||||
        box.add(this._name, { y_align: St.Align.MIDDLE, y_fill: false });
 | 
			
		||||
        this._userLoadedId = this._user.connect('notify::is-loaded', Lang.bind(this, this._updateUserName));
 | 
			
		||||
        this._userChangedId = this._user.connect('changed', Lang.bind(this, this._updateUserName));
 | 
			
		||||
        this._updateUserName();
 | 
			
		||||
 | 
			
		||||
        this._createSubMenu();
 | 
			
		||||
 | 
			
		||||
        this._updateSwitch(this._presence.status);
 | 
			
		||||
        this._presence.connectSignal('StatusChanged', Lang.bind(this, function (proxy, senderName, [status]) {
 | 
			
		||||
            this._updateSwitch(status);
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        this._userManager.connect('notify::is-loaded',
 | 
			
		||||
                                  Lang.bind(this, this._updateSwitchUser));
 | 
			
		||||
        this._userManager.connect('notify::has-multiple-users',
 | 
			
		||||
                                  Lang.bind(this, this._updateSwitchUser));
 | 
			
		||||
        this._userManager.connect('user-added',
 | 
			
		||||
                                  Lang.bind(this, this._updateSwitchUser));
 | 
			
		||||
        this._userManager.connect('user-removed',
 | 
			
		||||
@@ -467,7 +525,9 @@ UserMenuButton.prototype = {
 | 
			
		||||
 | 
			
		||||
    _updateSwitchUser: function() {
 | 
			
		||||
        let allowSwitch = !this._lockdownSettings.get_boolean(DISABLE_USER_SWITCH_KEY);
 | 
			
		||||
        if (allowSwitch && this._userManager.can_switch ())
 | 
			
		||||
        if (allowSwitch &&
 | 
			
		||||
            this._userManager.can_switch() &&
 | 
			
		||||
            this._userManager.has_multiple_users)
 | 
			
		||||
            this._loginScreenItem.actor.show();
 | 
			
		||||
        else
 | 
			
		||||
            this._loginScreenItem.actor.hide();
 | 
			
		||||
@@ -521,7 +581,7 @@ UserMenuButton.prototype = {
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateSwitch: function(presence, status) {
 | 
			
		||||
    _updateSwitch: function(status) {
 | 
			
		||||
        let active = status == GnomeSession.PresenceStatus.AVAILABLE;
 | 
			
		||||
        this._notificationsSwitch.setToggleState(active);
 | 
			
		||||
    },
 | 
			
		||||
@@ -547,6 +607,7 @@ UserMenuButton.prototype = {
 | 
			
		||||
        item = new IMStatusChooserItem();
 | 
			
		||||
        item.connect('activate', Lang.bind(this, this._onMyAccountActivate));
 | 
			
		||||
        this.menu.addMenuItem(item);
 | 
			
		||||
        this._statusChooser = item;
 | 
			
		||||
 | 
			
		||||
        item = new PopupMenu.PopupSwitchMenuItem(_("Notifications"));
 | 
			
		||||
        item.connect('activate', Lang.bind(this, this._updatePresenceStatus));
 | 
			
		||||
@@ -594,9 +655,22 @@ UserMenuButton.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updatePresenceStatus: function(item, event) {
 | 
			
		||||
        let status = item.state ? GnomeSession.PresenceStatus.AVAILABLE
 | 
			
		||||
                                : GnomeSession.PresenceStatus.BUSY;
 | 
			
		||||
        this._presence.setStatus(status);
 | 
			
		||||
        let status;
 | 
			
		||||
 | 
			
		||||
        if (item.state) {
 | 
			
		||||
            status = GnomeSession.PresenceStatus.AVAILABLE;
 | 
			
		||||
        } else {
 | 
			
		||||
            status = GnomeSession.PresenceStatus.BUSY;
 | 
			
		||||
 | 
			
		||||
            let [presence, s, msg] = this._accountMgr.get_most_available_presence();
 | 
			
		||||
            let newPresence = this._statusChooser.getIMPresenceForSessionStatus(status);
 | 
			
		||||
            if (newPresence != presence &&
 | 
			
		||||
                newPresence == Tp.ConnectionPresenceType.BUSY)
 | 
			
		||||
                Main.notify(_("Your chat status will be set to busy"),
 | 
			
		||||
                            _("Notifications are now disabled, including chat messages. Your online status has been adjusted to let others know that you might not see their messages."));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._presence.status = status;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onMyAccountActivate: function() {
 | 
			
		||||
@@ -649,4 +723,4 @@ UserMenuButton.prototype = {
 | 
			
		||||
            this._session.ShutdownRemote();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
@@ -12,13 +12,12 @@ const St = imports.gi.St;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Search = imports.ui.search;
 | 
			
		||||
const SearchDisplay = imports.ui.searchDisplay;
 | 
			
		||||
const ShellEntry = imports.ui.shellEntry;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
 | 
			
		||||
function BaseTab(titleActor, pageActor, name, a11yIcon) {
 | 
			
		||||
    this._init(titleActor, pageActor, name, a11yIcon);
 | 
			
		||||
}
 | 
			
		||||
const BaseTab = new Lang.Class({
 | 
			
		||||
    Name: 'BaseTab',
 | 
			
		||||
 | 
			
		||||
BaseTab.prototype = {
 | 
			
		||||
    _init: function(titleActor, pageActor, name, a11yIcon) {
 | 
			
		||||
        this.title = titleActor;
 | 
			
		||||
        this.page = new St.Bin({ child: pageActor,
 | 
			
		||||
@@ -74,16 +73,13 @@ BaseTab.prototype = {
 | 
			
		||||
    _activate: function() {
 | 
			
		||||
        this.emit('activated');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(BaseTab.prototype);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function ViewTab(id, label, pageActor, a11yIcon) {
 | 
			
		||||
    this._init(id, label, pageActor, a11yIcon);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ViewTab.prototype = {
 | 
			
		||||
    __proto__: BaseTab.prototype,
 | 
			
		||||
const ViewTab = new Lang.Class({
 | 
			
		||||
    Name: 'ViewTab',
 | 
			
		||||
    Extends: BaseTab,
 | 
			
		||||
 | 
			
		||||
    _init: function(id, label, pageActor, a11yIcon) {
 | 
			
		||||
        this.id = id;
 | 
			
		||||
@@ -92,17 +88,14 @@ ViewTab.prototype = {
 | 
			
		||||
                                         style_class: 'view-tab-title' });
 | 
			
		||||
        titleActor.connect('clicked', Lang.bind(this, this._activate));
 | 
			
		||||
 | 
			
		||||
        BaseTab.prototype._init.call(this, titleActor, pageActor, label, a11yIcon);
 | 
			
		||||
        this.parent(titleActor, pageActor, label, a11yIcon);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function SearchTab() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SearchTab.prototype = {
 | 
			
		||||
    __proto__: BaseTab.prototype,
 | 
			
		||||
const SearchTab = new Lang.Class({
 | 
			
		||||
    Name: 'SearchTab',
 | 
			
		||||
    Extends: BaseTab,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.active = false;
 | 
			
		||||
@@ -120,6 +113,7 @@ SearchTab.prototype = {
 | 
			
		||||
                                     hint_text: _("Type to search..."),
 | 
			
		||||
                                     track_hover: true,
 | 
			
		||||
                                     can_focus: true });
 | 
			
		||||
        ShellEntry.addContextMenu(this._entry);
 | 
			
		||||
        this._text = this._entry.clutter_text;
 | 
			
		||||
        this._text.connect('key-press-event', Lang.bind(this, this._onKeyPress));
 | 
			
		||||
 | 
			
		||||
@@ -134,11 +128,7 @@ SearchTab.prototype = {
 | 
			
		||||
        this._iconClickedId = 0;
 | 
			
		||||
 | 
			
		||||
        this._searchResults = new SearchDisplay.SearchResults(this._searchSystem, this._openSearchSystem);
 | 
			
		||||
        BaseTab.prototype._init.call(this,
 | 
			
		||||
                                     this._entry,
 | 
			
		||||
                                     this._searchResults.actor,
 | 
			
		||||
                                     _("Search"),
 | 
			
		||||
                                     'edit-find');
 | 
			
		||||
        this.parent(this._entry, this._searchResults.actor, _("Search"), 'edit-find');
 | 
			
		||||
 | 
			
		||||
        this._text.connect('text-changed', Lang.bind(this, this._onTextChanged));
 | 
			
		||||
        this._text.connect('key-press-event', Lang.bind(this, function (o, e) {
 | 
			
		||||
@@ -164,7 +154,7 @@ SearchTab.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hide: function() {
 | 
			
		||||
        BaseTab.prototype.hide.call(this);
 | 
			
		||||
        this.parent();
 | 
			
		||||
 | 
			
		||||
        // Leave the entry focused when it doesn't have any text;
 | 
			
		||||
        // when replacing a selected search term, Clutter emits
 | 
			
		||||
@@ -289,9 +279,11 @@ SearchTab.prototype = {
 | 
			
		||||
    _onCapturedEvent: function(actor, event) {
 | 
			
		||||
        if (event.type() == Clutter.EventType.BUTTON_PRESS) {
 | 
			
		||||
            let source = event.get_source();
 | 
			
		||||
            if (source != this._text && this._text.text == '') {
 | 
			
		||||
            if (source != this._text && this._text.text == '' &&
 | 
			
		||||
                !Main.layoutManager.keyboardBox.contains(source)) {
 | 
			
		||||
                // the user clicked outside after activating the entry, but
 | 
			
		||||
                // with no search term entered - cancel the search
 | 
			
		||||
                // with no search term entered and no keyboard button pressed
 | 
			
		||||
                // - cancel the search
 | 
			
		||||
                this._reset();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -306,14 +298,12 @@ SearchTab.prototype = {
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function ViewSelector() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const ViewSelector = new Lang.Class({
 | 
			
		||||
    Name: 'ViewSelector',
 | 
			
		||||
 | 
			
		||||
ViewSelector.prototype = {
 | 
			
		||||
    _init : function() {
 | 
			
		||||
        this.actor = new St.BoxLayout({ name: 'viewSelector',
 | 
			
		||||
                                        vertical: true });
 | 
			
		||||
@@ -573,5 +563,5 @@ ViewSelector.prototype = {
 | 
			
		||||
    removeSearchProvider: function(provider) {
 | 
			
		||||
        this._searchTab.removeSearchProvider(provider);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(ViewSelector.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
@@ -6,41 +6,14 @@ const Shell = imports.gi.Shell;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const MessageTray = imports.ui.messageTray;
 | 
			
		||||
 | 
			
		||||
function WindowAttentionHandler() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const WindowAttentionHandler = new Lang.Class({
 | 
			
		||||
    Name: 'WindowAttentionHandler',
 | 
			
		||||
 | 
			
		||||
WindowAttentionHandler.prototype = {
 | 
			
		||||
    _init : function() {
 | 
			
		||||
        this._startupIds = {};
 | 
			
		||||
        this._tracker = Shell.WindowTracker.get_default();
 | 
			
		||||
        this._tracker.connect('startup-sequence-changed', Lang.bind(this, this._onStartupSequenceChanged));
 | 
			
		||||
 | 
			
		||||
        global.display.connect('window-demands-attention', Lang.bind(this, this._onWindowDemandsAttention));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onStartupSequenceChanged : function(tracker) {
 | 
			
		||||
        let sequences = tracker.get_startup_sequences();
 | 
			
		||||
        this._startupIds = {};
 | 
			
		||||
        for(let i = 0; i < sequences.length; i++) {
 | 
			
		||||
            this._startupIds[sequences[i].get_id()] = true;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getTitle : function(app, window) {
 | 
			
		||||
        if (this._startupIds[window.get_startup_id()])
 | 
			
		||||
            return app.get_name();
 | 
			
		||||
        else
 | 
			
		||||
            return window.title;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getBanner : function(app, window) {
 | 
			
		||||
        if (this._startupIds[window.get_startup_id()])
 | 
			
		||||
            return _("%s has finished starting").format(app.get_name());
 | 
			
		||||
        else
 | 
			
		||||
            return _("'%s' is ready").format(window.title);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onWindowDemandsAttention : function(display, window) {
 | 
			
		||||
        // We don't want to show the notification when the window is already focused,
 | 
			
		||||
        // because this is rather pointless.
 | 
			
		||||
@@ -57,24 +30,25 @@ WindowAttentionHandler.prototype = {
 | 
			
		||||
        let source = new Source(app, window);
 | 
			
		||||
        Main.messageTray.add(source);
 | 
			
		||||
 | 
			
		||||
        let notification = new MessageTray.Notification(source, this._getTitle(app, window), this._getBanner(app, window));
 | 
			
		||||
        let banner = _("'%s' is ready").format(window.title);
 | 
			
		||||
        let title = app.get_name();
 | 
			
		||||
 | 
			
		||||
        let notification = new MessageTray.Notification(source, title, banner);
 | 
			
		||||
        source.notify(notification);
 | 
			
		||||
 | 
			
		||||
        source.signalIDs.push(window.connect('notify::title', Lang.bind(this, function(win) {
 | 
			
		||||
                                    notification.update(this._getTitle(app, win), this._getBanner(app, win));
 | 
			
		||||
                              })));
 | 
			
		||||
        source.signalIDs.push(window.connect('notify::title',
 | 
			
		||||
                                             Lang.bind(this, function() {
 | 
			
		||||
                                                 notification.update(title, banner);
 | 
			
		||||
                                             })));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function Source(app, window) {
 | 
			
		||||
    this._init(app, window);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Source.prototype = {
 | 
			
		||||
    __proto__ : MessageTray.Source.prototype,
 | 
			
		||||
const Source = new Lang.Class({
 | 
			
		||||
    Name: 'WindowAttentionSource',
 | 
			
		||||
    Extends: MessageTray.Source,
 | 
			
		||||
 | 
			
		||||
    _init: function(app, window) {
 | 
			
		||||
        MessageTray.Source.prototype._init.call(this, app.get_name());
 | 
			
		||||
        this.parent(app.get_name());
 | 
			
		||||
        this._window = window;
 | 
			
		||||
        this._app = app;
 | 
			
		||||
        this._setSummaryIcon(this.createNotificationIcon());
 | 
			
		||||
@@ -102,4 +76,4 @@ Source.prototype = {
 | 
			
		||||
        Main.activateWindow(this._window);
 | 
			
		||||
        this.destroy();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
@@ -19,47 +19,53 @@ const UNDIM_TIME = 0.250;
 | 
			
		||||
 | 
			
		||||
var dimShader = undefined;
 | 
			
		||||
 | 
			
		||||
function getDimShader() {
 | 
			
		||||
    if (dimShader === null)
 | 
			
		||||
        return null;
 | 
			
		||||
    if (!dimShader) {
 | 
			
		||||
        let source = Shell.get_file_contents_utf8_sync(global.datadir + '/shaders/dim-window.glsl');
 | 
			
		||||
        try {
 | 
			
		||||
            let shader = new Clutter.Shader();
 | 
			
		||||
            shader.set_fragment_source(source, -1);
 | 
			
		||||
            shader.compile();
 | 
			
		||||
 | 
			
		||||
            dimShader = shader;
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            log(e.message);
 | 
			
		||||
            dimShader = null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
function getDimShaderSource() {
 | 
			
		||||
    if (!dimShader)
 | 
			
		||||
        dimShader = Shell.get_file_contents_utf8_sync(global.datadir + '/shaders/dim-window.glsl');
 | 
			
		||||
    return dimShader;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function WindowDimmer(actor) {
 | 
			
		||||
    this._init(actor);
 | 
			
		||||
function getTopInvisibleBorder(metaWindow) {
 | 
			
		||||
    let outerRect = metaWindow.get_outer_rect();
 | 
			
		||||
    let inputRect = metaWindow.get_input_rect();
 | 
			
		||||
    return outerRect.y - inputRect.y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WindowDimmer.prototype = {
 | 
			
		||||
const WindowDimmer = new Lang.Class({
 | 
			
		||||
    Name: 'WindowDimmer',
 | 
			
		||||
 | 
			
		||||
    _init: function(actor) {
 | 
			
		||||
        if (Clutter.feature_available(Clutter.FeatureFlags.SHADERS_GLSL)) {
 | 
			
		||||
            this._effect = new Clutter.ShaderEffect({ shader_type: Clutter.ShaderType.FRAGMENT_SHADER });
 | 
			
		||||
            this._effect.set_shader_source(getDimShaderSource());
 | 
			
		||||
        } else {
 | 
			
		||||
            this._effect = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.actor = actor;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    set dimFraction(fraction) {
 | 
			
		||||
        this._dimFraction = fraction;
 | 
			
		||||
        let shader = getDimShader();
 | 
			
		||||
        if (!Meta.prefs_get_attach_modal_dialogs() || !shader) {
 | 
			
		||||
            this.actor.set_shader(null);
 | 
			
		||||
 | 
			
		||||
        if (this._effect == null)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (!Meta.prefs_get_attach_modal_dialogs()) {
 | 
			
		||||
            this._effect.enabled = false;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (fraction > 0.01) {
 | 
			
		||||
            this.actor.set_shader(shader);
 | 
			
		||||
            this.actor.set_shader_param_float('height', this.actor.get_height());
 | 
			
		||||
            this.actor.set_shader_param_float('fraction', fraction);
 | 
			
		||||
        } else
 | 
			
		||||
            this.actor.set_shader(null);
 | 
			
		||||
            Shell.shader_effect_set_double_uniform(this._effect, 'height', this.actor.get_height());
 | 
			
		||||
            Shell.shader_effect_set_double_uniform(this._effect, 'fraction', fraction);
 | 
			
		||||
 | 
			
		||||
            if (!this._effect.actor)
 | 
			
		||||
                this.actor.add_effect(this._effect);
 | 
			
		||||
        } else {
 | 
			
		||||
            if (this._effect.actor)
 | 
			
		||||
                this.actor.remove_effect(this._effect);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get dimFraction() {
 | 
			
		||||
@@ -67,24 +73,21 @@ WindowDimmer.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _dimFraction: 0.0
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function getWindowDimmer(texture) {
 | 
			
		||||
    if (!texture._windowDimmer)
 | 
			
		||||
        texture._windowDimmer = new WindowDimmer(texture);
 | 
			
		||||
function getWindowDimmer(actor) {
 | 
			
		||||
    if (!actor._windowDimmer)
 | 
			
		||||
        actor._windowDimmer = new WindowDimmer(actor);
 | 
			
		||||
 | 
			
		||||
    return texture._windowDimmer;
 | 
			
		||||
    return actor._windowDimmer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function WindowManager() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const WindowManager = new Lang.Class({
 | 
			
		||||
    Name: 'WindowManager',
 | 
			
		||||
 | 
			
		||||
WindowManager.prototype = {
 | 
			
		||||
    _init : function() {
 | 
			
		||||
        this._shellwm =  global.window_manager;
 | 
			
		||||
 | 
			
		||||
        this._keyBindingHandlers = [];
 | 
			
		||||
        this._minimizing = [];
 | 
			
		||||
        this._maximizing = [];
 | 
			
		||||
        this._unmaximizing = [];
 | 
			
		||||
@@ -113,15 +116,24 @@ WindowManager.prototype = {
 | 
			
		||||
        this._shellwm.connect('destroy', Lang.bind(this, this._destroyWindow));
 | 
			
		||||
 | 
			
		||||
        this._workspaceSwitcherPopup = null;
 | 
			
		||||
        this.setKeybindingHandler('switch_to_workspace_left', Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        this.setKeybindingHandler('switch_to_workspace_right', Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        this.setKeybindingHandler('switch_to_workspace_up', Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        this.setKeybindingHandler('switch_to_workspace_down', Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        this.setKeybindingHandler('switch_windows', Lang.bind(this, this._startAppSwitcher));
 | 
			
		||||
        this.setKeybindingHandler('switch_group', Lang.bind(this, this._startAppSwitcher));
 | 
			
		||||
        this.setKeybindingHandler('switch_windows_backward', Lang.bind(this, this._startAppSwitcher));
 | 
			
		||||
        this.setKeybindingHandler('switch_group_backward', Lang.bind(this, this._startAppSwitcher));
 | 
			
		||||
        this.setKeybindingHandler('switch_panels', Lang.bind(this, this._startA11ySwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('switch-to-workspace-left',
 | 
			
		||||
                                            Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('switch-to-workspace-right',
 | 
			
		||||
                                            Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('switch-to-workspace-up',
 | 
			
		||||
                                            Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('switch-to-workspace-down',
 | 
			
		||||
                                            Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('switch-windows',
 | 
			
		||||
                                            Lang.bind(this, this._startAppSwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('switch-group',
 | 
			
		||||
                                            Lang.bind(this, this._startAppSwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('switch-windows-backward',
 | 
			
		||||
                                            Lang.bind(this, this._startAppSwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('switch-group-backward',
 | 
			
		||||
                                            Lang.bind(this, this._startAppSwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('switch-panels',
 | 
			
		||||
                                            Lang.bind(this, this._startA11ySwitcher));
 | 
			
		||||
 | 
			
		||||
        Main.overview.connect('showing', Lang.bind(this, function() {
 | 
			
		||||
            for (let i = 0; i < this._dimmedWindows.length; i++)
 | 
			
		||||
@@ -133,16 +145,6 @@ WindowManager.prototype = {
 | 
			
		||||
        }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setKeybindingHandler: function(keybinding, handler){
 | 
			
		||||
        if (this._keyBindingHandlers[keybinding])
 | 
			
		||||
            this._shellwm.disconnect(this._keyBindingHandlers[keybinding]);
 | 
			
		||||
        else
 | 
			
		||||
            this._shellwm.takeover_keybinding(keybinding);
 | 
			
		||||
 | 
			
		||||
        this._keyBindingHandlers[keybinding] =
 | 
			
		||||
            this._shellwm.connect('keybinding::' + keybinding, handler);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    blockAnimations: function() {
 | 
			
		||||
        this._animationBlockCount++;
 | 
			
		||||
    },
 | 
			
		||||
@@ -152,7 +154,7 @@ WindowManager.prototype = {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _shouldAnimate : function(actor) {
 | 
			
		||||
        if (Main.overview.visible || this._animationsBlocked > 0)
 | 
			
		||||
        if (Main.overview.visible || this._animationBlockCount > 0)
 | 
			
		||||
            return false;
 | 
			
		||||
        if (actor && (actor.meta_window.get_window_type() != Meta.WindowType.NORMAL))
 | 
			
		||||
            return false;
 | 
			
		||||
@@ -268,30 +270,28 @@ WindowManager.prototype = {
 | 
			
		||||
        let actor = window.get_compositor_private();
 | 
			
		||||
        if (!actor)
 | 
			
		||||
            return;
 | 
			
		||||
        let texture = actor.get_texture();
 | 
			
		||||
        if (animate)
 | 
			
		||||
            Tweener.addTween(getWindowDimmer(texture),
 | 
			
		||||
            Tweener.addTween(getWindowDimmer(actor),
 | 
			
		||||
                             { dimFraction: 1.0,
 | 
			
		||||
                               time: DIM_TIME,
 | 
			
		||||
                               transition: 'linear'
 | 
			
		||||
                             });
 | 
			
		||||
        else
 | 
			
		||||
            getWindowDimmer(texture).dimFraction = 1.0;
 | 
			
		||||
            getWindowDimmer(actor).dimFraction = 1.0;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _undimWindow: function(window, animate) {
 | 
			
		||||
        let actor = window.get_compositor_private();
 | 
			
		||||
        if (!actor)
 | 
			
		||||
            return;
 | 
			
		||||
        let texture = actor.get_texture();
 | 
			
		||||
        if (animate)
 | 
			
		||||
            Tweener.addTween(getWindowDimmer(texture),
 | 
			
		||||
            Tweener.addTween(getWindowDimmer(actor),
 | 
			
		||||
                             { dimFraction: 0.0,
 | 
			
		||||
                               time: UNDIM_TIME,
 | 
			
		||||
                               transition: 'linear'
 | 
			
		||||
                             });
 | 
			
		||||
        else
 | 
			
		||||
            getWindowDimmer(texture).dimFraction = 0.0;
 | 
			
		||||
            getWindowDimmer(actor).dimFraction = 0.0;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _mapWindow : function(shellwm, actor) {
 | 
			
		||||
@@ -528,37 +528,41 @@ WindowManager.prototype = {
 | 
			
		||||
        shellwm.completed_switch_workspace();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _startAppSwitcher : function(shellwm, binding, window, backwards) {
 | 
			
		||||
    _startAppSwitcher : function(display, screen, window, binding) {
 | 
			
		||||
        /* prevent a corner case where both popups show up at once */
 | 
			
		||||
        if (this._workspaceSwitcherPopup != null)
 | 
			
		||||
            this._workspaceSwitcherPopup.actor.hide();
 | 
			
		||||
 | 
			
		||||
        let tabPopup = new AltTab.AltTabPopup();
 | 
			
		||||
 | 
			
		||||
        if (!tabPopup.show(backwards, binding))
 | 
			
		||||
        let modifiers = binding.get_modifiers();
 | 
			
		||||
        let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
 | 
			
		||||
        if (!tabPopup.show(backwards, binding.get_name(), binding.get_mask()))
 | 
			
		||||
            tabPopup.destroy();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _startA11ySwitcher : function(shellwm, binding, window, backwards) {
 | 
			
		||||
        Main.ctrlAltTabManager.popup(backwards);
 | 
			
		||||
    _startA11ySwitcher : function(display, screen, window, binding) {
 | 
			
		||||
        let modifiers = binding.get_modifiers();
 | 
			
		||||
        let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
 | 
			
		||||
        Main.ctrlAltTabManager.popup(backwards, binding.get_mask());
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showWorkspaceSwitcher : function(shellwm, binding, window, backwards) {
 | 
			
		||||
        if (global.screen.n_workspaces == 1)
 | 
			
		||||
    _showWorkspaceSwitcher : function(display, screen, window, binding) {
 | 
			
		||||
        if (screen.n_workspaces == 1)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (this._workspaceSwitcherPopup == null)
 | 
			
		||||
            this._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup();
 | 
			
		||||
 | 
			
		||||
        if (binding == 'switch_to_workspace_up')
 | 
			
		||||
        if (binding.get_name() == 'switch-to-workspace-up')
 | 
			
		||||
            this.actionMoveWorkspaceUp();
 | 
			
		||||
        else if (binding == 'switch_to_workspace_down')
 | 
			
		||||
        else if (binding.get_name() == 'switch-to-workspace-down')
 | 
			
		||||
            this.actionMoveWorkspaceDown();
 | 
			
		||||
        // left/right would effectively act as synonyms for up/down if we enabled them;
 | 
			
		||||
        // but that could be considered confusing.
 | 
			
		||||
        // else if (binding == 'switch_to_workspace_left')
 | 
			
		||||
        // else if (binding.get_name() == 'switch-to-workspace-left')
 | 
			
		||||
        //   this.actionMoveWorkspaceLeft();
 | 
			
		||||
        // else if (binding == 'switch_to_workspace_right')
 | 
			
		||||
        // else if (binding.get_name() == 'switch-to-workspace-right')
 | 
			
		||||
        //   this.actionMoveWorkspaceRight();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -619,4 +623,4 @@ WindowManager.prototype = {
 | 
			
		||||
        if (!Main.overview.visible)
 | 
			
		||||
            this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.DOWN, indexToActivate);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GConf = imports.gi.GConf;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
@@ -28,7 +28,8 @@ const CLOSE_BUTTON_FADE_TIME = 0.1;
 | 
			
		||||
 | 
			
		||||
const DRAGGING_WINDOW_OPACITY = 100;
 | 
			
		||||
 | 
			
		||||
const BUTTON_LAYOUT_KEY = '/desktop/gnome/shell/windows/button_layout';
 | 
			
		||||
const BUTTON_LAYOUT_SCHEMA = 'org.gnome.shell.overrides';
 | 
			
		||||
const BUTTON_LAYOUT_KEY = 'button-layout';
 | 
			
		||||
 | 
			
		||||
// Define a layout scheme for small window counts. For larger
 | 
			
		||||
// counts we fall back to an algorithm. We need more schemes here
 | 
			
		||||
@@ -55,11 +56,13 @@ function _clamp(value, min, max) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function ScaledPoint(x, y, scaleX, scaleY) {
 | 
			
		||||
    [this.x, this.y, this.scaleX, this.scaleY] = arguments;
 | 
			
		||||
}
 | 
			
		||||
const ScaledPoint = new Lang.Class({
 | 
			
		||||
    Name: 'ScaledPoint',
 | 
			
		||||
 | 
			
		||||
    _init: function(x, y, scaleX, scaleY) {
 | 
			
		||||
        [this.x, this.y, this.scaleX, this.scaleY] = arguments;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
ScaledPoint.prototype = {
 | 
			
		||||
    getPosition : function() {
 | 
			
		||||
        return [this.x, this.y];
 | 
			
		||||
    },
 | 
			
		||||
@@ -85,14 +88,12 @@ ScaledPoint.prototype = {
 | 
			
		||||
        return [_interpolate(this.scaleX, other.scaleX, step),
 | 
			
		||||
                _interpolate(this.scaleY, other.scaleY, step)];
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function WindowClone(realWindow) {
 | 
			
		||||
    this._init(realWindow);
 | 
			
		||||
}
 | 
			
		||||
const WindowClone = new Lang.Class({
 | 
			
		||||
    Name: 'WindowClone',
 | 
			
		||||
 | 
			
		||||
WindowClone.prototype = {
 | 
			
		||||
    _init : function(realWindow) {
 | 
			
		||||
        this.realWindow = realWindow;
 | 
			
		||||
        this.metaWindow = realWindow.meta_window;
 | 
			
		||||
@@ -135,8 +136,11 @@ WindowClone.prototype = {
 | 
			
		||||
        this._realWindowDestroyId = this.realWindow.connect('destroy',
 | 
			
		||||
            Lang.bind(this, this._disconnectRealWindowSignals));
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('button-release-event',
 | 
			
		||||
                           Lang.bind(this, this._onButtonRelease));
 | 
			
		||||
        let clickAction = new Clutter.ClickAction();
 | 
			
		||||
        clickAction.connect('clicked', Lang.bind(this, this._onClicked));
 | 
			
		||||
        clickAction.connect('long-press', Lang.bind(this, this._onLongPress));
 | 
			
		||||
 | 
			
		||||
        this.actor.add_action(clickAction);
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('scroll-event',
 | 
			
		||||
                           Lang.bind(this, this._onScroll));
 | 
			
		||||
@@ -147,6 +151,7 @@ WindowClone.prototype = {
 | 
			
		||||
 | 
			
		||||
        this._draggable = DND.makeDraggable(this.actor,
 | 
			
		||||
                                            { restoreOnSuccess: true,
 | 
			
		||||
                                              manualMode: true,
 | 
			
		||||
                                              dragActorMaxSize: WINDOW_DND_SIZE,
 | 
			
		||||
                                              dragActorOpacity: DRAGGING_WINDOW_OPACITY });
 | 
			
		||||
        this._draggable.connect('drag-begin', Lang.bind(this, this._onDragBegin));
 | 
			
		||||
@@ -345,9 +350,27 @@ WindowClone.prototype = {
 | 
			
		||||
        this._zoomStep           = undefined;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onButtonRelease : function (actor, event) {
 | 
			
		||||
    _onClicked: function(action, actor) {
 | 
			
		||||
        this._selected = true;
 | 
			
		||||
        this.emit('selected', event.get_time());
 | 
			
		||||
        this.emit('selected', global.get_current_time());
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onLongPress: function(action, actor, state) {
 | 
			
		||||
        // Take advantage of the Clutter policy to consider
 | 
			
		||||
        // a long-press canceled when the pointer movement
 | 
			
		||||
        // exceeds dnd-drag-threshold to manually start the drag
 | 
			
		||||
        if (state == Clutter.LongPressState.CANCEL) {
 | 
			
		||||
            // A click cancels a long-press before any click handler is
 | 
			
		||||
            // run - make sure to not start a drag in that case
 | 
			
		||||
            Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
 | 
			
		||||
                function() {
 | 
			
		||||
                    if (this._selected)
 | 
			
		||||
                        return;
 | 
			
		||||
                    let [x, y] = action.get_coords();
 | 
			
		||||
                    this._draggable.startDrag(x, y, global.get_current_time());
 | 
			
		||||
                }));
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDragBegin : function (draggable, time) {
 | 
			
		||||
@@ -395,7 +418,7 @@ WindowClone.prototype = {
 | 
			
		||||
 | 
			
		||||
        this.emit('drag-end');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(WindowClone.prototype);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -404,11 +427,9 @@ Signals.addSignalMethods(WindowClone.prototype);
 | 
			
		||||
 * @parentActor: The actor which will be the parent of all overlay items
 | 
			
		||||
 *               such as app icon and window caption
 | 
			
		||||
 */
 | 
			
		||||
function WindowOverlay(windowClone, parentActor) {
 | 
			
		||||
    this._init(windowClone, parentActor);
 | 
			
		||||
}
 | 
			
		||||
const WindowOverlay = new Lang.Class({
 | 
			
		||||
    Name: 'WindowOverlay',
 | 
			
		||||
 | 
			
		||||
WindowOverlay.prototype = {
 | 
			
		||||
    _init : function(windowClone, parentActor) {
 | 
			
		||||
        let metaWindow = windowClone.metaWindow;
 | 
			
		||||
 | 
			
		||||
@@ -505,8 +526,8 @@ WindowOverlay.prototype = {
 | 
			
		||||
        let button = this.closeButton;
 | 
			
		||||
        let title = this.title;
 | 
			
		||||
 | 
			
		||||
        let gconf = GConf.Client.get_default();
 | 
			
		||||
        let layout = gconf.get_string(BUTTON_LAYOUT_KEY);
 | 
			
		||||
        let settings = new Gio.Settings({ schema: BUTTON_LAYOUT_SCHEMA });
 | 
			
		||||
        let layout = settings.get_string(BUTTON_LAYOUT_KEY);
 | 
			
		||||
        let rtl = St.Widget.get_default_direction() == St.TextDirection.RTL;
 | 
			
		||||
 | 
			
		||||
        let split = layout.split(":");
 | 
			
		||||
@@ -619,7 +640,7 @@ WindowOverlay.prototype = {
 | 
			
		||||
 | 
			
		||||
        this._parentActor.queue_relayout();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(WindowOverlay.prototype);
 | 
			
		||||
 | 
			
		||||
const WindowPositionFlags = {
 | 
			
		||||
@@ -630,11 +651,9 @@ const WindowPositionFlags = {
 | 
			
		||||
/**
 | 
			
		||||
 * @metaWorkspace: a #Meta.Workspace, or null
 | 
			
		||||
 */
 | 
			
		||||
function Workspace(metaWorkspace, monitorIndex) {
 | 
			
		||||
    this._init(metaWorkspace, monitorIndex);
 | 
			
		||||
}
 | 
			
		||||
const Workspace = new Lang.Class({
 | 
			
		||||
    Name: 'Workspace',
 | 
			
		||||
 | 
			
		||||
Workspace.prototype = {
 | 
			
		||||
    _init : function(metaWorkspace, monitorIndex) {
 | 
			
		||||
        // When dragging a window, we use this slot for reserve space.
 | 
			
		||||
        this._reservedSlot = null;
 | 
			
		||||
@@ -1495,6 +1514,6 @@ Workspace.prototype = {
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Signals.addSignalMethods(Workspace.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
@@ -15,11 +15,9 @@ const DISPLAY_TIMEOUT = 600;
 | 
			
		||||
const UP = -1;
 | 
			
		||||
const DOWN = 1;
 | 
			
		||||
 | 
			
		||||
function WorkspaceSwitcherPopup() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const WorkspaceSwitcherPopup = new Lang.Class({
 | 
			
		||||
    Name: 'WorkspaceSwitcherPopup',
 | 
			
		||||
 | 
			
		||||
WorkspaceSwitcherPopup.prototype = {
 | 
			
		||||
    _init : function() {
 | 
			
		||||
        this.actor = new St.Group({ reactive: true,
 | 
			
		||||
                                         x: 0,
 | 
			
		||||
@@ -158,4 +156,4 @@ WorkspaceSwitcherPopup.prototype = {
 | 
			
		||||
                                            onCompleteScope: this
 | 
			
		||||
                                           });
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
@@ -20,11 +20,14 @@ let MAX_THUMBNAIL_SCALE = 1/8.;
 | 
			
		||||
const RESCALE_ANIMATION_TIME = 0.2;
 | 
			
		||||
const SLIDE_ANIMATION_TIME = 0.2;
 | 
			
		||||
 | 
			
		||||
function WindowClone(realWindow) {
 | 
			
		||||
    this._init(realWindow);
 | 
			
		||||
}
 | 
			
		||||
// When we create workspaces by dragging, we add a "cut" into the top and
 | 
			
		||||
// bottom of each workspace so that the user doesn't have to hit the
 | 
			
		||||
// placeholder exactly.
 | 
			
		||||
const WORKSPACE_CUT_SIZE = 10;
 | 
			
		||||
 | 
			
		||||
const WindowClone = new Lang.Class({
 | 
			
		||||
    Name: 'WindowClone',
 | 
			
		||||
 | 
			
		||||
WindowClone.prototype = {
 | 
			
		||||
    _init : function(realWindow) {
 | 
			
		||||
        this.actor = new Clutter.Clone({ source: realWindow.get_texture(),
 | 
			
		||||
                                         reactive: true });
 | 
			
		||||
@@ -121,7 +124,7 @@ WindowClone.prototype = {
 | 
			
		||||
 | 
			
		||||
        this.emit('drag-end');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(WindowClone.prototype);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -139,11 +142,9 @@ const ThumbnailState = {
 | 
			
		||||
/**
 | 
			
		||||
 * @metaWorkspace: a #Meta.Workspace
 | 
			
		||||
 */
 | 
			
		||||
function WorkspaceThumbnail(metaWorkspace) {
 | 
			
		||||
    this._init(metaWorkspace);
 | 
			
		||||
}
 | 
			
		||||
const WorkspaceThumbnail = new Lang.Class({
 | 
			
		||||
    Name: 'WorkspaceThumbnail',
 | 
			
		||||
 | 
			
		||||
WorkspaceThumbnail.prototype = {
 | 
			
		||||
    _init : function(metaWorkspace) {
 | 
			
		||||
        this.metaWorkspace = metaWorkspace;
 | 
			
		||||
        this.monitorIndex = Main.layoutManager.primaryIndex;
 | 
			
		||||
@@ -422,6 +423,11 @@ WorkspaceThumbnail.prototype = {
 | 
			
		||||
        if (this.state > ThumbnailState.NORMAL)
 | 
			
		||||
            return DND.DragMotionResult.CONTINUE;
 | 
			
		||||
 | 
			
		||||
        let [w, h] = this.actor.get_transformed_size();
 | 
			
		||||
        // Bubble up if we're in the "workspace cut".
 | 
			
		||||
        if (y < WORKSPACE_CUT_SIZE || y > h - WORKSPACE_CUT_SIZE)
 | 
			
		||||
            return DND.DragMotionResult.CONTINUE;
 | 
			
		||||
 | 
			
		||||
        if (source.realWindow && !this._isMyWindow(source.realWindow))
 | 
			
		||||
            return DND.DragMotionResult.MOVE_DROP;
 | 
			
		||||
        if (source.shellWorkspaceLaunch)
 | 
			
		||||
@@ -459,22 +465,21 @@ WorkspaceThumbnail.prototype = {
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Signals.addSignalMethods(WorkspaceThumbnail.prototype);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function ThumbnailsBox() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const ThumbnailsBox = new Lang.Class({
 | 
			
		||||
    Name: 'ThumbnailsBox',
 | 
			
		||||
 | 
			
		||||
ThumbnailsBox.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.actor = new Shell.GenericContainer({ style_class: 'workspace-thumbnails',
 | 
			
		||||
                                                  request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT });
 | 
			
		||||
        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._delegate = this;
 | 
			
		||||
 | 
			
		||||
        // When we animate the scale, we don't animate the requested size of the thumbnails, rather
 | 
			
		||||
        // we ask for our final size and then animate within that size. This slightly simplifies the
 | 
			
		||||
@@ -498,6 +503,10 @@ ThumbnailsBox.prototype = {
 | 
			
		||||
        this._indicator = indicator;
 | 
			
		||||
        this.actor.add_actor(indicator);
 | 
			
		||||
 | 
			
		||||
        this._dropPlaceholderPos = -1;
 | 
			
		||||
        this._dropPlaceholder = new St.Bin({ style_class: 'placeholder' });
 | 
			
		||||
        this.actor.add_actor(this._dropPlaceholder);
 | 
			
		||||
 | 
			
		||||
        this._targetScale = 0;
 | 
			
		||||
        this._scale = 0;
 | 
			
		||||
        this._pendingScaleUpdate = false;
 | 
			
		||||
@@ -512,6 +521,83 @@ ThumbnailsBox.prototype = {
 | 
			
		||||
        this._thumbnails = [];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // Draggable target interface
 | 
			
		||||
    handleDragOver : function(source, actor, x, y, time) {
 | 
			
		||||
        if (!source.realWindow && !source.shellWorkspaceLaunch)
 | 
			
		||||
            return DND.DragMotionResult.CONTINUE;
 | 
			
		||||
 | 
			
		||||
        let spacing = this.actor.get_theme_node().get_length('spacing');
 | 
			
		||||
        let thumbHeight = this._porthole.height * this._scale;
 | 
			
		||||
 | 
			
		||||
        let workspace = -1;
 | 
			
		||||
        let firstThumbY = this._thumbnails[0].actor.y;
 | 
			
		||||
        for (let i = 0; i < this._thumbnails.length; i ++) {
 | 
			
		||||
            let targetBase = firstThumbY + (thumbHeight + spacing) * i;
 | 
			
		||||
 | 
			
		||||
            // Allow the reorder target to have a 10px "cut" into
 | 
			
		||||
            // each side of the thumbnail, to make dragging onto the
 | 
			
		||||
            // placeholder easier
 | 
			
		||||
            let targetTop = targetBase - spacing - WORKSPACE_CUT_SIZE;
 | 
			
		||||
            let targetBottom = targetBase + WORKSPACE_CUT_SIZE;
 | 
			
		||||
 | 
			
		||||
            // Expand the target to include the placeholder, if it exists.
 | 
			
		||||
            if (i == this._dropPlaceholderPos)
 | 
			
		||||
                targetBottom += this._dropPlaceholder.get_height();
 | 
			
		||||
 | 
			
		||||
            if (y > targetTop && y <= targetBottom) {
 | 
			
		||||
                workspace = i;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._dropPlaceholderPos = workspace;
 | 
			
		||||
        this.actor.queue_relayout();
 | 
			
		||||
 | 
			
		||||
        if (workspace == -1)
 | 
			
		||||
            return DND.DragMotionResult.CONTINUE;
 | 
			
		||||
 | 
			
		||||
        return DND.DragMotionResult.MOVE_DROP;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    acceptDrop: function(source, actor, x, y, time) {
 | 
			
		||||
        if (this._dropPlaceholderPos == -1)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (!source.realWindow && !source.shellWorkspaceLaunch)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        let isWindow = !!source.realWindow;
 | 
			
		||||
 | 
			
		||||
        // To create a new workspace, we first slide all the windows on workspaces
 | 
			
		||||
        // below us to the next workspace, leaving a blank workspace for us to recycle.
 | 
			
		||||
        let newWorkspaceIndex;
 | 
			
		||||
        [newWorkspaceIndex, this._dropPlaceholderPos] = [this._dropPlaceholderPos, -1];
 | 
			
		||||
 | 
			
		||||
        // Nab all the windows below us.
 | 
			
		||||
        let windows = global.get_window_actors().filter(function(win) {
 | 
			
		||||
            if (isWindow)
 | 
			
		||||
                return win.get_workspace() >= newWorkspaceIndex && win != source;
 | 
			
		||||
            else
 | 
			
		||||
                return win.get_workspace() >= newWorkspaceIndex;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // ... move them down one.
 | 
			
		||||
        windows.forEach(function(win) {
 | 
			
		||||
            win.meta_window.change_workspace_by_index(win.get_workspace() + 1,
 | 
			
		||||
                                                      true, time);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        if (isWindow)
 | 
			
		||||
            // ... and bam, a workspace, good as new.
 | 
			
		||||
            source.metaWindow.change_workspace_by_index(newWorkspaceIndex,
 | 
			
		||||
                                                        true, time);
 | 
			
		||||
        else if (source.shellWorkspaceLaunch)
 | 
			
		||||
            source.shellWorkspaceLaunch({ workspace: newWorkspaceIndex,
 | 
			
		||||
                                          timestamp: time });
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    show: function() {
 | 
			
		||||
        this._switchWorkspaceNotifyId =
 | 
			
		||||
            global.window_manager.connect('switch-workspace',
 | 
			
		||||
@@ -840,20 +926,18 @@ ThumbnailsBox.prototype = {
 | 
			
		||||
 | 
			
		||||
        let y = contentBox.y1;
 | 
			
		||||
 | 
			
		||||
        if (this._dropPlaceholderPos == -1) {
 | 
			
		||||
            Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
 | 
			
		||||
                this._dropPlaceholder.hide();
 | 
			
		||||
            }));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < this._thumbnails.length; i++) {
 | 
			
		||||
            let thumbnail = this._thumbnails[i];
 | 
			
		||||
 | 
			
		||||
            if (i > 0)
 | 
			
		||||
                y += spacing - Math.round(thumbnail.collapseFraction * spacing);
 | 
			
		||||
 | 
			
		||||
            // We might end up with thumbnailHeight being something like 99.33
 | 
			
		||||
            // pixels. To make this work and not end up with a gap at the bottom,
 | 
			
		||||
            // we need some thumbnails to be 99 pixels and some 100 pixels height;
 | 
			
		||||
            // we compute an actual scale separately for each thumbnail.
 | 
			
		||||
            let y1 = Math.round(y);
 | 
			
		||||
            let y2 = Math.round(y + thumbnailHeight);
 | 
			
		||||
            let roundedVScale = (y2 - y1) / portholeHeight;
 | 
			
		||||
 | 
			
		||||
            let x1, x2;
 | 
			
		||||
            if (rtl) {
 | 
			
		||||
                x1 = contentBox.x1 + slideOffset * thumbnail.slidePosition;
 | 
			
		||||
@@ -863,6 +947,27 @@ ThumbnailsBox.prototype = {
 | 
			
		||||
                x2 = x1 + thumbnailWidth;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (i == this._dropPlaceholderPos) {
 | 
			
		||||
                let [minHeight, placeholderHeight] = this._dropPlaceholder.get_preferred_height(-1);
 | 
			
		||||
                childBox.x1 = x1;
 | 
			
		||||
                childBox.x2 = x1 + thumbnailWidth;
 | 
			
		||||
                childBox.y1 = Math.round(y);
 | 
			
		||||
                childBox.y2 = Math.round(y + placeholderHeight);
 | 
			
		||||
                this._dropPlaceholder.allocate(childBox, flags);
 | 
			
		||||
                Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
 | 
			
		||||
                    this._dropPlaceholder.show();
 | 
			
		||||
                }));
 | 
			
		||||
                y += placeholderHeight + spacing;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // We might end up with thumbnailHeight being something like 99.33
 | 
			
		||||
            // pixels. To make this work and not end up with a gap at the bottom,
 | 
			
		||||
            // we need some thumbnails to be 99 pixels and some 100 pixels height;
 | 
			
		||||
            // we compute an actual scale separately for each thumbnail.
 | 
			
		||||
            let y1 = Math.round(y);
 | 
			
		||||
            let y2 = Math.round(y + thumbnailHeight);
 | 
			
		||||
            let roundedVScale = (y2 - y1) / portholeHeight;
 | 
			
		||||
 | 
			
		||||
            if (thumbnail.metaWorkspace == indicatorWorkspace)
 | 
			
		||||
                indicatorY = y1;
 | 
			
		||||
 | 
			
		||||
@@ -917,4 +1022,4 @@ ThumbnailsBox.prototype = {
 | 
			
		||||
                           onCompleteScope: this
 | 
			
		||||
                         });
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
@@ -23,11 +23,9 @@ const MAX_WORKSPACES = 16;
 | 
			
		||||
const CONTROLS_POP_IN_TIME = 0.1;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function WorkspacesView(workspaces) {
 | 
			
		||||
    this._init(workspaces);
 | 
			
		||||
}
 | 
			
		||||
const WorkspacesView = new Lang.Class({
 | 
			
		||||
    Name: 'WorkspacesView',
 | 
			
		||||
 | 
			
		||||
WorkspacesView.prototype = {
 | 
			
		||||
    _init: function(workspaces) {
 | 
			
		||||
        this.actor = new St.Group({ style_class: 'workspaces-view' });
 | 
			
		||||
 | 
			
		||||
@@ -109,8 +107,6 @@ WorkspacesView.prototype = {
 | 
			
		||||
        this._scrollAdjustment.connect('notify::value',
 | 
			
		||||
                                       Lang.bind(this, this._onScroll));
 | 
			
		||||
 | 
			
		||||
        this._timeoutId = 0;
 | 
			
		||||
 | 
			
		||||
        this._switchWorkspaceNotifyId =
 | 
			
		||||
            global.window_manager.connect('switch-workspace',
 | 
			
		||||
                                          Lang.bind(this, this._activeWorkspaceChanged));
 | 
			
		||||
@@ -321,10 +317,6 @@ WorkspacesView.prototype = {
 | 
			
		||||
        if (this._inDrag)
 | 
			
		||||
            this._dragEnd();
 | 
			
		||||
 | 
			
		||||
        if (this._timeoutId) {
 | 
			
		||||
            Mainloop.source_remove(this._timeoutId);
 | 
			
		||||
            this._timeoutId = 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (this._itemDragBeginId > 0) {
 | 
			
		||||
            Main.overview.disconnect(this._itemDragBeginId);
 | 
			
		||||
            this._itemDragBeginId = 0;
 | 
			
		||||
@@ -383,72 +375,10 @@ WorkspacesView.prototype = {
 | 
			
		||||
                this._extraWorkspaces[i].setReservedSlot(dragEvent.dragActor._delegate);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let primary = Main.layoutManager.primaryMonitor;
 | 
			
		||||
 | 
			
		||||
        let activeWorkspaceIndex = global.screen.get_active_workspace_index();
 | 
			
		||||
        let topWorkspace, bottomWorkspace;
 | 
			
		||||
        topWorkspace  = this._workspaces[activeWorkspaceIndex - 1];
 | 
			
		||||
        bottomWorkspace = this._workspaces[activeWorkspaceIndex + 1];
 | 
			
		||||
        let hoverWorkspace = null;
 | 
			
		||||
 | 
			
		||||
        // reactive monitor edges
 | 
			
		||||
        let topEdge = primary.y;
 | 
			
		||||
        let switchTop = (dragEvent.y <= topEdge && topWorkspace);
 | 
			
		||||
        if (switchTop && this._dragOverLastY != topEdge) {
 | 
			
		||||
            topWorkspace.metaWorkspace.activate(global.get_current_time());
 | 
			
		||||
            this._dragOverLastY = topEdge;
 | 
			
		||||
 | 
			
		||||
            return DND.DragMotionResult.CONTINUE;
 | 
			
		||||
        }
 | 
			
		||||
        let bottomEdge = primary.y + primary.height - 1;
 | 
			
		||||
        let switchBottom = (dragEvent.y >= bottomEdge && bottomWorkspace);
 | 
			
		||||
        if (switchBottom && this._dragOverLastY != bottomEdge) {
 | 
			
		||||
            bottomWorkspace.metaWorkspace.activate(global.get_current_time());
 | 
			
		||||
            this._dragOverLastY = bottomEdge;
 | 
			
		||||
 | 
			
		||||
            return DND.DragMotionResult.CONTINUE;
 | 
			
		||||
        }
 | 
			
		||||
        this._dragOverLastY = dragEvent.y;
 | 
			
		||||
        let result = DND.DragMotionResult.CONTINUE;
 | 
			
		||||
 | 
			
		||||
        // check hover state of new workspace area / inactive workspaces
 | 
			
		||||
        if (topWorkspace) {
 | 
			
		||||
            if (topWorkspace.actor.contains(dragEvent.targetActor)) {
 | 
			
		||||
                hoverWorkspace = topWorkspace;
 | 
			
		||||
                result = topWorkspace.handleDragOver(dragEvent.source, dragEvent.dragActor);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (bottomWorkspace) {
 | 
			
		||||
            if (bottomWorkspace.actor.contains(dragEvent.targetActor)) {
 | 
			
		||||
                hoverWorkspace = bottomWorkspace;
 | 
			
		||||
                result = bottomWorkspace.handleDragOver(dragEvent.source, dragEvent.dragActor);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // handle delayed workspace switches
 | 
			
		||||
        if (hoverWorkspace) {
 | 
			
		||||
            if (!this._timeoutId)
 | 
			
		||||
                this._timeoutId = Mainloop.timeout_add_seconds(1,
 | 
			
		||||
                    Lang.bind(this, function() {
 | 
			
		||||
                       hoverWorkspace.metaWorkspace.activate(global.get_current_time());
 | 
			
		||||
                       return false;
 | 
			
		||||
                    }));
 | 
			
		||||
        } else {
 | 
			
		||||
            if (this._timeoutId) {
 | 
			
		||||
                Mainloop.source_remove(this._timeoutId);
 | 
			
		||||
                this._timeoutId = 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return result;
 | 
			
		||||
        return DND.DragMotionResult.CONTINUE;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _dragEnd: function() {
 | 
			
		||||
        if (this._timeoutId) {
 | 
			
		||||
            Mainloop.source_remove(this._timeoutId);
 | 
			
		||||
            this._timeoutId = 0;
 | 
			
		||||
        }
 | 
			
		||||
        DND.removeDragMonitor(this._dragMonitor);
 | 
			
		||||
        this._inDrag = false;
 | 
			
		||||
 | 
			
		||||
@@ -520,15 +450,13 @@ WorkspacesView.prototype = {
 | 
			
		||||
    _getWorkspaceIndexToRemove: function() {
 | 
			
		||||
        return global.screen.get_active_workspace_index();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(WorkspacesView.prototype);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function WorkspacesDisplay() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const WorkspacesDisplay = new Lang.Class({
 | 
			
		||||
    Name: 'WorkspacesDisplay',
 | 
			
		||||
 | 
			
		||||
WorkspacesDisplay.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.actor = new Shell.GenericContainer();
 | 
			
		||||
        this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
 | 
			
		||||
@@ -920,5 +848,5 @@ WorkspacesDisplay.prototype = {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(WorkspacesDisplay.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
@@ -6,11 +6,9 @@ const Shell = imports.gi.Shell;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const DND = imports.ui.dnd;
 | 
			
		||||
 | 
			
		||||
function XdndHandler() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
const XdndHandler = new Lang.Class({
 | 
			
		||||
    Name: 'XdndHandler',
 | 
			
		||||
 | 
			
		||||
XdndHandler.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        // Used to display a clone of the cursor window when the
 | 
			
		||||
        // window group is hidden (like it happens in the overview)
 | 
			
		||||
@@ -125,6 +123,6 @@ XdndHandler.prototype = {
 | 
			
		||||
                pickedActor = pickedActor.get_parent();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Signals.addSignalMethods(XdndHandler.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,8 @@
 | 
			
		||||
af
 | 
			
		||||
an
 | 
			
		||||
ar
 | 
			
		||||
as
 | 
			
		||||
ast
 | 
			
		||||
be
 | 
			
		||||
bg
 | 
			
		||||
bn
 | 
			
		||||
@@ -30,6 +32,7 @@ it
 | 
			
		||||
ja
 | 
			
		||||
ko
 | 
			
		||||
kn
 | 
			
		||||
ku
 | 
			
		||||
lt
 | 
			
		||||
lv
 | 
			
		||||
mr
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
data/gnome-shell.desktop.in.in
 | 
			
		||||
data/org.gnome.shell.gschema.xml.in
 | 
			
		||||
js/gdm/loginDialog.js
 | 
			
		||||
js/gdm/powerMenu.js
 | 
			
		||||
js/misc/util.js
 | 
			
		||||
js/ui/appDisplay.js
 | 
			
		||||
js/ui/appFavorites.js
 | 
			
		||||
@@ -24,6 +25,7 @@ js/ui/polkitAuthenticationAgent.js
 | 
			
		||||
js/ui/popupMenu.js
 | 
			
		||||
js/ui/runDialog.js
 | 
			
		||||
js/ui/searchDisplay.js
 | 
			
		||||
js/ui/shellEntry.js
 | 
			
		||||
js/ui/shellMountOperation.js
 | 
			
		||||
js/ui/status/accessibility.js
 | 
			
		||||
js/ui/status/bluetooth.js
 | 
			
		||||
@@ -43,4 +45,3 @@ src/shell-global.c
 | 
			
		||||
src/shell-mobile-providers.c
 | 
			
		||||
src/shell-polkit-authentication-agent.c
 | 
			
		||||
src/shell-util.c
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user