Compare commits
	
		
			360 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					c215247a6c | ||
| 
						 | 
					96b202c80d | ||
| 
						 | 
					0ac2f61a2c | ||
| 
						 | 
					2aa6dcd9d8 | ||
| 
						 | 
					469b85eb7c | ||
| 
						 | 
					673ddfde04 | ||
| 
						 | 
					56ca7eeb65 | ||
| 
						 | 
					b414955230 | ||
| 
						 | 
					af9072e725 | ||
| 
						 | 
					9b903e93e3 | ||
| 
						 | 
					7966f00a18 | ||
| 
						 | 
					9a99a80710 | ||
| 
						 | 
					be77874ec9 | ||
| 
						 | 
					768286bffb | ||
| 
						 | 
					f5c65d9ea1 | ||
| 
						 | 
					f328890ed1 | ||
| 
						 | 
					945bf626c6 | ||
| 
						 | 
					f6869bbbc2 | ||
| 
						 | 
					eafe11a7cf | ||
| 
						 | 
					daba1b511b | ||
| 
						 | 
					87a13d2c00 | ||
| 
						 | 
					11a9b4baa0 | ||
| 
						 | 
					de71fd0941 | ||
| 
						 | 
					87c973c260 | ||
| 
						 | 
					644ab0e270 | ||
| 
						 | 
					3142220443 | ||
| 
						 | 
					1f0ed5483a | ||
| 
						 | 
					72f5a36522 | ||
| 
						 | 
					7f19db1f7b | ||
| 
						 | 
					3f2d658f20 | ||
| 
						 | 
					05353c1f7e | ||
| 
						 | 
					4d23e7c202 | ||
| 
						 | 
					ad90b7dd2f | ||
| 
						 | 
					3356a43c04 | ||
| 
						 | 
					3a5a647d49 | ||
| 
						 | 
					a2ff8f4e1e | ||
| 
						 | 
					e294f6df8c | ||
| 
						 | 
					422ddeddb9 | ||
| 
						 | 
					8ef48a99ae | ||
| 
						 | 
					9d7af8a5fc | ||
| 
						 | 
					764c3dd137 | ||
| 
						 | 
					7e7c8ecbd4 | ||
| 
						 | 
					d561b3b18f | ||
| 
						 | 
					ce14bde08d | ||
| 
						 | 
					b91461ee39 | ||
| 
						 | 
					22c13b3144 | ||
| 
						 | 
					0bfebc3cae | ||
| 
						 | 
					db384a656c | ||
| 
						 | 
					1dea1813b1 | ||
| 
						 | 
					71c4138933 | ||
| 
						 | 
					9d73b4efbb | ||
| 
						 | 
					049f67df0a | ||
| 
						 | 
					2d878d3f55 | ||
| 
						 | 
					3c06f2dc90 | ||
| 
						 | 
					460e1fd7ca | ||
| 
						 | 
					f083935c6e | ||
| 
						 | 
					5c66bee84b | ||
| 
						 | 
					ef32bbdc99 | ||
| 
						 | 
					5f91a62f6f | ||
| 
						 | 
					152b2dab59 | ||
| 
						 | 
					625d3de2ee | ||
| 
						 | 
					f71315eb1e | ||
| 
						 | 
					0484ef142d | ||
| 
						 | 
					6609d9c6a4 | ||
| 
						 | 
					73c4342580 | ||
| 
						 | 
					0d5c24f13d | ||
| 
						 | 
					b6d070b06f | ||
| 
						 | 
					87eb5f8632 | ||
| 
						 | 
					5c60ea6635 | ||
| 
						 | 
					9abcf424b8 | ||
| 
						 | 
					cc7af83f8a | ||
| 
						 | 
					ae91a174e9 | ||
| 
						 | 
					9c73e21113 | ||
| 
						 | 
					a1d8110221 | ||
| 
						 | 
					9d6357f05a | ||
| 
						 | 
					1fc58faff9 | ||
| 
						 | 
					fea7ac84ee | ||
| 
						 | 
					20bee6f48e | ||
| 
						 | 
					fb5c0c3352 | ||
| 
						 | 
					5bc2bcd109 | ||
| 
						 | 
					d12390002a | ||
| 
						 | 
					13acf9e35d | ||
| 
						 | 
					3beb187cac | ||
| 
						 | 
					a3b8dcbd04 | ||
| 
						 | 
					3ff8b0051d | ||
| 
						 | 
					a8bf7934fb | ||
| 
						 | 
					7159845c6e | ||
| 
						 | 
					7bccd4f22f | ||
| 
						 | 
					e4e00b383e | ||
| 
						 | 
					36454542ae | ||
| 
						 | 
					34ba868b4c | ||
| 
						 | 
					274ea76eea | ||
| 
						 | 
					a180e8b87e | ||
| 
						 | 
					26c8086190 | ||
| 
						 | 
					34fbca0181 | ||
| 
						 | 
					4496fb4447 | ||
| 
						 | 
					7e66d2a484 | ||
| 
						 | 
					12135afa5e | ||
| 
						 | 
					cac660a5bc | ||
| 
						 | 
					dcce4e64bc | ||
| 
						 | 
					4d3511649b | ||
| 
						 | 
					d4ea2bbd9c | ||
| 
						 | 
					f303ec2eaa | ||
| 
						 | 
					2ca4ed6b04 | ||
| 
						 | 
					a5ad89dd65 | ||
| 
						 | 
					4a4d724e59 | ||
| 
						 | 
					8fdbae192a | ||
| 
						 | 
					2413e672c8 | ||
| 
						 | 
					c8432cc430 | ||
| 
						 | 
					015864da09 | ||
| 
						 | 
					669c9da2a4 | ||
| 
						 | 
					4d1d8e831e | ||
| 
						 | 
					9e199e6350 | ||
| 
						 | 
					4673d8f245 | ||
| 
						 | 
					90111c03a1 | ||
| 
						 | 
					23681800d9 | ||
| 
						 | 
					b47afe89d3 | ||
| 
						 | 
					af7f51b992 | ||
| 
						 | 
					f3d30d897f | ||
| 
						 | 
					dcc4ce4ff4 | ||
| 
						 | 
					b9fb4a5887 | ||
| 
						 | 
					d9985cd9bc | ||
| 
						 | 
					6e3f7b7ddc | ||
| 
						 | 
					2dd1f37820 | ||
| 
						 | 
					57af975154 | ||
| 
						 | 
					c5940580ed | ||
| 
						 | 
					8296d4cdce | ||
| 
						 | 
					bf9a00d5c9 | ||
| 
						 | 
					c1db9d9181 | ||
| 
						 | 
					9d2cd8ff87 | ||
| 
						 | 
					d514e8ab41 | ||
| 
						 | 
					44a60eb7e9 | ||
| 
						 | 
					6b92b45021 | ||
| 
						 | 
					ee461b5495 | ||
| 
						 | 
					46f3eb0b71 | ||
| 
						 | 
					ef32899b4d | ||
| 
						 | 
					5e9db422c9 | ||
| 
						 | 
					662dd6a289 | ||
| 
						 | 
					d5e6177900 | ||
| 
						 | 
					34ac80348c | ||
| 
						 | 
					8a7a01b0cf | ||
| 
						 | 
					2cabc067d1 | ||
| 
						 | 
					26c4c21e13 | ||
| 
						 | 
					6eda784cf0 | ||
| 
						 | 
					fb1459062f | ||
| 
						 | 
					bc9547f29e | ||
| 
						 | 
					89a371ec98 | ||
| 
						 | 
					2db71e73b4 | ||
| 
						 | 
					472f2a4b8e | ||
| 
						 | 
					db04ac9eb7 | ||
| 
						 | 
					75105e254f | ||
| 
						 | 
					901a05ad80 | ||
| 
						 | 
					ab6c4c82f6 | ||
| 
						 | 
					cacb32482c | ||
| 
						 | 
					4450b5bb14 | ||
| 
						 | 
					34421e90c3 | ||
| 
						 | 
					93b7137c62 | ||
| 
						 | 
					5ad15bb5e5 | ||
| 
						 | 
					cd4206764e | ||
| 
						 | 
					b10a017446 | ||
| 
						 | 
					d393cba39e | ||
| 
						 | 
					578f593d56 | ||
| 
						 | 
					55df99447a | ||
| 
						 | 
					d45080d32e | ||
| 
						 | 
					fa97364fa8 | ||
| 
						 | 
					41303101e5 | ||
| 
						 | 
					68542ae1ef | ||
| 
						 | 
					0c730d8feb | ||
| 
						 | 
					aeef98fd19 | ||
| 
						 | 
					69079b3b48 | ||
| 
						 | 
					ad7292faef | ||
| 
						 | 
					2f7843b295 | ||
| 
						 | 
					b24cd5ae08 | ||
| 
						 | 
					c782078e00 | ||
| 
						 | 
					5a86286aba | ||
| 
						 | 
					b1ac83d3b6 | ||
| 
						 | 
					e73f5cc8ab | ||
| 
						 | 
					593b417e5e | ||
| 
						 | 
					5e84c8f20b | ||
| 
						 | 
					9745f9f8ce | ||
| 
						 | 
					99f7be33ad | ||
| 
						 | 
					6492845f27 | ||
| 
						 | 
					fd1243d881 | ||
| 
						 | 
					00535b34b6 | ||
| 
						 | 
					a2b2a7a26f | ||
| 
						 | 
					9fdf487da1 | ||
| 
						 | 
					c5033616e9 | ||
| 
						 | 
					a0e038f34b | ||
| 
						 | 
					71dab32769 | ||
| 
						 | 
					c408cf7aac | ||
| 
						 | 
					e96eb0e82e | ||
| 
						 | 
					0015963457 | ||
| 
						 | 
					b832bc7424 | ||
| 
						 | 
					89b14babb9 | ||
| 
						 | 
					7ecde19aee | ||
| 
						 | 
					d7854794cf | ||
| 
						 | 
					f6f5f624d4 | ||
| 
						 | 
					7012c82fc7 | ||
| 
						 | 
					a0d2d207e7 | ||
| 
						 | 
					6e25c37da1 | ||
| 
						 | 
					061f434201 | ||
| 
						 | 
					638087fe78 | ||
| 
						 | 
					286a6ada5a | ||
| 
						 | 
					cb66ab5a87 | ||
| 
						 | 
					e72c6916aa | ||
| 
						 | 
					8b98cb818c | ||
| 
						 | 
					f8a4d450a5 | ||
| 
						 | 
					681cf95236 | ||
| 
						 | 
					90d6734f8c | ||
| 
						 | 
					213cd8a334 | ||
| 
						 | 
					3b1271d9be | ||
| 
						 | 
					13b6bd20ca | ||
| 
						 | 
					63e31af476 | ||
| 
						 | 
					718a89eb2f | ||
| 
						 | 
					a43ca7b5b1 | ||
| 
						 | 
					af00ca534a | ||
| 
						 | 
					4b2b431700 | ||
| 
						 | 
					2c1a6b6a12 | ||
| 
						 | 
					b3544f8ec1 | ||
| 
						 | 
					df384965c3 | ||
| 
						 | 
					700d367937 | ||
| 
						 | 
					7c5989c978 | ||
| 
						 | 
					8819d9ce66 | ||
| 
						 | 
					b63413e5b0 | ||
| 
						 | 
					cd1e1d4bf1 | ||
| 
						 | 
					9710c013c5 | ||
| 
						 | 
					05f8d79323 | ||
| 
						 | 
					f2546dfeea | ||
| 
						 | 
					47e339b46e | ||
| 
						 | 
					016b8f5b4a | ||
| 
						 | 
					b3821c4f90 | ||
| 
						 | 
					29e5c6c363 | ||
| 
						 | 
					e1704acda4 | ||
| 
						 | 
					60cbb41f42 | ||
| 
						 | 
					d88c8d9ced | ||
| 
						 | 
					60ab11ecbf | ||
| 
						 | 
					34516aeab6 | ||
| 
						 | 
					a37f632b1b | ||
| 
						 | 
					8a6542c242 | ||
| 
						 | 
					7e12000d97 | ||
| 
						 | 
					23f086da8a | ||
| 
						 | 
					4c2c1c4dd2 | ||
| 
						 | 
					545f298921 | ||
| 
						 | 
					64295e8cd7 | ||
| 
						 | 
					722d4c6c17 | ||
| 
						 | 
					cc8462969d | ||
| 
						 | 
					989bb6ebb1 | ||
| 
						 | 
					1dbda68839 | ||
| 
						 | 
					a460f88b31 | ||
| 
						 | 
					3e511b9591 | ||
| 
						 | 
					5664c703b7 | ||
| 
						 | 
					5c80c4b006 | ||
| 
						 | 
					22f91eba8d | ||
| 
						 | 
					d07e2f4090 | ||
| 
						 | 
					cd32e4a68a | ||
| 
						 | 
					4040a70781 | ||
| 
						 | 
					cb084cc841 | ||
| 
						 | 
					2deea6e0a3 | ||
| 
						 | 
					a116509301 | ||
| 
						 | 
					ead79f834c | ||
| 
						 | 
					7e431bd6bc | ||
| 
						 | 
					272e1fb296 | ||
| 
						 | 
					c39f18c2d4 | ||
| 
						 | 
					33acb5fea0 | ||
| 
						 | 
					591718dc02 | ||
| 
						 | 
					b6127eeda4 | ||
| 
						 | 
					eeff1b8b02 | ||
| 
						 | 
					354cc466af | ||
| 
						 | 
					9f5c38d121 | ||
| 
						 | 
					ead0e902ed | ||
| 
						 | 
					5d16194b03 | ||
| 
						 | 
					a74acf0ec2 | ||
| 
						 | 
					3044cfb7bf | ||
| 
						 | 
					f658740043 | ||
| 
						 | 
					c1613a16c0 | ||
| 
						 | 
					8e85015f91 | ||
| 
						 | 
					f127ee3bde | ||
| 
						 | 
					acd928044f | ||
| 
						 | 
					4ef2f2ce09 | ||
| 
						 | 
					bc81736e6b | ||
| 
						 | 
					49092397f2 | ||
| 
						 | 
					97705d3cfe | ||
| 
						 | 
					0364ea9140 | ||
| 
						 | 
					c0bdb3018b | ||
| 
						 | 
					924eaac358 | ||
| 
						 | 
					a9f5a5661f | ||
| 
						 | 
					9c589b6798 | ||
| 
						 | 
					113be01ce8 | ||
| 
						 | 
					28e59c5a8f | ||
| 
						 | 
					b588baf9f5 | ||
| 
						 | 
					9a825d9bee | ||
| 
						 | 
					f211b3ec90 | ||
| 
						 | 
					0510c3a621 | ||
| 
						 | 
					18db5d0799 | ||
| 
						 | 
					c061e26da5 | ||
| 
						 | 
					166668adc4 | ||
| 
						 | 
					ec797b055d | ||
| 
						 | 
					082cc9c83a | ||
| 
						 | 
					993bec37d7 | ||
| 
						 | 
					e496ed50d6 | ||
| 
						 | 
					a127d05790 | ||
| 
						 | 
					607730e96c | ||
| 
						 | 
					9203db0655 | ||
| 
						 | 
					64d40792c4 | ||
| 
						 | 
					e7356917b0 | ||
| 
						 | 
					fa58752276 | ||
| 
						 | 
					478b75e803 | ||
| 
						 | 
					492a1b244f | ||
| 
						 | 
					5d8ff2e34d | ||
| 
						 | 
					310083aeb2 | ||
| 
						 | 
					0faa900207 | ||
| 
						 | 
					b735571688 | ||
| 
						 | 
					5e249ad5eb | ||
| 
						 | 
					21bffe4aef | ||
| 
						 | 
					68283df4d9 | ||
| 
						 | 
					4f3de2ce39 | ||
| 
						 | 
					9f8b641472 | ||
| 
						 | 
					a9a21c801c | ||
| 
						 | 
					482a97466d | ||
| 
						 | 
					4e14bb9df3 | ||
| 
						 | 
					df90545258 | ||
| 
						 | 
					c954f9cc24 | ||
| 
						 | 
					d06b39d13c | ||
| 
						 | 
					f3595ebd08 | ||
| 
						 | 
					1e1ca47ec1 | ||
| 
						 | 
					2eec11b445 | ||
| 
						 | 
					8ff4597201 | ||
| 
						 | 
					d5f2468d88 | ||
| 
						 | 
					488dd0b402 | ||
| 
						 | 
					6565bca210 | ||
| 
						 | 
					60c22b6236 | ||
| 
						 | 
					d3111a9f07 | ||
| 
						 | 
					cdfb301200 | ||
| 
						 | 
					371560c2b6 | ||
| 
						 | 
					7616881afa | ||
| 
						 | 
					74c37d49c4 | ||
| 
						 | 
					d3142b92f0 | ||
| 
						 | 
					ae2afa7c5e | ||
| 
						 | 
					4a71621fbc | ||
| 
						 | 
					565b9d73d5 | ||
| 
						 | 
					90bd02ff4d | ||
| 
						 | 
					73ca0efaeb | ||
| 
						 | 
					790269db95 | ||
| 
						 | 
					cb82bd8afa | ||
| 
						 | 
					b1e06ed110 | ||
| 
						 | 
					fabe66e65f | ||
| 
						 | 
					4a965a37d1 | ||
| 
						 | 
					302ff7b95a | ||
| 
						 | 
					e2e241340c | ||
| 
						 | 
					461aea47dd | ||
| 
						 | 
					d87093fe29 | ||
| 
						 | 
					0cde7879d6 | ||
| 
						 | 
					89ffcee7ca | ||
| 
						 | 
					1250afef7b | ||
| 
						 | 
					3a577edaa7 | ||
| 
						 | 
					48dfde2073 | ||
| 
						 | 
					4a41d415f8 | ||
| 
						 | 
					1fb7ca398d | ||
| 
						 | 
					2b79935fd8 | ||
| 
						 | 
					e3c915350e | 
							
								
								
									
										115
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										115
									
								
								NEWS
									
									
									
									
									
								
							@@ -1,3 +1,118 @@
 | 
			
		||||
3.15.90
 | 
			
		||||
=======
 | 
			
		||||
* Initialize MetaOutput even when we can't get the EDID [Rui; #743412]
 | 
			
		||||
* Expose MetaMonitorManager to introspection [Rui; #743745]
 | 
			
		||||
* Fix flash on unredirection [Chris; #743858]
 | 
			
		||||
* Update xdg-shell implementation to v5 [Jonas; #744452]
 | 
			
		||||
* Do not try to use seat devices that aren't (yet) present [Ray; #744640]
 | 
			
		||||
* Add keybindings for switching to VT8-VT12 [Ray; #744800]
 | 
			
		||||
* Misc bug fixes [Jonas, Cosimo; #743678, #744500]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Jonas Ådahl, Cosimo Cecchi, Carlos Garnacho, Rui Matos, Jasper St. Pierre,
 | 
			
		||||
  Ray Strode, Chris Wilson
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
  Yosef Or Boczko [he], Yuri Myasoedov [ru], Kristjan SCHMIDT [eo],
 | 
			
		||||
  Matej Urbančič [sl], Dušan Kazik [sk]
 | 
			
		||||
 | 
			
		||||
3.15.4
 | 
			
		||||
======
 | 
			
		||||
* Use GTK+ theme for window decorations instead of metacity [Florian; #741917]
 | 
			
		||||
* Export the same EDID information on X11 and wayland [Carlos; #742882]
 | 
			
		||||
* Apply input device configuration on wayland [Carlos; #739397]
 | 
			
		||||
* Implement pointer barriers on wayland [Jonas; #706655]
 | 
			
		||||
* Misc. bug fixes (Ting-Wei, Rui, Ikey, Florian, Marek, Jonas; #741829,
 | 
			
		||||
  #738630, #737463, #698995, #727893, #742825, #742824, #742841, #743173,
 | 
			
		||||
  #743189, #743217, #743254]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Jonas Ådahl, Giovanni Campagna, Marek Chalupa, Ikey Doherty, Adel Gadllah,
 | 
			
		||||
  Carlos Garnacho, Ting-Wei Lan, Rui Matos, Florian Müllner, Jasper St. Pierre,
 | 
			
		||||
  Rico Tzschichholz
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
  Matej Urbančič [sl], Balázs Úr [hu], Marek Černocký [cs],
 | 
			
		||||
  Inaki Larranaga Murgoitio [eu], Rafael Ferreira [pt_BR],
 | 
			
		||||
  Daniel Mustieles [es], Fran Dieguez [gl]
 | 
			
		||||
 | 
			
		||||
3.15.3
 | 
			
		||||
======
 | 
			
		||||
* Don't leave left-over frames queued [Owen; #738686]
 | 
			
		||||
* Set CRTC configuration even if it might be redundant [Rui; #740838]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Rui Matos, Jasper St. Pierre, Rico Tzschichholz, Owen W. Taylor
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
  Trần Ngọc Quân [vi], Muhammet Kara [tr]
 | 
			
		||||
 | 
			
		||||
3.15.2
 | 
			
		||||
======
 | 
			
		||||
* Don't enable hiDPI on monitors with broken EDID [Bastien; #734839]
 | 
			
		||||
* Prevent crash applying monitor config for a closed lid [Rui; #739450]
 | 
			
		||||
* Fix "flicker" during startup transition [Ray; #740377]
 | 
			
		||||
* Misc. bug fixes [Lan, Florian, Carlos; #731521, #740133, #738890]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Emmanuele Bassi, Carlos Garnacho, Jonathon Jongsma, Ting-Wei Lan, Rui Matos,
 | 
			
		||||
  Florian Müllner, Bastien Nocera, Jasper St. Pierre, Ray Strode
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
  Kjartan Maraas [nb]
 | 
			
		||||
 | 
			
		||||
3.15.1
 | 
			
		||||
======
 | 
			
		||||
* Use GResources for theme loading [Cosimo; #736936]
 | 
			
		||||
* Fix headerbar drag getting stuck on xwayland [Carlos; #738411]
 | 
			
		||||
* Fix wayland hiDPI regressions [Adel; #739161]
 | 
			
		||||
* Misc bug fixes and cleanups [Jasper, Rui, Carlos; #662962, #738630, #738888,
 | 
			
		||||
  #738890]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Cosimo Cecchi, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner,
 | 
			
		||||
  Jasper St. Pierre
 | 
			
		||||
 | 
			
		||||
3.14.1
 | 
			
		||||
======
 | 
			
		||||
* Fix move-titlebar-onscreen function [Florian; #736915]
 | 
			
		||||
* Fix stacking of the guard window [Owen; #737233]
 | 
			
		||||
* Fix keycode lookup for non-default layouts [Rui; #737134]
 | 
			
		||||
* Fix workspaces-only-on-primary handling [Florian; #737178]
 | 
			
		||||
* Don't unstick sticky windows on workspace removal [Florian; #737625]
 | 
			
		||||
* Do not auto-minimize fullscreen windows [Jasper; #705177]
 | 
			
		||||
* Upload keymap to newly added keyboard devices [Rui; #737673]
 | 
			
		||||
* Apply keyboard repeat settings [Rui; #728055]
 | 
			
		||||
* Don't send pressed keys on enter [Rui; #727178]
 | 
			
		||||
* Fix build without wayland/native [Rico; #738225]
 | 
			
		||||
* Send modifiers after the key event [Rui; #738238]
 | 
			
		||||
* Fix unredirect heuristic [Adel; #738271]
 | 
			
		||||
* Do not show system chrome over fullscreen windows [Florian; #693991]
 | 
			
		||||
* Misc. bug fixes [Florian, Adel, Tom; #737135, #737581, #738146, #738384]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Tom Beckmann, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner,
 | 
			
		||||
  Jasper St. Pierre, Rico Tzschichholz, Owen W. Taylor
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
  Krishnababu Krothapalli [te], Мирослав Николић [sr, sr@latin],
 | 
			
		||||
  Alexander Shopov [bg], Saibal Ray [bn_IN], Milo Casagrande [it],
 | 
			
		||||
  Rūdolfs Mazurs [lv]
 | 
			
		||||
 | 
			
		||||
3.14.0
 | 
			
		||||
======
 | 
			
		||||
* Fix placement of popup windows on wayland [Jasper; #736812]
 | 
			
		||||
* Only increment serial once per event [Jasper; #736840]
 | 
			
		||||
* Fix window positioning regression with non-GTK+ toolkits [Owen; #736719]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Jasper St. Pierre, Owen W. Taylor
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
  Saibal Ray [bn_IN], Dušan Kazik [sk], Manoj Kumar Giri [or],
 | 
			
		||||
  Christian Kirbach [de], Ask H. Larsen [da], YunQiang Su [zh_CN],
 | 
			
		||||
  Bernd Homuth [de], Shankar Prasad [kn], Petr Kovar [cs], Rajesh Ranjan [hi]
 | 
			
		||||
 | 
			
		||||
3.13.92
 | 
			
		||||
=======
 | 
			
		||||
* Rewrite background code [Owen; #735637, #736568]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										59
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								configure.ac
									
									
									
									
									
								
							@@ -1,8 +1,8 @@
 | 
			
		||||
AC_PREREQ(2.62)
 | 
			
		||||
 | 
			
		||||
m4_define([mutter_major_version], [3])
 | 
			
		||||
m4_define([mutter_minor_version], [13])
 | 
			
		||||
m4_define([mutter_micro_version], [92])
 | 
			
		||||
m4_define([mutter_minor_version], [15])
 | 
			
		||||
m4_define([mutter_micro_version], [90])
 | 
			
		||||
 | 
			
		||||
m4_define([mutter_version],
 | 
			
		||||
          [mutter_major_version.mutter_minor_version.mutter_micro_version])
 | 
			
		||||
@@ -72,14 +72,12 @@ CLUTTER_PACKAGE=clutter-1.0
 | 
			
		||||
 | 
			
		||||
MUTTER_PC_MODULES="
 | 
			
		||||
   gtk+-3.0 >= 3.9.11
 | 
			
		||||
   gio-unix-2.0 >= 2.25.10
 | 
			
		||||
   gio-unix-2.0 >= 2.35.1
 | 
			
		||||
   pango >= 1.2.0
 | 
			
		||||
   cairo >= 1.10.0
 | 
			
		||||
   gsettings-desktop-schemas >= 3.7.3
 | 
			
		||||
   $CLUTTER_PACKAGE >= 1.19.5
 | 
			
		||||
   clutter-egl-1.0
 | 
			
		||||
   gsettings-desktop-schemas >= 3.15.4
 | 
			
		||||
   $CLUTTER_PACKAGE >= 1.21.3
 | 
			
		||||
   cogl-1.0 >= 1.17.1
 | 
			
		||||
   gbm
 | 
			
		||||
   upower-glib >= 0.99.0
 | 
			
		||||
   gnome-desktop-3.0
 | 
			
		||||
   xcomposite >= 0.2
 | 
			
		||||
@@ -202,22 +200,39 @@ AC_SUBST(XWAYLAND_PATH)
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [libdrm libsystemd libinput], [have_native_backend=yes], [have_native_backend=no])
 | 
			
		||||
if test $have_native_backend = yes; then
 | 
			
		||||
   AC_DEFINE([HAVE_NATIVE_BACKEND],[1],[Define if you want to enable the native (KMS) backend based on systemd])
 | 
			
		||||
fi
 | 
			
		||||
AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test $have_native_backend = yes])
 | 
			
		||||
MUTTER_NATIVE_BACKEND_MODULES="clutter-egl-1.0 libdrm libsystemd libinput gudev-1.0 gbm >= 10.3"
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(MUTTER_WAYLAND, [clutter-wayland-1.0 clutter-wayland-compositor-1.0 wayland-server >= 1.5.90], [have_wayland=yes], [have_wayland=no])
 | 
			
		||||
if test $have_wayland = yes; then
 | 
			
		||||
   AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
 | 
			
		||||
   AS_IF([test $WAYLAND_SCANNER = "no"],
 | 
			
		||||
     AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
 | 
			
		||||
   AC_SUBST([WAYLAND_SCANNER])
 | 
			
		||||
AC_ARG_ENABLE(native-backend,
 | 
			
		||||
  AS_HELP_STRING([--disable-native-backend], [disable mutter native (KMS) backend]),,
 | 
			
		||||
  enable_native_backend=auto
 | 
			
		||||
)
 | 
			
		||||
AS_IF([test "$enable_native_backend" = "yes"], [have_native_backend=yes],
 | 
			
		||||
      [test "$enable_native_backend" = "auto"], PKG_CHECK_EXISTS([$MUTTER_NATIVE_BACKEND_MODULES], [have_native_backend=yes]))
 | 
			
		||||
 | 
			
		||||
   AC_DEFINE([HAVE_WAYLAND],[1],[Define if you want to enable Wayland support])
 | 
			
		||||
fi
 | 
			
		||||
AM_CONDITIONAL([HAVE_WAYLAND],[test $have_wayland = yes])
 | 
			
		||||
AS_IF([test "$have_native_backend" = "yes"], [
 | 
			
		||||
  PKG_CHECK_MODULES([MUTTER_NATIVE_BACKEND], [$MUTTER_NATIVE_BACKEND_MODULES])
 | 
			
		||||
  AC_DEFINE([HAVE_NATIVE_BACKEND],[1], [Define if you want to enable the native (KMS) backend based on systemd])
 | 
			
		||||
])
 | 
			
		||||
AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test "$have_native_backend" = "yes"])
 | 
			
		||||
 | 
			
		||||
MUTTER_WAYLAND_MODULES="clutter-wayland-1.0 clutter-wayland-compositor-1.0 wayland-server >= 1.6.90"
 | 
			
		||||
 | 
			
		||||
AC_ARG_ENABLE(wayland,
 | 
			
		||||
  AS_HELP_STRING([--disable-wayland], [disable mutter on wayland support]),,
 | 
			
		||||
  enable_wayland=auto
 | 
			
		||||
)
 | 
			
		||||
AS_IF([test "$enable_wayland" = "yes"], [have_wayland=yes],
 | 
			
		||||
      [test "$enable_wayland" = "auto"], PKG_CHECK_EXISTS([$MUTTER_WAYLAND_MODULES], [have_wayland=yes]))
 | 
			
		||||
 | 
			
		||||
AS_IF([test "$have_wayland" = "yes"], [
 | 
			
		||||
  PKG_CHECK_MODULES([MUTTER_WAYLAND], [$MUTTER_WAYLAND_MODULES])
 | 
			
		||||
  AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
 | 
			
		||||
  AS_IF([test $WAYLAND_SCANNER = "no"],
 | 
			
		||||
    [AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols])])
 | 
			
		||||
  AC_SUBST([WAYLAND_SCANNER])
 | 
			
		||||
  AC_DEFINE([HAVE_WAYLAND],[1],[Define if you want to enable Wayland support])
 | 
			
		||||
])
 | 
			
		||||
AM_CONDITIONAL([HAVE_WAYLAND],[test "$have_wayland" = "yes"])
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_EXISTS([xi >= 1.6.99.1],
 | 
			
		||||
                 AC_DEFINE([HAVE_XI23],[1],[Define if you have support for XInput 2.3 or greater]))
 | 
			
		||||
@@ -418,6 +433,8 @@ mutter-$VERSION
 | 
			
		||||
	libcanberra:              ${have_libcanberra}
 | 
			
		||||
	Introspection:            ${found_introspection}
 | 
			
		||||
	Session management:       ${found_sm}
 | 
			
		||||
	Wayland:                  ${have_wayland}
 | 
			
		||||
	Native (KMS) backend:     ${have_native_backend}
 | 
			
		||||
"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,5 +29,25 @@
 | 
			
		||||
      <default><![CDATA[['<Primary><Alt>F7']]]></default>
 | 
			
		||||
      <_summary>Switch to VT 7</_summary>
 | 
			
		||||
    </key>
 | 
			
		||||
    <key name="switch-to-session-8" type="as">
 | 
			
		||||
      <default><![CDATA[['<Primary><Alt>F8']]]></default>
 | 
			
		||||
      <_summary>Switch to VT 8</_summary>
 | 
			
		||||
    </key>
 | 
			
		||||
    <key name="switch-to-session-9" type="as">
 | 
			
		||||
      <default><![CDATA[['<Primary><Alt>F9']]]></default>
 | 
			
		||||
      <_summary>Switch to VT 9</_summary>
 | 
			
		||||
    </key>
 | 
			
		||||
    <key name="switch-to-session-10" type="as">
 | 
			
		||||
      <default><![CDATA[['<Primary><Alt>F10']]]></default>
 | 
			
		||||
      <_summary>Switch to VT 10</_summary>
 | 
			
		||||
    </key>
 | 
			
		||||
    <key name="switch-to-session-11" type="as">
 | 
			
		||||
      <default><![CDATA[['<Primary><Alt>F11']]]></default>
 | 
			
		||||
      <_summary>Switch to VT 11</_summary>
 | 
			
		||||
    </key>
 | 
			
		||||
    <key name="switch-to-session-12" type="as">
 | 
			
		||||
      <default><![CDATA[['<Primary><Alt>F12']]]></default>
 | 
			
		||||
      <_summary>Switch to VT 12</_summary>
 | 
			
		||||
    </key>
 | 
			
		||||
  </schema>
 | 
			
		||||
</schemalist>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
SUBDIRS = man reference
 | 
			
		||||
 | 
			
		||||
EXTRA_DIST=theme-format.txt dialogs.txt code-overview.txt \
 | 
			
		||||
EXTRA_DIST = dialogs.txt code-overview.txt \
 | 
			
		||||
	how-to-get-focus-right.txt rationales.txt
 | 
			
		||||
 
 | 
			
		||||
@@ -81,6 +81,7 @@ IGNORE_HFILES= \
 | 
			
		||||
	keybindings-private.h \
 | 
			
		||||
	meta-background-actor-private.h \
 | 
			
		||||
	meta-background-group-private.h \
 | 
			
		||||
	meta-dbus-login1.h \
 | 
			
		||||
	meta-module.h \
 | 
			
		||||
	meta-plugin-manager.h \
 | 
			
		||||
	meta-shadow-factory-private.h \
 | 
			
		||||
@@ -111,6 +112,17 @@ IGNORE_HFILES= \
 | 
			
		||||
	xprops.h \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
if !HAVE_NATIVE_BACKEND
 | 
			
		||||
IGNORE_HFILES+= \
 | 
			
		||||
	meta-backend-native.h \
 | 
			
		||||
	meta-barrier-native.h \
 | 
			
		||||
	meta-cursor-renderer-native.h \
 | 
			
		||||
	meta-idle-monitor-native.h \
 | 
			
		||||
	meta-input-settings-native.h \
 | 
			
		||||
	meta-monitor-manager-kms.h \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
if !HAVE_WAYLAND
 | 
			
		||||
IGNORE_HFILES += \
 | 
			
		||||
	meta-surface-actor-wayland.h	\
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,6 @@
 | 
			
		||||
    <title>Mutter Core Reference</title>
 | 
			
		||||
    <xi:include href="xml/main.xml"/>
 | 
			
		||||
    <xi:include href="xml/common.xml"/>
 | 
			
		||||
    <xi:include href="xml/gradient.xml"/>
 | 
			
		||||
    <xi:include href="xml/prefs.xml"/>
 | 
			
		||||
    <xi:include href="xml/util.xml"/>
 | 
			
		||||
    <xi:include href="xml/errors.xml"/>
 | 
			
		||||
 
 | 
			
		||||
@@ -172,15 +172,6 @@ meta_error_trap_push_with_return
 | 
			
		||||
meta_error_trap_pop_with_return
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>gradient</FILE>
 | 
			
		||||
MetaGradientType
 | 
			
		||||
meta_gradient_create_simple
 | 
			
		||||
meta_gradient_create_multi
 | 
			
		||||
meta_gradient_create_interwoven
 | 
			
		||||
meta_gradient_add_alpha
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>group</FILE>
 | 
			
		||||
MetaGroup
 | 
			
		||||
 
 | 
			
		||||
@@ -1,396 +0,0 @@
 | 
			
		||||
Themes are in a simple XML-subset format. There are multiple versions
 | 
			
		||||
of the theme format, and a given theme can support more than one format.
 | 
			
		||||
 | 
			
		||||
Version 1:     THEMEDIR/metacity-1/metacity-theme-1.xml
 | 
			
		||||
  (original metacity format)
 | 
			
		||||
Version 2:     THEMEDIR/metacity-1/metacity-theme-2.xml
 | 
			
		||||
Version 3:     THEMEDIR/metacity-1/metacity-theme-3.xml
 | 
			
		||||
 | 
			
		||||
The subdirectory name is "metacity-1" in all versions.
 | 
			
		||||
 | 
			
		||||
As you might expect, older versions of metacity will not understand
 | 
			
		||||
newer theme formats. However, newer versions will use old themes.
 | 
			
		||||
Metacity will always use the newest theme format it understands that
 | 
			
		||||
the X server supports. Some format versions are only supported if you
 | 
			
		||||
have the right X server features.
 | 
			
		||||
 | 
			
		||||
Each format *requires* the corresponding filename. If you put version
 | 
			
		||||
2 format features in the metacity-1/metacity-theme-1.xml file, then
 | 
			
		||||
metacity will get angry.
 | 
			
		||||
 | 
			
		||||
This document has separate sections for each format version. You may
 | 
			
		||||
want to read the document in reverse order, since the base features
 | 
			
		||||
are discussed under version 1.
 | 
			
		||||
 | 
			
		||||
New Features in Theme Format Version 3.4
 | 
			
		||||
========================================
 | 
			
		||||
 | 
			
		||||
An additional color type is added to pick up custom colors defined
 | 
			
		||||
in the GTK+ theme's CSS:
 | 
			
		||||
 | 
			
		||||
  gtk:custom(name,fallback)
 | 
			
		||||
 | 
			
		||||
where <name> refers to a custom color defined with @define-color in
 | 
			
		||||
the GTK+ theme, and <fallback> provides an alternative color definition
 | 
			
		||||
in case the color referenced by <name> is not found.
 | 
			
		||||
 | 
			
		||||
New Features in Theme Format Version 3.3
 | 
			
		||||
========================================
 | 
			
		||||
 | 
			
		||||
Add two additional button background functions - left_single_background and
 | 
			
		||||
right_single_background - for button groups with just a single button.
 | 
			
		||||
 | 
			
		||||
There are now additional frame states to style left/right tiled windows
 | 
			
		||||
differently ("tiled_left", "tiled_right", "tiled_left_and_shaded",
 | 
			
		||||
"tiled_right_and_shaded").
 | 
			
		||||
 | 
			
		||||
New Features in Theme Format Version 3.2
 | 
			
		||||
========================================
 | 
			
		||||
 | 
			
		||||
A new window type 'attached' is added for modal dialogs which are
 | 
			
		||||
attached to their parent window. (When the attach_modal_dialogs preference
 | 
			
		||||
is turned on.) If no style is defined for the 'attached' window type,
 | 
			
		||||
the 'border' window type will be used instead.
 | 
			
		||||
 | 
			
		||||
New Features in Theme Format Version 3.1
 | 
			
		||||
========================================
 | 
			
		||||
 | 
			
		||||
Additional predefined variables are added for positioning expressions:
 | 
			
		||||
 | 
			
		||||
 frame_x_center: the X center of the entire frame, with respect to the
 | 
			
		||||
     piece currently being drawn.
 | 
			
		||||
 frame_y_center: the Y center of the entire frame, with respect to the
 | 
			
		||||
     piece currently being drawn.
 | 
			
		||||
 | 
			
		||||
The <title/> element now supports an "ellipsize_width" attribute. When
 | 
			
		||||
specified, this gives a width at which to ellipsize the title. If not
 | 
			
		||||
specified, the title will simply be clipped to the title area.
 | 
			
		||||
 | 
			
		||||
New Features in Theme Format Version 3
 | 
			
		||||
======================================
 | 
			
		||||
 | 
			
		||||
Format version 3 has exactly one new feature; any element in the file
 | 
			
		||||
can now have a version attribute:
 | 
			
		||||
 | 
			
		||||
  version="[<|<=|=>|>] MAJOR.MINOR"
 | 
			
		||||
 | 
			
		||||
(< and > should be to be entity escaped as < and >). If this
 | 
			
		||||
version check is not met, then the element and its children will be
 | 
			
		||||
ignored. This allows having alternate sections of the theme file for
 | 
			
		||||
older and newer version of the Metacity theme format.
 | 
			
		||||
 | 
			
		||||
When placed on the toplevel <metacity_theme> element, an unsatisfied
 | 
			
		||||
version check will not just cause the contents of the file to be
 | 
			
		||||
ignored, it will also cause the lookup of a theme file to proceed on
 | 
			
		||||
and look for an older format 2 or format 1 file. This allows making a
 | 
			
		||||
metacity-theme-3.xml file that is only used the format version 3.2 or
 | 
			
		||||
newer is supported, and using metacity-theme-1.xml for older window
 | 
			
		||||
managers.
 | 
			
		||||
 | 
			
		||||
New Features in Theme Format Version 2
 | 
			
		||||
======================================
 | 
			
		||||
 | 
			
		||||
The optional attributes rounded_top_left, rounded_top_right,
 | 
			
		||||
rounded_bottom_left and rounded_bottom_right on <frame_geometry>
 | 
			
		||||
should now be the radius of the corner in pixels. You may still use
 | 
			
		||||
the values "false" for 0 and "true" for 5, which means v1 values will
 | 
			
		||||
still work just fine.
 | 
			
		||||
 | 
			
		||||
<frame_geometry> has a new optional attribute, hide_buttons. If this
 | 
			
		||||
is true, no buttons will be displayed on the titlebar.
 | 
			
		||||
 | 
			
		||||
Anywhere you can use a positive integer, you can use an integer constant.
 | 
			
		||||
 | 
			
		||||
As well as constant integers and reals, you may define constant colours,
 | 
			
		||||
thus:
 | 
			
		||||
  <constant name="RevoltingPink" value="#FF00FF"/>
 | 
			
		||||
  <constant name="Background" value="gtk:bg[NORMAL]"/>
 | 
			
		||||
 | 
			
		||||
<frame_style> has two new optional attributes, background and alpha.
 | 
			
		||||
If you specify alpha, you must specify background. background is a
 | 
			
		||||
colour used for the background of the frame. alpha is the transparency
 | 
			
		||||
as a real between 0.0 and 1.0. If the current X server does not support
 | 
			
		||||
alpha channels, the value is ignored.
 | 
			
		||||
 | 
			
		||||
The filename attribute of <image> may begin with "theme:". If so, the
 | 
			
		||||
rest of the string is the name of a theme icon. The 64x64 version of the
 | 
			
		||||
icon is used, except for fallback mini_icons, which use the 16x16 version.
 | 
			
		||||
This does not affect ordinary resizing. For example:
 | 
			
		||||
  <button function="close" state="normal">
 | 
			
		||||
    <draw_ops>
 | 
			
		||||
      <include name="active_button"/>
 | 
			
		||||
      <image filename="theme:gnome-logout" x="2" y="2"
 | 
			
		||||
          width="width-4" height="height-4"/>
 | 
			
		||||
      <!-- Note: not "theme:gnome-logout.png" or similar. -->
 | 
			
		||||
    </draw_ops>
 | 
			
		||||
  </button>
 | 
			
		||||
 | 
			
		||||
<menu_icon>s are parsed but ignored.
 | 
			
		||||
 | 
			
		||||
Fallback icons can be specified using <fallback>. There are two
 | 
			
		||||
optional arguments, icon and mini_icon. The values of these arguments
 | 
			
		||||
are identical to that of the filename attribute of <image>. Fallback
 | 
			
		||||
icons are used when a window does not supply its own icon. If a fallback
 | 
			
		||||
icon is not specified with <fallback>, Metacity will use a built-in
 | 
			
		||||
icon, as in metacity-theme-1.
 | 
			
		||||
 | 
			
		||||
The <arc> element, as well as the original start_angle and end_angle
 | 
			
		||||
attributes, may be given from and to attributes. The values of these
 | 
			
		||||
attributes are given in degrees clockwise, with 0 being straight up.
 | 
			
		||||
For example:
 | 
			
		||||
  <arc from="0.0" to="90.0" filled="true" color="#FF00FF"
 | 
			
		||||
      x="0" y="5" width="15" height="15"/>
 | 
			
		||||
 | 
			
		||||
<frame state="shaded"> may now take an optional resize attribute, with
 | 
			
		||||
the same interpretation as the resize attribute on <frame state="normal">.
 | 
			
		||||
If this attribute is omitted for state="shaded", it defaults to "both".
 | 
			
		||||
(If it is omitted for state="normal", it remains an error.)
 | 
			
		||||
 | 
			
		||||
In addition to the four <button> functions which are required in
 | 
			
		||||
metacity-theme-1, there are six new functions in metacity-theme-2:
 | 
			
		||||
shade, unshade, above, unabove, stick and unstick.
 | 
			
		||||
      
 | 
			
		||||
Overview of Theme Format Version 1
 | 
			
		||||
==================================
 | 
			
		||||
 | 
			
		||||
<?xml version="1.0"?>
 | 
			
		||||
<metacity_theme>
 | 
			
		||||
<!-- Only one info section is allowed -->
 | 
			
		||||
<info>
 | 
			
		||||
  <name>Foo</name>
 | 
			
		||||
  <author>Foo P. Bar</author>
 | 
			
		||||
  <copyright>whoever, 2002</copyright>
 | 
			
		||||
  <date>Jan 31 2005</date>
 | 
			
		||||
  <description>A sentence about the theme.</description>
 | 
			
		||||
</info>
 | 
			
		||||
 | 
			
		||||
<!-- define a frame geometry to be referenced later -->
 | 
			
		||||
<!-- frame_geometry has an optional has_title attribute which 
 | 
			
		||||
     determines whether the title text height is included in the 
 | 
			
		||||
     height calculation. if not specified, defaults to true.
 | 
			
		||||
     It also has an optional text_size="medium" attribute
 | 
			
		||||
     (same sizes as with Pango markup, xx-small thru medium thru
 | 
			
		||||
     xx-large) 
 | 
			
		||||
 | 
			
		||||
     Finally it has optional args rounded_top_left=true, 
 | 
			
		||||
     rounded_top_right=true, rounded_bottom_left=true,
 | 
			
		||||
     rounded_bottom_right=true.
 | 
			
		||||
 | 
			
		||||
     -->
 | 
			
		||||
<frame_geometry name="normal" has_title="true" title_scale="medium">
 | 
			
		||||
  <distance name="left_width" value="6"/>
 | 
			
		||||
  <distance name="right_width" value="6"/>
 | 
			
		||||
  <distance name="bottom_height" value="7"/>
 | 
			
		||||
  <distance name="left_titlebar_edge" value="6"/>
 | 
			
		||||
  <distance name="right_titlebar_edge" value="6"/>
 | 
			
		||||
  <distance name="button_width" value="17"/>
 | 
			
		||||
  <distance name="button_height" value="17"/>
 | 
			
		||||
  <!-- alternative to button_width button_height distances -->
 | 
			
		||||
  <aspect_ratio name="button" value="1.0"/>
 | 
			
		||||
  <distance name="title_vertical_pad" value="4"/>
 | 
			
		||||
  <border name="title_border" left="3" right="12" top="4" bottom="3"/>
 | 
			
		||||
  <border name="button_border" left="0" right="0" top="1" bottom="1"/>
 | 
			
		||||
</frame_geometry>
 | 
			
		||||
 | 
			
		||||
<!-- inheritance is allowed; simply overwrites values from parent -->
 | 
			
		||||
<frame_geometry name="borderless" parent="normal">
 | 
			
		||||
  <distance name="left_width" value="0"/>
 | 
			
		||||
  <distance name="right_width" value="0"/>
 | 
			
		||||
  <distance name="bottom_height" value="0"/>
 | 
			
		||||
  <distance name="left_titlebar_edge" value="0"/>
 | 
			
		||||
  <distance name="right_titlebar_edge" value="0"/>
 | 
			
		||||
</frame_geometry>
 | 
			
		||||
 | 
			
		||||
<!-- define a constant to use in positions/sizes of draw operations;
 | 
			
		||||
     constant names must start with a capital letter.
 | 
			
		||||
  -->
 | 
			
		||||
<constant name="LineOffset" value="3"/>
 | 
			
		||||
 | 
			
		||||
<!-- define drawing operations to be referenced later; 
 | 
			
		||||
     these draw-op lists can also be placed inline. 
 | 
			
		||||
 | 
			
		||||
     Positions/lengths are given as expressions.
 | 
			
		||||
     Operators are: +,-,*,/,%,`max`,`min`
 | 
			
		||||
     All operators are infix including `max` and `min`, 
 | 
			
		||||
      i.e. "2 `max` 5"
 | 
			
		||||
     
 | 
			
		||||
     Some variables are predefined, and constants can also 
 | 
			
		||||
     be used. Variables are:
 | 
			
		||||
 | 
			
		||||
       width - width of target area
 | 
			
		||||
       height - height of target area
 | 
			
		||||
       object_width - natural width of object being drawn
 | 
			
		||||
       object_height - natural height of object being drawn
 | 
			
		||||
       left_width - distance from left of frame to client window
 | 
			
		||||
       right_width - distance from right of frame to client window
 | 
			
		||||
       top_height - distance from top of frame to client window
 | 
			
		||||
       bottom_height - distance from bottom of frame to client window
 | 
			
		||||
       mini_icon_width - width of mini icon for window
 | 
			
		||||
       mini_icon_height - height of mini icon
 | 
			
		||||
       icon_width - width of large icon
 | 
			
		||||
       icon_height - height of large icon
 | 
			
		||||
       title_width - width of title text
 | 
			
		||||
       title_height - height of title text
 | 
			
		||||
 | 
			
		||||
    All these are always defined, except object_width/object_height 
 | 
			
		||||
    which only exists for <image> right now.
 | 
			
		||||
 | 
			
		||||
  -->
 | 
			
		||||
 | 
			
		||||
<draw_ops name="demo_all_ops">
 | 
			
		||||
  <line color="#00FF00" x1="LineOffset" y1="0" x2="0" y2="height"/>
 | 
			
		||||
  <line color="gtk:fg[NORMAL]" 
 | 
			
		||||
        x1="width - 1" y1="0" x2="width - 1" y2="height" 
 | 
			
		||||
        width="3" dash_on_length="2" dash_off_length="3"/>
 | 
			
		||||
  <rectangle color="blend/gtk:fg[NORMAL]/gtk:bg[NORMAL]/0.7"
 | 
			
		||||
             x="0" y="0" width="width - 1" height="height - 1" filled="true"/>
 | 
			
		||||
  <arc color="dark gray" x="0" y="0" width="width - 1" height="height - 1" 
 | 
			
		||||
       filled="false" start_angle="30" extent_angle="180"/>
 | 
			
		||||
  <tint color="orange" alpha="0.5" x="0" y="0" width="width" height="height"/>
 | 
			
		||||
 <!-- may be vertical, horizontal, diagonal -->
 | 
			
		||||
  <gradient type="diagonal" 
 | 
			
		||||
            x="10" y="30" width="width / 3" height="height / 4">
 | 
			
		||||
    <!-- any number of colors allowed here. A color can be 
 | 
			
		||||
         a color name like "blue" (look at gcolorsel), a hex color
 | 
			
		||||
         as in HTML (#FFBB99), or a color from the gtk theme 
 | 
			
		||||
         given as "gtk:base[NORMAL]", "gtk:fg[ACTIVE]", etc.
 | 
			
		||||
       -->
 | 
			
		||||
    <color value="gtk:fg[SELECTED]"/>
 | 
			
		||||
    <!-- color obtained by a 0.5 alpha composite of the second color onto the first -->
 | 
			
		||||
    <color value="blend/gtk:bg[SELECTED]/gtk:fg[SELECTED]/0.5"/>
 | 
			
		||||
  </gradient>
 | 
			
		||||
  <!-- image has an optional colorize="#color" attribute to give the
 | 
			
		||||
       image a certain color -->
 | 
			
		||||
  <image filename="foo.png" alpha="0.7"
 | 
			
		||||
         x="10" y="30" width="width / 3" height="height / 4"/>
 | 
			
		||||
  <gtk_arrow state="normal" shadow="in" arrow="up"
 | 
			
		||||
             filled="true"
 | 
			
		||||
             x="2" y="2" width="width - 4" height="height - 4"/>
 | 
			
		||||
  <gtk_box state="normal" shadow="out"
 | 
			
		||||
           x="2" y="2" width="width - 4" height="height - 4"/>
 | 
			
		||||
  <gtk_vline state="normal" x="2" y1="0" y2="height"/>
 | 
			
		||||
  <!-- window's icon -->
 | 
			
		||||
  <icon alpha="0.7"
 | 
			
		||||
        x="10" y="30" width="width / 3" height="height / 4"/>
 | 
			
		||||
  <!-- window's title -->
 | 
			
		||||
  <title color="gtk:text[NORMAL]" x="20" y="30"/>
 | 
			
		||||
  <!-- include another draw ops list; has optional x/y/width/height attrs -->
 | 
			
		||||
  <include name="some_other_draw_ops"/>
 | 
			
		||||
  <!-- tile another draw ops list; has optional
 | 
			
		||||
       x/y/width/height/tile_xoffset/tile_yoffset -->
 | 
			
		||||
  <tile name="some_other_draw_ops" tile_width="10" tile_height="10"/>
 | 
			
		||||
</draw_ops>
 | 
			
		||||
 | 
			
		||||
<frame_style name="normal" geometry="normal">
 | 
			
		||||
  <!-- How to draw each piece of the frame.
 | 
			
		||||
       For each piece, a draw_ops can be given inline or referenced 
 | 
			
		||||
       by name. If a piece is omitted, then nothing will be drawn 
 | 
			
		||||
       for that piece.
 | 
			
		||||
 | 
			
		||||
       For each piece, the "width" and "height" variables in 
 | 
			
		||||
       coordinate expressions refers to the dimensions of the piece, 
 | 
			
		||||
       the origin is at the top left of the piece.
 | 
			
		||||
  
 | 
			
		||||
       So <rectangle x="0" y="0" width="width-1" height="height-1"/>
 | 
			
		||||
       will outline a piece.
 | 
			
		||||
    -->
 | 
			
		||||
 | 
			
		||||
  <piece position="entire_background" draw_ops="demo_all_ops"/>
 | 
			
		||||
  <piece position="left_titlebar_edge">
 | 
			
		||||
    <draw_ops>
 | 
			
		||||
      <line color="#00FF00" x1="0" y1="0" x2="0" y2="height"/>
 | 
			
		||||
    </draw_ops>
 | 
			
		||||
  </piece>
 | 
			
		||||
 | 
			
		||||
  <!-- The complete list of frame pieces:
 | 
			
		||||
 | 
			
		||||
       entire_background: whole frame
 | 
			
		||||
       titlebar: entire area above the app's window 
 | 
			
		||||
       titlebar_middle: area of titlebar_background not considered
 | 
			
		||||
                        part of an edge
 | 
			
		||||
       left_titlebar_edge: left side of titlebar background
 | 
			
		||||
       right_titlebar_edge: right side of titlebar background
 | 
			
		||||
       top_titlebar_edge: top side of titlebar background
 | 
			
		||||
       bottom_titlebar_edge: bottom side of titlebar background 
 | 
			
		||||
       title: the title area (doesn't include buttons)
 | 
			
		||||
       left_edge: left edge of the frame
 | 
			
		||||
       right_edge: right edge of the frame
 | 
			
		||||
       bottom_edge: bottom edge of the frame
 | 
			
		||||
       overlay: same area as entire_background, but drawn after 
 | 
			
		||||
                drawing all sub-pieces instead of before
 | 
			
		||||
 | 
			
		||||
   -->
 | 
			
		||||
 | 
			
		||||
  <!-- For buttons, drawing methods have to be provided for 
 | 
			
		||||
       each of three states: 
 | 
			
		||||
          normal, pressed, prelight
 | 
			
		||||
       and the button function or position must be provided:
 | 
			
		||||
          close, maximize, minimize, menu, 
 | 
			
		||||
          left_left_background, left_middle_background,
 | 
			
		||||
          left_right_background, right_left_background, 
 | 
			
		||||
          right_middle_background, right_right_background
 | 
			
		||||
       So a working theme needs 3*4 = 12 button declarations
 | 
			
		||||
       and a theme may have up to 3*10 = 30 button declarations
 | 
			
		||||
       in order to handle button-rearrangement preferences.
 | 
			
		||||
 
 | 
			
		||||
       (The name "function" for the attribute is from before the 
 | 
			
		||||
        background values existed.)
 | 
			
		||||
    -->
 | 
			
		||||
 | 
			
		||||
  <button function="close" state="normal" draw_ops="previously_named"/>
 | 
			
		||||
  <button function="menu" state="normal">
 | 
			
		||||
    <draw_ops>
 | 
			
		||||
      <icon alpha="0.7"
 | 
			
		||||
            x="0" y="0" width="object_width" height="object_height"/>
 | 
			
		||||
    </draw_ops>
 | 
			
		||||
  </button>
 | 
			
		||||
 | 
			
		||||
</frame_style>
 | 
			
		||||
 | 
			
		||||
<!-- styles can inherit from each other with the parent="" attribute. 
 | 
			
		||||
     In a subclass anything can be re-specified to override 
 | 
			
		||||
     the parent style. -->
 | 
			
		||||
<frame_style name="focused" parent="normal">
 | 
			
		||||
  <piece position="title">
 | 
			
		||||
    <draw_ops>
 | 
			
		||||
      <rectangle color="gtk:bg[SELECTED]"
 | 
			
		||||
                 x="0" y="0" width="width-1" height="height-1"/>
 | 
			
		||||
      <title color="gtk:fg[SELECTED]" x="(width - title_width) / 2"
 | 
			
		||||
                                      y="(height - title_height) / 2"/>
 | 
			
		||||
    </draw_ops>
 | 
			
		||||
  </piece>
 | 
			
		||||
</frame_style>
 | 
			
		||||
 | 
			
		||||
<!-- Maps styles to states of frame. 
 | 
			
		||||
 | 
			
		||||
     Focus: yes (focused), no (not focused)
 | 
			
		||||
     Window states: normal, maximized, shaded, maximized_and_shaded
 | 
			
		||||
     Window resizability: none, vertical, horizontal, both
 | 
			
		||||
 | 
			
		||||
     Everything unspecified just does the same as
 | 
			
		||||
     unfocused/normal/both.
 | 
			
		||||
 | 
			
		||||
     only state="normal" needs a resize="" attribute.
 | 
			
		||||
 -->
 | 
			
		||||
<frame_style_set name="normal">
 | 
			
		||||
<frame focus="yes" state="normal" resize="both" style="focused"/>
 | 
			
		||||
<frame focus="no" state="normal" resize="both" style="normal"/>
 | 
			
		||||
</frame_style_set>
 | 
			
		||||
 | 
			
		||||
<!-- Each window type needs a style set 
 | 
			
		||||
     Types: normal, dialog, modal_dialog, menu, utility, border
 | 
			
		||||
  -->
 | 
			
		||||
<window type="normal" style_set="normal"/>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<!-- For menu icons, drawing methods are needed for the same 
 | 
			
		||||
     four types as the buttons, and GTK states
 | 
			
		||||
     (insensitive,prelight,normal,etc.)
 | 
			
		||||
  -->
 | 
			
		||||
 | 
			
		||||
<menu_icon function="close" state="normal" draw_ops="previously_named"/>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
</metacity_theme>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -22,9 +22,7 @@ src/core/screen.c
 | 
			
		||||
src/core/util.c
 | 
			
		||||
src/core/window.c
 | 
			
		||||
src/ui/frames.c
 | 
			
		||||
src/ui/resizepopup.c
 | 
			
		||||
src/ui/theme.c
 | 
			
		||||
src/ui/theme-parser.c
 | 
			
		||||
src/x11/session.c
 | 
			
		||||
src/x11/window-props.c
 | 
			
		||||
src/x11/xprops.c
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2679
									
								
								po/bn_IN.po
									
									
									
									
									
								
							
							
						
						
									
										2679
									
								
								po/bn_IN.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										304
									
								
								po/hu.po
									
									
									
									
									
								
							
							
						
						
									
										304
									
								
								po/hu.po
									
									
									
									
									
								
							@@ -7,14 +7,13 @@
 | 
			
		||||
# Laszlo Dvornik <dvornik at gnome dot hu>, 2004.
 | 
			
		||||
# Gabor Kelemen <kelemeng at gnome dot hu>, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013.
 | 
			
		||||
# Balázs Úr <urbalazs at gmail dot com>, 2013, 2014.
 | 
			
		||||
# Balázs Úr <urbalazs@gmail.com>, 2014.
 | 
			
		||||
msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: mutter master\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
 | 
			
		||||
"product=mutter&keywords=I18N+L10N&component=general\n"
 | 
			
		||||
"POT-Creation-Date: 2014-09-11 09:53+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2014-09-11 18:20+0200\n"
 | 
			
		||||
"POT-Creation-Date: 2014-12-29 03:21+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2014-12-29 09:28+0100\n"
 | 
			
		||||
"Last-Translator: Balázs Úr <urbalazs@gmail.com>\n"
 | 
			
		||||
"Language-Team: Hungarian <gnome-hu-list at gnome dot org>\n"
 | 
			
		||||
"Language: hu\n"
 | 
			
		||||
@@ -45,7 +44,6 @@ msgid "Move window to workspace 4"
 | 
			
		||||
msgstr "Ablak áthelyezése a 4. munkaterületre"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:6
 | 
			
		||||
#| msgid "Move window to workspace 1"
 | 
			
		||||
msgid "Move window to last workspace"
 | 
			
		||||
msgstr "Ablak áthelyezése az utolsó munkaterületre"
 | 
			
		||||
 | 
			
		||||
@@ -86,7 +84,6 @@ msgid "Switch applications"
 | 
			
		||||
msgstr "Alkalmazásváltás"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:16
 | 
			
		||||
#| msgid "Switch applications"
 | 
			
		||||
msgid "Switch to previous application"
 | 
			
		||||
msgstr "Váltás az előző alkalmazásra"
 | 
			
		||||
 | 
			
		||||
@@ -95,7 +92,6 @@ msgid "Switch windows"
 | 
			
		||||
msgstr "Ablakváltás"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:18
 | 
			
		||||
#| msgid "Switch windows"
 | 
			
		||||
msgid "Switch to previous window"
 | 
			
		||||
msgstr "Váltás az előző ablakra"
 | 
			
		||||
 | 
			
		||||
@@ -104,7 +100,6 @@ msgid "Switch windows of an application"
 | 
			
		||||
msgstr "Váltás egy alkalmazás ablakai között"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:20
 | 
			
		||||
#| msgid "Switch windows of an application"
 | 
			
		||||
msgid "Switch to previous window of an application"
 | 
			
		||||
msgstr "Váltás egy alkalmazás előző ablakára"
 | 
			
		||||
 | 
			
		||||
@@ -113,7 +108,6 @@ msgid "Switch system controls"
 | 
			
		||||
msgstr "Váltás a rendszer vezérlői közt"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:22
 | 
			
		||||
#| msgid "Switch system controls"
 | 
			
		||||
msgid "Switch to previous system control"
 | 
			
		||||
msgstr "Váltás az előző rendszervezérlőre"
 | 
			
		||||
 | 
			
		||||
@@ -130,7 +124,6 @@ msgid "Switch windows of an app directly"
 | 
			
		||||
msgstr "Váltás egy alkalmazás ablakai között közvetlenül"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:26
 | 
			
		||||
#| msgid "Switch windows of an application"
 | 
			
		||||
msgid "Switch directly to previous window of an app"
 | 
			
		||||
msgstr "Váltás közvetlenül egy alkalmazás előző ablakára"
 | 
			
		||||
 | 
			
		||||
@@ -139,7 +132,6 @@ msgid "Switch system controls directly"
 | 
			
		||||
msgstr "Váltás a rendszer vezérlői közt közvetlenül"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:28
 | 
			
		||||
#| msgid "Switch system controls"
 | 
			
		||||
msgid "Switch directly to previous system control"
 | 
			
		||||
msgstr "Váltás közvetlenül az előző rendszervezérlőre"
 | 
			
		||||
 | 
			
		||||
@@ -164,7 +156,6 @@ msgid "Switch to workspace 4"
 | 
			
		||||
msgstr "Váltás a 4. munkaterületre"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:34
 | 
			
		||||
#| msgid "Switch to workspace 1"
 | 
			
		||||
msgid "Switch to last workspace"
 | 
			
		||||
msgstr "Váltás az utolsó munkaterületre"
 | 
			
		||||
 | 
			
		||||
@@ -417,70 +408,62 @@ msgid "Cancel tab popup"
 | 
			
		||||
msgstr "Tab felugró kikapcsolása"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:1
 | 
			
		||||
#| msgid "Switch to workspace 1"
 | 
			
		||||
msgid "Switch to VT 1"
 | 
			
		||||
msgstr "Váltás az 1. VT-re"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:2
 | 
			
		||||
#| msgid "Switch to workspace 2"
 | 
			
		||||
msgid "Switch to VT 2"
 | 
			
		||||
msgstr "Váltás a 2. VT-re"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:3
 | 
			
		||||
#| msgid "Switch to workspace 3"
 | 
			
		||||
msgid "Switch to VT 3"
 | 
			
		||||
msgstr "Váltás a 3. VT-re"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:4
 | 
			
		||||
#| msgid "Switch to workspace 4"
 | 
			
		||||
msgid "Switch to VT 4"
 | 
			
		||||
msgstr "Váltás a 4. VT-re"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:5
 | 
			
		||||
#| msgid "Switch to workspace 5"
 | 
			
		||||
msgid "Switch to VT 5"
 | 
			
		||||
msgstr "Váltás az 5. VT-re"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:6
 | 
			
		||||
#| msgid "Switch to workspace 6"
 | 
			
		||||
msgid "Switch to VT 6"
 | 
			
		||||
msgstr "Váltás a 6. VT-re"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:7
 | 
			
		||||
#| msgid "Switch to workspace 7"
 | 
			
		||||
msgid "Switch to VT 7"
 | 
			
		||||
msgstr "Váltás a 7. VT-re"
 | 
			
		||||
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:412
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:350
 | 
			
		||||
msgid "Built-in display"
 | 
			
		||||
msgstr "Beépített kijelző"
 | 
			
		||||
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:437
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:375
 | 
			
		||||
msgid "Unknown"
 | 
			
		||||
msgstr "Ismeretlen"
 | 
			
		||||
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:439
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:377
 | 
			
		||||
msgid "Unknown Display"
 | 
			
		||||
msgstr "Ismeretlen kijelző"
 | 
			
		||||
 | 
			
		||||
#. TRANSLATORS: this is a monitor vendor name, followed by a
 | 
			
		||||
#. * size in inches, like 'Dell 15"'
 | 
			
		||||
#.
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:447
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:385
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%s %s"
 | 
			
		||||
msgstr "%s %s"
 | 
			
		||||
 | 
			
		||||
#. This probably means that a non-WM compositor like xcompmgr is running;
 | 
			
		||||
#. * we have no way to get it to exit
 | 
			
		||||
#: ../src/compositor/compositor.c:443
 | 
			
		||||
#: ../src/compositor/compositor.c:456
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Another compositing manager is already running on screen %i on display \"%s"
 | 
			
		||||
"\"."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Már fut egy másik betűszedés-kezelő a(z) %i képernyőn a(z) „%s” "
 | 
			
		||||
"megjelenítőn."
 | 
			
		||||
"Már fut egy másik betűszedés-kezelő a(z) %i képernyőn a(z) „%s” megjelenítőn."
 | 
			
		||||
 | 
			
		||||
#: ../src/core/bell.c:185
 | 
			
		||||
msgid "Bell event"
 | 
			
		||||
@@ -511,7 +494,7 @@ msgstr "Vá_rakozás"
 | 
			
		||||
msgid "_Force Quit"
 | 
			
		||||
msgstr "_Erőltetett kilépés"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/display.c:547
 | 
			
		||||
#: ../src/core/display.c:550
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Failed to open X Window System display '%s'\n"
 | 
			
		||||
msgstr "Nem sikerült megnyitni a(z) „%s” X Window rendszer képernyőt\n"
 | 
			
		||||
@@ -585,30 +568,28 @@ msgstr "Verzió kinyomtatása"
 | 
			
		||||
msgid "Mutter plugin to use"
 | 
			
		||||
msgstr "Használandó Mutter bővítmény"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/prefs.c:2101
 | 
			
		||||
#: ../src/core/prefs.c:2064
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Workspace %d"
 | 
			
		||||
msgstr "%d. munkaterület"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/screen.c:548
 | 
			
		||||
#: ../src/core/screen.c:525
 | 
			
		||||
#, c-format
 | 
			
		||||
#| msgid ""
 | 
			
		||||
#| "Screen %d on display \"%s\" already has a window manager; try using the --"
 | 
			
		||||
#| "replace option to replace the current window manager.\n"
 | 
			
		||||
msgid ""
 | 
			
		||||
"Display \"%s\" already has a window manager; try using the --replace option "
 | 
			
		||||
"to replace the current window manager."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"A(z) „%s” kijelző már rendelkezik ablakkezelővel; próbálja a --replace "
 | 
			
		||||
"kapcsolóval helyettesíteni a jelenlegi ablakkezelőt."
 | 
			
		||||
 | 
			
		||||
#: ../src/core/screen.c:607
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Screen %d on display '%s' is invalid\n"
 | 
			
		||||
msgstr "A(z) %d képernyő a(z) „%s” megjelenítőn érvénytelen\n"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/screen.c:564
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Screen %d on display \"%s\" already has a window manager; try using the --"
 | 
			
		||||
"replace option to replace the current window manager.\n"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"A(z) %d képernyő a(z) „%s” megjelenítőn már rendelkezik egy ablakkezelővel; "
 | 
			
		||||
"próbálja a --replace opcióval helyettesíteni a jelenlegi ablakkezelőt.\n"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/screen.c:657
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Screen %d on display \"%s\" already has a window manager\n"
 | 
			
		||||
msgstr "A(z) %d képernyőnek a(z) „%s” megjelenítőn már van ablakkezelője\n"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/util.c:118
 | 
			
		||||
msgid "Mutter was compiled without support for verbose mode\n"
 | 
			
		||||
msgstr "A Mutter ablakkezelőt a részletes mód támogatása nélkül fordították\n"
 | 
			
		||||
@@ -621,48 +602,48 @@ msgstr "A Mutter ablakkezelőt a részletes mód támogatása nélkül fordítot
 | 
			
		||||
msgid "%d x %d"
 | 
			
		||||
msgstr "%d x %d"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:233
 | 
			
		||||
#: ../src/ui/theme.c:154
 | 
			
		||||
msgid "top"
 | 
			
		||||
msgstr "fent"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:235
 | 
			
		||||
#: ../src/ui/theme.c:156
 | 
			
		||||
msgid "bottom"
 | 
			
		||||
msgstr "lent"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:237
 | 
			
		||||
#: ../src/ui/theme.c:158
 | 
			
		||||
msgid "left"
 | 
			
		||||
msgstr "bal"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:239
 | 
			
		||||
#: ../src/ui/theme.c:160
 | 
			
		||||
msgid "right"
 | 
			
		||||
msgstr "jobb"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:267
 | 
			
		||||
#: ../src/ui/theme.c:188
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "frame geometry does not specify \"%s\" dimension"
 | 
			
		||||
msgstr "a keretgeometria nem határoz meg „%s” dimenziót"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:286
 | 
			
		||||
#: ../src/ui/theme.c:207
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "frame geometry does not specify dimension \"%s\" for border \"%s\""
 | 
			
		||||
msgstr "a keretgeometria nem határoz meg „%s” dimenziót „%s” szegélynek"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:323
 | 
			
		||||
#: ../src/ui/theme.c:244
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Button aspect ratio %g is not reasonable"
 | 
			
		||||
msgstr "%g gomb méretaránya nem fogadható el"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:335
 | 
			
		||||
#: ../src/ui/theme.c:256
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Frame geometry does not specify size of buttons"
 | 
			
		||||
msgstr "A keretgeometria nem határozza meg a gombok méretét"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1061
 | 
			
		||||
#: ../src/ui/theme.c:1024
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Gradients should have at least two colors"
 | 
			
		||||
msgstr "A színátmenetnek legalább két színűnek kell lennie"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1211
 | 
			
		||||
#: ../src/ui/theme.c:1174
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"GTK custom color specification must have color name and fallback in "
 | 
			
		||||
@@ -672,7 +653,7 @@ msgstr ""
 | 
			
		||||
"tartalékot, például gtk:custom(foo,bar); nem sikerült értelmezni a "
 | 
			
		||||
"következőt: „%s”"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1227
 | 
			
		||||
#: ../src/ui/theme.c:1190
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
 | 
			
		||||
@@ -681,7 +662,7 @@ msgstr ""
 | 
			
		||||
"Érvénytelen karakter („%c”) a gtk:custom color_name paraméterében, csak az A-"
 | 
			
		||||
"Za-z0-9-_ érvényes"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1241
 | 
			
		||||
#: ../src/ui/theme.c:1204
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
 | 
			
		||||
@@ -690,7 +671,7 @@ msgstr ""
 | 
			
		||||
"A Gtk:custom formátuma: „gtk:custom(színnév,tartalék)”, „%s” nem felel meg "
 | 
			
		||||
"ennek"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1286
 | 
			
		||||
#: ../src/ui/theme.c:1249
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] "
 | 
			
		||||
@@ -700,7 +681,7 @@ msgstr ""
 | 
			
		||||
"gtk:fg[NORMAL] ahol NORMAL az állapot; nem lehetett feldolgozni a "
 | 
			
		||||
"következőt: „%s”"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1300
 | 
			
		||||
#: ../src/ui/theme.c:1263
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"GTK color specification must have a close bracket after the state, e.g. gtk:"
 | 
			
		||||
@@ -710,17 +691,17 @@ msgstr ""
 | 
			
		||||
"után, például gtk:fg[NORMAL], ahol NORMAL az állapot; nem sikerült "
 | 
			
		||||
"értelmezni a következőt: „%s”"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1311
 | 
			
		||||
#: ../src/ui/theme.c:1274
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Did not understand state \"%s\" in color specification"
 | 
			
		||||
msgstr "Nem sikerült a(z) „%s” állapotot értelmezni a szín meghatározásban"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1324
 | 
			
		||||
#: ../src/ui/theme.c:1287
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Did not understand color component \"%s\" in color specification"
 | 
			
		||||
msgstr "Nem sikerült értelmezni „%s” színösszetevőt a színmeghatározásban"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1352
 | 
			
		||||
#: ../src/ui/theme.c:1315
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the "
 | 
			
		||||
@@ -729,44 +710,44 @@ msgstr ""
 | 
			
		||||
"A keverés formátuma: „blend/bg_color/fg_color/alpha”, „%s” nem felel meg "
 | 
			
		||||
"ennek"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1363
 | 
			
		||||
#: ../src/ui/theme.c:1326
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Could not parse alpha value \"%s\" in blended color"
 | 
			
		||||
msgstr "Nem sikerült értelmezni a(z) „%s” alfa értéket a kevert színben"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1373
 | 
			
		||||
#: ../src/ui/theme.c:1336
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Alpha value \"%s\" in blended color is not between 0.0 and 1.0"
 | 
			
		||||
msgstr "A(z) „%s” alfa érték a kevert színben nem 0.0 és 1.0 között van"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1419
 | 
			
		||||
#: ../src/ui/theme.c:1382
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Az árnyék formátuma: „shade/base_color/factor”, „%s” nem felel meg ennek"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1430
 | 
			
		||||
#: ../src/ui/theme.c:1393
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Could not parse shade factor \"%s\" in shaded color"
 | 
			
		||||
msgstr "Nem sikerült a(z) „%s” árnyéktényezőt feldolgozni az árnyékolt színben"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1440
 | 
			
		||||
#: ../src/ui/theme.c:1403
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Shade factor \"%s\" in shaded color is negative"
 | 
			
		||||
msgstr "„%s” árnyéktényező az árnyékolt színben negatív"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1469
 | 
			
		||||
#: ../src/ui/theme.c:1432
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Could not parse color \"%s\""
 | 
			
		||||
msgstr "Nem sikerült feldolgozni a(z) „%s” színt"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1778
 | 
			
		||||
#: ../src/ui/theme.c:1741
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression contains character '%s' which is not allowed"
 | 
			
		||||
msgstr "A koordinátakifejezés „%s” karaktert tartalmaz, ami nem megengedett"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1805
 | 
			
		||||
#: ../src/ui/theme.c:1768
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Coordinate expression contains floating point number '%s' which could not be "
 | 
			
		||||
@@ -775,14 +756,14 @@ msgstr ""
 | 
			
		||||
"A koordinátakifejezés „%s” lebegőpontos számot tartalmaz, amit nem sikerült "
 | 
			
		||||
"feldolgozni"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1819
 | 
			
		||||
#: ../src/ui/theme.c:1782
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression contains integer '%s' which could not be parsed"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"A koordinátakifejezés „%s” egész számot tartalmaz, amit nem sikerült "
 | 
			
		||||
"feldolgozni"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1940
 | 
			
		||||
#: ../src/ui/theme.c:1903
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Coordinate expression contained unknown operator at the start of this text: "
 | 
			
		||||
@@ -791,40 +772,40 @@ msgstr ""
 | 
			
		||||
"A koordinátakifejezés ismeretlen operátort tartalmaz ennek a szövegnek az "
 | 
			
		||||
"elején: „%s”"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1997
 | 
			
		||||
#: ../src/ui/theme.c:1960
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression was empty or not understood"
 | 
			
		||||
msgstr "A koordinátakifejezés üres vagy értelmezhetetlen volt"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2110 ../src/ui/theme.c:2120 ../src/ui/theme.c:2154
 | 
			
		||||
#: ../src/ui/theme.c:2073 ../src/ui/theme.c:2083 ../src/ui/theme.c:2117
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression results in division by zero"
 | 
			
		||||
msgstr "A koordinátakifejezés nullával való osztást okozott"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2162
 | 
			
		||||
#: ../src/ui/theme.c:2125
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Coordinate expression tries to use mod operator on a floating-point number"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"A koordinátakifejezés mod operátort próbált használni lebegőpontos számon"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2218
 | 
			
		||||
#: ../src/ui/theme.c:2181
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Coordinate expression has an operator \"%s\" where an operand was expected"
 | 
			
		||||
msgstr "A koordinátakifejezésben egy operandus helyén „%s” operátor volt"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2227
 | 
			
		||||
#: ../src/ui/theme.c:2190
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression had an operand where an operator was expected"
 | 
			
		||||
msgstr "A koordinátakifejezésben a várt operátor helyett operandus szerepelt"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2235
 | 
			
		||||
#: ../src/ui/theme.c:2198
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression ended with an operator instead of an operand"
 | 
			
		||||
msgstr "A koordinátakifejezés operátorral végződött, nem operandussal"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2245
 | 
			
		||||
#: ../src/ui/theme.c:2208
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Coordinate expression has operator \"%c\" following operator \"%c\" with no "
 | 
			
		||||
@@ -833,38 +814,38 @@ msgstr ""
 | 
			
		||||
"A koordinátakifejezésben „%c” operátort „%c” operátor követi úgy, hogy nincs "
 | 
			
		||||
"köztük operandus"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2396 ../src/ui/theme.c:2441
 | 
			
		||||
#: ../src/ui/theme.c:2359 ../src/ui/theme.c:2404
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression had unknown variable or constant \"%s\""
 | 
			
		||||
msgstr "A koordinátakifejezésben „%s” változó vagy állandó ismeretlen volt"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2495
 | 
			
		||||
#: ../src/ui/theme.c:2458
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression parser overflowed its buffer."
 | 
			
		||||
msgstr "A koordinátakifejezés-elemző túlcsordította a pufferét."
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2524
 | 
			
		||||
#: ../src/ui/theme.c:2487
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression had a close parenthesis with no open parenthesis"
 | 
			
		||||
msgstr "A koordinátakifejezésben záró zárójel szerepelt kezdő nélkül"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2588
 | 
			
		||||
#: ../src/ui/theme.c:2551
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression had an open parenthesis with no close parenthesis"
 | 
			
		||||
msgstr "A koordinátakifejezésben kezdő zárójel szerepelt záró nélkül"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2599
 | 
			
		||||
#: ../src/ui/theme.c:2562
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression doesn't seem to have any operators or operands"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"A koordinátakifejezésben úgy tűnik nincsenek sem operátorok, sem operandusok"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2812 ../src/ui/theme.c:2832 ../src/ui/theme.c:2852
 | 
			
		||||
#: ../src/ui/theme.c:2775 ../src/ui/theme.c:2795 ../src/ui/theme.c:2815
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Theme contained an expression that resulted in an error: %s\n"
 | 
			
		||||
msgstr "A téma által tartalmazott kifejezés hibát okozott: %s\n"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:4455
 | 
			
		||||
#: ../src/ui/theme.c:4055
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be "
 | 
			
		||||
@@ -873,25 +854,25 @@ msgstr ""
 | 
			
		||||
"Ehhez a keretstílushoz meg kell határozni a következő elemet: <button "
 | 
			
		||||
"function=\"%s\" state=\"%s\" draw_ops=\"bármi\"/>"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:4970 ../src/ui/theme.c:4995
 | 
			
		||||
#: ../src/ui/theme.c:4570 ../src/ui/theme.c:4595
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Hiányzó <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"bármi\"/> elem"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:5041
 | 
			
		||||
#: ../src/ui/theme.c:4641
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Failed to load theme \"%s\": %s\n"
 | 
			
		||||
msgstr "Hiba a(z) „%s” téma betöltése közben: %s\n"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:5177 ../src/ui/theme.c:5184 ../src/ui/theme.c:5191
 | 
			
		||||
#: ../src/ui/theme.c:5198 ../src/ui/theme.c:5205
 | 
			
		||||
#: ../src/ui/theme.c:4777 ../src/ui/theme.c:4784 ../src/ui/theme.c:4791
 | 
			
		||||
#: ../src/ui/theme.c:4798 ../src/ui/theme.c:4805
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "No <%s> set for theme \"%s\""
 | 
			
		||||
msgstr "Nincs <%s> beállítva a(z) „%s” témához"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:5213
 | 
			
		||||
#: ../src/ui/theme.c:4813
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
 | 
			
		||||
@@ -900,7 +881,7 @@ msgstr ""
 | 
			
		||||
"Nincs keretstílus beállítva a(z) „%s” ablaktípushoz a(z) „%s” témában, adjon "
 | 
			
		||||
"hozzá egy <window type=\"%s\" style_set=\"bármi\"/> elemet"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:5620 ../src/ui/theme.c:5682 ../src/ui/theme.c:5745
 | 
			
		||||
#: ../src/ui/theme.c:5220 ../src/ui/theme.c:5282 ../src/ui/theme.c:5345
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"User-defined constants must begin with a capital letter; \"%s\" does not"
 | 
			
		||||
@@ -908,7 +889,7 @@ msgstr ""
 | 
			
		||||
"A felhasználó által meghatározott konstansoknak nagybetűvel kell kezdődniük, "
 | 
			
		||||
"a(z) „%s” nem ilyen"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:5628 ../src/ui/theme.c:5690 ../src/ui/theme.c:5753
 | 
			
		||||
#: ../src/ui/theme.c:5228 ../src/ui/theme.c:5290 ../src/ui/theme.c:5353
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Constant \"%s\" has already been defined"
 | 
			
		||||
msgstr "A(z) „%s” konstans már definiálva van"
 | 
			
		||||
@@ -972,14 +953,14 @@ msgstr "A logikai értékek „true” vagy „false” kell legyenek, nem pedig
 | 
			
		||||
msgid "Angle must be between 0.0 and 360.0, was %g\n"
 | 
			
		||||
msgstr "Szögnek 0.0 és 360.0 között kell lennie, %g volt\n"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:800
 | 
			
		||||
#: ../src/ui/theme-parser.c:797
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g\n"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Az alfának 0.0 (átlátszó) és 1.0 (teljesen átlátszatlan) között kell lennie, "
 | 
			
		||||
"%g volt\n"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:865
 | 
			
		||||
#: ../src/ui/theme-parser.c:862
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Invalid title scale \"%s\" (must be one of xx-small,x-small,small,medium,"
 | 
			
		||||
@@ -988,60 +969,60 @@ msgstr ""
 | 
			
		||||
" „%s” érvénytelen címméret (lehetséges értékek: xx-small,x-small,small,"
 | 
			
		||||
"medium,large,x-large,xx-large)\n"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1021 ../src/ui/theme-parser.c:1084
 | 
			
		||||
#: ../src/ui/theme-parser.c:1118 ../src/ui/theme-parser.c:1221
 | 
			
		||||
#: ../src/ui/theme-parser.c:1018 ../src/ui/theme-parser.c:1081
 | 
			
		||||
#: ../src/ui/theme-parser.c:1115 ../src/ui/theme-parser.c:1218
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "<%s> name \"%s\" used a second time"
 | 
			
		||||
msgstr "<%s> „%s” név másodszor lett használva"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1033 ../src/ui/theme-parser.c:1130
 | 
			
		||||
#: ../src/ui/theme-parser.c:1233
 | 
			
		||||
#: ../src/ui/theme-parser.c:1030 ../src/ui/theme-parser.c:1127
 | 
			
		||||
#: ../src/ui/theme-parser.c:1230
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "<%s> parent \"%s\" has not been defined"
 | 
			
		||||
msgstr "<%s> „%s” szülő nincs meghatározva"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1143
 | 
			
		||||
#: ../src/ui/theme-parser.c:1140
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "<%s> geometry \"%s\" has not been defined"
 | 
			
		||||
msgstr "<%s> „%s” geometria nincs meghatározva"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1156
 | 
			
		||||
#: ../src/ui/theme-parser.c:1153
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "<%s> must specify either a geometry or a parent that has a geometry"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"<%s> vagy meg kell határozni a geometriát vagy szükség van egy szülőre "
 | 
			
		||||
"aminek van geometriája"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1198
 | 
			
		||||
#: ../src/ui/theme-parser.c:1195
 | 
			
		||||
msgid "You must specify a background for an alpha value to be meaningful"
 | 
			
		||||
msgstr "Meg kell adnia egy hátteret, hogy az alfa értéknek értelme legyen"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1266
 | 
			
		||||
#: ../src/ui/theme-parser.c:1263
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Unknown type \"%s\" on <%s> element"
 | 
			
		||||
msgstr "„%s” típus ismeretlen a(z) <%s> elemen"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1277
 | 
			
		||||
#: ../src/ui/theme-parser.c:1274
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Unknown style_set \"%s\" on <%s> element"
 | 
			
		||||
msgstr "„%s” ismeretlen style_set a(z) <%s> elemen"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1285
 | 
			
		||||
#: ../src/ui/theme-parser.c:1282
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Window type \"%s\" has already been assigned a style set"
 | 
			
		||||
msgstr "„%s” ablak típushoz már hozzá van rendelve egy stílus beállítás"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1315 ../src/ui/theme-parser.c:1379
 | 
			
		||||
#: ../src/ui/theme-parser.c:1605 ../src/ui/theme-parser.c:2840
 | 
			
		||||
#: ../src/ui/theme-parser.c:2886 ../src/ui/theme-parser.c:3036
 | 
			
		||||
#: ../src/ui/theme-parser.c:3272 ../src/ui/theme-parser.c:3310
 | 
			
		||||
#: ../src/ui/theme-parser.c:3348 ../src/ui/theme-parser.c:3386
 | 
			
		||||
#: ../src/ui/theme-parser.c:1312 ../src/ui/theme-parser.c:1376
 | 
			
		||||
#: ../src/ui/theme-parser.c:1602 ../src/ui/theme-parser.c:2821
 | 
			
		||||
#: ../src/ui/theme-parser.c:2867 ../src/ui/theme-parser.c:3017
 | 
			
		||||
#: ../src/ui/theme-parser.c:3253 ../src/ui/theme-parser.c:3291
 | 
			
		||||
#: ../src/ui/theme-parser.c:3329 ../src/ui/theme-parser.c:3367
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Element <%s> is not allowed below <%s>"
 | 
			
		||||
msgstr "<%s> elem nem engedélyezett <%s> alatt"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1429 ../src/ui/theme-parser.c:1443
 | 
			
		||||
#: ../src/ui/theme-parser.c:1488
 | 
			
		||||
#: ../src/ui/theme-parser.c:1426 ../src/ui/theme-parser.c:1440
 | 
			
		||||
#: ../src/ui/theme-parser.c:1485
 | 
			
		||||
msgid ""
 | 
			
		||||
"Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" "
 | 
			
		||||
"for buttons"
 | 
			
		||||
@@ -1049,125 +1030,125 @@ msgstr ""
 | 
			
		||||
"Nem lehet egyszerre megadni a gombok „button_width” vagy „button_height” és "
 | 
			
		||||
"az „aspect_ratio” paraméterét"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1452
 | 
			
		||||
#: ../src/ui/theme-parser.c:1449
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Distance \"%s\" is unknown"
 | 
			
		||||
msgstr "„%s” távolság ismeretlen"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1497
 | 
			
		||||
#: ../src/ui/theme-parser.c:1494
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Aspect ratio \"%s\" is unknown"
 | 
			
		||||
msgstr "„%s” méretarány ismeretlen"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1559
 | 
			
		||||
#: ../src/ui/theme-parser.c:1556
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Border \"%s\" is unknown"
 | 
			
		||||
msgstr "„%s” határ ismeretlen"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1870
 | 
			
		||||
#: ../src/ui/theme-parser.c:1867
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "No \"start_angle\" or \"from\" attribute on element <%s>"
 | 
			
		||||
msgstr "A(z) <%s> elemnek nincs „start_angle” vagy „from” attribútuma"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1877
 | 
			
		||||
#: ../src/ui/theme-parser.c:1874
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "No \"extent_angle\" or \"to\" attribute on element <%s>"
 | 
			
		||||
msgstr "A(z) <%s> elemnek nincs „extent_angle” vagy „to” attribútuma"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2117
 | 
			
		||||
#: ../src/ui/theme-parser.c:2114
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Did not understand value \"%s\" for type of gradient"
 | 
			
		||||
msgstr "Nem sikerült „%s” értéket értelmezni színátmenet típusaként"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2195 ../src/ui/theme-parser.c:2570
 | 
			
		||||
#: ../src/ui/theme-parser.c:2189 ../src/ui/theme-parser.c:2551
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Did not understand fill type \"%s\" for <%s> element"
 | 
			
		||||
msgstr "Nem sikerült a(z) „%s” fájltípust értelmezni a(z) <%s> elem számára"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2362 ../src/ui/theme-parser.c:2445
 | 
			
		||||
#: ../src/ui/theme-parser.c:2508
 | 
			
		||||
#: ../src/ui/theme-parser.c:2343 ../src/ui/theme-parser.c:2426
 | 
			
		||||
#: ../src/ui/theme-parser.c:2489
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Did not understand state \"%s\" for <%s> element"
 | 
			
		||||
msgstr "Nem sikerült értelmezni a(z) „%s” állapotot a(z) <%s> elem számára"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2372 ../src/ui/theme-parser.c:2455
 | 
			
		||||
#: ../src/ui/theme-parser.c:2353 ../src/ui/theme-parser.c:2436
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Did not understand shadow \"%s\" for <%s> element"
 | 
			
		||||
msgstr "Nem sikerült „%s” árnyékot értelmezni a(z) <%s> elem számára"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2382
 | 
			
		||||
#: ../src/ui/theme-parser.c:2363
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Did not understand arrow \"%s\" for <%s> element"
 | 
			
		||||
msgstr "Nem sikerült értelmezni a(z) „%s” nyilat a(z) <%s> elem számára"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2696 ../src/ui/theme-parser.c:2792
 | 
			
		||||
#: ../src/ui/theme-parser.c:2677 ../src/ui/theme-parser.c:2773
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "No <draw_ops> called \"%s\" has been defined"
 | 
			
		||||
msgstr "Nincsen „%s” nevű <draw_ops> meghatározva"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2708 ../src/ui/theme-parser.c:2804
 | 
			
		||||
#: ../src/ui/theme-parser.c:2689 ../src/ui/theme-parser.c:2785
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Including draw_ops \"%s\" here would create a circular reference"
 | 
			
		||||
msgstr "„%s” draw_ops ide beépítésével körkörös hivatkozás alakulna ki"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2919
 | 
			
		||||
#: ../src/ui/theme-parser.c:2900
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Unknown position \"%s\" for frame piece"
 | 
			
		||||
msgstr "„%s” pozíció ismeretlen a keretdarabhoz"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2927
 | 
			
		||||
#: ../src/ui/theme-parser.c:2908
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Frame style already has a piece at position %s"
 | 
			
		||||
msgstr "A keretstílusnak már van egy darabja a(z) „%s” pozícióban"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2944 ../src/ui/theme-parser.c:3021
 | 
			
		||||
#: ../src/ui/theme-parser.c:2925 ../src/ui/theme-parser.c:3002
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "No <draw_ops> with the name \"%s\" has been defined"
 | 
			
		||||
msgstr "Nincs „%s” nevű <draw_ops> meghatározva"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2974
 | 
			
		||||
#: ../src/ui/theme-parser.c:2955
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Unknown function \"%s\" for button"
 | 
			
		||||
msgstr "„%s” funkció ismeretlen a gombhoz"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2984
 | 
			
		||||
#: ../src/ui/theme-parser.c:2965
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Button function \"%s\" does not exist in this version (%d, need %d)"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"A(z) „%s” gombfunkció nem létezik ebben a verzióban (%d, szükséges: %d)"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2996
 | 
			
		||||
#: ../src/ui/theme-parser.c:2977
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Unknown state \"%s\" for button"
 | 
			
		||||
msgstr "„%s” állapot ismeretlen a gombhoz"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3004
 | 
			
		||||
#: ../src/ui/theme-parser.c:2985
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Frame style already has a button for function %s state %s"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"A keretstílusnak már van gombja a(z) „%s” funkcióra a(z) „%s” állapotban"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3075
 | 
			
		||||
#: ../src/ui/theme-parser.c:3056
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "\"%s\" is not a valid value for focus attribute"
 | 
			
		||||
msgstr "„%s” érték érvénytelen a fókusz attribútumhoz"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3084
 | 
			
		||||
#: ../src/ui/theme-parser.c:3065
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "\"%s\" is not a valid value for state attribute"
 | 
			
		||||
msgstr "„%s” érték érvénytelen az állapot attribútumhoz"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3094
 | 
			
		||||
#: ../src/ui/theme-parser.c:3075
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "A style called \"%s\" has not been defined"
 | 
			
		||||
msgstr "„%s” nevű stílus nincs meghatározva"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3115 ../src/ui/theme-parser.c:3138
 | 
			
		||||
#: ../src/ui/theme-parser.c:3096 ../src/ui/theme-parser.c:3119
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "\"%s\" is not a valid value for resize attribute"
 | 
			
		||||
msgstr "„%s” érték érvénytelen az átméretezés attribútumhoz"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3149
 | 
			
		||||
#: ../src/ui/theme-parser.c:3130
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Should not have \"resize\" attribute on <%s> element for maximized/shaded "
 | 
			
		||||
@@ -1176,7 +1157,7 @@ msgstr ""
 | 
			
		||||
"A(z) <%s> elemnek nem szabadna „resize” attribútummal rendelkeznie a teljes "
 | 
			
		||||
"méretű/felgördített állapothoz"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3163
 | 
			
		||||
#: ../src/ui/theme-parser.c:3144
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Should not have \"resize\" attribute on <%s> element for maximized states"
 | 
			
		||||
@@ -1184,20 +1165,20 @@ msgstr ""
 | 
			
		||||
"A(z) <%s> elemnek nem szabadna „resize” attribútummal rendelkeznie a teljes "
 | 
			
		||||
"méretű állapothoz"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3177 ../src/ui/theme-parser.c:3221
 | 
			
		||||
#: ../src/ui/theme-parser.c:3158 ../src/ui/theme-parser.c:3202
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Style has already been specified for state %s resize %s focus %s"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"%s állapothoz, %s átméretezéshez és %s fókuszhoz már meg van határozva stílus"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3188 ../src/ui/theme-parser.c:3199
 | 
			
		||||
#: ../src/ui/theme-parser.c:3210 ../src/ui/theme-parser.c:3232
 | 
			
		||||
#: ../src/ui/theme-parser.c:3243 ../src/ui/theme-parser.c:3254
 | 
			
		||||
#: ../src/ui/theme-parser.c:3169 ../src/ui/theme-parser.c:3180
 | 
			
		||||
#: ../src/ui/theme-parser.c:3191 ../src/ui/theme-parser.c:3213
 | 
			
		||||
#: ../src/ui/theme-parser.c:3224 ../src/ui/theme-parser.c:3235
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Style has already been specified for state %s focus %s"
 | 
			
		||||
msgstr "%s állapothoz és %s fókuszhoz már meg van határozva stílus"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3293
 | 
			
		||||
#: ../src/ui/theme-parser.c:3274
 | 
			
		||||
msgid ""
 | 
			
		||||
"Can't have a two draw_ops for a <piece> element (theme specified a draw_ops "
 | 
			
		||||
"attribute and also a <draw_ops> element, or specified two elements)"
 | 
			
		||||
@@ -1206,7 +1187,7 @@ msgstr ""
 | 
			
		||||
"draw_ops attribútumot és egy <draw_ops> elemet, vagy két elemet határozott "
 | 
			
		||||
"meg)"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3331
 | 
			
		||||
#: ../src/ui/theme-parser.c:3312
 | 
			
		||||
msgid ""
 | 
			
		||||
"Can't have a two draw_ops for a <button> element (theme specified a draw_ops "
 | 
			
		||||
"attribute and also a <draw_ops> element, or specified two elements)"
 | 
			
		||||
@@ -1214,7 +1195,7 @@ msgstr ""
 | 
			
		||||
"Nem lehet két draw_ops-a egy <button> elemnek (a téma meghatározott egy "
 | 
			
		||||
"draw_ops attribútumot és egy <draw_ops> elemet, vagy két elemet)"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3369
 | 
			
		||||
#: ../src/ui/theme-parser.c:3350
 | 
			
		||||
msgid ""
 | 
			
		||||
"Can't have a two draw_ops for a <menu_icon> element (theme specified a "
 | 
			
		||||
"draw_ops attribute and also a <draw_ops> element, or specified two elements)"
 | 
			
		||||
@@ -1222,12 +1203,12 @@ msgstr ""
 | 
			
		||||
"Nem lehet két draw_ops-a egy <menu_icon> elemnek (a téma meghatározott egy "
 | 
			
		||||
"draw_ops attribútumot és egy <draw_ops> elemet, vagy két elemet)"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3433
 | 
			
		||||
#: ../src/ui/theme-parser.c:3414
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Bad version specification '%s'"
 | 
			
		||||
msgstr "Hibás verziómeghatározás: „%s”"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3506
 | 
			
		||||
#: ../src/ui/theme-parser.c:3487
 | 
			
		||||
msgid ""
 | 
			
		||||
"\"version\" attribute cannot be used in metacity-theme-1.xml or metacity-"
 | 
			
		||||
"theme-2.xml"
 | 
			
		||||
@@ -1235,68 +1216,68 @@ msgstr ""
 | 
			
		||||
"A „version” attribútum nem használható a metacity-theme-1.xml vagy metacity-"
 | 
			
		||||
"theme-2.xml fájlban"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3529
 | 
			
		||||
#: ../src/ui/theme-parser.c:3510
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Theme requires version %s but latest supported theme version is %d.%d"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"A téma a(z) %s verziót igényli, de az utolsó támogatott témaverzió %d.%d"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3561
 | 
			
		||||
#: ../src/ui/theme-parser.c:3542
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Outermost element in theme must be <metacity_theme> not <%s>"
 | 
			
		||||
msgstr "A téma legkülső eleme <metacity_theme> kell legyen, nem pedig <%s>"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3581
 | 
			
		||||
#: ../src/ui/theme-parser.c:3562
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Element <%s> is not allowed inside a name/author/date/description element"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"A(z) <%s> elem nem megengedett egy name/author/date/description elemen belül"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3586
 | 
			
		||||
#: ../src/ui/theme-parser.c:3567
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Element <%s> is not allowed inside a <constant> element"
 | 
			
		||||
msgstr "A(z) <%s> elem nem megengedett egy <constant> elemen belül"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3598
 | 
			
		||||
#: ../src/ui/theme-parser.c:3579
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Element <%s> is not allowed inside a distance/border/aspect_ratio element"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"<%s> elem nem megengedett egy distance/border/aspect_ratio elemen belül"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3620
 | 
			
		||||
#: ../src/ui/theme-parser.c:3601
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Element <%s> is not allowed inside a draw operation element"
 | 
			
		||||
msgstr "<%s> elem nem megengedett egy rajzoló művelet elemen belül"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3630 ../src/ui/theme-parser.c:3660
 | 
			
		||||
#: ../src/ui/theme-parser.c:3665 ../src/ui/theme-parser.c:3670
 | 
			
		||||
#: ../src/ui/theme-parser.c:3611 ../src/ui/theme-parser.c:3641
 | 
			
		||||
#: ../src/ui/theme-parser.c:3646 ../src/ui/theme-parser.c:3651
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Element <%s> is not allowed inside a <%s> element"
 | 
			
		||||
msgstr "<%s> elem nem megengedett egy <%s> elemen belül"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3898
 | 
			
		||||
#: ../src/ui/theme-parser.c:3879
 | 
			
		||||
msgid "No draw_ops provided for frame piece"
 | 
			
		||||
msgstr "Nincsen draw_ops a keretdarabhoz"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3913
 | 
			
		||||
#: ../src/ui/theme-parser.c:3894
 | 
			
		||||
msgid "No draw_ops provided for button"
 | 
			
		||||
msgstr "Nincs draw_ops megadva a gombhoz"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3967
 | 
			
		||||
#: ../src/ui/theme-parser.c:3948
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "No text is allowed inside element <%s>"
 | 
			
		||||
msgstr "Nincs szöveg engedélyezve a(z) <%s> elemen belül"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:4025 ../src/ui/theme-parser.c:4037
 | 
			
		||||
#: ../src/ui/theme-parser.c:4049 ../src/ui/theme-parser.c:4061
 | 
			
		||||
#: ../src/ui/theme-parser.c:4073
 | 
			
		||||
#: ../src/ui/theme-parser.c:4006 ../src/ui/theme-parser.c:4018
 | 
			
		||||
#: ../src/ui/theme-parser.c:4030 ../src/ui/theme-parser.c:4042
 | 
			
		||||
#: ../src/ui/theme-parser.c:4054
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "<%s> specified twice for this theme"
 | 
			
		||||
msgstr "<%s> kétszer lett megadva ehhez a témához"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:4335
 | 
			
		||||
#: ../src/ui/theme-parser.c:4316
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Failed to find a valid file for theme %s\n"
 | 
			
		||||
msgstr "Nem található érvényes fájl a következő témához: %s\n"
 | 
			
		||||
@@ -1310,11 +1291,14 @@ msgstr ""
 | 
			
		||||
"mentését", emiatt ezeket a legközelebbi bejelentkezéskor manuálisan "
 | 
			
		||||
"újra kell indítania."
 | 
			
		||||
 | 
			
		||||
#: ../src/x11/window-props.c:515
 | 
			
		||||
#: ../src/x11/window-props.c:558
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%s (on %s)"
 | 
			
		||||
msgstr "%s (ezen: %s)"
 | 
			
		||||
 | 
			
		||||
#~ msgid "Screen %d on display \"%s\" already has a window manager\n"
 | 
			
		||||
#~ msgstr "A(z) %d képernyőnek a(z) „%s” megjelenítőn már van ablakkezelője\n"
 | 
			
		||||
 | 
			
		||||
#~ msgid "background texture could not be created from file"
 | 
			
		||||
#~ msgstr "nem hozható létre a háttér textúrája fájlból"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										273
									
								
								po/nb.po
									
									
									
									
									
								
							
							
						
						
									
										273
									
								
								po/nb.po
									
									
									
									
									
								
							@@ -4,10 +4,10 @@
 | 
			
		||||
#
 | 
			
		||||
msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: mutter 3.13.x\n"
 | 
			
		||||
"Project-Id-Version: mutter 3.15.x\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: \n"
 | 
			
		||||
"POT-Creation-Date: 2014-09-06 14:13+0200\n"
 | 
			
		||||
"PO-Revision-Date: 2014-08-23 13:37+0200\n"
 | 
			
		||||
"POT-Creation-Date: 2014-11-15 18:32+0100\n"
 | 
			
		||||
"PO-Revision-Date: 2014-11-15 18:34+0100\n"
 | 
			
		||||
"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
 | 
			
		||||
"Language-Team: Norwegian bokmål <i18n-no@lister.ping.uio.no>\n"
 | 
			
		||||
"Language: \n"
 | 
			
		||||
@@ -351,7 +351,7 @@ msgid ""
 | 
			
		||||
"If set to true, and the focus mode is either \"sloppy\" or \"mouse\" then "
 | 
			
		||||
"the focus will not be changed immediately when entering a window, but only "
 | 
			
		||||
"after the pointer stops moving."
 | 
			
		||||
msgstr ""
 | 
			
		||||
msgstr "Hvis denne settes til «true» og fokusmodus er enten «sloppy» eller «mouse» så vil fokus ikke endres med en gang markøren kommer inn i et vindu, men i stedet når markørens bevegelse stopper."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:15
 | 
			
		||||
msgid "Draggable border width"
 | 
			
		||||
@@ -385,7 +385,7 @@ msgstr "Plasser nye vinduer i senter"
 | 
			
		||||
msgid ""
 | 
			
		||||
"When true, the new windows will always be put in the center of the active "
 | 
			
		||||
"screen of the monitor."
 | 
			
		||||
msgstr ""
 | 
			
		||||
msgstr "Når denne er «true» vil mye vinduer alltid plasseres midt på aktivt område på skjermen."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:21
 | 
			
		||||
msgid "Select window from tab popup"
 | 
			
		||||
@@ -423,29 +423,29 @@ msgstr "Bytt til VT 6"
 | 
			
		||||
msgid "Switch to VT 7"
 | 
			
		||||
msgstr "Bytt til VT 7"
 | 
			
		||||
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:412
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:350
 | 
			
		||||
msgid "Built-in display"
 | 
			
		||||
msgstr "Innebygget skjerm"
 | 
			
		||||
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:437
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:375
 | 
			
		||||
msgid "Unknown"
 | 
			
		||||
msgstr "Ukjent"
 | 
			
		||||
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:439
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:377
 | 
			
		||||
msgid "Unknown Display"
 | 
			
		||||
msgstr "Ukjent skjerm"
 | 
			
		||||
 | 
			
		||||
#. TRANSLATORS: this is a monitor vendor name, followed by a
 | 
			
		||||
#. * size in inches, like 'Dell 15"'
 | 
			
		||||
#.
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:447
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:385
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%s %s"
 | 
			
		||||
msgstr "%s %s"
 | 
			
		||||
 | 
			
		||||
#. This probably means that a non-WM compositor like xcompmgr is running;
 | 
			
		||||
#. * we have no way to get it to exit
 | 
			
		||||
#: ../src/compositor/compositor.c:443
 | 
			
		||||
#: ../src/compositor/compositor.c:456
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Another compositing manager is already running on screen %i on display \"%s"
 | 
			
		||||
@@ -481,7 +481,7 @@ msgstr "_Vent"
 | 
			
		||||
msgid "_Force Quit"
 | 
			
		||||
msgstr "_Tvungen nedstenging"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/display.c:547
 | 
			
		||||
#: ../src/core/display.c:550
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Failed to open X Window System display '%s'\n"
 | 
			
		||||
msgstr "Feil under åpning av X Window System skjerm «%s»\n"
 | 
			
		||||
@@ -518,12 +518,12 @@ msgstr "Kjør som en wayland-kompositør"
 | 
			
		||||
msgid "Run as a full display server, rather than nested"
 | 
			
		||||
msgstr "Kjør som en full skjermtjener, heller enn nøstet"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/main.c:459
 | 
			
		||||
#: ../src/core/main.c:451
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Failed to scan themes directory: %s\n"
 | 
			
		||||
msgstr "Feil under søk i temakatalog: %s\n"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/main.c:475
 | 
			
		||||
#: ../src/core/main.c:467
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Could not find a theme! Be sure %s exists and contains the usual themes.\n"
 | 
			
		||||
@@ -553,17 +553,17 @@ msgstr "Skriv versjonsnummer"
 | 
			
		||||
msgid "Mutter plugin to use"
 | 
			
		||||
msgstr "Mutter-tillegg som skal brukes"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/prefs.c:2101
 | 
			
		||||
#: ../src/core/prefs.c:2064
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Workspace %d"
 | 
			
		||||
msgstr "Arbeidsområde %d"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/screen.c:548
 | 
			
		||||
#: ../src/core/screen.c:543
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Screen %d on display '%s' is invalid\n"
 | 
			
		||||
msgstr "Skjerm %d på display «%s» er ugyldig\n"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/screen.c:564
 | 
			
		||||
#: ../src/core/screen.c:559
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Screen %d on display \"%s\" already has a window manager; try using the --"
 | 
			
		||||
@@ -572,7 +572,7 @@ msgstr ""
 | 
			
		||||
"Skjerm %d på display «%s» har allerede en vindushåndterer; prøv å bruke "
 | 
			
		||||
"flagget --replace for å erstatte aktiv vindushåndterer.\n"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/screen.c:657
 | 
			
		||||
#: ../src/core/screen.c:652
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Screen %d on display \"%s\" already has a window manager\n"
 | 
			
		||||
msgstr "Skjerm %d på display «%s» har allerede en vinduhåndterer\n"
 | 
			
		||||
@@ -589,48 +589,48 @@ msgstr "Mutter er kompilert uten støtte for «verbose» modus\n"
 | 
			
		||||
msgid "%d x %d"
 | 
			
		||||
msgstr "%d x %d"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:233
 | 
			
		||||
#: ../src/ui/theme.c:154
 | 
			
		||||
msgid "top"
 | 
			
		||||
msgstr "topp"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:235
 | 
			
		||||
#: ../src/ui/theme.c:156
 | 
			
		||||
msgid "bottom"
 | 
			
		||||
msgstr "bunn"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:237
 | 
			
		||||
#: ../src/ui/theme.c:158
 | 
			
		||||
msgid "left"
 | 
			
		||||
msgstr "venstre"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:239
 | 
			
		||||
#: ../src/ui/theme.c:160
 | 
			
		||||
msgid "right"
 | 
			
		||||
msgstr "høyre"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:267
 | 
			
		||||
#: ../src/ui/theme.c:188
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "frame geometry does not specify \"%s\" dimension"
 | 
			
		||||
msgstr "rammegeometrien spesifiserer ikke «%s»-dimensjon"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:286
 | 
			
		||||
#: ../src/ui/theme.c:207
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "frame geometry does not specify dimension \"%s\" for border \"%s\""
 | 
			
		||||
msgstr "rammegeometri spesifiserer ikke dimensjon «%s» for kant «%s»"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:323
 | 
			
		||||
#: ../src/ui/theme.c:244
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Button aspect ratio %g is not reasonable"
 | 
			
		||||
msgstr "Aspektrate %g for knapp er ikke fornuftig"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:335
 | 
			
		||||
#: ../src/ui/theme.c:256
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Frame geometry does not specify size of buttons"
 | 
			
		||||
msgstr "Rammegeometrien spesifiserer ikke størrelse på knapper"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1061
 | 
			
		||||
#: ../src/ui/theme.c:1024
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Gradients should have at least two colors"
 | 
			
		||||
msgstr "Gradienter må ha minst to farger"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1211
 | 
			
		||||
#: ../src/ui/theme.c:1174
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"GTK custom color specification must have color name and fallback in "
 | 
			
		||||
@@ -639,7 +639,7 @@ msgstr ""
 | 
			
		||||
"Egendefinert GTK-fargespesifikasjon må ha fargenavn og reserve i parantes, f."
 | 
			
		||||
"eks gtk:custom(foo,bar); kunne ikke lese «%s»"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1227
 | 
			
		||||
#: ../src/ui/theme.c:1190
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
 | 
			
		||||
@@ -648,7 +648,7 @@ msgstr ""
 | 
			
		||||
"Ugyldig tegn «%c» i parameter color_name for gtk:custom, kun A-Za-z0-9-_ er "
 | 
			
		||||
"gyldig"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1241
 | 
			
		||||
#: ../src/ui/theme.c:1204
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
 | 
			
		||||
@@ -657,7 +657,7 @@ msgstr ""
 | 
			
		||||
"Gtk:custom-format er «gtk:custom(color_name,fallback)», «%s» passer ikke i "
 | 
			
		||||
"formatet"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1286
 | 
			
		||||
#: ../src/ui/theme.c:1249
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] "
 | 
			
		||||
@@ -666,7 +666,7 @@ msgstr ""
 | 
			
		||||
"GTK-fargespesifikasjon må ha tilstand i klammer, f.eks. gtk:fg[NORMAL], hvor "
 | 
			
		||||
"NORMAL er tilstanden; kunne ikke lese «%s»"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1300
 | 
			
		||||
#: ../src/ui/theme.c:1263
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"GTK color specification must have a close bracket after the state, e.g. gtk:"
 | 
			
		||||
@@ -675,17 +675,17 @@ msgstr ""
 | 
			
		||||
"GTK-fargespesifikasjon må ha en avsluttende klamme etter tilstanden, f.eks. "
 | 
			
		||||
"gtk:fg[NORMAL], hvor NORMAL er tilstanden; kunne ikke lese «%s»"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1311
 | 
			
		||||
#: ../src/ui/theme.c:1274
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Did not understand state \"%s\" in color specification"
 | 
			
		||||
msgstr "Forsto ikke tilstand «%s» i fargespesifikasjonen"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1324
 | 
			
		||||
#: ../src/ui/theme.c:1287
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Did not understand color component \"%s\" in color specification"
 | 
			
		||||
msgstr "Forsto ikke fargekomponent «%s» i fargespesifikasjonen"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1352
 | 
			
		||||
#: ../src/ui/theme.c:1315
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the "
 | 
			
		||||
@@ -694,56 +694,56 @@ msgstr ""
 | 
			
		||||
"Blandingsformat er «blend/bg_color/fg_color/alpha», «%s» passer ikke i "
 | 
			
		||||
"formatet"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1363
 | 
			
		||||
#: ../src/ui/theme.c:1326
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Could not parse alpha value \"%s\" in blended color"
 | 
			
		||||
msgstr "Kunne ikke lese alpha-verdi «%s» i blandet farge"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1373
 | 
			
		||||
#: ../src/ui/theme.c:1336
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Alpha value \"%s\" in blended color is not between 0.0 and 1.0"
 | 
			
		||||
msgstr "Alpha-verdi «%s» i blandet farge er ikke mellom 0.0 og 1.0"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1419
 | 
			
		||||
#: ../src/ui/theme.c:1382
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Skyggeformatet er «shade/base_color/factor», «%s» passer ikke i formatet"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1430
 | 
			
		||||
#: ../src/ui/theme.c:1393
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Could not parse shade factor \"%s\" in shaded color"
 | 
			
		||||
msgstr "Kunne ikke lese skyggefaktor «%s» i skyggelagt farge"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1440
 | 
			
		||||
#: ../src/ui/theme.c:1403
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Shade factor \"%s\" in shaded color is negative"
 | 
			
		||||
msgstr "Skyggefaktor «%s» i skyggelagt farge er negativ"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1469
 | 
			
		||||
#: ../src/ui/theme.c:1432
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Could not parse color \"%s\""
 | 
			
		||||
msgstr "Kunne ikke lese farge «%s»"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1778
 | 
			
		||||
#: ../src/ui/theme.c:1741
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression contains character '%s' which is not allowed"
 | 
			
		||||
msgstr "Koordinatuttrykk inneholder tegn «%s» som ikke er tillatt"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1805
 | 
			
		||||
#: ../src/ui/theme.c:1768
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Coordinate expression contains floating point number '%s' which could not be "
 | 
			
		||||
"parsed"
 | 
			
		||||
msgstr "Koordinatuttrykk inneholder flyttall «%s» som ikke kunne tolkes"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1819
 | 
			
		||||
#: ../src/ui/theme.c:1782
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression contains integer '%s' which could not be parsed"
 | 
			
		||||
msgstr "Koordinatuttrykk inneholder heltall «%s» som ikke kunne tolkes"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1940
 | 
			
		||||
#: ../src/ui/theme.c:1903
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Coordinate expression contained unknown operator at the start of this text: "
 | 
			
		||||
@@ -752,39 +752,39 @@ msgstr ""
 | 
			
		||||
"Koordinatuttrykket inneholdt en ukjent operator ved begynnelsen av denne "
 | 
			
		||||
"teksten: «%s»"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:1997
 | 
			
		||||
#: ../src/ui/theme.c:1960
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression was empty or not understood"
 | 
			
		||||
msgstr "Koordinatuttrykket var tomt eller ble ikke forstått"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2110 ../src/ui/theme.c:2120 ../src/ui/theme.c:2154
 | 
			
		||||
#: ../src/ui/theme.c:2073 ../src/ui/theme.c:2083 ../src/ui/theme.c:2117
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression results in division by zero"
 | 
			
		||||
msgstr "Koordinatuttrykket resulterer i divisjon med null"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2162
 | 
			
		||||
#: ../src/ui/theme.c:2125
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Coordinate expression tries to use mod operator on a floating-point number"
 | 
			
		||||
msgstr "Koordinatuttrykket prøver å bruke mod-operator på et flyttall"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2218
 | 
			
		||||
#: ../src/ui/theme.c:2181
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Coordinate expression has an operator \"%s\" where an operand was expected"
 | 
			
		||||
msgstr "Koordinatuttrykket har en operator «%s» hvor en operand var ventet"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2227
 | 
			
		||||
#: ../src/ui/theme.c:2190
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression had an operand where an operator was expected"
 | 
			
		||||
msgstr "Koordinatuttrykket hadde en operand hvor en operator var ventet"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2235
 | 
			
		||||
#: ../src/ui/theme.c:2198
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression ended with an operator instead of an operand"
 | 
			
		||||
msgstr "Koordinatuttrykket sluttet med en operator i stedet for en operand"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2245
 | 
			
		||||
#: ../src/ui/theme.c:2208
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Coordinate expression has operator \"%c\" following operator \"%c\" with no "
 | 
			
		||||
@@ -793,38 +793,38 @@ msgstr ""
 | 
			
		||||
"Koordinatuttrykket har en operator «%c» etter en operator «%c» og ingen "
 | 
			
		||||
"operand mellom dem."
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2396 ../src/ui/theme.c:2441
 | 
			
		||||
#: ../src/ui/theme.c:2359 ../src/ui/theme.c:2404
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression had unknown variable or constant \"%s\""
 | 
			
		||||
msgstr "Koordinatuttrykket haddeen ukjent variabel eller konstant «%s»"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2495
 | 
			
		||||
#: ../src/ui/theme.c:2458
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression parser overflowed its buffer."
 | 
			
		||||
msgstr "Tolkeren for koordinatuttrykk oversteg buffergrensen."
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2524
 | 
			
		||||
#: ../src/ui/theme.c:2487
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression had a close parenthesis with no open parenthesis"
 | 
			
		||||
msgstr "Koordinatuttrykket hadde en parantes slutt uten parantes start"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2588
 | 
			
		||||
#: ../src/ui/theme.c:2551
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression had an open parenthesis with no close parenthesis"
 | 
			
		||||
msgstr "Koordinatuttrykket hadde en åpen parantes uten en avsluttende parantes"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2599
 | 
			
		||||
#: ../src/ui/theme.c:2562
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Coordinate expression doesn't seem to have any operators or operands"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Koordinatuttrykket ser ikke ut til å ha noen operatorer eller operander"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:2812 ../src/ui/theme.c:2832 ../src/ui/theme.c:2852
 | 
			
		||||
#: ../src/ui/theme.c:2775 ../src/ui/theme.c:2795 ../src/ui/theme.c:2815
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Theme contained an expression that resulted in an error: %s\n"
 | 
			
		||||
msgstr "Tema inneholdt et uttrykk som resulterte i en feil: %s\n"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:4455
 | 
			
		||||
#: ../src/ui/theme.c:4055
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be "
 | 
			
		||||
@@ -833,25 +833,25 @@ msgstr ""
 | 
			
		||||
"<button function=«%s» state=«%s» draw_ops=«ett-eller-annet»/> må "
 | 
			
		||||
"spesifiseres for denne rammestilen"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:4970 ../src/ui/theme.c:4995
 | 
			
		||||
#: ../src/ui/theme.c:4570 ../src/ui/theme.c:4595
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Mangler <frame state=«%s» resize=«%s» focus=«%s» stil=«ett-eller-annet»/>"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:5041
 | 
			
		||||
#: ../src/ui/theme.c:4641
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Failed to load theme \"%s\": %s\n"
 | 
			
		||||
msgstr "Klarte ikke å laste tema «%s»: %s\n"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:5177 ../src/ui/theme.c:5184 ../src/ui/theme.c:5191
 | 
			
		||||
#: ../src/ui/theme.c:5198 ../src/ui/theme.c:5205
 | 
			
		||||
#: ../src/ui/theme.c:4777 ../src/ui/theme.c:4784 ../src/ui/theme.c:4791
 | 
			
		||||
#: ../src/ui/theme.c:4798 ../src/ui/theme.c:4805
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "No <%s> set for theme \"%s\""
 | 
			
		||||
msgstr "<%s> er ikke satt for tema «%s»"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:5213
 | 
			
		||||
#: ../src/ui/theme.c:4813
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
 | 
			
		||||
@@ -860,14 +860,14 @@ msgstr ""
 | 
			
		||||
"Ingen rammestil satt for vindutype «%s» i tema «%s», legg til et <window "
 | 
			
		||||
"type=«%s» style_set=«ett-eller-annet»/>-element"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:5620 ../src/ui/theme.c:5682 ../src/ui/theme.c:5745
 | 
			
		||||
#: ../src/ui/theme.c:5220 ../src/ui/theme.c:5282 ../src/ui/theme.c:5345
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"User-defined constants must begin with a capital letter; \"%s\" does not"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Brukerdefinerte konstanter må begynne med stor bokstav; «%s» gjør ikke det"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme.c:5628 ../src/ui/theme.c:5690 ../src/ui/theme.c:5753
 | 
			
		||||
#: ../src/ui/theme.c:5228 ../src/ui/theme.c:5290 ../src/ui/theme.c:5353
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Constant \"%s\" has already been defined"
 | 
			
		||||
msgstr "Konstant «%s» er allerede definert"
 | 
			
		||||
@@ -930,13 +930,13 @@ msgstr "Bolske verdier må være «sann» eller «usann» ikke «%s»"
 | 
			
		||||
msgid "Angle must be between 0.0 and 360.0, was %g\n"
 | 
			
		||||
msgstr "Vinkelen må være mellom 0.0 og 360.0, var %g\n"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:800
 | 
			
		||||
#: ../src/ui/theme-parser.c:797
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g\n"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Alpha må være mellom 0.0 (usynlig) og 1.0 (helt ugjennomsiktig), var %g\n"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:865
 | 
			
		||||
#: ../src/ui/theme-parser.c:862
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Invalid title scale \"%s\" (must be one of xx-small,x-small,small,medium,"
 | 
			
		||||
@@ -945,58 +945,58 @@ msgstr ""
 | 
			
		||||
"Ugyldig skalering av tittel «%s» (må være en av xx-small,x-small,small,"
 | 
			
		||||
"medium,large,x-large,xx-large)\n"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1021 ../src/ui/theme-parser.c:1084
 | 
			
		||||
#: ../src/ui/theme-parser.c:1118 ../src/ui/theme-parser.c:1221
 | 
			
		||||
#: ../src/ui/theme-parser.c:1018 ../src/ui/theme-parser.c:1081
 | 
			
		||||
#: ../src/ui/theme-parser.c:1115 ../src/ui/theme-parser.c:1218
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "<%s> name \"%s\" used a second time"
 | 
			
		||||
msgstr "<%s> navn «%s» brukt på nytt"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1033 ../src/ui/theme-parser.c:1130
 | 
			
		||||
#: ../src/ui/theme-parser.c:1233
 | 
			
		||||
#: ../src/ui/theme-parser.c:1030 ../src/ui/theme-parser.c:1127
 | 
			
		||||
#: ../src/ui/theme-parser.c:1230
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "<%s> parent \"%s\" has not been defined"
 | 
			
		||||
msgstr "<%s> opphav «%s» er ikke definert"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1143
 | 
			
		||||
#: ../src/ui/theme-parser.c:1140
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "<%s> geometry \"%s\" has not been defined"
 | 
			
		||||
msgstr "<%s> geometri «%s» er ikke definert"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1156
 | 
			
		||||
#: ../src/ui/theme-parser.c:1153
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "<%s> must specify either a geometry or a parent that has a geometry"
 | 
			
		||||
msgstr "<%s> må spesifisere enten en geometri eller et opphav som har geometri"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1198
 | 
			
		||||
#: ../src/ui/theme-parser.c:1195
 | 
			
		||||
msgid "You must specify a background for an alpha value to be meaningful"
 | 
			
		||||
msgstr "Du må oppgi en bakgrunn for at en alpha-verdi skal ha mening"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1266
 | 
			
		||||
#: ../src/ui/theme-parser.c:1263
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Unknown type \"%s\" on <%s> element"
 | 
			
		||||
msgstr "Ukjent type «%s» på <%s>-element"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1277
 | 
			
		||||
#: ../src/ui/theme-parser.c:1274
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Unknown style_set \"%s\" on <%s> element"
 | 
			
		||||
msgstr "Ukjent style_set «%s» på <%s>-element"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1285
 | 
			
		||||
#: ../src/ui/theme-parser.c:1282
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Window type \"%s\" has already been assigned a style set"
 | 
			
		||||
msgstr "Vindutype «%s» er allerede tildelt et stilsett"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1315 ../src/ui/theme-parser.c:1379
 | 
			
		||||
#: ../src/ui/theme-parser.c:1605 ../src/ui/theme-parser.c:2840
 | 
			
		||||
#: ../src/ui/theme-parser.c:2886 ../src/ui/theme-parser.c:3036
 | 
			
		||||
#: ../src/ui/theme-parser.c:3272 ../src/ui/theme-parser.c:3310
 | 
			
		||||
#: ../src/ui/theme-parser.c:3348 ../src/ui/theme-parser.c:3386
 | 
			
		||||
#: ../src/ui/theme-parser.c:1312 ../src/ui/theme-parser.c:1376
 | 
			
		||||
#: ../src/ui/theme-parser.c:1602 ../src/ui/theme-parser.c:2821
 | 
			
		||||
#: ../src/ui/theme-parser.c:2867 ../src/ui/theme-parser.c:3017
 | 
			
		||||
#: ../src/ui/theme-parser.c:3253 ../src/ui/theme-parser.c:3291
 | 
			
		||||
#: ../src/ui/theme-parser.c:3329 ../src/ui/theme-parser.c:3367
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Element <%s> is not allowed below <%s>"
 | 
			
		||||
msgstr "Element <%s> er ikke tillatt under <%s>"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1429 ../src/ui/theme-parser.c:1443
 | 
			
		||||
#: ../src/ui/theme-parser.c:1488
 | 
			
		||||
#: ../src/ui/theme-parser.c:1426 ../src/ui/theme-parser.c:1440
 | 
			
		||||
#: ../src/ui/theme-parser.c:1485
 | 
			
		||||
msgid ""
 | 
			
		||||
"Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" "
 | 
			
		||||
"for buttons"
 | 
			
		||||
@@ -1004,123 +1004,123 @@ msgstr ""
 | 
			
		||||
"Kan ikke spesifisere både «button_width»/«button_height» og «aspect_ratio» "
 | 
			
		||||
"for knapper"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1452
 | 
			
		||||
#: ../src/ui/theme-parser.c:1449
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Distance \"%s\" is unknown"
 | 
			
		||||
msgstr "Avstand «%s» er ukjent"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1497
 | 
			
		||||
#: ../src/ui/theme-parser.c:1494
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Aspect ratio \"%s\" is unknown"
 | 
			
		||||
msgstr "Aspektrate «%s» er ukjent"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1559
 | 
			
		||||
#: ../src/ui/theme-parser.c:1556
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Border \"%s\" is unknown"
 | 
			
		||||
msgstr "Grense «%s» er ukjent"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1870
 | 
			
		||||
#: ../src/ui/theme-parser.c:1867
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "No \"start_angle\" or \"from\" attribute on element <%s>"
 | 
			
		||||
msgstr "Ingen «start_angle» eller «from»-attributt på element <%s>"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:1877
 | 
			
		||||
#: ../src/ui/theme-parser.c:1874
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "No \"extent_angle\" or \"to\" attribute on element <%s>"
 | 
			
		||||
msgstr "Ingen «extent_angle» eller «to»-attributt <%s>-element"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2117
 | 
			
		||||
#: ../src/ui/theme-parser.c:2114
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Did not understand value \"%s\" for type of gradient"
 | 
			
		||||
msgstr "Forsto ikke verdi «%s» for gradienttype"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2195 ../src/ui/theme-parser.c:2570
 | 
			
		||||
#: ../src/ui/theme-parser.c:2189 ../src/ui/theme-parser.c:2551
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Did not understand fill type \"%s\" for <%s> element"
 | 
			
		||||
msgstr "Forsto ikke fyll-type «%s» for <%s>-element"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2362 ../src/ui/theme-parser.c:2445
 | 
			
		||||
#: ../src/ui/theme-parser.c:2508
 | 
			
		||||
#: ../src/ui/theme-parser.c:2343 ../src/ui/theme-parser.c:2426
 | 
			
		||||
#: ../src/ui/theme-parser.c:2489
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Did not understand state \"%s\" for <%s> element"
 | 
			
		||||
msgstr "Forsto ikke tilstand «%s» for element <%s>"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2372 ../src/ui/theme-parser.c:2455
 | 
			
		||||
#: ../src/ui/theme-parser.c:2353 ../src/ui/theme-parser.c:2436
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Did not understand shadow \"%s\" for <%s> element"
 | 
			
		||||
msgstr "Forsto ikke skygge «%s» for element <%s>"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2382
 | 
			
		||||
#: ../src/ui/theme-parser.c:2363
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Did not understand arrow \"%s\" for <%s> element"
 | 
			
		||||
msgstr "Forsto ikke pil «%s» for element <%s>"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2696 ../src/ui/theme-parser.c:2792
 | 
			
		||||
#: ../src/ui/theme-parser.c:2677 ../src/ui/theme-parser.c:2773
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "No <draw_ops> called \"%s\" has been defined"
 | 
			
		||||
msgstr "Ingen <draw_ops> kalt «%s» er definert"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2708 ../src/ui/theme-parser.c:2804
 | 
			
		||||
#: ../src/ui/theme-parser.c:2689 ../src/ui/theme-parser.c:2785
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Including draw_ops \"%s\" here would create a circular reference"
 | 
			
		||||
msgstr "Hvis du tar med draw_ops «%s» her vil dette lage en sirkulær referanse"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2919
 | 
			
		||||
#: ../src/ui/theme-parser.c:2900
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Unknown position \"%s\" for frame piece"
 | 
			
		||||
msgstr "Ukjent posisjon «%s» for rammesdel"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2927
 | 
			
		||||
#: ../src/ui/theme-parser.c:2908
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Frame style already has a piece at position %s"
 | 
			
		||||
msgstr "Rammestil har allerede en del i posisjon %s"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2944 ../src/ui/theme-parser.c:3021
 | 
			
		||||
#: ../src/ui/theme-parser.c:2925 ../src/ui/theme-parser.c:3002
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "No <draw_ops> with the name \"%s\" has been defined"
 | 
			
		||||
msgstr "Ingen <draw_ops> med navn «%s» er definert"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2974
 | 
			
		||||
#: ../src/ui/theme-parser.c:2955
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Unknown function \"%s\" for button"
 | 
			
		||||
msgstr "Ukjent funksjon «%s» for knapp"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2984
 | 
			
		||||
#: ../src/ui/theme-parser.c:2965
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Button function \"%s\" does not exist in this version (%d, need %d)"
 | 
			
		||||
msgstr "Knappefunksjon «%s» eksisterer ikke i denne versjonen (%d, trenger %d)"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:2996
 | 
			
		||||
#: ../src/ui/theme-parser.c:2977
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Unknown state \"%s\" for button"
 | 
			
		||||
msgstr "Ukjent tilstand «%s» for knapp"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3004
 | 
			
		||||
#: ../src/ui/theme-parser.c:2985
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Frame style already has a button for function %s state %s"
 | 
			
		||||
msgstr "Rammestil har allerede en knapp for funksjon %s tilstand %s"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3075
 | 
			
		||||
#: ../src/ui/theme-parser.c:3056
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "\"%s\" is not a valid value for focus attribute"
 | 
			
		||||
msgstr "«%s» er ikke en gyldig verdi for fokusattributt"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3084
 | 
			
		||||
#: ../src/ui/theme-parser.c:3065
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "\"%s\" is not a valid value for state attribute"
 | 
			
		||||
msgstr "«%s» er ikke en gyldig verdi for tilstandsattributt"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3094
 | 
			
		||||
#: ../src/ui/theme-parser.c:3075
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "A style called \"%s\" has not been defined"
 | 
			
		||||
msgstr "En stil med navn «%s» er ikke definert"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3115 ../src/ui/theme-parser.c:3138
 | 
			
		||||
#: ../src/ui/theme-parser.c:3096 ../src/ui/theme-parser.c:3119
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "\"%s\" is not a valid value for resize attribute"
 | 
			
		||||
msgstr "«%s» er ikke en gyldig verdi for attributt for endring av størrelse"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3149
 | 
			
		||||
#: ../src/ui/theme-parser.c:3130
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Should not have \"resize\" attribute on <%s> element for maximized/shaded "
 | 
			
		||||
@@ -1129,27 +1129,27 @@ msgstr ""
 | 
			
		||||
"Skal ikke være noen «resize»-attributt på <%s>-element for maksimert/"
 | 
			
		||||
"skyggelagt tilstand"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3163
 | 
			
		||||
#: ../src/ui/theme-parser.c:3144
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Should not have \"resize\" attribute on <%s> element for maximized states"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Skal ikke være noen «resize»-attributt på <%s>-element for maksimert tilstand"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3177 ../src/ui/theme-parser.c:3221
 | 
			
		||||
#: ../src/ui/theme-parser.c:3158 ../src/ui/theme-parser.c:3202
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Style has already been specified for state %s resize %s focus %s"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Stil er allerede spesifisert for tilstand %s størrelsesendring %s fokus %s"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3188 ../src/ui/theme-parser.c:3199
 | 
			
		||||
#: ../src/ui/theme-parser.c:3210 ../src/ui/theme-parser.c:3232
 | 
			
		||||
#: ../src/ui/theme-parser.c:3243 ../src/ui/theme-parser.c:3254
 | 
			
		||||
#: ../src/ui/theme-parser.c:3169 ../src/ui/theme-parser.c:3180
 | 
			
		||||
#: ../src/ui/theme-parser.c:3191 ../src/ui/theme-parser.c:3213
 | 
			
		||||
#: ../src/ui/theme-parser.c:3224 ../src/ui/theme-parser.c:3235
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Style has already been specified for state %s focus %s"
 | 
			
		||||
msgstr "Stil er allerede spesifisert for tilstand %s fokus %s"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3293
 | 
			
		||||
#: ../src/ui/theme-parser.c:3274
 | 
			
		||||
msgid ""
 | 
			
		||||
"Can't have a two draw_ops for a <piece> element (theme specified a draw_ops "
 | 
			
		||||
"attribute and also a <draw_ops> element, or specified two elements)"
 | 
			
		||||
@@ -1158,7 +1158,7 @@ msgstr ""
 | 
			
		||||
"draw_ops-attributt i tillegg til et <draw_ops>-element, eller så "
 | 
			
		||||
"spesifiserte det to elementer)"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3331
 | 
			
		||||
#: ../src/ui/theme-parser.c:3312
 | 
			
		||||
msgid ""
 | 
			
		||||
"Can't have a two draw_ops for a <button> element (theme specified a draw_ops "
 | 
			
		||||
"attribute and also a <draw_ops> element, or specified two elements)"
 | 
			
		||||
@@ -1167,7 +1167,7 @@ msgstr ""
 | 
			
		||||
"draw_ops-attributt i tillegg til et <draw_ops>-element, eller det "
 | 
			
		||||
"spesifiserte to elementer)"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3369
 | 
			
		||||
#: ../src/ui/theme-parser.c:3350
 | 
			
		||||
msgid ""
 | 
			
		||||
"Can't have a two draw_ops for a <menu_icon> element (theme specified a "
 | 
			
		||||
"draw_ops attribute and also a <draw_ops> element, or specified two elements)"
 | 
			
		||||
@@ -1176,12 +1176,12 @@ msgstr ""
 | 
			
		||||
"draw_ops-attributt i tillegg til et <draw_ops>-element, eller det "
 | 
			
		||||
"spesifiserte to elementer)"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3433
 | 
			
		||||
#: ../src/ui/theme-parser.c:3414
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Bad version specification '%s'"
 | 
			
		||||
msgstr "Ugyldig versjonspesifikasjon «%s»"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3506
 | 
			
		||||
#: ../src/ui/theme-parser.c:3487
 | 
			
		||||
msgid ""
 | 
			
		||||
"\"version\" attribute cannot be used in metacity-theme-1.xml or metacity-"
 | 
			
		||||
"theme-2.xml"
 | 
			
		||||
@@ -1189,66 +1189,66 @@ msgstr ""
 | 
			
		||||
"«version»-attributt kan ikke brukes i metacity-theme-1.xml eller metacity-"
 | 
			
		||||
"theme-2.xml"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3529
 | 
			
		||||
#: ../src/ui/theme-parser.c:3510
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Theme requires version %s but latest supported theme version is %d.%d"
 | 
			
		||||
msgstr "Tema krever versjon %s men siste støttede temaversjon er %d.%d"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3561
 | 
			
		||||
#: ../src/ui/theme-parser.c:3542
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Outermost element in theme must be <metacity_theme> not <%s>"
 | 
			
		||||
msgstr "Ytterste element i temaet må være <metacity_theme> ikke <%s>"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3581
 | 
			
		||||
#: ../src/ui/theme-parser.c:3562
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Element <%s> is not allowed inside a name/author/date/description element"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Element <%s> er ikke tillatt inne i et name/author/date/description element"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3586
 | 
			
		||||
#: ../src/ui/theme-parser.c:3567
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Element <%s> is not allowed inside a <constant> element"
 | 
			
		||||
msgstr "Element <%s> er ikke tillatt inne i et <constand> element"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3598
 | 
			
		||||
#: ../src/ui/theme-parser.c:3579
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Element <%s> is not allowed inside a distance/border/aspect_ratio element"
 | 
			
		||||
msgstr "Element <%s> er ikke tillatt inne i et avstand/kant/aspektrate-element"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3620
 | 
			
		||||
#: ../src/ui/theme-parser.c:3601
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Element <%s> is not allowed inside a draw operation element"
 | 
			
		||||
msgstr "Element <%s> er ikke tillatt inne i et element for tegneoperasjon"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3630 ../src/ui/theme-parser.c:3660
 | 
			
		||||
#: ../src/ui/theme-parser.c:3665 ../src/ui/theme-parser.c:3670
 | 
			
		||||
#: ../src/ui/theme-parser.c:3611 ../src/ui/theme-parser.c:3641
 | 
			
		||||
#: ../src/ui/theme-parser.c:3646 ../src/ui/theme-parser.c:3651
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Element <%s> is not allowed inside a <%s> element"
 | 
			
		||||
msgstr "Element <%s> er ikke tillatt inne i et <%s>-element"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3898
 | 
			
		||||
#: ../src/ui/theme-parser.c:3879
 | 
			
		||||
msgid "No draw_ops provided for frame piece"
 | 
			
		||||
msgstr "Ingen draw_ops tilbys for rammedelen"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3913
 | 
			
		||||
#: ../src/ui/theme-parser.c:3894
 | 
			
		||||
msgid "No draw_ops provided for button"
 | 
			
		||||
msgstr "Ingen draw_ops tilbys for knappen"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:3967
 | 
			
		||||
#: ../src/ui/theme-parser.c:3948
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "No text is allowed inside element <%s>"
 | 
			
		||||
msgstr "Ingen tekst er tillatt inne i element <%s>"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:4025 ../src/ui/theme-parser.c:4037
 | 
			
		||||
#: ../src/ui/theme-parser.c:4049 ../src/ui/theme-parser.c:4061
 | 
			
		||||
#: ../src/ui/theme-parser.c:4073
 | 
			
		||||
#: ../src/ui/theme-parser.c:4006 ../src/ui/theme-parser.c:4018
 | 
			
		||||
#: ../src/ui/theme-parser.c:4030 ../src/ui/theme-parser.c:4042
 | 
			
		||||
#: ../src/ui/theme-parser.c:4054
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "<%s> specified twice for this theme"
 | 
			
		||||
msgstr "<%s> spesifisert to ganger for dette temaet"
 | 
			
		||||
 | 
			
		||||
#: ../src/ui/theme-parser.c:4335
 | 
			
		||||
#: ../src/ui/theme-parser.c:4316
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Failed to find a valid file for theme %s\n"
 | 
			
		||||
msgstr "Fant ikke en gyldig fil for tema %s\n"
 | 
			
		||||
@@ -1261,10 +1261,7 @@ msgstr ""
 | 
			
		||||
"Disse vinduene støtter ikke "lagre aktiv konfigurasjon"og vil "
 | 
			
		||||
"måtte startes på nytt manuelt neste gang du logger inn."
 | 
			
		||||
 | 
			
		||||
#: ../src/x11/window-props.c:515
 | 
			
		||||
#: ../src/x11/window-props.c:558
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%s (on %s)"
 | 
			
		||||
msgstr "%s (på %s)"
 | 
			
		||||
 | 
			
		||||
#~ msgid "background texture could not be created from file"
 | 
			
		||||
#~ msgstr "bakgrunnstekstur kunne ikke lages fra fil"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1264
									
								
								po/pt_BR.po
									
									
									
									
									
								
							
							
						
						
									
										1264
									
								
								po/pt_BR.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1300
									
								
								po/sr@latin.po
									
									
									
									
									
								
							
							
						
						
									
										1300
									
								
								po/sr@latin.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1306
									
								
								po/zh_CN.po
									
									
									
									
									
								
							
							
						
						
									
										1306
									
								
								po/zh_CN.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -7,6 +7,7 @@ stackingdir = $(pkgdatadir)/tests/stacking
 | 
			
		||||
dist_stacking_DATA =				\
 | 
			
		||||
	tests/stacking/basic-x11.metatest	\
 | 
			
		||||
	tests/stacking/basic-wayland.metatest	\
 | 
			
		||||
	tests/stacking/minimized.metatest   	\
 | 
			
		||||
	tests/stacking/mixed-windows.metatest   \
 | 
			
		||||
	tests/stacking/override-redirect.metatest
 | 
			
		||||
 | 
			
		||||
@@ -40,11 +41,9 @@ endif
 | 
			
		||||
# Some random test programs for bits of the code
 | 
			
		||||
 | 
			
		||||
testboxes_SOURCES = core/testboxes.c
 | 
			
		||||
testgradient_SOURCES = ui/testgradient.c
 | 
			
		||||
testasyncgetprop_SOURCES = x11/testasyncgetprop.c
 | 
			
		||||
 | 
			
		||||
noinst_PROGRAMS+=testboxes testgradient testasyncgetprop
 | 
			
		||||
noinst_PROGRAMS+=testboxes testasyncgetprop
 | 
			
		||||
 | 
			
		||||
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
 | 
			
		||||
testgradient_LDADD = $(MUTTER_LIBS) libmutter.la
 | 
			
		||||
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ lib_LTLIBRARIES = libmutter.la
 | 
			
		||||
SUBDIRS=compositor/plugins
 | 
			
		||||
 | 
			
		||||
EXTRA_DIST =
 | 
			
		||||
NULL =
 | 
			
		||||
 | 
			
		||||
AM_CPPFLAGS = \
 | 
			
		||||
	-DCLUTTER_ENABLE_COMPOSITOR_API					\
 | 
			
		||||
@@ -31,31 +32,37 @@ AM_CPPFLAGS = \
 | 
			
		||||
	-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\"				\
 | 
			
		||||
	-DMUTTER_PLUGIN_DIR=\"$(MUTTER_PLUGIN_DIR)\"			\
 | 
			
		||||
	-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"			\
 | 
			
		||||
	-DXWAYLAND_PATH=\"$(XWAYLAND_PATH)\"
 | 
			
		||||
	-DXWAYLAND_PATH=\"$(XWAYLAND_PATH)\"				\
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
mutter_built_sources = \
 | 
			
		||||
	$(dbus_idle_built_sources)		\
 | 
			
		||||
	$(dbus_display_config_built_sources)	\
 | 
			
		||||
	$(dbus_login1_built_sources)		\
 | 
			
		||||
	mutter-enum-types.h 			\
 | 
			
		||||
	mutter-enum-types.c
 | 
			
		||||
	mutter-enum-types.c			\
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
if HAVE_WAYLAND
 | 
			
		||||
mutter_built_sources += \
 | 
			
		||||
	gtk-shell-protocol.c			\
 | 
			
		||||
	gtk-shell-server-protocol.h		\
 | 
			
		||||
	xdg-shell-protocol.c			\
 | 
			
		||||
	xdg-shell-server-protocol.h
 | 
			
		||||
	xdg-shell-server-protocol.h		\
 | 
			
		||||
	$(NULL)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
wayland_protocols = \
 | 
			
		||||
wayland_protocols =				\
 | 
			
		||||
	wayland/protocol/gtk-shell.xml		\
 | 
			
		||||
	wayland/protocol/xdg-shell.xml
 | 
			
		||||
	wayland/protocol/xdg-shell.xml		\
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
libmutter_la_SOURCES =				\
 | 
			
		||||
	backends/meta-backend.c			\
 | 
			
		||||
	meta/meta-backend.h			\
 | 
			
		||||
	backends/meta-backend-private.h		\
 | 
			
		||||
	backends/meta-barrier.c			\
 | 
			
		||||
	backends/meta-barrier-private.h		\
 | 
			
		||||
	backends/meta-cursor.c			\
 | 
			
		||||
	backends/meta-cursor.h			\
 | 
			
		||||
	backends/meta-cursor-private.h		\
 | 
			
		||||
@@ -68,10 +75,13 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	backends/meta-idle-monitor-private.h	\
 | 
			
		||||
	backends/meta-idle-monitor-dbus.c	\
 | 
			
		||||
	backends/meta-idle-monitor-dbus.h	\
 | 
			
		||||
	backends/meta-input-settings.c		\
 | 
			
		||||
	backends/meta-input-settings-private.h	\
 | 
			
		||||
	backends/meta-monitor-config.c		\
 | 
			
		||||
	backends/meta-monitor-config.h		\
 | 
			
		||||
	backends/meta-monitor-manager.c		\
 | 
			
		||||
	backends/meta-monitor-manager.h		\
 | 
			
		||||
	meta/meta-monitor-manager.h		\
 | 
			
		||||
	backends/meta-monitor-manager-private.h	\
 | 
			
		||||
	backends/meta-monitor-manager-dummy.c	\
 | 
			
		||||
	backends/meta-monitor-manager-dummy.h	\
 | 
			
		||||
	backends/meta-stage.h			\
 | 
			
		||||
@@ -80,15 +90,18 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	backends/edid.h				\
 | 
			
		||||
	backends/x11/meta-backend-x11.c			\
 | 
			
		||||
	backends/x11/meta-backend-x11.h			\
 | 
			
		||||
	backends/x11/meta-barrier-x11.c			\
 | 
			
		||||
	backends/x11/meta-barrier-x11.h			\
 | 
			
		||||
	backends/x11/meta-cursor-renderer-x11.c		\
 | 
			
		||||
	backends/x11/meta-cursor-renderer-x11.h		\
 | 
			
		||||
	backends/x11/meta-idle-monitor-xsync.c		\
 | 
			
		||||
	backends/x11/meta-idle-monitor-xsync.h		\
 | 
			
		||||
	backends/x11/meta-input-settings-x11.c		\
 | 
			
		||||
	backends/x11/meta-input-settings-x11.h		\
 | 
			
		||||
	backends/x11/meta-monitor-manager-xrandr.c	\
 | 
			
		||||
	backends/x11/meta-monitor-manager-xrandr.h	\
 | 
			
		||||
	core/meta-accel-parse.c			\
 | 
			
		||||
	core/meta-accel-parse.h			\
 | 
			
		||||
	core/barrier.c				\
 | 
			
		||||
	meta/barrier.h				\
 | 
			
		||||
	core/bell.c				\
 | 
			
		||||
	core/bell.h				\
 | 
			
		||||
@@ -109,6 +122,10 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	compositor/meta-background-group.c	\
 | 
			
		||||
	compositor/meta-cullable.c		\
 | 
			
		||||
	compositor/meta-cullable.h		\
 | 
			
		||||
	compositor/meta-dnd-actor.c		\
 | 
			
		||||
	compositor/meta-dnd-actor-private.h	\
 | 
			
		||||
	compositor/meta-feedback-actor.c	\
 | 
			
		||||
	compositor/meta-feedback-actor-private.h	\
 | 
			
		||||
	compositor/meta-module.c		\
 | 
			
		||||
	compositor/meta-module.h		\
 | 
			
		||||
	compositor/meta-plugin.c		\
 | 
			
		||||
@@ -158,8 +175,6 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	meta/errors.h				\
 | 
			
		||||
	core/frame.c				\
 | 
			
		||||
	core/frame.h				\
 | 
			
		||||
	ui/gradient.c				\
 | 
			
		||||
	meta/gradient.h				\
 | 
			
		||||
	core/meta-gesture-tracker.c		\
 | 
			
		||||
	core/meta-gesture-tracker-private.h	\
 | 
			
		||||
	core/keybindings.c			\
 | 
			
		||||
@@ -191,9 +206,6 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	ui/ui.h					\
 | 
			
		||||
	ui/frames.c				\
 | 
			
		||||
	ui/frames.h				\
 | 
			
		||||
	ui/resizepopup.c			\
 | 
			
		||||
	ui/resizepopup.h			\
 | 
			
		||||
	ui/theme-parser.c			\
 | 
			
		||||
	ui/theme.c				\
 | 
			
		||||
	meta/theme.h				\
 | 
			
		||||
	ui/theme-private.h			\
 | 
			
		||||
@@ -218,7 +230,8 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	x11/window-x11-private.h		\
 | 
			
		||||
	x11/xprops.c				\
 | 
			
		||||
	x11/xprops.h				\
 | 
			
		||||
	x11/mutter-Xatomtype.h
 | 
			
		||||
	x11/mutter-Xatomtype.h			\
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
if HAVE_WAYLAND
 | 
			
		||||
libmutter_la_SOURCES +=				\
 | 
			
		||||
@@ -230,12 +243,18 @@ libmutter_la_SOURCES +=				\
 | 
			
		||||
	wayland/meta-xwayland.c			\
 | 
			
		||||
	wayland/meta-xwayland.h			\
 | 
			
		||||
	wayland/meta-xwayland-private.h		\
 | 
			
		||||
	wayland/meta-wayland-buffer.c      	\
 | 
			
		||||
	wayland/meta-wayland-buffer.h      	\
 | 
			
		||||
	wayland/meta-wayland-region.c      	\
 | 
			
		||||
	wayland/meta-wayland-region.h      	\
 | 
			
		||||
	wayland/meta-wayland-data-device.c      \
 | 
			
		||||
	wayland/meta-wayland-data-device.h      \
 | 
			
		||||
	wayland/meta-wayland-keyboard.c		\
 | 
			
		||||
	wayland/meta-wayland-keyboard.h		\
 | 
			
		||||
	wayland/meta-wayland-pointer.c		\
 | 
			
		||||
	wayland/meta-wayland-pointer.h		\
 | 
			
		||||
	wayland/meta-wayland-popup.c		\
 | 
			
		||||
	wayland/meta-wayland-popup.h		\
 | 
			
		||||
	wayland/meta-wayland-seat.c		\
 | 
			
		||||
	wayland/meta-wayland-seat.h		\
 | 
			
		||||
	wayland/meta-wayland-touch.c		\
 | 
			
		||||
@@ -247,29 +266,35 @@ libmutter_la_SOURCES +=				\
 | 
			
		||||
	wayland/meta-wayland-outputs.c		\
 | 
			
		||||
	wayland/meta-wayland-outputs.h		\
 | 
			
		||||
	wayland/window-wayland.c		\
 | 
			
		||||
	wayland/window-wayland.h
 | 
			
		||||
	wayland/window-wayland.h		\
 | 
			
		||||
	$(NULL)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
if HAVE_NATIVE_BACKEND
 | 
			
		||||
libmutter_la_SOURCES +=					\
 | 
			
		||||
	backends/native/meta-backend-native.c		\
 | 
			
		||||
	backends/native/meta-backend-native.h		\
 | 
			
		||||
	backends/native/meta-backend-native-private.h	\
 | 
			
		||||
	backends/native/meta-barrier-native.c		\
 | 
			
		||||
	backends/native/meta-barrier-native.h		\
 | 
			
		||||
	backends/native/meta-cursor-renderer-native.c	\
 | 
			
		||||
	backends/native/meta-cursor-renderer-native.h	\
 | 
			
		||||
	backends/native/meta-idle-monitor-native.c	\
 | 
			
		||||
	backends/native/meta-idle-monitor-native.h	\
 | 
			
		||||
	backends/native/meta-input-settings-native.c	\
 | 
			
		||||
	backends/native/meta-input-settings-native.h	\
 | 
			
		||||
	backends/native/meta-monitor-manager-kms.c	\
 | 
			
		||||
	backends/native/meta-monitor-manager-kms.h	\
 | 
			
		||||
	backends/native/meta-launcher.c			\
 | 
			
		||||
	backends/native/meta-launcher.h			\
 | 
			
		||||
	backends/native/dbus-utils.c			\
 | 
			
		||||
	backends/native/dbus-utils.h
 | 
			
		||||
	backends/native/dbus-utils.h			\
 | 
			
		||||
	$(NULL)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
nodist_libmutter_la_SOURCES =			\
 | 
			
		||||
	$(mutter_built_sources)
 | 
			
		||||
nodist_libmutter_la_SOURCES = $(mutter_built_sources)
 | 
			
		||||
 | 
			
		||||
libmutter_la_LDFLAGS = -no-undefined
 | 
			
		||||
libmutter_la_LDFLAGS = -no-undefined -export-symbols-regex "^(meta|ag)_.*"
 | 
			
		||||
libmutter_la_LIBADD  = $(MUTTER_LIBS) $(MUTTER_NATIVE_BACKEND_LIBS)
 | 
			
		||||
 | 
			
		||||
# Headers installed for plugins; introspected information will
 | 
			
		||||
@@ -282,7 +307,6 @@ libmutterinclude_headers =			\
 | 
			
		||||
	meta/compositor.h			\
 | 
			
		||||
	meta/display.h				\
 | 
			
		||||
	meta/errors.h				\
 | 
			
		||||
	meta/gradient.h				\
 | 
			
		||||
	meta/group.h				\
 | 
			
		||||
	meta/keybindings.h			\
 | 
			
		||||
	meta/main.h				\
 | 
			
		||||
@@ -294,6 +318,7 @@ libmutterinclude_headers =			\
 | 
			
		||||
	meta/meta-cursor-tracker.h		\
 | 
			
		||||
	meta/meta-idle-monitor.h		\
 | 
			
		||||
	meta/meta-plugin.h			\
 | 
			
		||||
	meta/meta-monitor-manager.h		\
 | 
			
		||||
	meta/meta-shaped-texture.h		\
 | 
			
		||||
	meta/meta-shadow-factory.h		\
 | 
			
		||||
	meta/meta-window-actor.h		\
 | 
			
		||||
@@ -303,7 +328,8 @@ libmutterinclude_headers =			\
 | 
			
		||||
	meta/types.h				\
 | 
			
		||||
	meta/util.h				\
 | 
			
		||||
	meta/window.h				\
 | 
			
		||||
	meta/workspace.h
 | 
			
		||||
	meta/workspace.h			\
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
libmutterinclude_built_headers =		\
 | 
			
		||||
	meta/meta-version.h
 | 
			
		||||
@@ -384,14 +410,15 @@ DISTCLEANFILES = 				\
 | 
			
		||||
pkgconfigdir = $(libdir)/pkgconfig
 | 
			
		||||
pkgconfig_DATA = libmutter.pc
 | 
			
		||||
 | 
			
		||||
EXTRA_DIST +=				\
 | 
			
		||||
	$(wayland_protocols)		\
 | 
			
		||||
	libmutter.pc.in \
 | 
			
		||||
	mutter-enum-types.h.in \
 | 
			
		||||
	mutter-enum-types.c.in \
 | 
			
		||||
	org.freedesktop.login1.xml	\
 | 
			
		||||
EXTRA_DIST +=					\
 | 
			
		||||
	$(wayland_protocols)			\
 | 
			
		||||
	libmutter.pc.in				\
 | 
			
		||||
	mutter-enum-types.h.in			\
 | 
			
		||||
	mutter-enum-types.c.in			\
 | 
			
		||||
	org.freedesktop.login1.xml		\
 | 
			
		||||
	org.gnome.Mutter.DisplayConfig.xml	\
 | 
			
		||||
	org.gnome.Mutter.IdleMonitor.xml
 | 
			
		||||
	org.gnome.Mutter.IdleMonitor.xml	\
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
BUILT_SOURCES =					\
 | 
			
		||||
	$(mutter_built_sources)			\
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,7 @@
 | 
			
		||||
#include <meta/meta-backend.h>
 | 
			
		||||
#include <meta/meta-idle-monitor.h>
 | 
			
		||||
#include "meta-cursor-renderer.h"
 | 
			
		||||
#include "meta-monitor-manager.h"
 | 
			
		||||
#include "meta-monitor-manager-private.h"
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_XKB_RULES_FILE "evdev"
 | 
			
		||||
#define DEFAULT_XKB_MODEL "pc105+inet"
 | 
			
		||||
@@ -49,8 +49,7 @@ struct _MetaBackend
 | 
			
		||||
{
 | 
			
		||||
  GObject parent;
 | 
			
		||||
 | 
			
		||||
  MetaIdleMonitor *device_monitors[256];
 | 
			
		||||
  int device_id_max;
 | 
			
		||||
  GHashTable *device_monitors;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaBackendClass
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@
 | 
			
		||||
 | 
			
		||||
#include <meta/meta-backend.h>
 | 
			
		||||
#include "meta-backend-private.h"
 | 
			
		||||
#include "meta-input-settings-private.h"
 | 
			
		||||
 | 
			
		||||
#include "backends/x11/meta-backend-x11.h"
 | 
			
		||||
#include "meta-stage.h"
 | 
			
		||||
@@ -34,6 +35,10 @@
 | 
			
		||||
#include "backends/native/meta-backend-native.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "backends/meta-idle-monitor-private.h"
 | 
			
		||||
 | 
			
		||||
#include "backends/meta-monitor-manager-dummy.h"
 | 
			
		||||
 | 
			
		||||
static MetaBackend *_backend;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -53,6 +58,7 @@ struct _MetaBackendPrivate
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManager *monitor_manager;
 | 
			
		||||
  MetaCursorRenderer *cursor_renderer;
 | 
			
		||||
  MetaInputSettings *input_settings;
 | 
			
		||||
 | 
			
		||||
  ClutterActor *stage;
 | 
			
		||||
};
 | 
			
		||||
@@ -65,15 +71,11 @@ meta_backend_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackend *backend = META_BACKEND (object);
 | 
			
		||||
  MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  g_clear_object (&priv->monitor_manager);
 | 
			
		||||
  g_clear_object (&priv->input_settings);
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i <= backend->device_id_max; i++)
 | 
			
		||||
    {
 | 
			
		||||
      if (backend->device_monitors[i])
 | 
			
		||||
        g_object_unref (backend->device_monitors[i]);
 | 
			
		||||
    }
 | 
			
		||||
  g_hash_table_destroy (backend->device_monitors);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
@@ -108,27 +110,19 @@ static void
 | 
			
		||||
create_device_monitor (MetaBackend *backend,
 | 
			
		||||
                       int          device_id)
 | 
			
		||||
{
 | 
			
		||||
  g_assert (backend->device_monitors[device_id] == NULL);
 | 
			
		||||
  MetaIdleMonitor *idle_monitor;
 | 
			
		||||
 | 
			
		||||
  backend->device_monitors[device_id] = meta_backend_create_idle_monitor (backend, device_id);
 | 
			
		||||
  backend->device_id_max = MAX (backend->device_id_max, device_id);
 | 
			
		||||
  g_assert (g_hash_table_lookup (backend->device_monitors, &device_id) == NULL);
 | 
			
		||||
 | 
			
		||||
  idle_monitor = meta_backend_create_idle_monitor (backend, device_id);
 | 
			
		||||
  g_hash_table_insert (backend->device_monitors, &idle_monitor->device_id, idle_monitor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
destroy_device_monitor (MetaBackend *backend,
 | 
			
		||||
                        int          device_id)
 | 
			
		||||
{
 | 
			
		||||
  g_clear_object (&backend->device_monitors[device_id]);
 | 
			
		||||
 | 
			
		||||
  if (device_id == backend->device_id_max)
 | 
			
		||||
    {
 | 
			
		||||
      /* Reset the max device ID */
 | 
			
		||||
      int i, new_max = 0;
 | 
			
		||||
      for (i = 0; i < backend->device_id_max; i++)
 | 
			
		||||
        if (backend->device_monitors[i] != NULL)
 | 
			
		||||
          new_max = i;
 | 
			
		||||
      backend->device_id_max = new_max;
 | 
			
		||||
    }
 | 
			
		||||
  g_hash_table_remove (backend->device_monitors, &device_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -153,6 +147,15 @@ on_device_removed (ClutterDeviceManager *device_manager,
 | 
			
		||||
  destroy_device_monitor (backend, device_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaMonitorManager *
 | 
			
		||||
create_monitor_manager (MetaBackend *backend)
 | 
			
		||||
{
 | 
			
		||||
  if (g_getenv ("META_DUMMY_MONITORS"))
 | 
			
		||||
    return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL);
 | 
			
		||||
 | 
			
		||||
  return META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_backend_real_post_init (MetaBackend *backend)
 | 
			
		||||
{
 | 
			
		||||
@@ -162,7 +165,7 @@ meta_backend_real_post_init (MetaBackend *backend)
 | 
			
		||||
  clutter_actor_realize (priv->stage);
 | 
			
		||||
  META_BACKEND_GET_CLASS (backend)->select_stage_events (backend);
 | 
			
		||||
 | 
			
		||||
  priv->monitor_manager = META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend);
 | 
			
		||||
  priv->monitor_manager = create_monitor_manager (backend);
 | 
			
		||||
 | 
			
		||||
  g_signal_connect (priv->monitor_manager, "monitors-changed",
 | 
			
		||||
                    G_CALLBACK (on_monitors_changed), backend);
 | 
			
		||||
@@ -170,6 +173,9 @@ meta_backend_real_post_init (MetaBackend *backend)
 | 
			
		||||
 | 
			
		||||
  priv->cursor_renderer = META_BACKEND_GET_CLASS (backend)->create_cursor_renderer (backend);
 | 
			
		||||
 | 
			
		||||
  backend->device_monitors = g_hash_table_new_full (g_int_hash, g_int_equal,
 | 
			
		||||
                                                    NULL, (GDestroyNotify) g_object_unref);
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    ClutterDeviceManager *manager;
 | 
			
		||||
    GSList *devices, *l;
 | 
			
		||||
@@ -193,6 +199,8 @@ meta_backend_real_post_init (MetaBackend *backend)
 | 
			
		||||
 | 
			
		||||
    g_slist_free (devices);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  priv->input_settings = meta_input_settings_create ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaCursorRenderer *
 | 
			
		||||
@@ -281,9 +289,7 @@ MetaIdleMonitor *
 | 
			
		||||
meta_backend_get_idle_monitor (MetaBackend *backend,
 | 
			
		||||
                               int          device_id)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (device_id >= 0 && device_id < 256, NULL);
 | 
			
		||||
 | 
			
		||||
  return backend->device_monitors[device_id];
 | 
			
		||||
  return g_hash_table_lookup (backend->device_monitors, &device_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										81
									
								
								src/backends/meta-barrier-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								src/backends/meta-barrier-private.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014-2015 Red Hat
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
 * published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 | 
			
		||||
 * 02111-1307, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * Written by:
 | 
			
		||||
 *     Jasper St. Pierre <jstpierre@mecheye.net>
 | 
			
		||||
 *     Jonas Ådahl <jadahl@gmail.com>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef META_BARRIER_PRIVATE_H
 | 
			
		||||
#define META_BARRIER_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_BARRIER_IMPL            (meta_barrier_impl_get_type ())
 | 
			
		||||
#define META_BARRIER_IMPL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BARRIER_IMPL, MetaBarrierImpl))
 | 
			
		||||
#define META_BARRIER_IMPL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_BARRIER_IMPL, MetaBarrierImplClass))
 | 
			
		||||
#define META_IS_BARRIER_IMPL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BARRIER_IMPL))
 | 
			
		||||
#define META_IS_BARRIER_IMPL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_BARRIER_IMPL))
 | 
			
		||||
#define META_BARRIER_IMPL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_BARRIER_IMPL, MetaBarrierImplClass))
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaBarrierImpl        MetaBarrierImpl;
 | 
			
		||||
typedef struct _MetaBarrierImplClass   MetaBarrierImplClass;
 | 
			
		||||
 | 
			
		||||
struct _MetaBarrierImpl
 | 
			
		||||
{
 | 
			
		||||
  GObject parent;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaBarrierImplClass
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass parent_class;
 | 
			
		||||
 | 
			
		||||
  gboolean (*is_active) (MetaBarrierImpl *barrier);
 | 
			
		||||
  void (*release) (MetaBarrierImpl  *barrier,
 | 
			
		||||
                   MetaBarrierEvent *event);
 | 
			
		||||
  void (*destroy) (MetaBarrierImpl *barrier);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType meta_barrier_impl_get_type (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
void _meta_barrier_emit_hit_signal (MetaBarrier      *barrier,
 | 
			
		||||
                                    MetaBarrierEvent *event);
 | 
			
		||||
void _meta_barrier_emit_left_signal (MetaBarrier      *barrier,
 | 
			
		||||
                                     MetaBarrierEvent *event);
 | 
			
		||||
 | 
			
		||||
void meta_barrier_event_unref (MetaBarrierEvent *event);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
struct _MetaBarrierPrivate
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display;
 | 
			
		||||
 | 
			
		||||
  int x1;
 | 
			
		||||
  int y1;
 | 
			
		||||
  int x2;
 | 
			
		||||
  int y2;
 | 
			
		||||
 | 
			
		||||
  MetaBarrierDirection directions;
 | 
			
		||||
 | 
			
		||||
  MetaBarrierImpl *impl;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif /* META_BARRIER_PRIVATE_H */
 | 
			
		||||
@@ -10,15 +10,16 @@
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
 | 
			
		||||
#include <X11/extensions/XInput2.h>
 | 
			
		||||
#include <X11/extensions/Xfixes.h>
 | 
			
		||||
#include <meta/util.h>
 | 
			
		||||
#include <meta/barrier.h>
 | 
			
		||||
#include "display-private.h"
 | 
			
		||||
#include "backends/native/meta-backend-native.h"
 | 
			
		||||
#include "backends/native/meta-barrier-native.h"
 | 
			
		||||
#include "backends/x11/meta-backend-x11.h"
 | 
			
		||||
#include "backends/x11/meta-barrier-x11.h"
 | 
			
		||||
#include "mutter-enum-types.h"
 | 
			
		||||
#include "core.h"
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaBarrier, meta_barrier, G_TYPE_OBJECT)
 | 
			
		||||
G_DEFINE_TYPE (MetaBarrierImpl, meta_barrier_impl, G_TYPE_OBJECT)
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
  PROP_0,
 | 
			
		||||
@@ -45,21 +46,6 @@ enum {
 | 
			
		||||
 | 
			
		||||
static guint obj_signals[LAST_SIGNAL];
 | 
			
		||||
 | 
			
		||||
struct _MetaBarrierPrivate
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display;
 | 
			
		||||
 | 
			
		||||
  int x1;
 | 
			
		||||
  int y1;
 | 
			
		||||
  int x2;
 | 
			
		||||
  int y2;
 | 
			
		||||
 | 
			
		||||
  MetaBarrierDirection directions;
 | 
			
		||||
 | 
			
		||||
  PointerBarrier xbarrier;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void meta_barrier_event_unref (MetaBarrierEvent *event);
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_barrier_get_property (GObject    *object,
 | 
			
		||||
@@ -133,13 +119,11 @@ static void
 | 
			
		||||
meta_barrier_dispose (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrier *barrier = META_BARRIER (object);
 | 
			
		||||
  MetaBarrierPrivate *priv = barrier->priv;
 | 
			
		||||
 | 
			
		||||
  if (meta_barrier_is_active (barrier))
 | 
			
		||||
    {
 | 
			
		||||
      meta_bug ("MetaBarrier wrapper %p for X barrier %ld was destroyed"
 | 
			
		||||
                " while the X barrier is still active.",
 | 
			
		||||
                barrier, priv->xbarrier);
 | 
			
		||||
      meta_bug ("MetaBarrier %p was destroyed while it was still active.",
 | 
			
		||||
                barrier);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_barrier_parent_class)->dispose (object);
 | 
			
		||||
@@ -148,7 +132,12 @@ meta_barrier_dispose (GObject *object)
 | 
			
		||||
gboolean
 | 
			
		||||
meta_barrier_is_active (MetaBarrier *barrier)
 | 
			
		||||
{
 | 
			
		||||
  return barrier->priv->xbarrier != 0;
 | 
			
		||||
  MetaBarrierImpl *impl = barrier->priv->impl;
 | 
			
		||||
 | 
			
		||||
  if (impl)
 | 
			
		||||
    return META_BARRIER_IMPL_GET_CLASS (impl)->is_active (impl);
 | 
			
		||||
  else
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -165,15 +154,10 @@ void
 | 
			
		||||
meta_barrier_release (MetaBarrier      *barrier,
 | 
			
		||||
                      MetaBarrierEvent *event)
 | 
			
		||||
{
 | 
			
		||||
#ifdef HAVE_XI23
 | 
			
		||||
  MetaBarrierPrivate *priv = barrier->priv;
 | 
			
		||||
  if (META_DISPLAY_HAS_XINPUT_23 (priv->display))
 | 
			
		||||
    {
 | 
			
		||||
      XIBarrierReleasePointer (priv->display->xdisplay,
 | 
			
		||||
                               META_VIRTUAL_CORE_POINTER_ID,
 | 
			
		||||
                               priv->xbarrier, event->event_id);
 | 
			
		||||
    }
 | 
			
		||||
#endif /* HAVE_XI23 */
 | 
			
		||||
  MetaBarrierImpl *impl = barrier->priv->impl;
 | 
			
		||||
 | 
			
		||||
  if (impl)
 | 
			
		||||
    META_BARRIER_IMPL_GET_CLASS (impl)->release (impl, event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -181,31 +165,26 @@ meta_barrier_constructed (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrier *barrier = META_BARRIER (object);
 | 
			
		||||
  MetaBarrierPrivate *priv = barrier->priv;
 | 
			
		||||
  Display *dpy;
 | 
			
		||||
  Window root;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (priv->x1 == priv->x2 || priv->y1 == priv->y2);
 | 
			
		||||
 | 
			
		||||
  if (priv->display == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("A display must be provided when constructing a barrier.");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
#if defined(HAVE_NATIVE_BACKEND)
 | 
			
		||||
  if (META_IS_BACKEND_NATIVE (meta_get_backend ()))
 | 
			
		||||
    priv->impl = meta_barrier_impl_native_new (barrier);
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(HAVE_XI23)
 | 
			
		||||
  if (META_IS_BACKEND_X11 (meta_get_backend ()) &&
 | 
			
		||||
      !meta_is_wayland_compositor ())
 | 
			
		||||
    priv->impl = meta_barrier_impl_x11_new (barrier);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  dpy = priv->display->xdisplay;
 | 
			
		||||
  root = DefaultRootWindow (dpy);
 | 
			
		||||
  if (priv->impl == NULL)
 | 
			
		||||
    g_warning ("Created a non-working barrier");
 | 
			
		||||
 | 
			
		||||
  priv->xbarrier = XFixesCreatePointerBarrier (dpy, root,
 | 
			
		||||
                                               priv->x1, priv->y1,
 | 
			
		||||
                                               priv->x2, priv->y2,
 | 
			
		||||
                                               priv->directions, 0, NULL);
 | 
			
		||||
 | 
			
		||||
  /* Take a ref that we'll release when the XID dies inside destroy(),
 | 
			
		||||
   * so that the object stays alive and doesn't get GC'd. */
 | 
			
		||||
  /* Take a ref that we'll release in destroy() so that the object stays
 | 
			
		||||
   * alive while active. */
 | 
			
		||||
  g_object_ref (barrier);
 | 
			
		||||
 | 
			
		||||
  g_hash_table_insert (priv->display->xids, &priv->xbarrier, barrier);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_barrier_parent_class)->constructed (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -306,20 +285,10 @@ meta_barrier_class_init (MetaBarrierClass *klass)
 | 
			
		||||
void
 | 
			
		||||
meta_barrier_destroy (MetaBarrier *barrier)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierPrivate *priv = barrier->priv;
 | 
			
		||||
  Display *dpy;
 | 
			
		||||
  MetaBarrierImpl *impl = barrier->priv->impl;
 | 
			
		||||
 | 
			
		||||
  if (priv->display == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  dpy = priv->display->xdisplay;
 | 
			
		||||
 | 
			
		||||
  if (!meta_barrier_is_active (barrier))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  XFixesDestroyPointerBarrier (dpy, priv->xbarrier);
 | 
			
		||||
  g_hash_table_remove (priv->display->xids, &priv->xbarrier);
 | 
			
		||||
  priv->xbarrier = 0;
 | 
			
		||||
  if (impl)
 | 
			
		||||
    return META_BARRIER_IMPL_GET_CLASS (impl)->destroy (impl);
 | 
			
		||||
 | 
			
		||||
  g_object_unref (barrier);
 | 
			
		||||
}
 | 
			
		||||
@@ -330,71 +299,32 @@ meta_barrier_init (MetaBarrier *barrier)
 | 
			
		||||
  barrier->priv = G_TYPE_INSTANCE_GET_PRIVATE (barrier, META_TYPE_BARRIER, MetaBarrierPrivate);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_XI23
 | 
			
		||||
void
 | 
			
		||||
_meta_barrier_emit_hit_signal (MetaBarrier      *barrier,
 | 
			
		||||
                               MetaBarrierEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  g_signal_emit (barrier, obj_signals[HIT], 0, event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
_meta_barrier_emit_left_signal (MetaBarrier      *barrier,
 | 
			
		||||
                                MetaBarrierEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  g_signal_emit (barrier, obj_signals[LEFT], 0, event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_barrier_fire_event (MetaBarrier    *barrier,
 | 
			
		||||
                         XIBarrierEvent *xevent)
 | 
			
		||||
meta_barrier_impl_class_init (MetaBarrierImplClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierEvent *event = g_slice_new0 (MetaBarrierEvent);
 | 
			
		||||
 | 
			
		||||
  event->ref_count = 1;
 | 
			
		||||
  event->event_id = xevent->eventid;
 | 
			
		||||
  event->time = xevent->time;
 | 
			
		||||
  event->dt = xevent->dtime;
 | 
			
		||||
 | 
			
		||||
  event->x = xevent->root_x;
 | 
			
		||||
  event->y = xevent->root_y;
 | 
			
		||||
  event->dx = xevent->dx;
 | 
			
		||||
  event->dy = xevent->dy;
 | 
			
		||||
 | 
			
		||||
  event->released = (xevent->flags & XIBarrierPointerReleased) != 0;
 | 
			
		||||
  event->grabbed = (xevent->flags & XIBarrierDeviceIsGrabbed) != 0;
 | 
			
		||||
 | 
			
		||||
  switch (xevent->evtype)
 | 
			
		||||
    {
 | 
			
		||||
    case XI_BarrierHit:
 | 
			
		||||
      g_signal_emit (barrier, obj_signals[HIT], 0, event);
 | 
			
		||||
      break;
 | 
			
		||||
    case XI_BarrierLeave:
 | 
			
		||||
      g_signal_emit (barrier, obj_signals[LEFT], 0, event);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_barrier_event_unref (event);
 | 
			
		||||
  klass->is_active = NULL;
 | 
			
		||||
  klass->release = NULL;
 | 
			
		||||
  klass->destroy = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_display_process_barrier_event (MetaDisplay *display,
 | 
			
		||||
                                    XIEvent     *event)
 | 
			
		||||
static void
 | 
			
		||||
meta_barrier_impl_init (MetaBarrierImpl *impl)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrier *barrier;
 | 
			
		||||
  XIBarrierEvent *xev;
 | 
			
		||||
 | 
			
		||||
  if (event == NULL)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  switch (event->evtype)
 | 
			
		||||
    {
 | 
			
		||||
    case XI_BarrierHit:
 | 
			
		||||
    case XI_BarrierLeave:
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  xev = (XIBarrierEvent *) event;
 | 
			
		||||
  barrier = g_hash_table_lookup (display->xids, &xev->barrier);
 | 
			
		||||
  if (barrier != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      meta_barrier_fire_event (barrier, xev);
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
#endif /* HAVE_XI23 */
 | 
			
		||||
 | 
			
		||||
static MetaBarrierEvent *
 | 
			
		||||
meta_barrier_event_ref (MetaBarrierEvent *event)
 | 
			
		||||
@@ -406,7 +336,7 @@ meta_barrier_event_ref (MetaBarrierEvent *event)
 | 
			
		||||
  return event;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
void
 | 
			
		||||
meta_barrier_event_unref (MetaBarrierEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (event != NULL);
 | 
			
		||||
@@ -25,12 +25,18 @@
 | 
			
		||||
#include "meta-cursor.h"
 | 
			
		||||
 | 
			
		||||
#include <cogl/cogl.h>
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
#include <gbm.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  CoglTexture2D *texture;
 | 
			
		||||
  struct gbm_bo *bo;
 | 
			
		||||
  int hot_x, hot_y;
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
  struct gbm_bo *bo;
 | 
			
		||||
#endif
 | 
			
		||||
} MetaCursorImage;
 | 
			
		||||
 | 
			
		||||
struct _MetaCursorReference {
 | 
			
		||||
@@ -44,8 +50,10 @@ CoglTexture *meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor
 | 
			
		||||
                                                     int                 *hot_x,
 | 
			
		||||
                                                     int                 *hot_y);
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
struct gbm_bo *meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
 | 
			
		||||
                                                 int                 *hot_x,
 | 
			
		||||
                                                 int                 *hot_y);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* META_CURSOR_PRIVATE_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -30,8 +30,6 @@
 | 
			
		||||
#include <meta/screen.h>
 | 
			
		||||
#include "meta-cursor.h"
 | 
			
		||||
 | 
			
		||||
#include <gbm.h>
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_CURSOR_RENDERER            (meta_cursor_renderer_get_type ())
 | 
			
		||||
#define META_CURSOR_RENDERER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_RENDERER, MetaCursorRenderer))
 | 
			
		||||
#define META_CURSOR_RENDERER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_CURSOR_RENDERER, MetaCursorRendererClass))
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,9 @@
 | 
			
		||||
 *                     pointer abstraction"
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <config.h>
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "meta-cursor-tracker-private.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <meta/main.h>
 | 
			
		||||
#include <meta/util.h>
 | 
			
		||||
@@ -38,11 +40,10 @@
 | 
			
		||||
 | 
			
		||||
#include <gdk/gdk.h>
 | 
			
		||||
#include <gdk/gdkx.h>
 | 
			
		||||
#include <X11/extensions/Xfixes.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-backend-private.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-cursor-private.h"
 | 
			
		||||
#include "meta-cursor-tracker-private.h"
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -55,9 +55,13 @@ meta_cursor_reference_ref (MetaCursorReference *self)
 | 
			
		||||
static void
 | 
			
		||||
meta_cursor_image_free (MetaCursorImage *image)
 | 
			
		||||
{
 | 
			
		||||
  cogl_object_unref (image->texture);
 | 
			
		||||
  if (image->texture)
 | 
			
		||||
    cogl_object_unref (image->texture);
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
  if (image->bo)
 | 
			
		||||
    gbm_bo_destroy (image->bo);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -139,70 +143,90 @@ load_cursor_on_client (MetaCursor cursor)
 | 
			
		||||
                                  meta_prefs_get_cursor_size ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
static void
 | 
			
		||||
get_hardware_cursor_size (uint64_t *cursor_width, uint64_t *cursor_height)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackend *meta_backend = meta_get_backend ();
 | 
			
		||||
  MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
 | 
			
		||||
 | 
			
		||||
  if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
 | 
			
		||||
    {
 | 
			
		||||
      meta_cursor_renderer_native_get_cursor_size (META_CURSOR_RENDERER_NATIVE (renderer), cursor_width, cursor_height);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_assert_not_reached ();
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
static void
 | 
			
		||||
meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
 | 
			
		||||
                                   MetaCursorImage   *image,
 | 
			
		||||
                                   uint8_t           *pixels,
 | 
			
		||||
                                   int                width,
 | 
			
		||||
                                   int                height,
 | 
			
		||||
                                   uint               width,
 | 
			
		||||
                                   uint               height,
 | 
			
		||||
                                   int                rowstride,
 | 
			
		||||
                                   uint32_t           gbm_format)
 | 
			
		||||
{
 | 
			
		||||
  if (width > 64 || height > 64)
 | 
			
		||||
  uint64_t cursor_width, cursor_height;
 | 
			
		||||
  get_hardware_cursor_size (&cursor_width, &cursor_height);
 | 
			
		||||
 | 
			
		||||
  if (width > cursor_width || height > cursor_height)
 | 
			
		||||
    {
 | 
			
		||||
      meta_warning ("Invalid theme cursor size (must be at most 64x64)\n");
 | 
			
		||||
      meta_warning ("Invalid theme cursor size (must be at most %ux%u)\n",
 | 
			
		||||
                    (unsigned int)cursor_width, (unsigned int)cursor_height);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (gbm_device_is_format_supported (gbm, gbm_format,
 | 
			
		||||
                                      GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE))
 | 
			
		||||
                                      GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE))
 | 
			
		||||
    {
 | 
			
		||||
      uint8_t buf[4 * 64 * 64];
 | 
			
		||||
      int i;
 | 
			
		||||
      uint8_t buf[4 * cursor_width * cursor_height];
 | 
			
		||||
      uint i;
 | 
			
		||||
 | 
			
		||||
      image->bo = gbm_bo_create (gbm, 64, 64,
 | 
			
		||||
                                 gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
 | 
			
		||||
      image->bo = gbm_bo_create (gbm, cursor_width, cursor_height,
 | 
			
		||||
                                 gbm_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
 | 
			
		||||
 | 
			
		||||
      memset (buf, 0, sizeof(buf));
 | 
			
		||||
      for (i = 0; i < height; i++)
 | 
			
		||||
        memcpy (buf + i * 4 * 64, pixels + i * rowstride, width * 4);
 | 
			
		||||
        memcpy (buf + i * 4 * cursor_width, pixels + i * rowstride, width * 4);
 | 
			
		||||
 | 
			
		||||
      gbm_bo_write (image->bo, buf, 64 * 64 * 4);
 | 
			
		||||
      gbm_bo_write (image->bo, buf, cursor_width * cursor_height * 4);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    meta_warning ("HW cursor for format %d not supported\n", gbm_format);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
static struct gbm_device *
 | 
			
		||||
get_gbm_device (void)
 | 
			
		||||
{
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
  MetaBackend *meta_backend = meta_get_backend ();
 | 
			
		||||
  MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
 | 
			
		||||
 | 
			
		||||
  if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
 | 
			
		||||
    return meta_cursor_renderer_native_get_gbm_device (META_CURSOR_RENDERER_NATIVE (renderer));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  return NULL;
 | 
			
		||||
  else
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_cursor_image_load_from_xcursor_image (MetaCursorImage   *image,
 | 
			
		||||
                                           XcursorImage      *xc_image)
 | 
			
		||||
{
 | 
			
		||||
  int width, height, rowstride;
 | 
			
		||||
  uint width, height, rowstride;
 | 
			
		||||
  CoglPixelFormat cogl_format;
 | 
			
		||||
  uint32_t gbm_format;
 | 
			
		||||
  ClutterBackend *clutter_backend;
 | 
			
		||||
  CoglContext *cogl_context;
 | 
			
		||||
  struct gbm_device *gbm;
 | 
			
		||||
 | 
			
		||||
  width           = xc_image->width;
 | 
			
		||||
  height          = xc_image->height;
 | 
			
		||||
  rowstride       = width * 4;
 | 
			
		||||
 | 
			
		||||
  gbm_format = GBM_FORMAT_ARGB8888;
 | 
			
		||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
 | 
			
		||||
  cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
 | 
			
		||||
#else
 | 
			
		||||
@@ -221,31 +245,41 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage   *image,
 | 
			
		||||
                                                  (uint8_t *) xc_image->pixels,
 | 
			
		||||
                                                  NULL);
 | 
			
		||||
 | 
			
		||||
  gbm = get_gbm_device ();
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
  struct gbm_device *gbm = get_gbm_device ();
 | 
			
		||||
  if (gbm)
 | 
			
		||||
    meta_cursor_image_load_gbm_buffer (gbm,
 | 
			
		||||
                                       image,
 | 
			
		||||
                                       (uint8_t *) xc_image->pixels,
 | 
			
		||||
                                       width, height, rowstride,
 | 
			
		||||
                                       gbm_format);
 | 
			
		||||
                                       GBM_FORMAT_ARGB8888);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
load_cursor_image (MetaCursorReference *cursor)
 | 
			
		||||
{
 | 
			
		||||
  XcursorImage *image;
 | 
			
		||||
 | 
			
		||||
  /* Either cursors are loaded from X cursors or buffers. Since
 | 
			
		||||
   * buffers are converted over immediately, we can make sure to
 | 
			
		||||
   * load this directly. */
 | 
			
		||||
  g_assert (cursor->cursor != META_CURSOR_NONE);
 | 
			
		||||
 | 
			
		||||
  image = load_cursor_on_client (cursor->cursor);
 | 
			
		||||
  if (!image)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  meta_cursor_image_load_from_xcursor_image (&cursor->image, image);
 | 
			
		||||
  XcursorImageDestroy (image);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaCursorReference *
 | 
			
		||||
meta_cursor_reference_from_theme (MetaCursor cursor)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorReference *self;
 | 
			
		||||
  XcursorImage *image;
 | 
			
		||||
 | 
			
		||||
  image = load_cursor_on_client (cursor);
 | 
			
		||||
  if (!image)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  self = g_slice_new0 (MetaCursorReference);
 | 
			
		||||
  MetaCursorReference *self = g_slice_new0 (MetaCursorReference);
 | 
			
		||||
  self->ref_count = 1;
 | 
			
		||||
  self->cursor = cursor;
 | 
			
		||||
  meta_cursor_image_load_from_xcursor_image (&self->image, image);
 | 
			
		||||
 | 
			
		||||
  XcursorImageDestroy (image);
 | 
			
		||||
  return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -256,13 +290,8 @@ meta_cursor_image_load_from_buffer (MetaCursorImage    *image,
 | 
			
		||||
                                    int                 hot_x,
 | 
			
		||||
                                    int                 hot_y)
 | 
			
		||||
{
 | 
			
		||||
  struct gbm_device *gbm = get_gbm_device ();
 | 
			
		||||
 | 
			
		||||
  ClutterBackend *backend;
 | 
			
		||||
  CoglContext *cogl_context;
 | 
			
		||||
  struct wl_shm_buffer *shm_buffer;
 | 
			
		||||
  uint32_t gbm_format;
 | 
			
		||||
  int width, height;
 | 
			
		||||
 | 
			
		||||
  image->hot_x = hot_x;
 | 
			
		||||
  image->hot_y = hot_y;
 | 
			
		||||
@@ -272,16 +301,24 @@ meta_cursor_image_load_from_buffer (MetaCursorImage    *image,
 | 
			
		||||
 | 
			
		||||
  image->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
 | 
			
		||||
 | 
			
		||||
  width = cogl_texture_get_width (COGL_TEXTURE (image->texture));
 | 
			
		||||
  height = cogl_texture_get_height (COGL_TEXTURE (image->texture));
 | 
			
		||||
 | 
			
		||||
  shm_buffer = wl_shm_buffer_get (buffer);
 | 
			
		||||
  if (shm_buffer)
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
  struct gbm_device *gbm = get_gbm_device ();
 | 
			
		||||
  if (gbm)
 | 
			
		||||
    {
 | 
			
		||||
      if (gbm)
 | 
			
		||||
      uint32_t gbm_format;
 | 
			
		||||
      uint64_t cursor_width, cursor_height;
 | 
			
		||||
      uint width, height;
 | 
			
		||||
 | 
			
		||||
      width = cogl_texture_get_width (COGL_TEXTURE (image->texture));
 | 
			
		||||
      height = cogl_texture_get_height (COGL_TEXTURE (image->texture));
 | 
			
		||||
 | 
			
		||||
      struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (buffer);
 | 
			
		||||
      if (shm_buffer)
 | 
			
		||||
        {
 | 
			
		||||
          int rowstride = wl_shm_buffer_get_stride (shm_buffer);
 | 
			
		||||
 | 
			
		||||
          wl_shm_buffer_begin_access (shm_buffer);
 | 
			
		||||
 | 
			
		||||
          switch (wl_shm_buffer_get_format (shm_buffer))
 | 
			
		||||
            {
 | 
			
		||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
 | 
			
		||||
@@ -309,30 +346,31 @@ meta_cursor_image_load_from_buffer (MetaCursorImage    *image,
 | 
			
		||||
                                             (uint8_t *) wl_shm_buffer_get_data (shm_buffer),
 | 
			
		||||
                                             width, height, rowstride,
 | 
			
		||||
                                             gbm_format);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      /* HW cursors must be 64x64, but 64x64 is huge, and no cursor theme actually uses
 | 
			
		||||
         that, so themed cursors must be padded with transparent pixels to fill the
 | 
			
		||||
         overlay. This is trivial if we have CPU access to the data, but it's not
 | 
			
		||||
         possible if the buffer is in GPU memory (and possibly tiled too), so if we
 | 
			
		||||
         don't get the right size, we fallback to GL.
 | 
			
		||||
      */
 | 
			
		||||
      if (width != 64 || height != 64)
 | 
			
		||||
        {
 | 
			
		||||
          meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (gbm)
 | 
			
		||||
          wl_shm_buffer_end_access (shm_buffer);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          image->bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER,
 | 
			
		||||
                                     buffer, GBM_BO_USE_CURSOR_64X64);
 | 
			
		||||
          /* HW cursors have a predefined size (at least 64x64), which usually is bigger than cursor theme
 | 
			
		||||
             size, so themed cursors must be padded with transparent pixels to fill the
 | 
			
		||||
             overlay. This is trivial if we have CPU access to the data, but it's not
 | 
			
		||||
             possible if the buffer is in GPU memory (and possibly tiled too), so if we
 | 
			
		||||
             don't get the right size, we fallback to GL.
 | 
			
		||||
          */
 | 
			
		||||
          get_hardware_cursor_size (&cursor_width, &cursor_height);
 | 
			
		||||
 | 
			
		||||
          if (width != cursor_width || height != cursor_height)
 | 
			
		||||
            {
 | 
			
		||||
              meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
 | 
			
		||||
              return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          image->bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER, buffer, GBM_BO_USE_CURSOR);
 | 
			
		||||
          if (!image->bo)
 | 
			
		||||
            meta_warning ("Importing HW cursor from wl_buffer failed\n");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaCursorReference *
 | 
			
		||||
@@ -355,24 +393,33 @@ meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor,
 | 
			
		||||
                                        int                 *hot_x,
 | 
			
		||||
                                        int                 *hot_y)
 | 
			
		||||
{
 | 
			
		||||
  if (!cursor->image.texture)
 | 
			
		||||
    load_cursor_image (cursor);
 | 
			
		||||
 | 
			
		||||
  if (hot_x)
 | 
			
		||||
    *hot_x = cursor->image.hot_x;
 | 
			
		||||
  if (hot_y)
 | 
			
		||||
    *hot_y = cursor->image.hot_y;
 | 
			
		||||
 | 
			
		||||
  return COGL_TEXTURE (cursor->image.texture);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
struct gbm_bo *
 | 
			
		||||
meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
 | 
			
		||||
                                  int                 *hot_x,
 | 
			
		||||
                                  int                 *hot_y)
 | 
			
		||||
{
 | 
			
		||||
  if (!cursor->image.bo)
 | 
			
		||||
    load_cursor_image (cursor);
 | 
			
		||||
 | 
			
		||||
  if (hot_x)
 | 
			
		||||
    *hot_x = cursor->image.hot_x;
 | 
			
		||||
  if (hot_y)
 | 
			
		||||
    *hot_y = cursor->image.hot_y;
 | 
			
		||||
  return cursor->image.bo;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
MetaCursor
 | 
			
		||||
meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										83
									
								
								src/backends/meta-input-settings-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								src/backends/meta-input-settings-private.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2014 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 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Carlos Garnacho <carlosg@gnome.org>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef META_INPUT_SETTINGS_PRIVATE_H
 | 
			
		||||
#define META_INPUT_SETTINGS_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include "display-private.h"
 | 
			
		||||
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_INPUT_SETTINGS             (meta_input_settings_get_type ())
 | 
			
		||||
#define META_INPUT_SETTINGS(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_INPUT_SETTINGS, MetaInputSettings))
 | 
			
		||||
#define META_INPUT_SETTINGS_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_INPUT_SETTINGS, MetaInputSettingsClass))
 | 
			
		||||
#define META_IS_INPUT_SETTINGS(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_INPUT_SETTINGS))
 | 
			
		||||
#define META_IS_INPUT_SETTINGS_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_INPUT_SETTINGS))
 | 
			
		||||
#define META_INPUT_SETTINGS_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_INPUT_SETTINGS, MetaInputSettingsClass))
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaInputSettings MetaInputSettings;
 | 
			
		||||
typedef struct _MetaInputSettingsClass MetaInputSettingsClass;
 | 
			
		||||
 | 
			
		||||
struct _MetaInputSettings
 | 
			
		||||
{
 | 
			
		||||
  GObject parent_instance;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaInputSettingsClass
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass parent_class;
 | 
			
		||||
 | 
			
		||||
  void (* set_send_events)   (MetaInputSettings        *settings,
 | 
			
		||||
                              ClutterInputDevice       *device,
 | 
			
		||||
                              GDesktopDeviceSendEvents  mode);
 | 
			
		||||
  void (* set_matrix)        (MetaInputSettings  *settings,
 | 
			
		||||
                              ClutterInputDevice *device,
 | 
			
		||||
                              gfloat              matrix[6]);
 | 
			
		||||
  void (* set_speed)         (MetaInputSettings  *settings,
 | 
			
		||||
                              ClutterInputDevice *device,
 | 
			
		||||
                              gdouble             speed);
 | 
			
		||||
  void (* set_left_handed)   (MetaInputSettings  *settings,
 | 
			
		||||
                              ClutterInputDevice *device,
 | 
			
		||||
                              gboolean            enabled);
 | 
			
		||||
  void (* set_tap_enabled)   (MetaInputSettings  *settings,
 | 
			
		||||
                              ClutterInputDevice *device,
 | 
			
		||||
                              gboolean            enabled);
 | 
			
		||||
  void (* set_invert_scroll) (MetaInputSettings  *settings,
 | 
			
		||||
                              ClutterInputDevice *device,
 | 
			
		||||
                              gboolean            inverted);
 | 
			
		||||
  void (* set_scroll_method) (MetaInputSettings            *settings,
 | 
			
		||||
                              ClutterInputDevice           *device,
 | 
			
		||||
                              GDesktopTouchpadScrollMethod  mode);
 | 
			
		||||
  void (* set_scroll_button) (MetaInputSettings  *settings,
 | 
			
		||||
                              ClutterInputDevice *device,
 | 
			
		||||
                              guint               button);
 | 
			
		||||
 | 
			
		||||
  void (* set_keyboard_repeat) (MetaInputSettings *settings,
 | 
			
		||||
                                gboolean           repeat,
 | 
			
		||||
                                guint              delay,
 | 
			
		||||
                                guint              interval);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType meta_input_settings_get_type (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
MetaInputSettings * meta_input_settings_create (void);
 | 
			
		||||
 | 
			
		||||
#endif /* META_INPUT_SETTINGS_PRIVATE_H */
 | 
			
		||||
							
								
								
									
										838
									
								
								src/backends/meta-input-settings.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										838
									
								
								src/backends/meta-input-settings.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,838 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2014 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 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Carlos Garnacho <carlosg@gnome.org>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SECTION:input-settings
 | 
			
		||||
 * @title: MetaInputSettings
 | 
			
		||||
 * @short_description: Mutter input device configuration
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-backend-private.h"
 | 
			
		||||
#include "meta-input-settings-private.h"
 | 
			
		||||
#include "x11/meta-input-settings-x11.h"
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
#include "native/meta-backend-native.h"
 | 
			
		||||
#include "native/meta-input-settings-native.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <meta/util.h>
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaInputSettingsPrivate MetaInputSettingsPrivate;
 | 
			
		||||
typedef struct _DeviceMappingInfo DeviceMappingInfo;
 | 
			
		||||
 | 
			
		||||
struct _DeviceMappingInfo
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettings *input_settings;
 | 
			
		||||
  ClutterInputDevice *device;
 | 
			
		||||
  GSettings *settings;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaInputSettingsPrivate
 | 
			
		||||
{
 | 
			
		||||
  ClutterDeviceManager *device_manager;
 | 
			
		||||
  MetaMonitorManager *monitor_manager;
 | 
			
		||||
  guint monitors_changed_id;
 | 
			
		||||
 | 
			
		||||
  GSettings *mouse_settings;
 | 
			
		||||
  GSettings *touchpad_settings;
 | 
			
		||||
  GSettings *trackball_settings;
 | 
			
		||||
  GSettings *keyboard_settings;
 | 
			
		||||
 | 
			
		||||
  GHashTable *mappable_devices;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef void (*ConfigBoolFunc)   (MetaInputSettings  *input_settings,
 | 
			
		||||
                                  ClutterInputDevice *device,
 | 
			
		||||
                                  gboolean            setting);
 | 
			
		||||
typedef void (*ConfigDoubleFunc) (MetaInputSettings  *input_settings,
 | 
			
		||||
                                  ClutterInputDevice *device,
 | 
			
		||||
                                  gdouble             value);
 | 
			
		||||
typedef void (*ConfigUintFunc)   (MetaInputSettings  *input_settings,
 | 
			
		||||
                                  ClutterInputDevice *device,
 | 
			
		||||
                                  guint               value);
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaInputSettings, meta_input_settings, G_TYPE_OBJECT)
 | 
			
		||||
 | 
			
		||||
static GSList *
 | 
			
		||||
meta_input_settings_get_devices (MetaInputSettings      *settings,
 | 
			
		||||
                                 ClutterInputDeviceType  type)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  const GSList *devices;
 | 
			
		||||
  GSList *list = NULL;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (settings);
 | 
			
		||||
  devices = clutter_device_manager_peek_devices (priv->device_manager);
 | 
			
		||||
 | 
			
		||||
  while (devices)
 | 
			
		||||
    {
 | 
			
		||||
      ClutterInputDevice *device = devices->data;
 | 
			
		||||
 | 
			
		||||
      if (clutter_input_device_get_device_type (device) == type &&
 | 
			
		||||
          clutter_input_device_get_device_mode (device) != CLUTTER_INPUT_MODE_MASTER)
 | 
			
		||||
        list = g_slist_prepend (list, device);
 | 
			
		||||
 | 
			
		||||
      devices = devices->next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return list;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_dispose (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettings *settings = META_INPUT_SETTINGS (object);
 | 
			
		||||
  MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (settings);
 | 
			
		||||
 | 
			
		||||
  g_clear_object (&priv->mouse_settings);
 | 
			
		||||
  g_clear_object (&priv->touchpad_settings);
 | 
			
		||||
  g_clear_object (&priv->trackball_settings);
 | 
			
		||||
  g_clear_object (&priv->keyboard_settings);
 | 
			
		||||
  g_clear_pointer (&priv->mappable_devices, g_hash_table_unref);
 | 
			
		||||
 | 
			
		||||
  if (priv->monitors_changed_id && priv->monitor_manager)
 | 
			
		||||
    {
 | 
			
		||||
      g_signal_handler_disconnect (priv->monitor_manager,
 | 
			
		||||
                                   priv->monitors_changed_id);
 | 
			
		||||
      priv->monitors_changed_id = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_clear_object (&priv->monitor_manager);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_input_settings_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
settings_device_set_bool_setting (MetaInputSettings  *input_settings,
 | 
			
		||||
                                  ClutterInputDevice *device,
 | 
			
		||||
                                  ConfigBoolFunc      func,
 | 
			
		||||
                                  gboolean            enabled)
 | 
			
		||||
{
 | 
			
		||||
  func (input_settings, device, enabled);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
settings_set_bool_setting (MetaInputSettings      *input_settings,
 | 
			
		||||
                           ClutterInputDeviceType  type,
 | 
			
		||||
                           ConfigBoolFunc          func,
 | 
			
		||||
                           gboolean                enabled)
 | 
			
		||||
{
 | 
			
		||||
  GSList *devices, *d;
 | 
			
		||||
 | 
			
		||||
  devices = meta_input_settings_get_devices (input_settings, type);
 | 
			
		||||
 | 
			
		||||
  for (d = devices; d; d = d->next)
 | 
			
		||||
    settings_device_set_bool_setting (input_settings, d->data, func, enabled);
 | 
			
		||||
 | 
			
		||||
  g_slist_free (devices);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
settings_device_set_double_setting (MetaInputSettings  *input_settings,
 | 
			
		||||
                                    ClutterInputDevice *device,
 | 
			
		||||
                                    ConfigDoubleFunc    func,
 | 
			
		||||
                                    gdouble             value)
 | 
			
		||||
{
 | 
			
		||||
  func (input_settings, device, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
settings_set_double_setting (MetaInputSettings      *input_settings,
 | 
			
		||||
                             ClutterInputDeviceType  type,
 | 
			
		||||
                             ConfigDoubleFunc        func,
 | 
			
		||||
                             gdouble                 value)
 | 
			
		||||
{
 | 
			
		||||
  GSList *devices, *d;
 | 
			
		||||
 | 
			
		||||
  devices = meta_input_settings_get_devices (input_settings, type);
 | 
			
		||||
 | 
			
		||||
  for (d = devices; d; d = d->next)
 | 
			
		||||
    settings_device_set_double_setting (input_settings, d->data, func, value);
 | 
			
		||||
 | 
			
		||||
  g_slist_free (devices);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
settings_device_set_uint_setting (MetaInputSettings  *input_settings,
 | 
			
		||||
                                  ClutterInputDevice *device,
 | 
			
		||||
                                  ConfigUintFunc      func,
 | 
			
		||||
                                  guint               value)
 | 
			
		||||
{
 | 
			
		||||
  (func) (input_settings, device, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
settings_set_uint_setting (MetaInputSettings      *input_settings,
 | 
			
		||||
                           ClutterInputDeviceType  type,
 | 
			
		||||
                           ConfigUintFunc          func,
 | 
			
		||||
                           guint                   value)
 | 
			
		||||
{
 | 
			
		||||
  GSList *devices, *d;
 | 
			
		||||
 | 
			
		||||
  devices = meta_input_settings_get_devices (input_settings, type);
 | 
			
		||||
 | 
			
		||||
  for (d = devices; d; d = d->next)
 | 
			
		||||
    settings_device_set_uint_setting (input_settings, d->data, func, value);
 | 
			
		||||
 | 
			
		||||
  g_slist_free (devices);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_touchpad_left_handed (MetaInputSettings  *input_settings,
 | 
			
		||||
                             ClutterInputDevice *device)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsClass *input_settings_class;
 | 
			
		||||
  GDesktopTouchpadHandedness handedness;
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  gboolean enabled = FALSE;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
 | 
			
		||||
  handedness = g_settings_get_enum (priv->touchpad_settings, "left-handed");
 | 
			
		||||
 | 
			
		||||
  switch (handedness)
 | 
			
		||||
    {
 | 
			
		||||
    case G_DESKTOP_TOUCHPAD_HANDEDNESS_RIGHT:
 | 
			
		||||
      enabled = FALSE;
 | 
			
		||||
      break;
 | 
			
		||||
    case G_DESKTOP_TOUCHPAD_HANDEDNESS_LEFT:
 | 
			
		||||
      enabled = TRUE;
 | 
			
		||||
      break;
 | 
			
		||||
    case G_DESKTOP_TOUCHPAD_HANDEDNESS_MOUSE:
 | 
			
		||||
      enabled = g_settings_get_boolean (priv->mouse_settings, "left-handed");
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (device)
 | 
			
		||||
    {
 | 
			
		||||
      g_assert (clutter_input_device_get_device_type (device) == CLUTTER_TOUCHPAD_DEVICE);
 | 
			
		||||
      settings_device_set_bool_setting (input_settings, device,
 | 
			
		||||
                                        input_settings_class->set_left_handed,
 | 
			
		||||
                                        enabled);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
 | 
			
		||||
                                 input_settings_class->set_left_handed,
 | 
			
		||||
                                 enabled);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_mouse_left_handed (MetaInputSettings  *input_settings,
 | 
			
		||||
                          ClutterInputDevice *device)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsClass *input_settings_class;
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  gboolean enabled;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
 | 
			
		||||
  enabled = g_settings_get_boolean (priv->mouse_settings, "left-handed");
 | 
			
		||||
 | 
			
		||||
  if (device)
 | 
			
		||||
    {
 | 
			
		||||
      g_assert (clutter_input_device_get_device_type (device) == CLUTTER_POINTER_DEVICE);
 | 
			
		||||
      settings_device_set_bool_setting (input_settings, device,
 | 
			
		||||
                                        input_settings_class->set_left_handed,
 | 
			
		||||
                                        enabled);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      GDesktopTouchpadHandedness touchpad_handedness;
 | 
			
		||||
 | 
			
		||||
      settings_set_bool_setting (input_settings, CLUTTER_POINTER_DEVICE,
 | 
			
		||||
                                 input_settings_class->set_left_handed,
 | 
			
		||||
                                 enabled);
 | 
			
		||||
 | 
			
		||||
      touchpad_handedness = g_settings_get_enum (priv->touchpad_settings,
 | 
			
		||||
                                                 "left-handed");
 | 
			
		||||
 | 
			
		||||
      /* Also update touchpads if they're following mouse settings */
 | 
			
		||||
      if (touchpad_handedness == G_DESKTOP_TOUCHPAD_HANDEDNESS_MOUSE)
 | 
			
		||||
        update_touchpad_left_handed (input_settings, NULL);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_device_speed (MetaInputSettings      *input_settings,
 | 
			
		||||
                     GSettings              *settings,
 | 
			
		||||
                     ClutterInputDevice     *device,
 | 
			
		||||
                     ClutterInputDeviceType  type)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsClass *input_settings_class;
 | 
			
		||||
  gdouble speed;
 | 
			
		||||
 | 
			
		||||
  input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
 | 
			
		||||
  speed = g_settings_get_double (settings, "speed");
 | 
			
		||||
 | 
			
		||||
  if (device)
 | 
			
		||||
    settings_device_set_double_setting (input_settings, device,
 | 
			
		||||
                                        input_settings_class->set_speed,
 | 
			
		||||
                                        speed);
 | 
			
		||||
  else
 | 
			
		||||
    settings_set_double_setting (input_settings, type,
 | 
			
		||||
                                 input_settings_class->set_speed,
 | 
			
		||||
                                 speed);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_device_natural_scroll (MetaInputSettings      *input_settings,
 | 
			
		||||
                              GSettings              *settings,
 | 
			
		||||
                              ClutterInputDevice     *device,
 | 
			
		||||
                              ClutterInputDeviceType  type)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsClass *input_settings_class;
 | 
			
		||||
  gboolean enabled;
 | 
			
		||||
 | 
			
		||||
  input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
 | 
			
		||||
  enabled = g_settings_get_boolean (settings, "natural-scroll");
 | 
			
		||||
 | 
			
		||||
  if (device)
 | 
			
		||||
    {
 | 
			
		||||
      settings_device_set_bool_setting (input_settings, device,
 | 
			
		||||
                                        input_settings_class->set_invert_scroll,
 | 
			
		||||
                                        enabled);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      settings_set_bool_setting (input_settings, type,
 | 
			
		||||
                                 input_settings_class->set_invert_scroll,
 | 
			
		||||
                                 enabled);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_touchpad_tap_enabled (MetaInputSettings  *input_settings,
 | 
			
		||||
                             ClutterInputDevice *device)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsClass *input_settings_class;
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  gboolean enabled;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
 | 
			
		||||
  enabled = g_settings_get_boolean (priv->touchpad_settings, "tap-to-click");
 | 
			
		||||
 | 
			
		||||
  if (device)
 | 
			
		||||
    {
 | 
			
		||||
      settings_device_set_bool_setting (input_settings, device,
 | 
			
		||||
                                        input_settings_class->set_tap_enabled,
 | 
			
		||||
                                        enabled);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
 | 
			
		||||
                                 input_settings_class->set_tap_enabled,
 | 
			
		||||
                                 enabled);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_touchpad_scroll_method (MetaInputSettings *input_settings,
 | 
			
		||||
                               ClutterInputDevice *device)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsClass *input_settings_class;
 | 
			
		||||
  GDesktopTouchpadScrollMethod method;
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
 | 
			
		||||
  method = g_settings_get_enum (priv->touchpad_settings, "scroll-method");
 | 
			
		||||
 | 
			
		||||
  if (device)
 | 
			
		||||
    {
 | 
			
		||||
      settings_device_set_uint_setting (input_settings, device,
 | 
			
		||||
                                        input_settings_class->set_scroll_method,
 | 
			
		||||
                                        method);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      settings_set_uint_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
 | 
			
		||||
                                 (ConfigUintFunc) input_settings_class->set_scroll_method,
 | 
			
		||||
                                 method);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_touchpad_send_events (MetaInputSettings  *input_settings,
 | 
			
		||||
                             ClutterInputDevice *device)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsClass *input_settings_class;
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  GDesktopDeviceSendEvents mode;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
 | 
			
		||||
  mode = g_settings_get_enum (priv->touchpad_settings, "send-events");
 | 
			
		||||
 | 
			
		||||
  if (device)
 | 
			
		||||
    {
 | 
			
		||||
      settings_device_set_uint_setting (input_settings, device,
 | 
			
		||||
                                        input_settings_class->set_send_events,
 | 
			
		||||
                                        mode);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      settings_set_uint_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
 | 
			
		||||
                                 input_settings_class->set_send_events,
 | 
			
		||||
                                 mode);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
device_is_trackball (ClutterInputDevice *device)
 | 
			
		||||
{
 | 
			
		||||
  gboolean is_trackball;
 | 
			
		||||
  char *name;
 | 
			
		||||
 | 
			
		||||
  if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  name = g_ascii_strdown (clutter_input_device_get_device_name (device), -1);
 | 
			
		||||
  is_trackball = strstr (name, "trackball") != NULL;
 | 
			
		||||
  g_free (name);
 | 
			
		||||
 | 
			
		||||
  return is_trackball;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_trackball_scroll_button (MetaInputSettings  *input_settings,
 | 
			
		||||
                                ClutterInputDevice *device)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsClass *input_settings_class;
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  guint button;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
 | 
			
		||||
  button = g_settings_get_uint (priv->trackball_settings, "scroll-wheel-emulation-button");
 | 
			
		||||
 | 
			
		||||
  if (device && device_is_trackball (device))
 | 
			
		||||
    {
 | 
			
		||||
      input_settings_class->set_scroll_button (input_settings, device, button);
 | 
			
		||||
    }
 | 
			
		||||
  else if (!device)
 | 
			
		||||
    {
 | 
			
		||||
      MetaInputSettingsPrivate *priv;
 | 
			
		||||
      const GSList *devices;
 | 
			
		||||
 | 
			
		||||
      priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
      devices = clutter_device_manager_peek_devices (priv->device_manager);
 | 
			
		||||
 | 
			
		||||
      while (devices)
 | 
			
		||||
        {
 | 
			
		||||
          ClutterInputDevice *device = devices->data;
 | 
			
		||||
 | 
			
		||||
          if (device_is_trackball (device))
 | 
			
		||||
            input_settings_class->set_scroll_button (input_settings, device, button);
 | 
			
		||||
 | 
			
		||||
          devices = devices->next;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_keyboard_repeat (MetaInputSettings *input_settings)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsClass *input_settings_class;
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  guint delay, interval;
 | 
			
		||||
  gboolean repeat;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  repeat = g_settings_get_boolean (priv->keyboard_settings, "repeat");
 | 
			
		||||
  delay = g_settings_get_uint (priv->keyboard_settings, "delay");
 | 
			
		||||
  interval = g_settings_get_uint (priv->keyboard_settings, "repeat-interval");
 | 
			
		||||
 | 
			
		||||
  input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
 | 
			
		||||
  input_settings_class->set_keyboard_repeat (input_settings,
 | 
			
		||||
                                             repeat, delay, interval);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaOutput *
 | 
			
		||||
meta_input_settings_find_output (MetaInputSettings  *input_settings,
 | 
			
		||||
                                 GSettings          *settings,
 | 
			
		||||
                                 ClutterInputDevice *device)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  guint n_values, n_outputs, i;
 | 
			
		||||
  MetaOutput *outputs;
 | 
			
		||||
  gchar **edid;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  edid = g_settings_get_strv (settings, "display");
 | 
			
		||||
  n_values = g_strv_length (edid);
 | 
			
		||||
 | 
			
		||||
  if (n_values != 3)
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("EDID configuration for device '%s' "
 | 
			
		||||
                 "is incorrect, must have 3 values",
 | 
			
		||||
                 clutter_input_device_get_device_name (device));
 | 
			
		||||
      return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!*edid[0] && !*edid[1] && !*edid[2])
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  outputs = meta_monitor_manager_get_outputs (priv->monitor_manager,
 | 
			
		||||
                                              &n_outputs);
 | 
			
		||||
  for (i = 0; i < n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      if (g_strcmp0 (outputs[i].vendor, edid[0]) == 0 &&
 | 
			
		||||
          g_strcmp0 (outputs[i].product, edid[1]) == 0 &&
 | 
			
		||||
          g_strcmp0 (outputs[i].serial, edid[2]) == 0)
 | 
			
		||||
        return &outputs[i];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_device_display (MetaInputSettings  *input_settings,
 | 
			
		||||
                       GSettings          *settings,
 | 
			
		||||
                       ClutterInputDevice *device)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsClass *input_settings_class;
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  gfloat matrix[6] = { 1, 0, 0, 0, 1, 0 };
 | 
			
		||||
  MetaOutput *output;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
 | 
			
		||||
  output = meta_input_settings_find_output (input_settings, settings, device);
 | 
			
		||||
 | 
			
		||||
  if (output)
 | 
			
		||||
    meta_monitor_manager_get_monitor_matrix (priv->monitor_manager,
 | 
			
		||||
                                             output, matrix);
 | 
			
		||||
 | 
			
		||||
  input_settings_class->set_matrix (input_settings, device, matrix);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_changed_cb (GSettings  *settings,
 | 
			
		||||
                                const char *key,
 | 
			
		||||
                                gpointer    user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettings *input_settings = META_INPUT_SETTINGS (user_data);
 | 
			
		||||
  MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
 | 
			
		||||
  if (settings == priv->mouse_settings)
 | 
			
		||||
    {
 | 
			
		||||
      if (strcmp (key, "left-handed") == 0)
 | 
			
		||||
        update_mouse_left_handed (input_settings, NULL);
 | 
			
		||||
      else if (strcmp (key, "speed") == 0)
 | 
			
		||||
        update_device_speed (input_settings, settings, NULL,
 | 
			
		||||
                             CLUTTER_POINTER_DEVICE);
 | 
			
		||||
      else if (strcmp (key, "natural-scroll") == 0)
 | 
			
		||||
        update_device_natural_scroll (input_settings, settings,
 | 
			
		||||
                                      NULL, CLUTTER_POINTER_DEVICE);
 | 
			
		||||
    }
 | 
			
		||||
  else if (settings == priv->touchpad_settings)
 | 
			
		||||
    {
 | 
			
		||||
      if (strcmp (key, "left-handed") == 0)
 | 
			
		||||
        update_touchpad_left_handed (input_settings, NULL);
 | 
			
		||||
      else if (strcmp (key, "speed") == 0)
 | 
			
		||||
        update_device_speed (input_settings, settings, NULL,
 | 
			
		||||
                             CLUTTER_TOUCHPAD_DEVICE);
 | 
			
		||||
      else if (strcmp (key, "natural-scroll") == 0)
 | 
			
		||||
        update_device_natural_scroll (input_settings, settings,
 | 
			
		||||
                                      NULL, CLUTTER_TOUCHPAD_DEVICE);
 | 
			
		||||
      else if (strcmp (key, "tap-to-click") == 0)
 | 
			
		||||
        update_touchpad_tap_enabled (input_settings, NULL);
 | 
			
		||||
      else if (strcmp (key, "send-events") == 0)
 | 
			
		||||
        update_touchpad_send_events (input_settings, NULL);
 | 
			
		||||
      else if (strcmp (key, "scroll-method") == 0)
 | 
			
		||||
        update_touchpad_scroll_method (input_settings, NULL);
 | 
			
		||||
    }
 | 
			
		||||
  else if (settings == priv->trackball_settings)
 | 
			
		||||
    {
 | 
			
		||||
      if (strcmp (key, "scroll-wheel-emulation-button") == 0)
 | 
			
		||||
        update_trackball_scroll_button (input_settings, NULL);
 | 
			
		||||
    }
 | 
			
		||||
  else if (settings == priv->keyboard_settings)
 | 
			
		||||
    {
 | 
			
		||||
      if (strcmp (key, "repeat") == 0 ||
 | 
			
		||||
          strcmp (key, "repeat-interval") == 0 ||
 | 
			
		||||
          strcmp (key, "delay") == 0)
 | 
			
		||||
        update_keyboard_repeat (input_settings);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
mapped_device_changed_cb (GSettings         *settings,
 | 
			
		||||
                          const gchar       *key,
 | 
			
		||||
                          DeviceMappingInfo *info)
 | 
			
		||||
{
 | 
			
		||||
  if (strcmp (key, "display") == 0)
 | 
			
		||||
    update_device_display (info->input_settings, settings, info->device);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GSettings *
 | 
			
		||||
lookup_device_settings (ClutterInputDevice *device)
 | 
			
		||||
{
 | 
			
		||||
  const gchar *group, *schema, *vendor, *product;
 | 
			
		||||
  ClutterInputDeviceType type;
 | 
			
		||||
  GSettings *settings;
 | 
			
		||||
  gchar *path;
 | 
			
		||||
 | 
			
		||||
  type = clutter_input_device_get_device_type (device);
 | 
			
		||||
 | 
			
		||||
  if (type == CLUTTER_TOUCHSCREEN_DEVICE)
 | 
			
		||||
    {
 | 
			
		||||
      group = "touchscreens";
 | 
			
		||||
      schema = "org.gnome.desktop.peripherals.touchscreen";
 | 
			
		||||
    }
 | 
			
		||||
  else if (type == CLUTTER_TABLET_DEVICE ||
 | 
			
		||||
           type == CLUTTER_PEN_DEVICE ||
 | 
			
		||||
           type == CLUTTER_ERASER_DEVICE ||
 | 
			
		||||
           type == CLUTTER_CURSOR_DEVICE)
 | 
			
		||||
    {
 | 
			
		||||
      group = "tablets";
 | 
			
		||||
      schema = "org.gnome.desktop.peripherals.tablet";
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  vendor = clutter_input_device_get_vendor_id (device);
 | 
			
		||||
  product = clutter_input_device_get_product_id (device);
 | 
			
		||||
  path = g_strdup_printf ("/org/gnome/desktop/peripherals/%s/%s:%s/",
 | 
			
		||||
                          group, vendor, product);
 | 
			
		||||
 | 
			
		||||
  settings = g_settings_new_with_path (schema, path);
 | 
			
		||||
  g_free (path);
 | 
			
		||||
 | 
			
		||||
  return settings;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
monitors_changed_cb (MetaMonitorManager *monitor_manager,
 | 
			
		||||
                     MetaInputSettings  *input_settings)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  ClutterInputDevice *device;
 | 
			
		||||
  GSettings *settings;
 | 
			
		||||
  GHashTableIter iter;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  g_hash_table_iter_init (&iter, priv->mappable_devices);
 | 
			
		||||
 | 
			
		||||
  while (g_hash_table_iter_next (&iter, (gpointer *) &device,
 | 
			
		||||
                                 (gpointer *) &settings))
 | 
			
		||||
    update_device_display (input_settings, settings, device);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
check_add_mappable_device (MetaInputSettings  *input_settings,
 | 
			
		||||
                           ClutterInputDevice *device)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  DeviceMappingInfo *info;
 | 
			
		||||
  GSettings *settings;
 | 
			
		||||
 | 
			
		||||
  settings = lookup_device_settings (device);
 | 
			
		||||
 | 
			
		||||
  if (!settings)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
 | 
			
		||||
  info = g_new0 (DeviceMappingInfo, 1);
 | 
			
		||||
  info->input_settings = input_settings;
 | 
			
		||||
  info->device = device;
 | 
			
		||||
  info->settings = settings;
 | 
			
		||||
 | 
			
		||||
  g_signal_connect_data (settings, "changed",
 | 
			
		||||
                         G_CALLBACK (mapped_device_changed_cb),
 | 
			
		||||
                         info, (GClosureNotify) g_free, 0);
 | 
			
		||||
 | 
			
		||||
  g_hash_table_insert (priv->mappable_devices, device, settings);
 | 
			
		||||
 | 
			
		||||
  update_device_display (input_settings, settings, device);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_device_added (ClutterDeviceManager *device_manager,
 | 
			
		||||
                                  ClutterInputDevice   *device,
 | 
			
		||||
                                  MetaInputSettings    *input_settings)
 | 
			
		||||
{
 | 
			
		||||
  ClutterInputDeviceType type;
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
 | 
			
		||||
  if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  type = clutter_input_device_get_device_type (device);
 | 
			
		||||
 | 
			
		||||
  if (type == CLUTTER_POINTER_DEVICE)
 | 
			
		||||
    {
 | 
			
		||||
      update_mouse_left_handed (input_settings, device);
 | 
			
		||||
      update_device_speed (input_settings, priv->mouse_settings, device, type);
 | 
			
		||||
 | 
			
		||||
      if (device_is_trackball (device))
 | 
			
		||||
        update_trackball_scroll_button (input_settings, device);
 | 
			
		||||
    }
 | 
			
		||||
  else if (type == CLUTTER_TOUCHPAD_DEVICE)
 | 
			
		||||
    {
 | 
			
		||||
      update_touchpad_left_handed (input_settings, device);
 | 
			
		||||
      update_touchpad_tap_enabled (input_settings, device);
 | 
			
		||||
      update_touchpad_scroll_method (input_settings, device);
 | 
			
		||||
      update_touchpad_send_events (input_settings, device);
 | 
			
		||||
 | 
			
		||||
      update_device_speed (input_settings, priv->touchpad_settings,
 | 
			
		||||
                           device, type);
 | 
			
		||||
      update_device_natural_scroll (input_settings, priv->touchpad_settings,
 | 
			
		||||
                                    device, type);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      check_add_mappable_device (input_settings, device);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_device_removed (ClutterDeviceManager *device_manager,
 | 
			
		||||
                                    ClutterInputDevice   *device,
 | 
			
		||||
                                    MetaInputSettings    *input_settings)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  g_hash_table_remove (priv->mappable_devices, device);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
check_mappable_devices (MetaInputSettings *input_settings)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  const GSList *devices, *l;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  devices = clutter_device_manager_peek_devices (priv->device_manager);
 | 
			
		||||
 | 
			
		||||
  for (l = devices; l; l = l->next)
 | 
			
		||||
    {
 | 
			
		||||
      ClutterInputDevice *device = l->data;
 | 
			
		||||
 | 
			
		||||
      if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      check_add_mappable_device (input_settings, device);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_constructed (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettings *input_settings = META_INPUT_SETTINGS (object);
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
 | 
			
		||||
  update_mouse_left_handed (input_settings, NULL);
 | 
			
		||||
 | 
			
		||||
  update_touchpad_left_handed (input_settings, NULL);
 | 
			
		||||
  update_touchpad_tap_enabled (input_settings, NULL);
 | 
			
		||||
  update_touchpad_send_events (input_settings, NULL);
 | 
			
		||||
 | 
			
		||||
  update_device_natural_scroll (input_settings, priv->touchpad_settings,
 | 
			
		||||
                                NULL, CLUTTER_TOUCHPAD_DEVICE);
 | 
			
		||||
  update_device_speed (input_settings, priv->touchpad_settings, NULL,
 | 
			
		||||
                       CLUTTER_TOUCHPAD_DEVICE);
 | 
			
		||||
  update_device_speed (input_settings, priv->mouse_settings, NULL,
 | 
			
		||||
                       CLUTTER_POINTER_DEVICE);
 | 
			
		||||
 | 
			
		||||
  update_keyboard_repeat (input_settings);
 | 
			
		||||
 | 
			
		||||
  check_mappable_devices (input_settings);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_class_init (MetaInputSettingsClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->dispose = meta_input_settings_dispose;
 | 
			
		||||
  object_class->constructed = meta_input_settings_constructed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_init (MetaInputSettings *settings)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (settings);
 | 
			
		||||
  priv->device_manager = clutter_device_manager_get_default ();
 | 
			
		||||
  g_signal_connect (priv->device_manager, "device-added",
 | 
			
		||||
                    G_CALLBACK (meta_input_settings_device_added), settings);
 | 
			
		||||
  g_signal_connect (priv->device_manager, "device-removed",
 | 
			
		||||
                    G_CALLBACK (meta_input_settings_device_removed), settings);
 | 
			
		||||
 | 
			
		||||
  priv->mouse_settings = g_settings_new ("org.gnome.desktop.peripherals.mouse");
 | 
			
		||||
  g_signal_connect (priv->mouse_settings, "changed",
 | 
			
		||||
                    G_CALLBACK (meta_input_settings_changed_cb), settings);
 | 
			
		||||
 | 
			
		||||
  priv->touchpad_settings = g_settings_new ("org.gnome.desktop.peripherals.touchpad");
 | 
			
		||||
  g_signal_connect (priv->touchpad_settings, "changed",
 | 
			
		||||
                    G_CALLBACK (meta_input_settings_changed_cb), settings);
 | 
			
		||||
 | 
			
		||||
  priv->trackball_settings = g_settings_new ("org.gnome.desktop.peripherals.trackball");
 | 
			
		||||
  g_signal_connect (priv->trackball_settings, "changed",
 | 
			
		||||
                    G_CALLBACK (meta_input_settings_changed_cb), settings);
 | 
			
		||||
 | 
			
		||||
  priv->keyboard_settings = g_settings_new ("org.gnome.desktop.peripherals.keyboard");
 | 
			
		||||
  g_signal_connect (priv->keyboard_settings, "changed",
 | 
			
		||||
                    G_CALLBACK (meta_input_settings_changed_cb), settings);
 | 
			
		||||
 | 
			
		||||
  priv->mappable_devices =
 | 
			
		||||
    g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_object_unref);
 | 
			
		||||
 | 
			
		||||
  priv->monitor_manager = g_object_ref (meta_monitor_manager_get ());
 | 
			
		||||
  g_signal_connect (priv->monitor_manager, "monitors-changed",
 | 
			
		||||
                    G_CALLBACK (monitors_changed_cb), settings);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaInputSettings *
 | 
			
		||||
meta_input_settings_create (void)
 | 
			
		||||
{
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
  MetaBackend *backend;
 | 
			
		||||
 | 
			
		||||
  backend = meta_get_backend ();
 | 
			
		||||
 | 
			
		||||
  if (META_IS_BACKEND_NATIVE (backend))
 | 
			
		||||
    return g_object_new (META_TYPE_INPUT_SETTINGS_NATIVE, NULL);
 | 
			
		||||
#endif
 | 
			
		||||
  if (!meta_is_wayland_compositor ())
 | 
			
		||||
    return g_object_new (META_TYPE_INPUT_SETTINGS_X11, NULL);
 | 
			
		||||
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
@@ -34,6 +34,7 @@
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "boxes-private.h"
 | 
			
		||||
#include "meta-monitor-config.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
@@ -67,6 +68,7 @@ typedef struct {
 | 
			
		||||
} MetaOutputConfig;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  guint refcount;
 | 
			
		||||
  MetaOutputKey *keys;
 | 
			
		||||
  MetaOutputConfig *outputs;
 | 
			
		||||
  unsigned int n_outputs;
 | 
			
		||||
@@ -77,7 +79,6 @@ struct _MetaMonitorConfig {
 | 
			
		||||
 | 
			
		||||
  GHashTable *configs;
 | 
			
		||||
  MetaConfiguration *current;
 | 
			
		||||
  gboolean current_is_stored;
 | 
			
		||||
  gboolean current_is_for_laptop_lid;
 | 
			
		||||
  MetaConfiguration *previous;
 | 
			
		||||
 | 
			
		||||
@@ -124,11 +125,29 @@ config_clear (MetaConfiguration *config)
 | 
			
		||||
  g_free (config->outputs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
config_free (gpointer config)
 | 
			
		||||
static MetaConfiguration *
 | 
			
		||||
config_ref (MetaConfiguration *config)
 | 
			
		||||
{
 | 
			
		||||
  config_clear (config);
 | 
			
		||||
  g_slice_free (MetaConfiguration, config);
 | 
			
		||||
  config->refcount++;
 | 
			
		||||
  return config;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
config_unref (MetaConfiguration *config)
 | 
			
		||||
{
 | 
			
		||||
  if (--config->refcount == 0)
 | 
			
		||||
    {
 | 
			
		||||
      config_clear (config);
 | 
			
		||||
      g_slice_free (MetaConfiguration, config);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaConfiguration *
 | 
			
		||||
config_new (void)
 | 
			
		||||
{
 | 
			
		||||
  MetaConfiguration *config = g_slice_new0 (MetaConfiguration);
 | 
			
		||||
  config->refcount = 1;
 | 
			
		||||
  return config;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned long
 | 
			
		||||
@@ -220,7 +239,7 @@ meta_monitor_config_init (MetaMonitorConfig *self)
 | 
			
		||||
  const char *filename;
 | 
			
		||||
  char *path;
 | 
			
		||||
 | 
			
		||||
  self->configs = g_hash_table_new_full (config_hash, config_equal, NULL, config_free);
 | 
			
		||||
  self->configs = g_hash_table_new_full (config_hash, config_equal, NULL, (GDestroyNotify) config_unref);
 | 
			
		||||
 | 
			
		||||
  filename = g_getenv ("MUTTER_MONITOR_FILENAME");
 | 
			
		||||
  if (filename == NULL)
 | 
			
		||||
@@ -796,27 +815,6 @@ make_config_key (MetaConfiguration *key,
 | 
			
		||||
  key->n_outputs = o;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_monitor_config_match_current (MetaMonitorConfig  *self,
 | 
			
		||||
                                   MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
  MetaOutput *outputs;
 | 
			
		||||
  unsigned n_outputs;
 | 
			
		||||
  MetaConfiguration key;
 | 
			
		||||
  gboolean ok;
 | 
			
		||||
 | 
			
		||||
  if (self->current == NULL)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
 | 
			
		||||
 | 
			
		||||
  make_config_key (&key, outputs, n_outputs, -1);
 | 
			
		||||
  ok = config_equal (&key, self->current);
 | 
			
		||||
 | 
			
		||||
  config_clear (&key);
 | 
			
		||||
  return ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
@@ -851,73 +849,45 @@ meta_monitor_config_get_stored (MetaMonitorConfig *self,
 | 
			
		||||
  return stored;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
set_current (MetaMonitorConfig *self,
 | 
			
		||||
             MetaConfiguration *config)
 | 
			
		||||
{
 | 
			
		||||
  g_clear_pointer (&self->previous, (GDestroyNotify) config_unref);
 | 
			
		||||
  self->previous = self->current;
 | 
			
		||||
  self->current = config_ref (config);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
apply_configuration (MetaMonitorConfig  *self,
 | 
			
		||||
                     MetaConfiguration  *config,
 | 
			
		||||
		     MetaMonitorManager *manager,
 | 
			
		||||
                     gboolean            stored)
 | 
			
		||||
		     MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
  GPtrArray *crtcs, *outputs;
 | 
			
		||||
  gboolean ret = FALSE;
 | 
			
		||||
 | 
			
		||||
  crtcs = g_ptr_array_new_full (config->n_outputs, (GDestroyNotify)meta_crtc_info_free);
 | 
			
		||||
  outputs = g_ptr_array_new_full (config->n_outputs, (GDestroyNotify)meta_output_info_free);
 | 
			
		||||
 | 
			
		||||
  if (!meta_monitor_config_assign_crtcs (config, manager, crtcs, outputs))
 | 
			
		||||
    {
 | 
			
		||||
      g_ptr_array_unref (crtcs);
 | 
			
		||||
      g_ptr_array_unref (outputs);
 | 
			
		||||
      if (!stored)
 | 
			
		||||
        config_free (config);
 | 
			
		||||
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  meta_monitor_manager_apply_configuration (manager,
 | 
			
		||||
                                            (MetaCRTCInfo**)crtcs->pdata, crtcs->len,
 | 
			
		||||
                                            (MetaOutputInfo**)outputs->pdata, outputs->len);
 | 
			
		||||
 | 
			
		||||
  /* Stored (persistent) configurations override the previous one always.
 | 
			
		||||
     Also, we clear the previous configuration if the current one (which is
 | 
			
		||||
     about to become previous) is stored, or if the current one has
 | 
			
		||||
     different outputs.
 | 
			
		||||
  */
 | 
			
		||||
  if (stored ||
 | 
			
		||||
      (self->current && self->current_is_stored))
 | 
			
		||||
    {
 | 
			
		||||
      if (self->previous)
 | 
			
		||||
        config_free (self->previous);
 | 
			
		||||
      self->previous = NULL;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      /* Despite the name, config_equal() only checks the set of outputs,
 | 
			
		||||
         not their modes
 | 
			
		||||
      */
 | 
			
		||||
      if (self->current && config_equal (self->current, config))
 | 
			
		||||
        {
 | 
			
		||||
          self->previous = self->current;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          if (self->current)
 | 
			
		||||
            config_free (self->current);
 | 
			
		||||
          self->previous = NULL;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  set_current (self, config);
 | 
			
		||||
 | 
			
		||||
  self->current = config;
 | 
			
		||||
  self->current_is_stored = stored;
 | 
			
		||||
  /* If true, we'll be overridden at the end of this call
 | 
			
		||||
     inside turn_off_laptop_display()
 | 
			
		||||
  */
 | 
			
		||||
   * inside turn_off_laptop_display / apply_configuration_with_lid */
 | 
			
		||||
  self->current_is_for_laptop_lid = FALSE;
 | 
			
		||||
 | 
			
		||||
  if (self->current == self->previous)
 | 
			
		||||
    self->previous = NULL;
 | 
			
		||||
  ret = TRUE;
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  g_ptr_array_unref (crtcs);
 | 
			
		||||
  g_ptr_array_unref (outputs);
 | 
			
		||||
  return TRUE;
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
@@ -928,6 +898,20 @@ key_is_laptop (MetaOutputKey *key)
 | 
			
		||||
    g_str_has_prefix (key->connector, "eDP");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
output_is_laptop (MetaOutput *output)
 | 
			
		||||
{
 | 
			
		||||
  /* FIXME: extend with better heuristics */
 | 
			
		||||
  switch (output->connector_type)
 | 
			
		||||
    {
 | 
			
		||||
    case META_CONNECTOR_TYPE_eDP:
 | 
			
		||||
    case META_CONNECTOR_TYPE_LVDS:
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    default:
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
laptop_display_is_on (MetaConfiguration *config)
 | 
			
		||||
{
 | 
			
		||||
@@ -945,6 +929,19 @@ laptop_display_is_on (MetaConfiguration *config)
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
multiple_outputs_are_enabled (MetaConfiguration *config)
 | 
			
		||||
{
 | 
			
		||||
  unsigned int i, enabled;
 | 
			
		||||
 | 
			
		||||
  enabled = 0;
 | 
			
		||||
  for (i = 0; i < config->n_outputs; i++)
 | 
			
		||||
    if (config->outputs[i].enabled)
 | 
			
		||||
      enabled++;
 | 
			
		||||
 | 
			
		||||
  return enabled > 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaConfiguration *
 | 
			
		||||
make_laptop_lid_config (MetaConfiguration  *reference)
 | 
			
		||||
{
 | 
			
		||||
@@ -954,9 +951,9 @@ make_laptop_lid_config (MetaConfiguration  *reference)
 | 
			
		||||
  int x_after, y_after;
 | 
			
		||||
  int x_offset, y_offset;
 | 
			
		||||
 | 
			
		||||
  g_assert (reference->n_outputs > 1);
 | 
			
		||||
  g_assert (multiple_outputs_are_enabled (reference));
 | 
			
		||||
 | 
			
		||||
  new = g_slice_new0 (MetaConfiguration);
 | 
			
		||||
  new = config_new ();
 | 
			
		||||
  new->n_outputs = reference->n_outputs;
 | 
			
		||||
  new->keys = g_new0 (MetaOutputKey, reference->n_outputs);
 | 
			
		||||
  new->outputs = g_new0 (MetaOutputConfig, reference->n_outputs);
 | 
			
		||||
@@ -973,8 +970,7 @@ make_laptop_lid_config (MetaConfiguration  *reference)
 | 
			
		||||
      new->keys[i].product = g_strdup (current_key->product);
 | 
			
		||||
      new->keys[i].serial = g_strdup (current_key->serial);
 | 
			
		||||
 | 
			
		||||
      if (g_str_has_prefix (current_key->connector, "LVDS") ||
 | 
			
		||||
          g_str_has_prefix (current_key->connector, "eDP"))
 | 
			
		||||
      if (key_is_laptop (current_key))
 | 
			
		||||
        {
 | 
			
		||||
          new->outputs[i].enabled = FALSE;
 | 
			
		||||
          x_after = current_output->rect.x;
 | 
			
		||||
@@ -1011,6 +1007,32 @@ make_laptop_lid_config (MetaConfiguration  *reference)
 | 
			
		||||
  return new;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
apply_configuration_with_lid (MetaMonitorConfig  *self,
 | 
			
		||||
                              MetaConfiguration  *config,
 | 
			
		||||
                              MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
  if (self->lid_is_closed &&
 | 
			
		||||
      multiple_outputs_are_enabled (config) &&
 | 
			
		||||
      laptop_display_is_on (config))
 | 
			
		||||
    {
 | 
			
		||||
      MetaConfiguration *laptop_lid_config = make_laptop_lid_config (config);
 | 
			
		||||
      if (apply_configuration (self, laptop_lid_config, manager))
 | 
			
		||||
        {
 | 
			
		||||
          self->current_is_for_laptop_lid = TRUE;
 | 
			
		||||
          config_unref (laptop_lid_config);
 | 
			
		||||
          return TRUE;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          config_unref (laptop_lid_config);
 | 
			
		||||
          return FALSE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    return apply_configuration (self, config, manager);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_monitor_config_apply_stored (MetaMonitorConfig  *self,
 | 
			
		||||
				  MetaMonitorManager *manager)
 | 
			
		||||
@@ -1023,23 +1045,7 @@ meta_monitor_config_apply_stored (MetaMonitorConfig  *self,
 | 
			
		||||
  stored = meta_monitor_config_get_stored (self, outputs, n_outputs);
 | 
			
		||||
 | 
			
		||||
  if (stored)
 | 
			
		||||
    {
 | 
			
		||||
      if (self->lid_is_closed &&
 | 
			
		||||
          stored->n_outputs > 1 &&
 | 
			
		||||
          laptop_display_is_on (stored))
 | 
			
		||||
        {
 | 
			
		||||
          if (apply_configuration (self, make_laptop_lid_config (stored),
 | 
			
		||||
                                   manager, FALSE))
 | 
			
		||||
            {
 | 
			
		||||
              self->current_is_for_laptop_lid = TRUE;
 | 
			
		||||
              return TRUE;
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
            return FALSE;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        return apply_configuration (self, stored, manager, TRUE);
 | 
			
		||||
    }
 | 
			
		||||
    return apply_configuration_with_lid (self, stored, manager);
 | 
			
		||||
  else
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
@@ -1068,8 +1074,7 @@ find_primary_output (MetaOutput *outputs,
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      if (g_str_has_prefix (outputs[i].name, "LVDS") ||
 | 
			
		||||
          g_str_has_prefix (outputs[i].name, "eDP"))
 | 
			
		||||
      if (output_is_laptop (&outputs[i]))
 | 
			
		||||
        return &outputs[i];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1089,47 +1094,123 @@ find_primary_output (MetaOutput *outputs,
 | 
			
		||||
  return best;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaConfiguration *
 | 
			
		||||
make_default_config (MetaMonitorConfig *self,
 | 
			
		||||
                     MetaOutput        *outputs,
 | 
			
		||||
                     unsigned           n_outputs,
 | 
			
		||||
                     int                max_width,
 | 
			
		||||
                     int                max_height)
 | 
			
		||||
static void
 | 
			
		||||
init_config_from_preferred_mode (MetaOutputConfig *config,
 | 
			
		||||
                                 MetaOutput *output)
 | 
			
		||||
{
 | 
			
		||||
  unsigned i, j;
 | 
			
		||||
  int x, y;
 | 
			
		||||
  MetaConfiguration *ret;
 | 
			
		||||
  config->enabled = TRUE;
 | 
			
		||||
  config->rect.x = 0;
 | 
			
		||||
  config->rect.y = 0;
 | 
			
		||||
  config->rect.width = output->preferred_mode->width;
 | 
			
		||||
  config->rect.height = output->preferred_mode->height;
 | 
			
		||||
  config->refresh_rate = output->preferred_mode->refresh_rate;
 | 
			
		||||
  config->transform = META_MONITOR_TRANSFORM_NORMAL;
 | 
			
		||||
  config->is_primary = FALSE;
 | 
			
		||||
  config->is_presentation = FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This function handles configuring the outputs when the driver provides a
 | 
			
		||||
 * suggested layout position for each output. This is done in recent versions
 | 
			
		||||
 * of qxl and allows displays to be aligned on the guest in the same order as
 | 
			
		||||
 * they are aligned on the client.
 | 
			
		||||
 */
 | 
			
		||||
static gboolean
 | 
			
		||||
make_suggested_config (MetaMonitorConfig *self,
 | 
			
		||||
                       MetaOutput        *outputs,
 | 
			
		||||
                       unsigned           n_outputs,
 | 
			
		||||
                       int                max_width,
 | 
			
		||||
                       int                max_height,
 | 
			
		||||
                       MetaConfiguration *config)
 | 
			
		||||
{
 | 
			
		||||
  unsigned int i;
 | 
			
		||||
  MetaOutput *primary;
 | 
			
		||||
  GList *region = NULL;
 | 
			
		||||
 | 
			
		||||
  ret = g_slice_new (MetaConfiguration);
 | 
			
		||||
  make_config_key (ret, outputs, n_outputs, -1);
 | 
			
		||||
  ret->outputs = g_new0 (MetaOutputConfig, n_outputs);
 | 
			
		||||
  g_return_val_if_fail (config != NULL, FALSE);
 | 
			
		||||
  primary = find_primary_output (outputs, n_outputs);
 | 
			
		||||
 | 
			
		||||
  /* Special case the simple case: one output, primary at preferred mode,
 | 
			
		||||
     nothing else to do */
 | 
			
		||||
  if (n_outputs == 1)
 | 
			
		||||
  for (i = 0; i < n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      ret->outputs[0].enabled = TRUE;
 | 
			
		||||
      ret->outputs[0].rect.x = 0;
 | 
			
		||||
      ret->outputs[0].rect.y = 0;
 | 
			
		||||
      ret->outputs[0].rect.width = outputs[0].preferred_mode->width;
 | 
			
		||||
      ret->outputs[0].rect.height = outputs[0].preferred_mode->height;
 | 
			
		||||
      ret->outputs[0].refresh_rate = outputs[0].preferred_mode->refresh_rate;
 | 
			
		||||
      ret->outputs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
 | 
			
		||||
      ret->outputs[0].is_primary = TRUE;
 | 
			
		||||
      gboolean is_primary = (&outputs[i] == primary);
 | 
			
		||||
 | 
			
		||||
      return ret;
 | 
			
		||||
      if (outputs[i].suggested_x < 0 || outputs[i].suggested_y < 0)
 | 
			
		||||
          return FALSE;
 | 
			
		||||
 | 
			
		||||
      init_config_from_preferred_mode (&config->outputs[i], &outputs[i]);
 | 
			
		||||
      config->outputs[i].is_primary = is_primary;
 | 
			
		||||
 | 
			
		||||
      config->outputs[i].rect.x = outputs[i].suggested_x;
 | 
			
		||||
      config->outputs[i].rect.y = outputs[i].suggested_y;
 | 
			
		||||
 | 
			
		||||
      /* Reject the configuration if the suggested positions result in
 | 
			
		||||
       * overlapping displays */
 | 
			
		||||
      if (meta_rectangle_overlaps_with_region (region, &config->outputs[i].rect))
 | 
			
		||||
        {
 | 
			
		||||
          g_warning ("Overlapping outputs, rejecting suggested configuration");
 | 
			
		||||
          g_list_free (region);
 | 
			
		||||
          return FALSE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      region = g_list_prepend (region, &config->outputs[i].rect);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* If we reach this point, this is either the first time mutter runs
 | 
			
		||||
     on this system ever, or we just hotplugged a new screen.
 | 
			
		||||
     In the latter case, search for a configuration that includes one
 | 
			
		||||
     less screen, then add the new one as a presentation screen
 | 
			
		||||
     in preferred mode.
 | 
			
		||||
  g_list_free (region);
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
     XXX: but presentation mode is not implemented in the control-center
 | 
			
		||||
     or in mutter core, so let's do extended for now.
 | 
			
		||||
static void
 | 
			
		||||
make_linear_config (MetaMonitorConfig *self,
 | 
			
		||||
                    MetaOutput        *outputs,
 | 
			
		||||
                    unsigned           n_outputs,
 | 
			
		||||
                    int                max_width,
 | 
			
		||||
                    int                max_height,
 | 
			
		||||
                    MetaConfiguration *config)
 | 
			
		||||
{
 | 
			
		||||
  MetaOutput *primary;
 | 
			
		||||
  unsigned i;
 | 
			
		||||
  int x;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (config != NULL);
 | 
			
		||||
 | 
			
		||||
  primary = find_primary_output (outputs, n_outputs);
 | 
			
		||||
 | 
			
		||||
  x = primary->preferred_mode->width;
 | 
			
		||||
  for (i = 0; i < n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      gboolean is_primary = (&outputs[i] == primary);
 | 
			
		||||
 | 
			
		||||
      init_config_from_preferred_mode (&config->outputs[i], &outputs[i]);
 | 
			
		||||
      config->outputs[i].is_primary = is_primary;
 | 
			
		||||
 | 
			
		||||
      if (is_primary)
 | 
			
		||||
        {
 | 
			
		||||
          config->outputs[i].rect.x = 0;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          config->outputs[i].rect.x = x;
 | 
			
		||||
          x += config->outputs[i].rect.width;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Search for a configuration that includes one less screen, then add the new
 | 
			
		||||
 * one as a presentation screen in preferred mode.
 | 
			
		||||
 *
 | 
			
		||||
 * XXX: but presentation mode is not implemented in the control-center or in
 | 
			
		||||
 * mutter core, so let's do extended for now.
 | 
			
		||||
  */
 | 
			
		||||
static gboolean
 | 
			
		||||
extend_stored_config (MetaMonitorConfig *self,
 | 
			
		||||
                      MetaOutput        *outputs,
 | 
			
		||||
                      unsigned           n_outputs,
 | 
			
		||||
                      int                max_width,
 | 
			
		||||
                      int                max_height,
 | 
			
		||||
                      MetaConfiguration *config)
 | 
			
		||||
{
 | 
			
		||||
  int x, y;
 | 
			
		||||
  unsigned i, j;
 | 
			
		||||
 | 
			
		||||
  x = 0;
 | 
			
		||||
  y = 0;
 | 
			
		||||
  for (i = 0; i < n_outputs; i++)
 | 
			
		||||
@@ -1147,69 +1228,80 @@ make_default_config (MetaMonitorConfig *self,
 | 
			
		||||
            {
 | 
			
		||||
              if (j < i)
 | 
			
		||||
                {
 | 
			
		||||
                  g_assert (output_key_equal (&ret->keys[j], &ref->keys[j]));
 | 
			
		||||
                  ret->outputs[j] = ref->outputs[j];
 | 
			
		||||
                  g_assert (output_key_equal (&config->keys[j], &ref->keys[j]));
 | 
			
		||||
                  config->outputs[j] = ref->outputs[j];
 | 
			
		||||
                  x = MAX (x, ref->outputs[j].rect.x + ref->outputs[j].rect.width);
 | 
			
		||||
                  y = MAX (y, ref->outputs[j].rect.y + ref->outputs[j].rect.height);
 | 
			
		||||
                }
 | 
			
		||||
              else if (j > i)
 | 
			
		||||
                {
 | 
			
		||||
                  g_assert (output_key_equal (&ret->keys[j], &ref->keys[j - 1]));
 | 
			
		||||
                  ret->outputs[j] = ref->outputs[j - 1];
 | 
			
		||||
                  g_assert (output_key_equal (&config->keys[j], &ref->keys[j - 1]));
 | 
			
		||||
                  config->outputs[j] = ref->outputs[j - 1];
 | 
			
		||||
                  x = MAX (x, ref->outputs[j - 1].rect.x + ref->outputs[j - 1].rect.width);
 | 
			
		||||
                  y = MAX (y, ref->outputs[j - 1].rect.y + ref->outputs[j - 1].rect.height);
 | 
			
		||||
                }
 | 
			
		||||
              else
 | 
			
		||||
                {
 | 
			
		||||
                  ret->outputs[j].enabled = TRUE;
 | 
			
		||||
                  ret->outputs[j].rect.x = 0;
 | 
			
		||||
                  ret->outputs[j].rect.y = 0;
 | 
			
		||||
                  ret->outputs[j].rect.width = outputs[0].preferred_mode->width;
 | 
			
		||||
                  ret->outputs[j].rect.height = outputs[0].preferred_mode->height;
 | 
			
		||||
                  ret->outputs[j].refresh_rate = outputs[0].preferred_mode->refresh_rate;
 | 
			
		||||
                  ret->outputs[j].transform = META_MONITOR_TRANSFORM_NORMAL;
 | 
			
		||||
                  ret->outputs[j].is_primary = FALSE;
 | 
			
		||||
                  ret->outputs[j].is_presentation = FALSE;
 | 
			
		||||
                  init_config_from_preferred_mode (&config->outputs[j], &outputs[0]);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          /* Place the new output at the right end of the screen, if it fits,
 | 
			
		||||
             otherwise below it, otherwise disable it (or apply_configuration will fail) */
 | 
			
		||||
          if (x + ret->outputs[i].rect.width <= max_width)
 | 
			
		||||
            ret->outputs[i].rect.x = x;
 | 
			
		||||
          else if (y + ret->outputs[i].rect.height <= max_height)
 | 
			
		||||
            ret->outputs[i].rect.y = y;
 | 
			
		||||
          if (x + config->outputs[i].rect.width <= max_width)
 | 
			
		||||
            config->outputs[i].rect.x = x;
 | 
			
		||||
          else if (y + config->outputs[i].rect.height <= max_height)
 | 
			
		||||
            config->outputs[i].rect.y = y;
 | 
			
		||||
          else
 | 
			
		||||
            ret->outputs[i].enabled = FALSE;
 | 
			
		||||
            config->outputs[i].enabled = FALSE;
 | 
			
		||||
 | 
			
		||||
          return ret;
 | 
			
		||||
          return TRUE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* No previous configuration found, try with a really default one, which
 | 
			
		||||
     is one primary that goes first and the rest to the right of it, extended.
 | 
			
		||||
  */
 | 
			
		||||
  primary = find_primary_output (outputs, n_outputs);
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  x = primary->preferred_mode->width;
 | 
			
		||||
static MetaConfiguration *
 | 
			
		||||
make_default_config (MetaMonitorConfig *self,
 | 
			
		||||
                     MetaOutput        *outputs,
 | 
			
		||||
                     unsigned           n_outputs,
 | 
			
		||||
                     int                max_width,
 | 
			
		||||
                     int                max_height,
 | 
			
		||||
                     gboolean           use_stored_config)
 | 
			
		||||
{
 | 
			
		||||
  MetaConfiguration *ret = NULL;
 | 
			
		||||
  unsigned i;
 | 
			
		||||
 | 
			
		||||
  ret = config_new ();
 | 
			
		||||
  make_config_key (ret, outputs, n_outputs, -1);
 | 
			
		||||
  ret->outputs = g_new0 (MetaOutputConfig, n_outputs);
 | 
			
		||||
 | 
			
		||||
  /* Special case the simple case: one output, primary at preferred mode,
 | 
			
		||||
     nothing else to do */
 | 
			
		||||
  if (n_outputs == 1)
 | 
			
		||||
    {
 | 
			
		||||
      init_config_from_preferred_mode (&ret->outputs[0], &outputs[0]);
 | 
			
		||||
      ret->outputs[0].is_primary = TRUE;
 | 
			
		||||
      goto check_limits;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (make_suggested_config (self, outputs, n_outputs, max_width, max_height, ret))
 | 
			
		||||
      goto check_limits;
 | 
			
		||||
 | 
			
		||||
  if (use_stored_config &&
 | 
			
		||||
      extend_stored_config (self, outputs, n_outputs, max_width, max_height, ret))
 | 
			
		||||
      goto check_limits;
 | 
			
		||||
 | 
			
		||||
  make_linear_config (self, outputs, n_outputs, max_width, max_height, ret);
 | 
			
		||||
 | 
			
		||||
check_limits:
 | 
			
		||||
  /* Disable outputs that would go beyond framebuffer limits */
 | 
			
		||||
  for (i = 0; i < n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaOutput *output = &outputs[i];
 | 
			
		||||
 | 
			
		||||
      ret->outputs[i].enabled = TRUE;
 | 
			
		||||
      ret->outputs[i].rect.x = (output == primary) ? 0 : x;
 | 
			
		||||
      ret->outputs[i].rect.y = 0;
 | 
			
		||||
      ret->outputs[i].rect.width = output->preferred_mode->width;
 | 
			
		||||
      ret->outputs[i].rect.height = output->preferred_mode->height;
 | 
			
		||||
      ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate;
 | 
			
		||||
      ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
 | 
			
		||||
      ret->outputs[i].is_primary = (output == primary);
 | 
			
		||||
 | 
			
		||||
      /* Disable outputs that would go beyond framebuffer limits */
 | 
			
		||||
      if (ret->outputs[i].rect.x + ret->outputs[i].rect.width > max_width)
 | 
			
		||||
        ret->outputs[i].enabled = FALSE;
 | 
			
		||||
      else if (output != primary)
 | 
			
		||||
        x += output->preferred_mode->width;
 | 
			
		||||
        if ((ret->outputs[i].rect.x + ret->outputs[i].rect.width > max_width)
 | 
			
		||||
            || (ret->outputs[i].rect.y + ret->outputs[i].rect.height > max_height))
 | 
			
		||||
          ret->outputs[i].enabled = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return ret;
 | 
			
		||||
@@ -1221,7 +1313,7 @@ ensure_at_least_one_output (MetaMonitorConfig  *self,
 | 
			
		||||
                            MetaOutput         *outputs,
 | 
			
		||||
                            unsigned            n_outputs)
 | 
			
		||||
{
 | 
			
		||||
  MetaConfiguration *ret;
 | 
			
		||||
  MetaConfiguration *config;
 | 
			
		||||
  MetaOutput *primary;
 | 
			
		||||
  unsigned i;
 | 
			
		||||
 | 
			
		||||
@@ -1232,34 +1324,29 @@ ensure_at_least_one_output (MetaMonitorConfig  *self,
 | 
			
		||||
 | 
			
		||||
  /* Oh no, we don't! Activate the primary one and disable everything else */
 | 
			
		||||
 | 
			
		||||
  ret = g_slice_new (MetaConfiguration);
 | 
			
		||||
  make_config_key (ret, outputs, n_outputs, -1);
 | 
			
		||||
  ret->outputs = g_new0 (MetaOutputConfig, n_outputs);
 | 
			
		||||
  config = config_new ();
 | 
			
		||||
  make_config_key (config, outputs, n_outputs, -1);
 | 
			
		||||
  config->outputs = g_new0 (MetaOutputConfig, n_outputs);
 | 
			
		||||
 | 
			
		||||
  primary = find_primary_output (outputs, n_outputs);
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaOutput *output = &outputs[i];
 | 
			
		||||
      gboolean is_primary = (&outputs[i] == primary);
 | 
			
		||||
 | 
			
		||||
      if (output == primary)
 | 
			
		||||
      if (is_primary)
 | 
			
		||||
        {
 | 
			
		||||
          ret->outputs[i].enabled = TRUE;
 | 
			
		||||
          ret->outputs[i].rect.x = 0;
 | 
			
		||||
          ret->outputs[i].rect.y = 0;
 | 
			
		||||
          ret->outputs[i].rect.width = output->preferred_mode->width;
 | 
			
		||||
          ret->outputs[i].rect.height = output->preferred_mode->height;
 | 
			
		||||
          ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate;
 | 
			
		||||
          ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
 | 
			
		||||
          ret->outputs[i].is_primary = TRUE;
 | 
			
		||||
          init_config_from_preferred_mode (&config->outputs[i], &outputs[0]);
 | 
			
		||||
          config->outputs[i].is_primary = TRUE;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          ret->outputs[i].enabled = FALSE;
 | 
			
		||||
          config->outputs[i].enabled = FALSE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  apply_configuration (self, ret, manager, FALSE);
 | 
			
		||||
  apply_configuration (self, config, manager);
 | 
			
		||||
  config_unref (config);
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1270,8 +1357,9 @@ meta_monitor_config_make_default (MetaMonitorConfig  *self,
 | 
			
		||||
  MetaOutput *outputs;
 | 
			
		||||
  MetaConfiguration *default_config;
 | 
			
		||||
  unsigned n_outputs;
 | 
			
		||||
  gboolean ok;
 | 
			
		||||
  gboolean ok = FALSE;
 | 
			
		||||
  int max_width, max_height;
 | 
			
		||||
  gboolean use_stored_config;
 | 
			
		||||
 | 
			
		||||
  outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
 | 
			
		||||
  meta_monitor_manager_get_screen_limits (manager, &max_width, &max_height);
 | 
			
		||||
@@ -1282,23 +1370,21 @@ meta_monitor_config_make_default (MetaMonitorConfig  *self,
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  default_config = make_default_config (self, outputs, n_outputs, max_width, max_height);
 | 
			
		||||
  /* if the device has hotplug_mode_update, it's possible that the
 | 
			
		||||
   * current display configuration does not match a stored configuration.
 | 
			
		||||
   * Since extend_existing_config() tries to build a configuration that is
 | 
			
		||||
   * based on a previously-stored configuration, it's quite likely that the
 | 
			
		||||
   * resulting config will fail. Even if it doesn't fail, it may result in
 | 
			
		||||
   * an unexpected configuration, so don't attempt to use a stored config
 | 
			
		||||
   * in this situation. */
 | 
			
		||||
  use_stored_config = !meta_monitor_manager_has_hotplug_mode_update (manager);
 | 
			
		||||
  default_config = make_default_config (self, outputs, n_outputs, max_width, max_height, use_stored_config);
 | 
			
		||||
 | 
			
		||||
  if (default_config != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      if (self->lid_is_closed &&
 | 
			
		||||
          default_config->n_outputs > 1 &&
 | 
			
		||||
          laptop_display_is_on (default_config))
 | 
			
		||||
        {
 | 
			
		||||
          ok = apply_configuration (self, make_laptop_lid_config (default_config),
 | 
			
		||||
                                    manager, FALSE);
 | 
			
		||||
          config_free (default_config);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        ok = apply_configuration (self, default_config, manager, FALSE);
 | 
			
		||||
      ok = apply_configuration_with_lid (self, default_config, manager);
 | 
			
		||||
      config_unref (default_config);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    ok = FALSE;
 | 
			
		||||
 | 
			
		||||
  if (!ok)
 | 
			
		||||
    {
 | 
			
		||||
@@ -1335,7 +1421,7 @@ meta_monitor_config_update_current (MetaMonitorConfig  *self,
 | 
			
		||||
 | 
			
		||||
  outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
 | 
			
		||||
 | 
			
		||||
  current = g_slice_new (MetaConfiguration);
 | 
			
		||||
  current = config_new ();
 | 
			
		||||
  current->n_outputs = n_outputs;
 | 
			
		||||
  current->outputs = g_new0 (MetaOutputConfig, n_outputs);
 | 
			
		||||
  current->keys = g_new0 (MetaOutputKey, n_outputs);
 | 
			
		||||
@@ -1348,15 +1434,11 @@ meta_monitor_config_update_current (MetaMonitorConfig  *self,
 | 
			
		||||
 | 
			
		||||
  if (self->current && config_equal_full (current, self->current))
 | 
			
		||||
    {
 | 
			
		||||
      config_free (current);
 | 
			
		||||
      config_unref (current);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (self->current && !self->current_is_stored)
 | 
			
		||||
    config_free (self->current);
 | 
			
		||||
 | 
			
		||||
  self->current = current;
 | 
			
		||||
  self->current_is_stored = FALSE;
 | 
			
		||||
  set_current (self, current);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -1364,7 +1446,17 @@ meta_monitor_config_restore_previous (MetaMonitorConfig  *self,
 | 
			
		||||
                                      MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
  if (self->previous)
 | 
			
		||||
    apply_configuration (self, self->previous, manager, FALSE);
 | 
			
		||||
    {
 | 
			
		||||
      /* The user chose to restore the previous configuration. In this
 | 
			
		||||
       * case, restore the previous configuration. */
 | 
			
		||||
      MetaConfiguration *prev_config = config_ref (self->previous);
 | 
			
		||||
      apply_configuration (self, prev_config, manager);
 | 
			
		||||
      config_unref (prev_config);
 | 
			
		||||
 | 
			
		||||
      /* After this, self->previous contains the rejected configuration.
 | 
			
		||||
       * Since it was rejected, nuke it. */
 | 
			
		||||
      g_clear_pointer (&self->previous, (GDestroyNotify) config_unref);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      if (!meta_monitor_config_apply_stored (self, manager))
 | 
			
		||||
@@ -1378,11 +1470,12 @@ turn_off_laptop_display (MetaMonitorConfig  *self,
 | 
			
		||||
{
 | 
			
		||||
  MetaConfiguration *new;
 | 
			
		||||
 | 
			
		||||
  if (self->current->n_outputs == 1)
 | 
			
		||||
  if (!multiple_outputs_are_enabled (self->current))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  new = make_laptop_lid_config (self->current);
 | 
			
		||||
  apply_configuration (self, new, manager, FALSE);
 | 
			
		||||
  apply_configuration (self, new, manager);
 | 
			
		||||
  config_unref (new);
 | 
			
		||||
  self->current_is_for_laptop_lid = TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1541,16 +1634,7 @@ meta_monitor_config_save (MetaMonitorConfig *self)
 | 
			
		||||
void
 | 
			
		||||
meta_monitor_config_make_persistent (MetaMonitorConfig *self)
 | 
			
		||||
{
 | 
			
		||||
  if (self->current_is_stored)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  self->current_is_stored = TRUE;
 | 
			
		||||
  g_hash_table_replace (self->configs, self->current, self->current);
 | 
			
		||||
 | 
			
		||||
  if (self->previous)
 | 
			
		||||
    config_free (self->previous);
 | 
			
		||||
  self->previous = NULL;
 | 
			
		||||
 | 
			
		||||
  g_hash_table_replace (self->configs, self->current, config_ref (self->current));
 | 
			
		||||
  meta_monitor_config_save (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@
 | 
			
		||||
#ifndef META_MONITOR_CONFIG_H
 | 
			
		||||
#define META_MONITOR_CONFIG_H
 | 
			
		||||
 | 
			
		||||
#include "meta-monitor-manager.h"
 | 
			
		||||
#include "meta-monitor-manager-private.h"
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_MONITOR_CONFIG            (meta_monitor_config_get_type ())
 | 
			
		||||
#define META_MONITOR_CONFIG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig))
 | 
			
		||||
@@ -36,9 +36,6 @@ GType meta_monitor_config_get_type (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
MetaMonitorConfig *meta_monitor_config_new (void);
 | 
			
		||||
 | 
			
		||||
gboolean           meta_monitor_config_match_current (MetaMonitorConfig  *config,
 | 
			
		||||
                                                      MetaMonitorManager *manager);
 | 
			
		||||
 | 
			
		||||
gboolean           meta_monitor_config_apply_stored (MetaMonitorConfig  *config,
 | 
			
		||||
                                                     MetaMonitorManager *manager);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -95,6 +95,7 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
 | 
			
		||||
  manager->outputs[0].backlight = -1;
 | 
			
		||||
  manager->outputs[0].backlight_min = 0;
 | 
			
		||||
  manager->outputs[0].backlight_max = 0;
 | 
			
		||||
  manager->outputs[0].connector_type = META_CONNECTOR_TYPE_LVDS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@
 | 
			
		||||
#ifndef META_MONITOR_MANAGER_DUMMY_H
 | 
			
		||||
#define META_MONITOR_MANAGER_DUMMY_H
 | 
			
		||||
 | 
			
		||||
#include "meta-monitor-manager.h"
 | 
			
		||||
#include "meta-monitor-manager-private.h"
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_MONITOR_MANAGER_DUMMY            (meta_monitor_manager_dummy_get_type ())
 | 
			
		||||
#define META_MONITOR_MANAGER_DUMMY(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_DUMMY, MetaMonitorManagerDummy))
 | 
			
		||||
 
 | 
			
		||||
@@ -41,18 +41,17 @@
 | 
			
		||||
#include "display-private.h"
 | 
			
		||||
#include <meta/screen.h>
 | 
			
		||||
#include "stack-tracker.h"
 | 
			
		||||
#include <meta/meta-monitor-manager.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-display-config-shared.h"
 | 
			
		||||
#include "meta-dbus-display-config.h"
 | 
			
		||||
#include "meta-cursor.h"
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaMonitorManagerClass    MetaMonitorManagerClass;
 | 
			
		||||
typedef struct _MetaMonitorManager         MetaMonitorManager;
 | 
			
		||||
typedef struct _MetaMonitorConfigClass    MetaMonitorConfigClass;
 | 
			
		||||
typedef struct _MetaMonitorConfig         MetaMonitorConfig;
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaOutput MetaOutput;
 | 
			
		||||
typedef struct _MetaCRTC MetaCRTC;
 | 
			
		||||
typedef struct _MetaOutput MetaOutput;
 | 
			
		||||
typedef struct _MetaMonitorMode MetaMonitorMode;
 | 
			
		||||
typedef struct _MetaMonitorInfo MetaMonitorInfo;
 | 
			
		||||
typedef struct _MetaCRTCInfo MetaCRTCInfo;
 | 
			
		||||
@@ -69,6 +68,27 @@ typedef enum {
 | 
			
		||||
  META_MONITOR_TRANSFORM_FLIPPED_270,
 | 
			
		||||
} MetaMonitorTransform;
 | 
			
		||||
 | 
			
		||||
/* This matches the values in drm_mode.h */
 | 
			
		||||
typedef enum {
 | 
			
		||||
  META_CONNECTOR_TYPE_Unknown = 0,
 | 
			
		||||
  META_CONNECTOR_TYPE_VGA = 1,
 | 
			
		||||
  META_CONNECTOR_TYPE_DVII = 2,
 | 
			
		||||
  META_CONNECTOR_TYPE_DVID = 3,
 | 
			
		||||
  META_CONNECTOR_TYPE_DVIA = 4,
 | 
			
		||||
  META_CONNECTOR_TYPE_Composite = 5,
 | 
			
		||||
  META_CONNECTOR_TYPE_SVIDEO = 6,
 | 
			
		||||
  META_CONNECTOR_TYPE_LVDS = 7,
 | 
			
		||||
  META_CONNECTOR_TYPE_Component = 8,
 | 
			
		||||
  META_CONNECTOR_TYPE_9PinDIN = 9,
 | 
			
		||||
  META_CONNECTOR_TYPE_DisplayPort = 10,
 | 
			
		||||
  META_CONNECTOR_TYPE_HDMIA = 11,
 | 
			
		||||
  META_CONNECTOR_TYPE_HDMIB = 12,
 | 
			
		||||
  META_CONNECTOR_TYPE_TV = 13,
 | 
			
		||||
  META_CONNECTOR_TYPE_eDP = 14,
 | 
			
		||||
  META_CONNECTOR_TYPE_VIRTUAL = 15,
 | 
			
		||||
  META_CONNECTOR_TYPE_DSI = 16,
 | 
			
		||||
} MetaConnectorType;
 | 
			
		||||
 | 
			
		||||
struct _MetaOutput
 | 
			
		||||
{
 | 
			
		||||
  /* The CRTC driving this output, NULL if the output is not enabled */
 | 
			
		||||
@@ -84,6 +104,8 @@ struct _MetaOutput
 | 
			
		||||
  CoglSubpixelOrder subpixel_order;
 | 
			
		||||
  int scale;
 | 
			
		||||
 | 
			
		||||
  MetaConnectorType connector_type;
 | 
			
		||||
 | 
			
		||||
  MetaMonitorMode *preferred_mode;
 | 
			
		||||
  MetaMonitorMode **modes;
 | 
			
		||||
  unsigned int n_modes;
 | 
			
		||||
@@ -116,6 +138,8 @@ struct _MetaOutput
 | 
			
		||||
 | 
			
		||||
  /* get a new preferred mode on hotplug events, to handle dynamic guest resizing */
 | 
			
		||||
  gboolean hotplug_mode_update;
 | 
			
		||||
  gint suggested_x;
 | 
			
		||||
  gint suggested_y;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaCRTC
 | 
			
		||||
@@ -297,10 +321,6 @@ struct _MetaMonitorManagerClass
 | 
			
		||||
                          unsigned short     *);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType meta_monitor_manager_get_type (void);
 | 
			
		||||
 | 
			
		||||
MetaMonitorManager *meta_monitor_manager_get  (void);
 | 
			
		||||
 | 
			
		||||
void                meta_monitor_manager_rebuild_derived   (MetaMonitorManager *manager);
 | 
			
		||||
 | 
			
		||||
MetaMonitorInfo    *meta_monitor_manager_get_monitor_infos (MetaMonitorManager *manager,
 | 
			
		||||
@@ -336,14 +356,19 @@ void                meta_monitor_manager_apply_configuration (MetaMonitorManager
 | 
			
		||||
void                meta_monitor_manager_confirm_configuration (MetaMonitorManager *manager,
 | 
			
		||||
                                                                gboolean            ok);
 | 
			
		||||
 | 
			
		||||
void               meta_output_parse_edid (MetaOutput *output,
 | 
			
		||||
                                           GBytes     *edid);
 | 
			
		||||
 | 
			
		||||
void               meta_crtc_info_free   (MetaCRTCInfo   *info);
 | 
			
		||||
void               meta_output_info_free (MetaOutputInfo *info);
 | 
			
		||||
 | 
			
		||||
void               meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
 | 
			
		||||
                                                           int         n_old_outputs);
 | 
			
		||||
void               meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
 | 
			
		||||
                                                         int              n_old_modes);
 | 
			
		||||
gboolean           meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager);
 | 
			
		||||
void               meta_monitor_manager_read_current_config (MetaMonitorManager *manager);
 | 
			
		||||
void               meta_monitor_manager_on_hotplug (MetaMonitorManager *manager);
 | 
			
		||||
 | 
			
		||||
gboolean           meta_monitor_manager_get_monitor_matrix (MetaMonitorManager *manager,
 | 
			
		||||
                                                            MetaOutput         *output,
 | 
			
		||||
                                                            gfloat              matrix[6]);
 | 
			
		||||
 | 
			
		||||
/* Returns true if transform causes width and height to be inverted
 | 
			
		||||
   This is true for the odd transforms in the enum */
 | 
			
		||||
@@ -25,7 +25,7 @@
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-monitor-manager.h"
 | 
			
		||||
#include "meta-monitor-manager-private.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
@@ -35,6 +35,7 @@
 | 
			
		||||
#include <meta/main.h>
 | 
			
		||||
#include "util-private.h"
 | 
			
		||||
#include <meta/errors.h>
 | 
			
		||||
#include "edid.h"
 | 
			
		||||
#include "meta-monitor-config.h"
 | 
			
		||||
#include "backends/x11/meta-monitor-manager-xrandr.h"
 | 
			
		||||
#include "meta-backend-private.h"
 | 
			
		||||
@@ -44,10 +45,16 @@ enum {
 | 
			
		||||
  SIGNALS_LAST
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
  PROP_0,
 | 
			
		||||
  PROP_POWER_SAVE_MODE,
 | 
			
		||||
  PROP_LAST
 | 
			
		||||
/* Array index matches MetaMonitorTransform */
 | 
			
		||||
static gfloat transform_matrices[][6] = {
 | 
			
		||||
  {  1,  0,  0,  0,  1,  0 }, /* normal */
 | 
			
		||||
  {  0, -1,  1,  1,  0,  0 }, /* 90° */
 | 
			
		||||
  { -1,  0,  1,  0, -1,  1 }, /* 180° */
 | 
			
		||||
  {  0,  1,  0, -1,  0,  1 }, /* 270° */
 | 
			
		||||
  { -1,  0,  1,  0,  1,  0 }, /* normal flipped */
 | 
			
		||||
  {  0,  1,  0,  1,  0,  0 }, /* 90° flipped */
 | 
			
		||||
  {  1,  0,  0,  0, -1,  1 }, /* 180° flipped */
 | 
			
		||||
  {  0, -1,  1, -1,  0,  1 }, /* 270° flipped */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int signals[SIGNALS_LAST];
 | 
			
		||||
@@ -64,14 +71,6 @@ meta_monitor_manager_init (MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
read_current_config (MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
  manager->serial++;
 | 
			
		||||
 | 
			
		||||
  META_MONITOR_MANAGER_GET_CLASS (manager)->read_current (manager);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * make_logical_config:
 | 
			
		||||
 *
 | 
			
		||||
@@ -167,16 +166,44 @@ make_logical_config (MetaMonitorManager *manager)
 | 
			
		||||
  manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
power_save_mode_changed (MetaMonitorManager *manager,
 | 
			
		||||
                         GParamSpec         *pspec,
 | 
			
		||||
                         gpointer            user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerClass *klass;
 | 
			
		||||
  int mode = meta_dbus_display_config_get_power_save_mode (META_DBUS_DISPLAY_CONFIG (manager));
 | 
			
		||||
 | 
			
		||||
  if (mode == META_POWER_SAVE_UNSUPPORTED)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  /* If DPMS is unsupported, force the property back. */
 | 
			
		||||
  if (manager->power_save_mode == META_POWER_SAVE_UNSUPPORTED)
 | 
			
		||||
    {
 | 
			
		||||
      meta_dbus_display_config_set_power_save_mode (META_DBUS_DISPLAY_CONFIG (manager), META_POWER_SAVE_UNSUPPORTED);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  klass = META_MONITOR_MANAGER_GET_CLASS (manager);
 | 
			
		||||
  if (klass->set_power_save_mode)
 | 
			
		||||
    klass->set_power_save_mode (manager, mode);
 | 
			
		||||
 | 
			
		||||
  manager->power_save_mode = mode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_constructed (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManager *manager = META_MONITOR_MANAGER (object);
 | 
			
		||||
 | 
			
		||||
  g_signal_connect_object (manager, "notify::power-save-mode",
 | 
			
		||||
                           G_CALLBACK (power_save_mode_changed), manager, 0);
 | 
			
		||||
 | 
			
		||||
  manager->in_init = TRUE;
 | 
			
		||||
 | 
			
		||||
  manager->config = meta_monitor_config_new ();
 | 
			
		||||
 | 
			
		||||
  read_current_config (manager);
 | 
			
		||||
  meta_monitor_manager_read_current_config (manager);
 | 
			
		||||
 | 
			
		||||
  if (!meta_monitor_config_apply_stored (manager->config, manager))
 | 
			
		||||
    meta_monitor_config_make_default (manager->config, manager);
 | 
			
		||||
@@ -189,24 +216,7 @@ meta_monitor_manager_constructed (GObject *object)
 | 
			
		||||
     so this is not needed.
 | 
			
		||||
  */
 | 
			
		||||
  if (META_IS_MONITOR_MANAGER_XRANDR (manager))
 | 
			
		||||
    {
 | 
			
		||||
      MetaOutput *old_outputs;
 | 
			
		||||
      MetaCRTC *old_crtcs;
 | 
			
		||||
      MetaMonitorMode *old_modes;
 | 
			
		||||
      unsigned int n_old_outputs, n_old_modes;
 | 
			
		||||
 | 
			
		||||
      old_outputs = manager->outputs;
 | 
			
		||||
      n_old_outputs = manager->n_outputs;
 | 
			
		||||
      old_modes = manager->modes;
 | 
			
		||||
      n_old_modes = manager->n_modes;
 | 
			
		||||
      old_crtcs = manager->crtcs;
 | 
			
		||||
 | 
			
		||||
      read_current_config (manager);
 | 
			
		||||
 | 
			
		||||
      meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
 | 
			
		||||
      meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
 | 
			
		||||
      g_free (old_crtcs);
 | 
			
		||||
    }
 | 
			
		||||
    meta_monitor_manager_read_current_config (manager);
 | 
			
		||||
 | 
			
		||||
  make_logical_config (manager);
 | 
			
		||||
  initialize_dbus_interface (manager);
 | 
			
		||||
@@ -215,23 +225,6 @@ meta_monitor_manager_constructed (GObject *object)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_set_power_save_mode (MetaMonitorManager *manager,
 | 
			
		||||
                                          MetaPowerSave       mode)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerClass *klass;
 | 
			
		||||
 | 
			
		||||
  if (manager->power_save_mode == META_POWER_SAVE_UNSUPPORTED ||
 | 
			
		||||
      mode == META_POWER_SAVE_UNSUPPORTED)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  klass = META_MONITOR_MANAGER_GET_CLASS (manager);
 | 
			
		||||
  if (klass->set_power_save_mode)
 | 
			
		||||
    klass->set_power_save_mode (manager, mode);
 | 
			
		||||
 | 
			
		||||
  manager->power_save_mode = mode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
 | 
			
		||||
                                        int         n_old_outputs)
 | 
			
		||||
{
 | 
			
		||||
@@ -254,7 +247,7 @@ meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
 | 
			
		||||
  g_free (old_outputs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
 | 
			
		||||
                                      int              n_old_modes)
 | 
			
		||||
{
 | 
			
		||||
@@ -298,44 +291,6 @@ meta_monitor_manager_dispose (GObject *object)
 | 
			
		||||
  G_OBJECT_CLASS (meta_monitor_manager_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_set_property (GObject      *object,
 | 
			
		||||
                                   guint         prop_id,
 | 
			
		||||
                                   const GValue *value,
 | 
			
		||||
                                   GParamSpec   *pspec)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManager *self = META_MONITOR_MANAGER (object);
 | 
			
		||||
 | 
			
		||||
  switch (prop_id)
 | 
			
		||||
    {
 | 
			
		||||
    case PROP_POWER_SAVE_MODE:
 | 
			
		||||
      meta_monitor_manager_set_power_save_mode (self, g_value_get_int (value));
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_get_property (GObject      *object,
 | 
			
		||||
                                   guint         prop_id,
 | 
			
		||||
                                   GValue       *value,
 | 
			
		||||
                                   GParamSpec   *pspec)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManager *self = META_MONITOR_MANAGER (object);
 | 
			
		||||
 | 
			
		||||
  switch (prop_id)
 | 
			
		||||
    {
 | 
			
		||||
    case PROP_POWER_SAVE_MODE:
 | 
			
		||||
      g_value_set_int (value, self->power_save_mode);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GBytes *
 | 
			
		||||
meta_monitor_manager_real_read_edid (MetaMonitorManager *manager,
 | 
			
		||||
                                     MetaOutput         *output)
 | 
			
		||||
@@ -356,8 +311,6 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->constructed = meta_monitor_manager_constructed;
 | 
			
		||||
  object_class->get_property = meta_monitor_manager_get_property;
 | 
			
		||||
  object_class->set_property = meta_monitor_manager_set_property;
 | 
			
		||||
  object_class->dispose = meta_monitor_manager_dispose;
 | 
			
		||||
  object_class->finalize = meta_monitor_manager_finalize;
 | 
			
		||||
 | 
			
		||||
@@ -371,8 +324,6 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
 | 
			
		||||
		  0,
 | 
			
		||||
                  NULL, NULL, NULL,
 | 
			
		||||
		  G_TYPE_NONE, 0);
 | 
			
		||||
 | 
			
		||||
  g_object_class_override_property (object_class, PROP_POWER_SAVE_MODE, "power-save-mode");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const double known_diagonals[] = {
 | 
			
		||||
@@ -406,11 +357,14 @@ make_display_name (MetaMonitorManager *manager,
 | 
			
		||||
  char *vendor_name = NULL;
 | 
			
		||||
  char *ret;
 | 
			
		||||
 | 
			
		||||
  if (g_str_has_prefix (output->name, "LVDS") ||
 | 
			
		||||
      g_str_has_prefix (output->name, "eDP"))
 | 
			
		||||
  switch (output->connector_type)
 | 
			
		||||
    {
 | 
			
		||||
    case META_CONNECTOR_TYPE_LVDS:
 | 
			
		||||
    case META_CONNECTOR_TYPE_eDP:
 | 
			
		||||
      ret = g_strdup (_("Built-in display"));
 | 
			
		||||
      goto out;
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (output->width_mm > 0 && output->height_mm > 0)
 | 
			
		||||
@@ -458,6 +412,32 @@ make_display_name (MetaMonitorManager *manager,
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *
 | 
			
		||||
get_connector_type_name (MetaConnectorType connector_type)
 | 
			
		||||
{
 | 
			
		||||
  switch (connector_type)
 | 
			
		||||
    {
 | 
			
		||||
    case META_CONNECTOR_TYPE_Unknown: return "Unknown";
 | 
			
		||||
    case META_CONNECTOR_TYPE_VGA: return "VGA";
 | 
			
		||||
    case META_CONNECTOR_TYPE_DVII: return "DVII";
 | 
			
		||||
    case META_CONNECTOR_TYPE_DVID: return "DVID";
 | 
			
		||||
    case META_CONNECTOR_TYPE_DVIA: return "DVIA";
 | 
			
		||||
    case META_CONNECTOR_TYPE_Composite: return "Composite";
 | 
			
		||||
    case META_CONNECTOR_TYPE_SVIDEO: return "SVIDEO";
 | 
			
		||||
    case META_CONNECTOR_TYPE_LVDS: return "LVDS";
 | 
			
		||||
    case META_CONNECTOR_TYPE_Component: return "Component";
 | 
			
		||||
    case META_CONNECTOR_TYPE_9PinDIN: return "9PinDIN";
 | 
			
		||||
    case META_CONNECTOR_TYPE_DisplayPort: return "DisplayPort";
 | 
			
		||||
    case META_CONNECTOR_TYPE_HDMIA: return "HDMIA";
 | 
			
		||||
    case META_CONNECTOR_TYPE_HDMIB: return "HDMIB";
 | 
			
		||||
    case META_CONNECTOR_TYPE_TV: return "TV";
 | 
			
		||||
    case META_CONNECTOR_TYPE_eDP: return "eDP";
 | 
			
		||||
    case META_CONNECTOR_TYPE_VIRTUAL: return "VIRTUAL";
 | 
			
		||||
    case META_CONNECTOR_TYPE_DSI: return "DSI";
 | 
			
		||||
    default: g_assert_not_reached ();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
 | 
			
		||||
                                           GDBusMethodInvocation *invocation)
 | 
			
		||||
@@ -538,6 +518,8 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
 | 
			
		||||
                             g_variant_new_boolean (output->is_primary));
 | 
			
		||||
      g_variant_builder_add (&properties, "{sv}", "presentation",
 | 
			
		||||
                             g_variant_new_boolean (output->is_presentation));
 | 
			
		||||
      g_variant_builder_add (&properties, "{sv}", "connector-type",
 | 
			
		||||
                             g_variant_new_string (get_connector_type_name (output->connector_type)));
 | 
			
		||||
 | 
			
		||||
      edid_file = manager_class->get_edid_file (manager, output);
 | 
			
		||||
      if (edid_file)
 | 
			
		||||
@@ -1125,6 +1107,13 @@ initialize_dbus_interface (MetaMonitorManager *manager)
 | 
			
		||||
                                          g_object_unref);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_monitor_manager_get:
 | 
			
		||||
 *
 | 
			
		||||
 * Accessor for the singleton MetaMonitorManager.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: (transfer none): The only #MetaMonitorManager there is.
 | 
			
		||||
 */
 | 
			
		||||
MetaMonitorManager *
 | 
			
		||||
meta_monitor_manager_get (void)
 | 
			
		||||
{
 | 
			
		||||
@@ -1199,6 +1188,31 @@ meta_monitor_manager_get_screen_limits (MetaMonitorManager *manager,
 | 
			
		||||
  *height = manager->max_screen_height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_monitor_manager_read_current_config (MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
  MetaOutput *old_outputs;
 | 
			
		||||
  MetaCRTC *old_crtcs;
 | 
			
		||||
  MetaMonitorMode *old_modes;
 | 
			
		||||
  unsigned int n_old_outputs, n_old_modes;
 | 
			
		||||
 | 
			
		||||
  /* Some implementations of read_current use the existing information
 | 
			
		||||
   * we have available, so don't free the old configuration until after
 | 
			
		||||
   * read_current finishes. */
 | 
			
		||||
  old_outputs = manager->outputs;
 | 
			
		||||
  n_old_outputs = manager->n_outputs;
 | 
			
		||||
  old_modes = manager->modes;
 | 
			
		||||
  n_old_modes = manager->n_modes;
 | 
			
		||||
  old_crtcs = manager->crtcs;
 | 
			
		||||
 | 
			
		||||
  manager->serial++;
 | 
			
		||||
  META_MONITOR_MANAGER_GET_CLASS (manager)->read_current (manager);
 | 
			
		||||
 | 
			
		||||
  meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
 | 
			
		||||
  meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
 | 
			
		||||
  g_free (old_crtcs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
@@ -1216,3 +1230,141 @@ meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager)
 | 
			
		||||
  g_free (old_monitor_infos);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_output_parse_edid (MetaOutput *meta_output,
 | 
			
		||||
                        GBytes     *edid)
 | 
			
		||||
{
 | 
			
		||||
  MonitorInfo *parsed_edid;
 | 
			
		||||
  gsize len;
 | 
			
		||||
 | 
			
		||||
  if (!edid)
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  parsed_edid = decode_edid (g_bytes_get_data (edid, &len));
 | 
			
		||||
 | 
			
		||||
  if (parsed_edid)
 | 
			
		||||
    {
 | 
			
		||||
      meta_output->vendor = g_strndup (parsed_edid->manufacturer_code, 4);
 | 
			
		||||
      if (parsed_edid->dsc_product_name[0])
 | 
			
		||||
        meta_output->product = g_strndup (parsed_edid->dsc_product_name, 14);
 | 
			
		||||
      else
 | 
			
		||||
        meta_output->product = g_strdup_printf ("0x%04x", (unsigned) parsed_edid->product_code);
 | 
			
		||||
      if (parsed_edid->dsc_serial_number[0])
 | 
			
		||||
        meta_output->serial = g_strndup (parsed_edid->dsc_serial_number, 14);
 | 
			
		||||
      else
 | 
			
		||||
        meta_output->serial = g_strdup_printf ("0x%08x", parsed_edid->serial_number);
 | 
			
		||||
 | 
			
		||||
      g_free (parsed_edid);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  if (!meta_output->vendor)
 | 
			
		||||
    {
 | 
			
		||||
      meta_output->vendor = g_strdup ("unknown");
 | 
			
		||||
      meta_output->product = g_strdup ("unknown");
 | 
			
		||||
      meta_output->serial = g_strdup ("unknown");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_monitor_manager_on_hotplug (MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
  gboolean applied_config = FALSE;
 | 
			
		||||
 | 
			
		||||
  /* If the monitor has hotplug_mode_update (which is used by VMs), don't bother
 | 
			
		||||
   * applying our stored configuration, because it's likely the user just resizing
 | 
			
		||||
   * the window.
 | 
			
		||||
   */
 | 
			
		||||
  if (!meta_monitor_manager_has_hotplug_mode_update (manager))
 | 
			
		||||
    {
 | 
			
		||||
      if (meta_monitor_config_apply_stored (manager->config, manager))
 | 
			
		||||
        applied_config = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* If we haven't applied any configuration, apply the default configuration. */
 | 
			
		||||
  if (!applied_config)
 | 
			
		||||
    meta_monitor_config_make_default (manager->config, manager);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
calculate_viewport_matrix (MetaMonitorManager *manager,
 | 
			
		||||
                           MetaOutput         *output,
 | 
			
		||||
                           gfloat              viewport[6])
 | 
			
		||||
{
 | 
			
		||||
  gfloat x, y, width, height;
 | 
			
		||||
 | 
			
		||||
  if (!output->crtc)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  x = (float) output->crtc->rect.x / manager->screen_width;
 | 
			
		||||
  y = (float) output->crtc->rect.y / manager->screen_height;
 | 
			
		||||
  width  = (float) output->crtc->rect.width / manager->screen_width;
 | 
			
		||||
  height = (float) output->crtc->rect.height / manager->screen_height;
 | 
			
		||||
 | 
			
		||||
  viewport[0] = width;
 | 
			
		||||
  viewport[1] = 0.0f;
 | 
			
		||||
  viewport[2] = x;
 | 
			
		||||
  viewport[3] = 0.0f;
 | 
			
		||||
  viewport[4] = height;
 | 
			
		||||
  viewport[5] = y;
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
multiply_matrix (float a[6],
 | 
			
		||||
		 float b[6],
 | 
			
		||||
		 float res[6])
 | 
			
		||||
{
 | 
			
		||||
  res[0] = a[0] * b[0] + a[1] * b[3];
 | 
			
		||||
  res[1] = a[0] * b[1] + a[1] * b[4];
 | 
			
		||||
  res[2] = a[0] * b[2] + a[1] * b[5] + a[2];
 | 
			
		||||
  res[3] = a[3] * b[0] + a[4] * b[3];
 | 
			
		||||
  res[4] = a[3] * b[1] + a[4] * b[4];
 | 
			
		||||
  res[5] = a[3] * b[2] + a[4] * b[5] + a[5];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_monitor_manager_get_monitor_matrix (MetaMonitorManager *manager,
 | 
			
		||||
                                         MetaOutput         *output,
 | 
			
		||||
                                         gfloat              matrix[6])
 | 
			
		||||
{
 | 
			
		||||
  gfloat viewport[9];
 | 
			
		||||
 | 
			
		||||
  if (!calculate_viewport_matrix (manager, output, viewport))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  multiply_matrix (viewport, transform_matrices[output->crtc->transform],
 | 
			
		||||
                   matrix);
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_monitor_manager_get_output_geometry:
 | 
			
		||||
 * @manager: A #MetaMonitorManager
 | 
			
		||||
 * @id: A valid #MetaOutput id
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: The monitor index or -1 if @id isn't valid or the output
 | 
			
		||||
 * isn't associated with a logical monitor.
 | 
			
		||||
 */
 | 
			
		||||
gint
 | 
			
		||||
meta_monitor_manager_get_monitor_for_output (MetaMonitorManager *manager,
 | 
			
		||||
                                             guint               id)
 | 
			
		||||
{
 | 
			
		||||
  MetaOutput *output;
 | 
			
		||||
  guint i;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (META_IS_MONITOR_MANAGER (manager), -1);
 | 
			
		||||
  g_return_val_if_fail (id < manager->n_outputs, -1);
 | 
			
		||||
 | 
			
		||||
  output = &manager->outputs[id];
 | 
			
		||||
  if (!output || !output->crtc)
 | 
			
		||||
    return -1;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < manager->n_monitor_infos; i++)
 | 
			
		||||
    if (meta_rectangle_contains_rect (&manager->monitor_infos[i].rect,
 | 
			
		||||
                                      &output->crtc->rect))
 | 
			
		||||
      return i;
 | 
			
		||||
 | 
			
		||||
  return -1;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								src/backends/native/meta-backend-native-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/backends/native/meta-backend-native-private.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2015 Red Hat
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
 * published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 | 
			
		||||
 * 02111-1307, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * Written by:
 | 
			
		||||
 *     Jonas Ådahl <jadahl@gmail.com>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef META_BACKEND_NATIVE_PRIVATE_H
 | 
			
		||||
#define META_BACKEND_NATIVE_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include "backends/native/meta-barrier-native.h"
 | 
			
		||||
 | 
			
		||||
MetaBarrierManagerNative *meta_backend_native_get_barrier_manager (MetaBackendNative *native);
 | 
			
		||||
 | 
			
		||||
#endif /* META_BACKEND_NATIVE_PRIVATE_H */
 | 
			
		||||
@@ -24,10 +24,13 @@
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-backend-native.h"
 | 
			
		||||
#include "meta-backend-native-private.h"
 | 
			
		||||
 | 
			
		||||
#include <meta/main.h>
 | 
			
		||||
#include <clutter/evdev/clutter-evdev.h>
 | 
			
		||||
#include "meta-backend-native.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-barrier-native.h"
 | 
			
		||||
#include "meta-idle-monitor-native.h"
 | 
			
		||||
#include "meta-monitor-manager-kms.h"
 | 
			
		||||
#include "meta-cursor-renderer-native.h"
 | 
			
		||||
@@ -36,11 +39,42 @@
 | 
			
		||||
struct _MetaBackendNativePrivate
 | 
			
		||||
{
 | 
			
		||||
  MetaLauncher *launcher;
 | 
			
		||||
 | 
			
		||||
  MetaBarrierManagerNative *barrier_manager;
 | 
			
		||||
 | 
			
		||||
  GSettings *keyboard_settings;
 | 
			
		||||
};
 | 
			
		||||
typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate;
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendNative, meta_backend_native, META_TYPE_BACKEND);
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_backend_native_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackendNative *native = META_BACKEND_NATIVE (object);
 | 
			
		||||
  MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
 | 
			
		||||
 | 
			
		||||
  meta_launcher_free (priv->launcher);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_backend_native_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
constrain_to_barriers (ClutterInputDevice *device,
 | 
			
		||||
                       guint32             time,
 | 
			
		||||
                       float              *new_x,
 | 
			
		||||
                       float              *new_y)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackendNative *native = META_BACKEND_NATIVE (meta_get_backend ());
 | 
			
		||||
  MetaBackendNativePrivate *priv =
 | 
			
		||||
    meta_backend_native_get_instance_private (native);
 | 
			
		||||
 | 
			
		||||
  meta_barrier_manager_native_process (priv->barrier_manager,
 | 
			
		||||
                                       device,
 | 
			
		||||
                                       time,
 | 
			
		||||
                                       new_x, new_y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The pointer constrain code is mostly a rip-off of the XRandR code from Xorg.
 | 
			
		||||
 * (from xserver/randr/rrcrtc.c, RRConstrainCursorHarder)
 | 
			
		||||
@@ -130,6 +164,9 @@ pointer_constrain_callback (ClutterInputDevice *device,
 | 
			
		||||
  unsigned int n_monitors;
 | 
			
		||||
  gboolean ret;
 | 
			
		||||
 | 
			
		||||
  /* Constrain to barriers */
 | 
			
		||||
  constrain_to_barriers (device, time, new_x, new_y);
 | 
			
		||||
 | 
			
		||||
  monitor_manager = meta_monitor_manager_get ();
 | 
			
		||||
  monitors = meta_monitor_manager_get_monitor_infos (monitor_manager, &n_monitors);
 | 
			
		||||
 | 
			
		||||
@@ -236,6 +273,9 @@ static void
 | 
			
		||||
meta_backend_native_class_init (MetaBackendNativeClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->finalize = meta_backend_native_finalize;
 | 
			
		||||
 | 
			
		||||
  backend_class->post_init = meta_backend_native_post_init;
 | 
			
		||||
  backend_class->create_idle_monitor = meta_backend_native_create_idle_monitor;
 | 
			
		||||
@@ -255,6 +295,8 @@ meta_backend_native_init (MetaBackendNative *native)
 | 
			
		||||
 | 
			
		||||
  /* We're a display server, so start talking to weston-launch. */
 | 
			
		||||
  priv->launcher = meta_launcher_new ();
 | 
			
		||||
 | 
			
		||||
  priv->barrier_manager = meta_barrier_manager_native_new ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
@@ -267,11 +309,20 @@ meta_activate_vt (int vt, GError **error)
 | 
			
		||||
  return meta_launcher_activate_vt (priv->launcher, vt, error);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaBarrierManagerNative *
 | 
			
		||||
meta_backend_native_get_barrier_manager (MetaBackendNative *native)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackendNativePrivate *priv =
 | 
			
		||||
    meta_backend_native_get_instance_private (native);
 | 
			
		||||
 | 
			
		||||
  return priv->barrier_manager;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_activate_session:
 | 
			
		||||
 *
 | 
			
		||||
 * Tells mutter to activate the session. When mutter is a
 | 
			
		||||
 * Wayland compositor, this tells logind to switch over to
 | 
			
		||||
 * display server, this tells logind to switch over to
 | 
			
		||||
 * the new session.
 | 
			
		||||
 */
 | 
			
		||||
gboolean
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										744
									
								
								src/backends/native/meta-barrier-native.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										744
									
								
								src/backends/native/meta-barrier-native.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,744 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2015 Red Hat
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
 * published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 | 
			
		||||
 * 02111-1307, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * Written by:
 | 
			
		||||
 *     Jonas Ådahl <jadahl@gmail.com>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SECTION:barrier-native
 | 
			
		||||
 * @Title: MetaBarrierImplNative
 | 
			
		||||
 * @Short_Description: Pointer barriers implementation for the native backend
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include <meta/barrier.h>
 | 
			
		||||
#include <meta/util.h>
 | 
			
		||||
#include "backends/meta-backend-private.h"
 | 
			
		||||
#include "backends/meta-barrier-private.h"
 | 
			
		||||
#include "backends/native/meta-backend-native.h"
 | 
			
		||||
#include "backends/native/meta-backend-native-private.h"
 | 
			
		||||
#include "backends/native/meta-barrier-native.h"
 | 
			
		||||
 | 
			
		||||
struct _MetaBarrierManagerNative
 | 
			
		||||
{
 | 
			
		||||
  GHashTable *barriers;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  /* The barrier is active and responsive to pointer motion. */
 | 
			
		||||
  META_BARRIER_STATE_ACTIVE,
 | 
			
		||||
 | 
			
		||||
  /* An intermediate state after a pointer hit the pointer barrier. */
 | 
			
		||||
  META_BARRIER_STATE_HIT,
 | 
			
		||||
 | 
			
		||||
  /* The barrier was hit by a pointer and is still within the hit box and
 | 
			
		||||
   * has not been released.*/
 | 
			
		||||
  META_BARRIER_STATE_HELD,
 | 
			
		||||
 | 
			
		||||
  /* The pointer was released by the user. If the following motion hits
 | 
			
		||||
   * the barrier, it will pass through. */
 | 
			
		||||
  META_BARRIER_STATE_RELEASE,
 | 
			
		||||
 | 
			
		||||
  /* An intermediate state when the pointer has left the barrier. */
 | 
			
		||||
  META_BARRIER_STATE_LEFT,
 | 
			
		||||
} MetaBarrierState;
 | 
			
		||||
 | 
			
		||||
struct _MetaBarrierImplNativePrivate
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrier              *barrier;
 | 
			
		||||
  MetaBarrierManagerNative *manager;
 | 
			
		||||
 | 
			
		||||
  gboolean                  is_active;
 | 
			
		||||
  MetaBarrierState          state;
 | 
			
		||||
  int                       trigger_serial;
 | 
			
		||||
  guint32                   last_event_time;
 | 
			
		||||
  MetaBarrierDirection      blocked_dir;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaBarrierImplNative, meta_barrier_impl_native,
 | 
			
		||||
                            META_TYPE_BARRIER_IMPL)
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
next_serial (void)
 | 
			
		||||
{
 | 
			
		||||
  static int barrier_serial = 1;
 | 
			
		||||
 | 
			
		||||
  barrier_serial++;
 | 
			
		||||
 | 
			
		||||
  /* If it wraps, avoid 0 as it's not a valid serial. */
 | 
			
		||||
  if (barrier_serial == 0)
 | 
			
		||||
    barrier_serial++;
 | 
			
		||||
 | 
			
		||||
  return barrier_serial;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct _Vector2
 | 
			
		||||
{
 | 
			
		||||
  float x, y;
 | 
			
		||||
} Vector2;
 | 
			
		||||
 | 
			
		||||
static float
 | 
			
		||||
vector2_cross_product (Vector2 a, Vector2 b)
 | 
			
		||||
{
 | 
			
		||||
  return a.x * b.y - a.y * b.x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Vector2
 | 
			
		||||
vector2_add (Vector2 a, Vector2 b)
 | 
			
		||||
{
 | 
			
		||||
  return (Vector2) {
 | 
			
		||||
    .x = a.x + b.x,
 | 
			
		||||
    .y = a.y + b.y,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Vector2
 | 
			
		||||
vector2_subtract (Vector2 a, Vector2 b)
 | 
			
		||||
{
 | 
			
		||||
  return (Vector2) {
 | 
			
		||||
    .x = a.x - b.x,
 | 
			
		||||
    .y = a.y - b.y,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Vector2
 | 
			
		||||
vector2_multiply_constant (float c, Vector2 a)
 | 
			
		||||
{
 | 
			
		||||
  return (Vector2) {
 | 
			
		||||
    .x = c * a.x,
 | 
			
		||||
    .y = c * a.y,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct _Line2
 | 
			
		||||
{
 | 
			
		||||
  Vector2 a;
 | 
			
		||||
  Vector2 b;
 | 
			
		||||
} Line2;
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
lines_intersect (Line2 *line1, Line2 *line2, Vector2 *intersection)
 | 
			
		||||
{
 | 
			
		||||
  Vector2 p = line1->a;
 | 
			
		||||
  Vector2 r = vector2_subtract (line1->b, line1->a);
 | 
			
		||||
  Vector2 q = line2->a;
 | 
			
		||||
  Vector2 s = vector2_subtract (line2->b, line2->a);
 | 
			
		||||
  float rxs;
 | 
			
		||||
  float sxr;
 | 
			
		||||
  float t;
 | 
			
		||||
  float u;
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * The line (p, r) and (q, s) intersects where
 | 
			
		||||
   *
 | 
			
		||||
   *   p + t r = q + u s
 | 
			
		||||
   *
 | 
			
		||||
   * Calculate t:
 | 
			
		||||
   *
 | 
			
		||||
   *   (p + t r) × s = (q + u s) × s
 | 
			
		||||
   *   p × s + t (r × s) = q × s + u (s × s)
 | 
			
		||||
   *   p × s + t (r × s) = q × s
 | 
			
		||||
   *   t (r × s) = q × s - p × s
 | 
			
		||||
   *   t (r × s) = (q - p) × s
 | 
			
		||||
   *   t = ((q - p) × s) / (r × s)
 | 
			
		||||
   *
 | 
			
		||||
   * Using the same method, for u we get:
 | 
			
		||||
   *
 | 
			
		||||
   *   u = ((p - q) × r) / (s × r)
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  rxs = vector2_cross_product (r, s);
 | 
			
		||||
  sxr = vector2_cross_product (s, r);
 | 
			
		||||
 | 
			
		||||
  /* If r × s = 0 then the lines are either parallel or collinear. */
 | 
			
		||||
  if (fabs ( rxs) < DBL_MIN)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  t = vector2_cross_product (vector2_subtract (q, p), s) / rxs;
 | 
			
		||||
  u = vector2_cross_product (vector2_subtract (p, q), r) / sxr;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  /* The lines only intersect if 0 ≤ t ≤ 1 and 0 ≤ u ≤ 1. */
 | 
			
		||||
  if (t < 0.0 || t > 1.0 || u < 0.0 || u > 1.0)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  *intersection = vector2_add (p, vector2_multiply_constant (t, r));
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
is_barrier_horizontal (MetaBarrier *barrier)
 | 
			
		||||
{
 | 
			
		||||
  return barrier->priv->y1 == barrier->priv->y2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
is_barrier_blocking_directions (MetaBarrier         *barrier,
 | 
			
		||||
                                MetaBarrierDirection directions)
 | 
			
		||||
{
 | 
			
		||||
  /* Barriers doesn't block parallel motions. */
 | 
			
		||||
  if (is_barrier_horizontal (barrier))
 | 
			
		||||
    {
 | 
			
		||||
      if ((directions & (META_BARRIER_DIRECTION_POSITIVE_Y |
 | 
			
		||||
                         META_BARRIER_DIRECTION_NEGATIVE_Y)) == 0)
 | 
			
		||||
        return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      if ((directions & (META_BARRIER_DIRECTION_POSITIVE_X |
 | 
			
		||||
                         META_BARRIER_DIRECTION_NEGATIVE_X)) == 0)
 | 
			
		||||
        return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return (barrier->priv->directions & directions) != directions;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
dismiss_pointer (MetaBarrierImplNative *self)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierImplNativePrivate *priv =
 | 
			
		||||
    meta_barrier_impl_native_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
  priv->state = META_BARRIER_STATE_LEFT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Line2
 | 
			
		||||
barrier_to_line (MetaBarrier *barrier)
 | 
			
		||||
{
 | 
			
		||||
  return (Line2) {
 | 
			
		||||
    .a = (Vector2) {
 | 
			
		||||
      .x = MIN (barrier->priv->x1, barrier->priv->x2),
 | 
			
		||||
      .y = MIN (barrier->priv->y1, barrier->priv->y2),
 | 
			
		||||
    },
 | 
			
		||||
    .b = (Vector2) {
 | 
			
		||||
      .x = MAX (barrier->priv->x1, barrier->priv->x2),
 | 
			
		||||
      .y = MAX (barrier->priv->y1, barrier->priv->y2),
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Calculate the hit box for a held motion. The hit box is a 2 px wide region
 | 
			
		||||
 * in the opposite direction of every direction the barrier blocks. The purpose
 | 
			
		||||
 * of this is to allow small movements without receiving a "left" signal. This
 | 
			
		||||
 * heuristic comes from the X.org pointer barrier implementation.
 | 
			
		||||
 */
 | 
			
		||||
static Line2
 | 
			
		||||
calculate_barrier_hit_box (MetaBarrier *barrier)
 | 
			
		||||
{
 | 
			
		||||
  Line2 hit_box = barrier_to_line (barrier);
 | 
			
		||||
 | 
			
		||||
  if (is_barrier_horizontal (barrier))
 | 
			
		||||
    {
 | 
			
		||||
      if (is_barrier_blocking_directions (barrier,
 | 
			
		||||
                                          META_BARRIER_DIRECTION_POSITIVE_Y))
 | 
			
		||||
        hit_box.a.y -= 2.0f;
 | 
			
		||||
      if (is_barrier_blocking_directions (barrier,
 | 
			
		||||
                                          META_BARRIER_DIRECTION_NEGATIVE_Y))
 | 
			
		||||
        hit_box.b.y += 2.0f;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      if (is_barrier_blocking_directions (barrier,
 | 
			
		||||
                                          META_BARRIER_DIRECTION_POSITIVE_X))
 | 
			
		||||
        hit_box.a.x -= 2.0f;
 | 
			
		||||
      if (is_barrier_blocking_directions (barrier,
 | 
			
		||||
                                          META_BARRIER_DIRECTION_NEGATIVE_X))
 | 
			
		||||
        hit_box.b.x += 2.0f;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return hit_box;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
is_within_box (Line2 box, Vector2 point)
 | 
			
		||||
{
 | 
			
		||||
  return (point.x >= box.a.x && point.x < box.b.x &&
 | 
			
		||||
          point.y >= box.a.y && point.y < box.b.y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
maybe_release_barrier (gpointer key,
 | 
			
		||||
                       gpointer value,
 | 
			
		||||
                       gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierImplNative *self = key;
 | 
			
		||||
  MetaBarrierImplNativePrivate *priv =
 | 
			
		||||
    meta_barrier_impl_native_get_instance_private (self);
 | 
			
		||||
  MetaBarrier *barrier = priv->barrier;
 | 
			
		||||
  Line2 *motion = user_data;
 | 
			
		||||
  Line2 hit_box;
 | 
			
		||||
 | 
			
		||||
  if (priv->state != META_BARRIER_STATE_HELD)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  /* Release if we end up outside barrier end points. */
 | 
			
		||||
  if (is_barrier_horizontal (barrier))
 | 
			
		||||
    {
 | 
			
		||||
      if (motion->b.x > MAX (barrier->priv->x1, barrier->priv->x2) ||
 | 
			
		||||
          motion->b.x < MIN (barrier->priv->x1, barrier->priv->x2))
 | 
			
		||||
        {
 | 
			
		||||
          dismiss_pointer (self);
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      if (motion->b.y > MAX (barrier->priv->y1, barrier->priv->y2) ||
 | 
			
		||||
          motion->b.y < MIN (barrier->priv->y1, barrier->priv->y2))
 | 
			
		||||
        {
 | 
			
		||||
          dismiss_pointer (self);
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* Release if we don't intersect and end up outside of hit box. */
 | 
			
		||||
  hit_box = calculate_barrier_hit_box (barrier);
 | 
			
		||||
  if (!is_within_box (hit_box, motion->b))
 | 
			
		||||
    {
 | 
			
		||||
      dismiss_pointer (self);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
maybe_release_barriers (MetaBarrierManagerNative *manager,
 | 
			
		||||
                        float                     prev_x,
 | 
			
		||||
                        float                     prev_y,
 | 
			
		||||
                        float                     x,
 | 
			
		||||
                        float                     y)
 | 
			
		||||
{
 | 
			
		||||
  Line2 motion = {
 | 
			
		||||
    .a = {
 | 
			
		||||
      .x = prev_x,
 | 
			
		||||
      .y = prev_y,
 | 
			
		||||
    },
 | 
			
		||||
    .b = {
 | 
			
		||||
      .x = x,
 | 
			
		||||
      .y = y,
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  g_hash_table_foreach (manager->barriers,
 | 
			
		||||
                        maybe_release_barrier,
 | 
			
		||||
                        &motion);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaClosestBarrierData
 | 
			
		||||
{
 | 
			
		||||
  struct
 | 
			
		||||
  {
 | 
			
		||||
    Line2                       motion;
 | 
			
		||||
    MetaBarrierDirection        directions;
 | 
			
		||||
  } in;
 | 
			
		||||
 | 
			
		||||
  struct
 | 
			
		||||
  {
 | 
			
		||||
    float                       closest_distance_2;
 | 
			
		||||
    MetaBarrierImplNative      *barrier_impl;
 | 
			
		||||
  } out;
 | 
			
		||||
} MetaClosestBarrierData;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_closest_barrier (gpointer key,
 | 
			
		||||
                        gpointer value,
 | 
			
		||||
                        gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierImplNative *self = key;
 | 
			
		||||
  MetaBarrierImplNativePrivate *priv =
 | 
			
		||||
    meta_barrier_impl_native_get_instance_private (self);
 | 
			
		||||
  MetaBarrier *barrier = priv->barrier;
 | 
			
		||||
  MetaClosestBarrierData *data = user_data;
 | 
			
		||||
  Line2 barrier_line;
 | 
			
		||||
  Vector2 intersection;
 | 
			
		||||
  float dx, dy;
 | 
			
		||||
  float distance_2;
 | 
			
		||||
 | 
			
		||||
  /* Ignore if the barrier is not blocking in any of the motions directions. */
 | 
			
		||||
  if (!is_barrier_blocking_directions (barrier, data->in.directions))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  /* Ignore if the barrier released the pointer. */
 | 
			
		||||
  if (priv->state == META_BARRIER_STATE_RELEASE)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  /* Ignore if we are moving away from barrier. */
 | 
			
		||||
  if (priv->state == META_BARRIER_STATE_HELD &&
 | 
			
		||||
      (data->in.directions & priv->blocked_dir) == 0)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  /* Check if the motion intersects with the barrier, and retrieve the
 | 
			
		||||
   * intersection point if any. */
 | 
			
		||||
  barrier_line = (Line2) {
 | 
			
		||||
    .a = {
 | 
			
		||||
      .x = barrier->priv->x1,
 | 
			
		||||
      .y = barrier->priv->y1
 | 
			
		||||
    },
 | 
			
		||||
    .b = {
 | 
			
		||||
      .x = barrier->priv->x2,
 | 
			
		||||
      .y = barrier->priv->y2
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
  if (!lines_intersect (&barrier_line, &data->in.motion, &intersection))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  /* Calculate the distance to the barrier and keep track of the closest
 | 
			
		||||
   * barrier. */
 | 
			
		||||
  dx = intersection.x - data->in.motion.a.x;
 | 
			
		||||
  dy = intersection.y - data->in.motion.a.y;
 | 
			
		||||
  distance_2 = dx*dx + dy*dy;
 | 
			
		||||
  if (data->out.barrier_impl == NULL ||
 | 
			
		||||
      distance_2 < data->out.closest_distance_2)
 | 
			
		||||
    {
 | 
			
		||||
      data->out.barrier_impl = self;
 | 
			
		||||
      data->out.closest_distance_2 = distance_2;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
get_closest_barrier (MetaBarrierManagerNative *manager,
 | 
			
		||||
                     float                     prev_x,
 | 
			
		||||
                     float                     prev_y,
 | 
			
		||||
                     float                     x,
 | 
			
		||||
                     float                     y,
 | 
			
		||||
                     MetaBarrierDirection      motion_dir,
 | 
			
		||||
                     MetaBarrierImplNative   **barrier_impl)
 | 
			
		||||
{
 | 
			
		||||
  MetaClosestBarrierData closest_barrier_data;
 | 
			
		||||
 | 
			
		||||
  closest_barrier_data = (MetaClosestBarrierData) {
 | 
			
		||||
    .in = {
 | 
			
		||||
      .motion = {
 | 
			
		||||
        .a = {
 | 
			
		||||
          .x = prev_x,
 | 
			
		||||
          .y = prev_y,
 | 
			
		||||
        },
 | 
			
		||||
        .b = {
 | 
			
		||||
          .x = x,
 | 
			
		||||
          .y = y,
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
      .directions = motion_dir,
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  g_hash_table_foreach (manager->barriers,
 | 
			
		||||
                        update_closest_barrier,
 | 
			
		||||
                        &closest_barrier_data);
 | 
			
		||||
 | 
			
		||||
  if (closest_barrier_data.out.barrier_impl != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      *barrier_impl = closest_barrier_data.out.barrier_impl;
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaBarrierEventData
 | 
			
		||||
{
 | 
			
		||||
  guint32             time;
 | 
			
		||||
  float               prev_x;
 | 
			
		||||
  float               prev_y;
 | 
			
		||||
  float               x;
 | 
			
		||||
  float               y;
 | 
			
		||||
  float               dx;
 | 
			
		||||
  float               dy;
 | 
			
		||||
} MetaBarrierEventData;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
emit_barrier_event (MetaBarrierImplNative *self,
 | 
			
		||||
                    guint32                time,
 | 
			
		||||
                    float                  prev_x,
 | 
			
		||||
                    float                  prev_y,
 | 
			
		||||
                    float                  x,
 | 
			
		||||
                    float                  y,
 | 
			
		||||
                    float                  dx,
 | 
			
		||||
                    float                  dy)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierImplNativePrivate *priv =
 | 
			
		||||
    meta_barrier_impl_native_get_instance_private (self);
 | 
			
		||||
  MetaBarrier *barrier = priv->barrier;
 | 
			
		||||
  MetaBarrierEvent *event = g_slice_new0 (MetaBarrierEvent);
 | 
			
		||||
  MetaBarrierState old_state = priv->state;
 | 
			
		||||
 | 
			
		||||
  switch (priv->state)
 | 
			
		||||
    {
 | 
			
		||||
    case META_BARRIER_STATE_HIT:
 | 
			
		||||
      priv->state = META_BARRIER_STATE_HELD;
 | 
			
		||||
      priv->trigger_serial = next_serial ();
 | 
			
		||||
      event->dt = 0;
 | 
			
		||||
 | 
			
		||||
      break;
 | 
			
		||||
    case META_BARRIER_STATE_RELEASE:
 | 
			
		||||
    case META_BARRIER_STATE_LEFT:
 | 
			
		||||
      priv->state = META_BARRIER_STATE_ACTIVE;
 | 
			
		||||
 | 
			
		||||
      /* Intentional fall-through. */
 | 
			
		||||
    case META_BARRIER_STATE_HELD:
 | 
			
		||||
      event->dt = time - priv->last_event_time;
 | 
			
		||||
 | 
			
		||||
      break;
 | 
			
		||||
    case META_BARRIER_STATE_ACTIVE:
 | 
			
		||||
      g_assert_not_reached (); /* Invalid state. */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  event->ref_count = 1;
 | 
			
		||||
  event->event_id = priv->trigger_serial;
 | 
			
		||||
  event->time = time;
 | 
			
		||||
 | 
			
		||||
  event->x = x;
 | 
			
		||||
  event->y = y;
 | 
			
		||||
  event->dx = dx;
 | 
			
		||||
  event->dy = dy;
 | 
			
		||||
 | 
			
		||||
  event->grabbed = priv->state == META_BARRIER_STATE_HELD;
 | 
			
		||||
  event->released = old_state == META_BARRIER_STATE_RELEASE;
 | 
			
		||||
 | 
			
		||||
  priv->last_event_time = time;
 | 
			
		||||
 | 
			
		||||
  if (priv->state == META_BARRIER_STATE_HELD)
 | 
			
		||||
    _meta_barrier_emit_hit_signal (barrier, event);
 | 
			
		||||
  else
 | 
			
		||||
    _meta_barrier_emit_left_signal (barrier, event);
 | 
			
		||||
 | 
			
		||||
  meta_barrier_event_unref (event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
maybe_emit_barrier_event (gpointer key, gpointer value, gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierImplNative *self = key;
 | 
			
		||||
  MetaBarrierImplNativePrivate *priv =
 | 
			
		||||
    meta_barrier_impl_native_get_instance_private (self);
 | 
			
		||||
  MetaBarrierEventData *data = user_data;
 | 
			
		||||
 | 
			
		||||
  switch (priv->state) {
 | 
			
		||||
    case META_BARRIER_STATE_ACTIVE:
 | 
			
		||||
      break;
 | 
			
		||||
    case META_BARRIER_STATE_HIT:
 | 
			
		||||
    case META_BARRIER_STATE_HELD:
 | 
			
		||||
    case META_BARRIER_STATE_RELEASE:
 | 
			
		||||
    case META_BARRIER_STATE_LEFT:
 | 
			
		||||
      emit_barrier_event (self,
 | 
			
		||||
                          data->time,
 | 
			
		||||
                          data->prev_x,
 | 
			
		||||
                          data->prev_y,
 | 
			
		||||
                          data->x,
 | 
			
		||||
                          data->y,
 | 
			
		||||
                          data->dx,
 | 
			
		||||
                          data->dy);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Clamp (x, y) to the barrier and remove clamped direction from motion_dir. */
 | 
			
		||||
static void
 | 
			
		||||
clamp_to_barrier (MetaBarrierImplNative *self,
 | 
			
		||||
                  MetaBarrierDirection *motion_dir,
 | 
			
		||||
                  float *x,
 | 
			
		||||
                  float *y)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierImplNativePrivate *priv =
 | 
			
		||||
    meta_barrier_impl_native_get_instance_private (self);
 | 
			
		||||
  MetaBarrier *barrier = priv->barrier;
 | 
			
		||||
 | 
			
		||||
  if (is_barrier_horizontal (barrier))
 | 
			
		||||
    {
 | 
			
		||||
      if (*motion_dir & META_BARRIER_DIRECTION_POSITIVE_Y)
 | 
			
		||||
        *y = barrier->priv->y1;
 | 
			
		||||
      else if (*motion_dir & META_BARRIER_DIRECTION_NEGATIVE_Y)
 | 
			
		||||
        *y = barrier->priv->y1;
 | 
			
		||||
 | 
			
		||||
      priv->blocked_dir = *motion_dir & (META_BARRIER_DIRECTION_POSITIVE_Y |
 | 
			
		||||
                                         META_BARRIER_DIRECTION_NEGATIVE_Y);
 | 
			
		||||
      *motion_dir &= ~(META_BARRIER_DIRECTION_POSITIVE_Y |
 | 
			
		||||
                       META_BARRIER_DIRECTION_NEGATIVE_Y);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      if (*motion_dir & META_BARRIER_DIRECTION_POSITIVE_X)
 | 
			
		||||
        *x = barrier->priv->x1;
 | 
			
		||||
      else if (*motion_dir & META_BARRIER_DIRECTION_NEGATIVE_X)
 | 
			
		||||
        *x = barrier->priv->x1;
 | 
			
		||||
 | 
			
		||||
      priv->blocked_dir = *motion_dir & (META_BARRIER_DIRECTION_POSITIVE_X |
 | 
			
		||||
                                         META_BARRIER_DIRECTION_NEGATIVE_X);
 | 
			
		||||
      *motion_dir &= ~(META_BARRIER_DIRECTION_POSITIVE_X |
 | 
			
		||||
                       META_BARRIER_DIRECTION_NEGATIVE_X);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  priv->state = META_BARRIER_STATE_HIT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_barrier_manager_native_process (MetaBarrierManagerNative *manager,
 | 
			
		||||
                                     ClutterInputDevice       *device,
 | 
			
		||||
                                     guint32                   time,
 | 
			
		||||
                                     float                    *x,
 | 
			
		||||
                                     float                    *y)
 | 
			
		||||
{
 | 
			
		||||
  ClutterPoint prev_pos;
 | 
			
		||||
  float prev_x;
 | 
			
		||||
  float prev_y;
 | 
			
		||||
  float orig_x = *x;
 | 
			
		||||
  float orig_y = *y;
 | 
			
		||||
  MetaBarrierDirection motion_dir = 0;
 | 
			
		||||
  MetaBarrierEventData barrier_event_data;
 | 
			
		||||
  MetaBarrierImplNative *barrier_impl;
 | 
			
		||||
 | 
			
		||||
  if (!clutter_input_device_get_coords (device, NULL, &prev_pos))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  prev_x = prev_pos.x;
 | 
			
		||||
  prev_y = prev_pos.y;
 | 
			
		||||
 | 
			
		||||
  /* Get the direction of the motion vector. */
 | 
			
		||||
  if (prev_x < *x)
 | 
			
		||||
    motion_dir |= META_BARRIER_DIRECTION_POSITIVE_X;
 | 
			
		||||
  else if (prev_x > *x)
 | 
			
		||||
    motion_dir |= META_BARRIER_DIRECTION_NEGATIVE_X;
 | 
			
		||||
  if (prev_y < *y)
 | 
			
		||||
    motion_dir |= META_BARRIER_DIRECTION_POSITIVE_Y;
 | 
			
		||||
  else if (prev_y > *y)
 | 
			
		||||
    motion_dir |= META_BARRIER_DIRECTION_NEGATIVE_Y;
 | 
			
		||||
 | 
			
		||||
  /* Clamp to the closest barrier in any direction until either there are no
 | 
			
		||||
   * more barriers to clamp to or all directions have been clamped. */
 | 
			
		||||
  while (motion_dir != 0)
 | 
			
		||||
    {
 | 
			
		||||
      if (get_closest_barrier (manager,
 | 
			
		||||
                               prev_x, prev_y,
 | 
			
		||||
                               *x, *y,
 | 
			
		||||
                               motion_dir,
 | 
			
		||||
                               &barrier_impl))
 | 
			
		||||
        clamp_to_barrier (barrier_impl, &motion_dir, x, y);
 | 
			
		||||
      else
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* Potentially release active barrier movements. */
 | 
			
		||||
  maybe_release_barriers (manager, prev_x, prev_y, *x, *y);
 | 
			
		||||
 | 
			
		||||
  /* Initiate or continue barrier interaction. */
 | 
			
		||||
  barrier_event_data = (MetaBarrierEventData) {
 | 
			
		||||
    .time = time,
 | 
			
		||||
    .prev_x = prev_x,
 | 
			
		||||
    .prev_y = prev_y,
 | 
			
		||||
    .x = *x,
 | 
			
		||||
    .y = *y,
 | 
			
		||||
    .dx = orig_x - prev_x,
 | 
			
		||||
    .dy = orig_y - prev_y,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  g_hash_table_foreach (manager->barriers,
 | 
			
		||||
                        maybe_emit_barrier_event,
 | 
			
		||||
                        &barrier_event_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
_meta_barrier_impl_native_is_active (MetaBarrierImpl *impl)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierImplNative *self = META_BARRIER_IMPL_NATIVE (impl);
 | 
			
		||||
  MetaBarrierImplNativePrivate *priv =
 | 
			
		||||
    meta_barrier_impl_native_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
  return priv->is_active;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
_meta_barrier_impl_native_release (MetaBarrierImpl  *impl,
 | 
			
		||||
                                   MetaBarrierEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierImplNative *self = META_BARRIER_IMPL_NATIVE (impl);
 | 
			
		||||
  MetaBarrierImplNativePrivate *priv =
 | 
			
		||||
    meta_barrier_impl_native_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
  if (priv->state == META_BARRIER_STATE_HELD &&
 | 
			
		||||
      event->event_id == priv->trigger_serial)
 | 
			
		||||
    priv->state = META_BARRIER_STATE_RELEASE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
_meta_barrier_impl_native_destroy (MetaBarrierImpl *impl)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierImplNative *self = META_BARRIER_IMPL_NATIVE (impl);
 | 
			
		||||
  MetaBarrierImplNativePrivate *priv =
 | 
			
		||||
    meta_barrier_impl_native_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
  g_hash_table_remove (priv->manager->barriers, self);
 | 
			
		||||
  priv->is_active = FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaBarrierImpl *
 | 
			
		||||
meta_barrier_impl_native_new (MetaBarrier *barrier)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierImplNative *self;
 | 
			
		||||
  MetaBarrierImplNativePrivate *priv;
 | 
			
		||||
  MetaBackendNative *native;
 | 
			
		||||
  MetaBarrierManagerNative *manager;
 | 
			
		||||
 | 
			
		||||
  self = g_object_new (META_TYPE_BARRIER_IMPL_NATIVE, NULL);
 | 
			
		||||
  priv = meta_barrier_impl_native_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
  priv->barrier = barrier;
 | 
			
		||||
  priv->is_active = TRUE;
 | 
			
		||||
 | 
			
		||||
  native = META_BACKEND_NATIVE (meta_get_backend ());
 | 
			
		||||
  manager = meta_backend_native_get_barrier_manager (native);
 | 
			
		||||
  priv->manager = manager;
 | 
			
		||||
  g_hash_table_add (manager->barriers, self);
 | 
			
		||||
 | 
			
		||||
  return META_BARRIER_IMPL (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_barrier_impl_native_class_init (MetaBarrierImplNativeClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierImplClass *impl_class = META_BARRIER_IMPL_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  impl_class->is_active = _meta_barrier_impl_native_is_active;
 | 
			
		||||
  impl_class->release = _meta_barrier_impl_native_release;
 | 
			
		||||
  impl_class->destroy = _meta_barrier_impl_native_destroy;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_barrier_impl_native_init (MetaBarrierImplNative *self)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaBarrierManagerNative *
 | 
			
		||||
meta_barrier_manager_native_new (void)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierManagerNative *manager;
 | 
			
		||||
 | 
			
		||||
  manager = g_new0 (MetaBarrierManagerNative, 1);
 | 
			
		||||
 | 
			
		||||
  manager->barriers = g_hash_table_new (NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  return manager;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										68
									
								
								src/backends/native/meta-barrier-native.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/backends/native/meta-barrier-native.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2015 Red Hat
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
 * published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 | 
			
		||||
 * 02111-1307, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * Written by:
 | 
			
		||||
 *     Jonas Ådahl <jadahl@gmail.com>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef META_BARRIER_NATIVE_H
 | 
			
		||||
#define META_BARRIER_NATIVE_H
 | 
			
		||||
 | 
			
		||||
#include "backends/meta-barrier-private.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_BARRIER_IMPL_NATIVE            (meta_barrier_impl_native_get_type ())
 | 
			
		||||
#define META_BARRIER_IMPL_NATIVE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BARRIER_IMPL_NATIVE, MetaBarrierImplNative))
 | 
			
		||||
#define META_BARRIER_IMPL_NATIVE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_BARRIER_IMPL_NATIVE, MetaBarrierImplNativeClass))
 | 
			
		||||
#define META_IS_BARRIER_IMPL_NATIVE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BARRIER_IMPL_NATIVE))
 | 
			
		||||
#define META_IS_BARRIER_IMPL_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_BARRIER_IMPL_NATIVE))
 | 
			
		||||
#define META_BARRIER_IMPL_NATIVE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_BARRIER_IMPL_NATIVE, MetaBarrierImplNativeClass))
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaBarrierImplNative        MetaBarrierImplNative;
 | 
			
		||||
typedef struct _MetaBarrierImplNativeClass   MetaBarrierImplNativeClass;
 | 
			
		||||
typedef struct _MetaBarrierImplNativePrivate MetaBarrierImplNativePrivate;
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaBarrierManagerNative     MetaBarrierManagerNative;
 | 
			
		||||
 | 
			
		||||
struct _MetaBarrierImplNative
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierImpl parent;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaBarrierImplNativeClass
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierImplClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType meta_barrier_impl_native_get_type (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
MetaBarrierImpl *meta_barrier_impl_native_new (MetaBarrier *barrier);
 | 
			
		||||
 | 
			
		||||
MetaBarrierManagerNative *meta_barrier_manager_native_new (void);
 | 
			
		||||
void meta_barrier_manager_native_process (MetaBarrierManagerNative *manager,
 | 
			
		||||
                                          ClutterInputDevice       *device,
 | 
			
		||||
                                          guint32                   time,
 | 
			
		||||
                                          float                    *x,
 | 
			
		||||
                                          float                    *y);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* META_BARRIER_NATIVE_H */
 | 
			
		||||
@@ -27,9 +27,17 @@
 | 
			
		||||
#include "meta-cursor-renderer-native.h"
 | 
			
		||||
 | 
			
		||||
#include <gbm.h>
 | 
			
		||||
#include <xf86drm.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-cursor-private.h"
 | 
			
		||||
#include "meta-monitor-manager.h"
 | 
			
		||||
#include "meta-monitor-manager-private.h"
 | 
			
		||||
 | 
			
		||||
#ifndef DRM_CAP_CURSOR_WIDTH
 | 
			
		||||
#define DRM_CAP_CURSOR_WIDTH 0x8
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef DRM_CAP_CURSOR_HEIGHT
 | 
			
		||||
#define DRM_CAP_CURSOR_HEIGHT 0x9
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct _MetaCursorRendererNativePrivate
 | 
			
		||||
{
 | 
			
		||||
@@ -37,6 +45,9 @@ struct _MetaCursorRendererNativePrivate
 | 
			
		||||
 | 
			
		||||
  int drm_fd;
 | 
			
		||||
  struct gbm_device *gbm;
 | 
			
		||||
 | 
			
		||||
  uint64_t cursor_width;
 | 
			
		||||
  uint64_t cursor_height;
 | 
			
		||||
};
 | 
			
		||||
typedef struct _MetaCursorRendererNativePrivate MetaCursorRendererNativePrivate;
 | 
			
		||||
 | 
			
		||||
@@ -71,17 +82,13 @@ set_crtc_cursor (MetaCursorRendererNative *native,
 | 
			
		||||
    {
 | 
			
		||||
      struct gbm_bo *bo;
 | 
			
		||||
      union gbm_bo_handle handle;
 | 
			
		||||
      int width, height;
 | 
			
		||||
      int hot_x, hot_y;
 | 
			
		||||
 | 
			
		||||
      bo = meta_cursor_reference_get_gbm_bo (cursor, &hot_x, &hot_y);
 | 
			
		||||
 | 
			
		||||
      handle = gbm_bo_get_handle (bo);
 | 
			
		||||
      width = gbm_bo_get_width (bo);
 | 
			
		||||
      height = gbm_bo_get_height (bo);
 | 
			
		||||
 | 
			
		||||
      drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, handle.u32,
 | 
			
		||||
                         width, height, hot_x, hot_y);
 | 
			
		||||
                         priv->cursor_width, priv->cursor_height, hot_x, hot_y);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
@@ -186,6 +193,19 @@ meta_cursor_renderer_native_init (MetaCursorRendererNative *native)
 | 
			
		||||
      CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (ctx));
 | 
			
		||||
      priv->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
 | 
			
		||||
      priv->gbm = gbm_create_device (priv->drm_fd);
 | 
			
		||||
 | 
			
		||||
      uint64_t width, height;
 | 
			
		||||
      if (drmGetCap (priv->drm_fd, DRM_CAP_CURSOR_WIDTH, &width) == 0 &&
 | 
			
		||||
          drmGetCap (priv->drm_fd, DRM_CAP_CURSOR_HEIGHT, &height) == 0)
 | 
			
		||||
        {
 | 
			
		||||
          priv->cursor_width = width;
 | 
			
		||||
          priv->cursor_height = height;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          priv->cursor_width = 64;
 | 
			
		||||
          priv->cursor_height = 64;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
@@ -198,6 +218,16 @@ meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *native)
 | 
			
		||||
  return priv->gbm;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_cursor_renderer_native_get_cursor_size (MetaCursorRendererNative *native,
 | 
			
		||||
                                             uint64_t *width, uint64_t *height)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
 | 
			
		||||
 | 
			
		||||
  *width = priv->cursor_width;
 | 
			
		||||
  *height = priv->cursor_height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_cursor_renderer_native_force_update (MetaCursorRendererNative *native)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -50,6 +50,7 @@ struct _MetaCursorRendererNativeClass
 | 
			
		||||
GType meta_cursor_renderer_native_get_type (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
struct gbm_device * meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *renderer);
 | 
			
		||||
void meta_cursor_renderer_native_get_cursor_size (MetaCursorRendererNative *native, uint64_t *width, uint64_t *height);
 | 
			
		||||
void meta_cursor_renderer_native_force_update (MetaCursorRendererNative *renderer);
 | 
			
		||||
 | 
			
		||||
#endif /* META_CURSOR_RENDERER_NATIVE_H */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										217
									
								
								src/backends/native/meta-input-settings-native.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								src/backends/native/meta-input-settings-native.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,217 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014 Red Hat
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
 * published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 | 
			
		||||
 * 02111-1307, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Carlos Garnacho <carlosg@gnome.org>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include <clutter/evdev/clutter-evdev.h>
 | 
			
		||||
#include <libinput.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-input-settings-native.h"
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaInputSettingsNative, meta_input_settings_native, META_TYPE_INPUT_SETTINGS)
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_native_set_send_events (MetaInputSettings        *settings,
 | 
			
		||||
                                            ClutterInputDevice       *device,
 | 
			
		||||
                                            GDesktopDeviceSendEvents  mode)
 | 
			
		||||
{
 | 
			
		||||
  enum libinput_config_send_events_mode libinput_mode;
 | 
			
		||||
  struct libinput_device *libinput_device;
 | 
			
		||||
 | 
			
		||||
  switch (mode)
 | 
			
		||||
    {
 | 
			
		||||
    case G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED:
 | 
			
		||||
      libinput_mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
 | 
			
		||||
      break;
 | 
			
		||||
    case G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE:
 | 
			
		||||
      libinput_mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
 | 
			
		||||
      break;
 | 
			
		||||
    case G_DESKTOP_DEVICE_SEND_EVENTS_ENABLED:
 | 
			
		||||
      libinput_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  libinput_device = clutter_evdev_input_device_get_libinput_device (device);
 | 
			
		||||
  libinput_device_config_send_events_set_mode (libinput_device, libinput_mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_native_set_matrix (MetaInputSettings  *settings,
 | 
			
		||||
                                       ClutterInputDevice *device,
 | 
			
		||||
                                       gfloat              matrix[6])
 | 
			
		||||
{
 | 
			
		||||
  struct libinput_device *libinput_device;
 | 
			
		||||
 | 
			
		||||
  libinput_device = clutter_evdev_input_device_get_libinput_device (device);
 | 
			
		||||
 | 
			
		||||
  if (libinput_device_config_calibration_has_matrix (libinput_device) > 0)
 | 
			
		||||
    libinput_device_config_calibration_set_matrix (libinput_device, matrix);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_native_set_speed (MetaInputSettings  *settings,
 | 
			
		||||
                                      ClutterInputDevice *device,
 | 
			
		||||
                                      gdouble             speed)
 | 
			
		||||
{
 | 
			
		||||
  struct libinput_device *libinput_device;
 | 
			
		||||
 | 
			
		||||
  libinput_device = clutter_evdev_input_device_get_libinput_device (device);
 | 
			
		||||
  libinput_device_config_accel_set_speed (libinput_device,
 | 
			
		||||
                                          CLAMP (speed, -1, 1));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_native_set_left_handed (MetaInputSettings  *settings,
 | 
			
		||||
                                            ClutterInputDevice *device,
 | 
			
		||||
                                            gboolean            enabled)
 | 
			
		||||
{
 | 
			
		||||
  struct libinput_device *libinput_device;
 | 
			
		||||
 | 
			
		||||
  libinput_device = clutter_evdev_input_device_get_libinput_device (device);
 | 
			
		||||
 | 
			
		||||
  if (libinput_device_config_left_handed_is_available (libinput_device))
 | 
			
		||||
    libinput_device_config_left_handed_set (libinput_device, enabled);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_native_set_tap_enabled (MetaInputSettings  *settings,
 | 
			
		||||
                                            ClutterInputDevice *device,
 | 
			
		||||
                                            gboolean            enabled)
 | 
			
		||||
{
 | 
			
		||||
  struct libinput_device *libinput_device;
 | 
			
		||||
 | 
			
		||||
  libinput_device = clutter_evdev_input_device_get_libinput_device (device);
 | 
			
		||||
 | 
			
		||||
  if (libinput_device_config_tap_get_finger_count (libinput_device) > 0)
 | 
			
		||||
    libinput_device_config_tap_set_enabled (libinput_device,
 | 
			
		||||
                                            enabled ?
 | 
			
		||||
                                            LIBINPUT_CONFIG_TAP_ENABLED :
 | 
			
		||||
                                            LIBINPUT_CONFIG_TAP_DISABLED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_native_set_invert_scroll (MetaInputSettings  *settings,
 | 
			
		||||
                                              ClutterInputDevice *device,
 | 
			
		||||
                                              gboolean            inverted)
 | 
			
		||||
{
 | 
			
		||||
  struct libinput_device *libinput_device;
 | 
			
		||||
 | 
			
		||||
  libinput_device = clutter_evdev_input_device_get_libinput_device (device);
 | 
			
		||||
 | 
			
		||||
  if (libinput_device_config_scroll_has_natural_scroll (libinput_device))
 | 
			
		||||
    libinput_device_config_scroll_set_natural_scroll_enabled (libinput_device,
 | 
			
		||||
                                                              inverted);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
device_set_scroll_method (struct libinput_device             *libinput_device,
 | 
			
		||||
                          enum libinput_config_scroll_method  method)
 | 
			
		||||
{
 | 
			
		||||
  enum libinput_config_scroll_method supported;
 | 
			
		||||
 | 
			
		||||
  supported = libinput_device_config_scroll_get_methods (libinput_device);
 | 
			
		||||
 | 
			
		||||
  if (method & supported)
 | 
			
		||||
    libinput_device_config_scroll_set_method (libinput_device, method);
 | 
			
		||||
 | 
			
		||||
  return (method & supported) != 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_native_set_scroll_method (MetaInputSettings            *settings,
 | 
			
		||||
                                              ClutterInputDevice           *device,
 | 
			
		||||
                                              GDesktopTouchpadScrollMethod  mode)
 | 
			
		||||
{
 | 
			
		||||
  enum libinput_config_scroll_method scroll_method = 0;
 | 
			
		||||
  struct libinput_device *libinput_device;
 | 
			
		||||
 | 
			
		||||
  libinput_device = clutter_evdev_input_device_get_libinput_device (device);
 | 
			
		||||
 | 
			
		||||
  switch (mode)
 | 
			
		||||
    {
 | 
			
		||||
    case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_DISABLED:
 | 
			
		||||
      scroll_method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
 | 
			
		||||
      break;
 | 
			
		||||
    case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_EDGE_SCROLLING:
 | 
			
		||||
      scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;
 | 
			
		||||
      break;
 | 
			
		||||
    case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_TWO_FINGER_SCROLLING:
 | 
			
		||||
      scroll_method = LIBINPUT_CONFIG_SCROLL_EDGE;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
      return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  device_set_scroll_method (libinput_device, scroll_method);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_native_set_scroll_button (MetaInputSettings  *settings,
 | 
			
		||||
                                              ClutterInputDevice *device,
 | 
			
		||||
                                              guint               button)
 | 
			
		||||
{
 | 
			
		||||
  struct libinput_device *libinput_device;
 | 
			
		||||
 | 
			
		||||
  libinput_device = clutter_evdev_input_device_get_libinput_device (device);
 | 
			
		||||
 | 
			
		||||
  if (!device_set_scroll_method (libinput_device,
 | 
			
		||||
                                 LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  libinput_device_config_scroll_set_button (libinput_device, button);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_native_set_keyboard_repeat (MetaInputSettings *settings,
 | 
			
		||||
                                                gboolean           enabled,
 | 
			
		||||
                                                guint              delay,
 | 
			
		||||
                                                guint              interval)
 | 
			
		||||
{
 | 
			
		||||
  ClutterDeviceManager *manager = clutter_device_manager_get_default ();
 | 
			
		||||
 | 
			
		||||
  clutter_evdev_set_keyboard_repeat (manager, enabled, delay, interval);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_native_class_init (MetaInputSettingsNativeClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsClass *input_settings_class = META_INPUT_SETTINGS_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  input_settings_class->set_send_events = meta_input_settings_native_set_send_events;
 | 
			
		||||
  input_settings_class->set_matrix = meta_input_settings_native_set_matrix;
 | 
			
		||||
  input_settings_class->set_speed = meta_input_settings_native_set_speed;
 | 
			
		||||
  input_settings_class->set_left_handed = meta_input_settings_native_set_left_handed;
 | 
			
		||||
  input_settings_class->set_tap_enabled = meta_input_settings_native_set_tap_enabled;
 | 
			
		||||
  input_settings_class->set_invert_scroll = meta_input_settings_native_set_invert_scroll;
 | 
			
		||||
  input_settings_class->set_scroll_method = meta_input_settings_native_set_scroll_method;
 | 
			
		||||
  input_settings_class->set_scroll_button = meta_input_settings_native_set_scroll_button;
 | 
			
		||||
  input_settings_class->set_keyboard_repeat = meta_input_settings_native_set_keyboard_repeat;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_native_init (MetaInputSettingsNative *settings)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								src/backends/native/meta-input-settings-native.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/backends/native/meta-input-settings-native.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2014 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 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Carlos Garnacho <carlosg@gnome.org>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef META_INPUT_SETTINGS_NATIVE_H
 | 
			
		||||
#define META_INPUT_SETTINGS_NATIVE_H
 | 
			
		||||
 | 
			
		||||
#include "meta-input-settings-private.h"
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_INPUT_SETTINGS_NATIVE             (meta_input_settings_native_get_type ())
 | 
			
		||||
#define META_INPUT_SETTINGS_NATIVE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_INPUT_SETTINGS_NATIVE, MetaInputSettingsNative))
 | 
			
		||||
#define META_INPUT_SETTINGS_NATIVE_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_INPUT_SETTINGS_NATIVE, MetaInputSettingsNativeClass))
 | 
			
		||||
#define META_IS_INPUT_SETTINGS_NATIVE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_INPUT_SETTINGS_NATIVE))
 | 
			
		||||
#define META_IS_INPUT_SETTINGS_NATIVE_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_INPUT_SETTINGS_NATIVE))
 | 
			
		||||
#define META_INPUT_SETTINGS_NATIVE_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_INPUT_SETTINGS_NATIVE, MetaInputSettingsNativeClass))
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaInputSettingsNative MetaInputSettingsNative;
 | 
			
		||||
typedef struct _MetaInputSettingsNativeClass MetaInputSettingsNativeClass;
 | 
			
		||||
 | 
			
		||||
struct _MetaInputSettingsNative
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettings parent_instance;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaInputSettingsNativeClass
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType meta_input_settings_native_get_type (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
#endif /* META_INPUT_SETTINGS_NATIVE_H */
 | 
			
		||||
@@ -130,8 +130,8 @@ take_device (Login1Session *session_proxy,
 | 
			
		||||
{
 | 
			
		||||
  gboolean ret = FALSE;
 | 
			
		||||
  GVariant *fd_variant = NULL;
 | 
			
		||||
  GUnixFDList *fd_list = NULL;
 | 
			
		||||
  int fd = -1;
 | 
			
		||||
  GUnixFDList *fd_list;
 | 
			
		||||
 | 
			
		||||
  if (!login1_session_call_take_device_sync (session_proxy,
 | 
			
		||||
                                             dev_major,
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-monitor-manager-kms.h"
 | 
			
		||||
#include "meta-monitor-config.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
@@ -38,7 +39,8 @@
 | 
			
		||||
 | 
			
		||||
#include <meta/main.h>
 | 
			
		||||
#include <meta/errors.h>
 | 
			
		||||
#include "edid.h"
 | 
			
		||||
 | 
			
		||||
#include <gudev/gudev.h>
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  drmModeConnector *connector;
 | 
			
		||||
@@ -68,6 +70,8 @@ struct _MetaMonitorManagerKms
 | 
			
		||||
  unsigned int       n_encoders;
 | 
			
		||||
 | 
			
		||||
  drmModeEncoder    *current_encoder;
 | 
			
		||||
 | 
			
		||||
  GUdevClient *udev;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaMonitorManagerKmsClass
 | 
			
		||||
@@ -202,7 +206,7 @@ find_properties (MetaMonitorManagerKms *manager_kms,
 | 
			
		||||
               strcmp (prop->name, "EDID") == 0)
 | 
			
		||||
        output_kms->edid_blob_id = output_kms->connector->prop_values[i];
 | 
			
		||||
 | 
			
		||||
      drmModeFreeProperty(prop);
 | 
			
		||||
      drmModeFreeProperty (prop);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -224,8 +228,10 @@ read_output_edid (MetaMonitorManagerKms *manager_kms,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (edid_blob->length > 0)
 | 
			
		||||
    return g_bytes_new_with_free_func (edid_blob->data, edid_blob->length,
 | 
			
		||||
                                       (GDestroyNotify)drmModeFreePropertyBlob, edid_blob);
 | 
			
		||||
    {
 | 
			
		||||
      return g_bytes_new_with_free_func (edid_blob->data, edid_blob->length,
 | 
			
		||||
                                         (GDestroyNotify)drmModeFreePropertyBlob, edid_blob);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      drmModeFreePropertyBlob (edid_blob);
 | 
			
		||||
@@ -410,6 +416,8 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
 | 
			
		||||
	  meta_output->name = make_output_name (connector);
 | 
			
		||||
	  meta_output->width_mm = connector->mmWidth;
 | 
			
		||||
	  meta_output->height_mm = connector->mmHeight;
 | 
			
		||||
	  meta_output->suggested_x = -1;
 | 
			
		||||
	  meta_output->suggested_y = -1;
 | 
			
		||||
 | 
			
		||||
          switch (connector->subpixel)
 | 
			
		||||
            {
 | 
			
		||||
@@ -504,29 +512,11 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
 | 
			
		||||
          find_properties (manager_kms, output_kms);
 | 
			
		||||
 | 
			
		||||
          edid = read_output_edid (manager_kms, meta_output);
 | 
			
		||||
          if (edid)
 | 
			
		||||
            {
 | 
			
		||||
              MonitorInfo *parsed_edid;
 | 
			
		||||
              gsize len;
 | 
			
		||||
          meta_output_parse_edid (meta_output, edid);
 | 
			
		||||
          g_bytes_unref (edid);
 | 
			
		||||
 | 
			
		||||
              parsed_edid = decode_edid (g_bytes_get_data (edid, &len));
 | 
			
		||||
              if (parsed_edid)
 | 
			
		||||
                {
 | 
			
		||||
                  meta_output->vendor = g_strndup (parsed_edid->manufacturer_code, 4);
 | 
			
		||||
                  meta_output->product = g_strndup (parsed_edid->dsc_product_name, 14);
 | 
			
		||||
                  meta_output->serial = g_strndup (parsed_edid->dsc_serial_number, 14);
 | 
			
		||||
 | 
			
		||||
                  g_free (parsed_edid);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
              g_bytes_unref (edid);
 | 
			
		||||
            }
 | 
			
		||||
          if (!meta_output->vendor)
 | 
			
		||||
            {
 | 
			
		||||
              meta_output->vendor = g_strdup ("unknown");
 | 
			
		||||
              meta_output->product = g_strdup ("unknown");
 | 
			
		||||
              meta_output->serial = g_strdup ("unknown");
 | 
			
		||||
            }
 | 
			
		||||
          /* MetaConnectorType matches DRM's connector types */
 | 
			
		||||
          meta_output->connector_type = (MetaConnectorType) connector->connector_type;
 | 
			
		||||
 | 
			
		||||
          /* FIXME: backlight is a very driver specific thing unfortunately,
 | 
			
		||||
             every DDX does its own thing, and the dumb KMS API does not include it.
 | 
			
		||||
@@ -893,6 +883,23 @@ meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
 | 
			
		||||
  drmModeCrtcSetGamma (manager_kms->fd, crtc->crtc_id, size, red, green, blue);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_uevent (GUdevClient *client,
 | 
			
		||||
           const char  *action,
 | 
			
		||||
           GUdevDevice *device,
 | 
			
		||||
           gpointer     user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (user_data);
 | 
			
		||||
  MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
 | 
			
		||||
 | 
			
		||||
  if (!g_udev_device_get_property_as_boolean (device, "HOTPLUG"))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  meta_monitor_manager_read_current_config (manager);
 | 
			
		||||
 | 
			
		||||
  meta_monitor_manager_on_hotplug (manager);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
 | 
			
		||||
{
 | 
			
		||||
@@ -907,6 +914,21 @@ meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
 | 
			
		||||
  cogl_renderer = cogl_display_get_renderer (cogl_display);
 | 
			
		||||
 | 
			
		||||
  manager_kms->fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
 | 
			
		||||
 | 
			
		||||
  const char *subsystems[2] = { "drm", NULL };
 | 
			
		||||
  manager_kms->udev = g_udev_client_new (subsystems);
 | 
			
		||||
  g_signal_connect (manager_kms->udev, "uevent",
 | 
			
		||||
                    G_CALLBACK (on_uevent), manager_kms);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_kms_dispose (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (object);
 | 
			
		||||
 | 
			
		||||
  g_clear_object (&manager_kms->udev);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_monitor_manager_kms_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -925,6 +947,7 @@ meta_monitor_manager_kms_class_init (MetaMonitorManagerKmsClass *klass)
 | 
			
		||||
  MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->dispose = meta_monitor_manager_kms_dispose;
 | 
			
		||||
  object_class->finalize = meta_monitor_manager_kms_finalize;
 | 
			
		||||
 | 
			
		||||
  manager_class->read_current = meta_monitor_manager_kms_read_current;
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@
 | 
			
		||||
#ifndef META_MONITOR_MANAGER_KMS_H
 | 
			
		||||
#define META_MONITOR_MANAGER_KMS_H
 | 
			
		||||
 | 
			
		||||
#include "meta-monitor-manager.h"
 | 
			
		||||
#include "meta-monitor-manager-private.h"
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_MONITOR_MANAGER_KMS            (meta_monitor_manager_kms_get_type ())
 | 
			
		||||
#define META_MONITOR_MANAGER_KMS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKms))
 | 
			
		||||
 
 | 
			
		||||
@@ -65,20 +65,29 @@ struct _MetaBackendX11Private
 | 
			
		||||
  uint8_t xkb_error_base;
 | 
			
		||||
 | 
			
		||||
  struct xkb_keymap *keymap;
 | 
			
		||||
  gchar *keymap_layouts;
 | 
			
		||||
  gchar *keymap_variants;
 | 
			
		||||
  gchar *keymap_options;
 | 
			
		||||
};
 | 
			
		||||
typedef struct _MetaBackendX11Private MetaBackendX11Private;
 | 
			
		||||
 | 
			
		||||
static void apply_keymap (MetaBackendX11 *x11);
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendX11, meta_backend_x11, META_TYPE_BACKEND);
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
handle_alarm_notify (MetaBackend *backend,
 | 
			
		||||
                     XEvent      *event)
 | 
			
		||||
{
 | 
			
		||||
  int i;
 | 
			
		||||
  GHashTableIter iter;
 | 
			
		||||
  gpointer value;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i <= backend->device_id_max; i++)
 | 
			
		||||
    if (backend->device_monitors[i])
 | 
			
		||||
      meta_idle_monitor_xsync_handle_xevent (backend->device_monitors[i], (XSyncAlarmNotifyEvent*) event);
 | 
			
		||||
  g_hash_table_iter_init (&iter, backend->device_monitors);
 | 
			
		||||
  while (g_hash_table_iter_next (&iter, NULL, &value))
 | 
			
		||||
    {
 | 
			
		||||
      MetaIdleMonitor *device_monitor = META_IDLE_MONITOR (value);
 | 
			
		||||
      meta_idle_monitor_xsync_handle_xevent (device_monitor, (XSyncAlarmNotifyEvent*) event);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -120,6 +129,21 @@ translate_device_event (MetaBackendX11 *x11,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
translate_crossing_event (MetaBackendX11 *x11,
 | 
			
		||||
                          XIEnterEvent   *enter_event)
 | 
			
		||||
{
 | 
			
		||||
  /* Throw out weird events generated by grabs. */
 | 
			
		||||
  if (enter_event->mode == XINotifyGrab ||
 | 
			
		||||
      enter_event->mode == XINotifyUngrab)
 | 
			
		||||
    {
 | 
			
		||||
      enter_event->event = None;
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  enter_event->event = meta_backend_x11_get_xwindow (x11);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Clutter makes the assumption that there is only one X window
 | 
			
		||||
 * per stage, which is a valid assumption to make for a generic
 | 
			
		||||
 * application toolkit. As such, it will ignore any events sent
 | 
			
		||||
@@ -152,6 +176,10 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
 | 
			
		||||
        case XI_TouchEnd:
 | 
			
		||||
          translate_device_event (x11, (XIDeviceEvent *) input_event);
 | 
			
		||||
          break;
 | 
			
		||||
        case XI_Enter:
 | 
			
		||||
        case XI_Leave:
 | 
			
		||||
          translate_crossing_event (x11, (XIEnterEvent *) input_event);
 | 
			
		||||
          break;
 | 
			
		||||
        default:
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
@@ -326,6 +354,17 @@ take_touch_grab (MetaBackend *backend)
 | 
			
		||||
                    False, &mask, 1, &mods);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_device_added (ClutterDeviceManager *device_manager,
 | 
			
		||||
                 ClutterInputDevice   *device,
 | 
			
		||||
                 gpointer              user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackendX11 *x11 = META_BACKEND_X11 (user_data);
 | 
			
		||||
 | 
			
		||||
  if (clutter_input_device_get_device_type (device) == CLUTTER_KEYBOARD_DEVICE)
 | 
			
		||||
    apply_keymap (x11);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_backend_x11_post_init (MetaBackend *backend)
 | 
			
		||||
{
 | 
			
		||||
@@ -376,6 +415,9 @@ meta_backend_x11_post_init (MetaBackend *backend)
 | 
			
		||||
    meta_fatal ("X server doesn't have the XKB extension, version %d.%d or newer\n",
 | 
			
		||||
                XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION);
 | 
			
		||||
 | 
			
		||||
  g_signal_connect_object (clutter_device_manager_get_default (), "device-added",
 | 
			
		||||
                           G_CALLBACK (on_device_added), backend, 0);
 | 
			
		||||
 | 
			
		||||
  META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -560,21 +602,22 @@ upload_xkb_description (Display              *xdisplay,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_backend_x11_set_keymap (MetaBackend *backend,
 | 
			
		||||
                             const char  *layouts,
 | 
			
		||||
                             const char  *variants,
 | 
			
		||||
                             const char  *options)
 | 
			
		||||
apply_keymap (MetaBackendX11 *x11)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
 | 
			
		||||
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
 | 
			
		||||
  XkbRF_RulesRec *xkb_rules;
 | 
			
		||||
  XkbRF_VarDefsRec xkb_var_defs = { 0 };
 | 
			
		||||
  gchar *rules_file_path;
 | 
			
		||||
 | 
			
		||||
  if (!priv->keymap_layouts ||
 | 
			
		||||
      !priv->keymap_variants ||
 | 
			
		||||
      !priv->keymap_options)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  get_xkbrf_var_defs (priv->xdisplay,
 | 
			
		||||
                      layouts,
 | 
			
		||||
                      variants,
 | 
			
		||||
                      options,
 | 
			
		||||
                      priv->keymap_layouts,
 | 
			
		||||
                      priv->keymap_variants,
 | 
			
		||||
                      priv->keymap_options,
 | 
			
		||||
                      &rules_file_path,
 | 
			
		||||
                      &xkb_var_defs);
 | 
			
		||||
 | 
			
		||||
@@ -598,6 +641,25 @@ meta_backend_x11_set_keymap (MetaBackend *backend,
 | 
			
		||||
  g_free (rules_file_path);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_backend_x11_set_keymap (MetaBackend *backend,
 | 
			
		||||
                             const char  *layouts,
 | 
			
		||||
                             const char  *variants,
 | 
			
		||||
                             const char  *options)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
 | 
			
		||||
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
 | 
			
		||||
 | 
			
		||||
  g_free (priv->keymap_layouts);
 | 
			
		||||
  priv->keymap_layouts = g_strdup (layouts);
 | 
			
		||||
  g_free (priv->keymap_variants);
 | 
			
		||||
  priv->keymap_variants = g_strdup (variants);
 | 
			
		||||
  g_free (priv->keymap_options);
 | 
			
		||||
  priv->keymap_options = g_strdup (options);
 | 
			
		||||
 | 
			
		||||
  apply_keymap (x11);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct xkb_keymap *
 | 
			
		||||
meta_backend_x11_get_keymap (MetaBackend *backend)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										216
									
								
								src/backends/x11/meta-barrier-x11.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								src/backends/x11/meta-barrier-x11.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,216 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014-2015 Red Hat
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
 * published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 | 
			
		||||
 * 02111-1307, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * Written by:
 | 
			
		||||
 *     Jasper St. Pierre <jstpierre@mecheye.net>
 | 
			
		||||
 *     Jonas Ådahl <jadahl@gmail.com>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SECTION:barrier-x11
 | 
			
		||||
 * @Title: MetaBarrierImplX11
 | 
			
		||||
 * @Short_Description: Pointer barriers implementation for X11
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_XI23
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
 | 
			
		||||
#include <X11/extensions/XInput2.h>
 | 
			
		||||
#include <X11/extensions/Xfixes.h>
 | 
			
		||||
#include <meta/barrier.h>
 | 
			
		||||
#include "backends/x11/meta-barrier-x11.h"
 | 
			
		||||
#include "display-private.h"
 | 
			
		||||
 | 
			
		||||
struct _MetaBarrierImplX11Private
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrier *barrier;
 | 
			
		||||
  PointerBarrier xbarrier;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaBarrierImplX11, meta_barrier_impl_x11,
 | 
			
		||||
                            META_TYPE_BARRIER_IMPL)
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
_meta_barrier_impl_x11_is_active (MetaBarrierImpl *impl)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierImplX11 *self = META_BARRIER_IMPL_X11 (impl);
 | 
			
		||||
  MetaBarrierImplX11Private *priv =
 | 
			
		||||
    meta_barrier_impl_x11_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
  return priv->xbarrier != 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
_meta_barrier_impl_x11_release (MetaBarrierImpl  *impl,
 | 
			
		||||
                                MetaBarrierEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierImplX11 *self = META_BARRIER_IMPL_X11 (impl);
 | 
			
		||||
  MetaBarrierImplX11Private *priv =
 | 
			
		||||
    meta_barrier_impl_x11_get_instance_private (self);
 | 
			
		||||
  MetaDisplay *display = priv->barrier->priv->display;
 | 
			
		||||
 | 
			
		||||
  if (META_DISPLAY_HAS_XINPUT_23 (display))
 | 
			
		||||
    {
 | 
			
		||||
      XIBarrierReleasePointer (display->xdisplay,
 | 
			
		||||
                               META_VIRTUAL_CORE_POINTER_ID,
 | 
			
		||||
                               priv->xbarrier, event->event_id);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
_meta_barrier_impl_x11_destroy (MetaBarrierImpl *impl)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierImplX11 *self = META_BARRIER_IMPL_X11 (impl);
 | 
			
		||||
  MetaBarrierImplX11Private *priv =
 | 
			
		||||
    meta_barrier_impl_x11_get_instance_private (self);
 | 
			
		||||
  MetaDisplay *display = priv->barrier->priv->display;
 | 
			
		||||
  Display *dpy;
 | 
			
		||||
 | 
			
		||||
  if (display == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  dpy = display->xdisplay;
 | 
			
		||||
 | 
			
		||||
  if (!meta_barrier_is_active (priv->barrier))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  XFixesDestroyPointerBarrier (dpy, priv->xbarrier);
 | 
			
		||||
  g_hash_table_remove (display->xids, &priv->xbarrier);
 | 
			
		||||
  priv->xbarrier = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaBarrierImpl *
 | 
			
		||||
meta_barrier_impl_x11_new (MetaBarrier *barrier)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierImplX11 *self;
 | 
			
		||||
  MetaBarrierImplX11Private *priv;
 | 
			
		||||
  MetaDisplay *display = barrier->priv->display;
 | 
			
		||||
  Display *dpy;
 | 
			
		||||
  Window root;
 | 
			
		||||
 | 
			
		||||
  if (display == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("A display must be provided when constructing a barrier.");
 | 
			
		||||
      return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  self = g_object_new (META_TYPE_BARRIER_IMPL_X11, NULL);
 | 
			
		||||
  priv = meta_barrier_impl_x11_get_instance_private (self);
 | 
			
		||||
  priv->barrier = barrier;
 | 
			
		||||
 | 
			
		||||
  dpy = display->xdisplay;
 | 
			
		||||
  root = DefaultRootWindow (dpy);
 | 
			
		||||
 | 
			
		||||
  priv->xbarrier = XFixesCreatePointerBarrier (dpy, root,
 | 
			
		||||
                                               barrier->priv->x1,
 | 
			
		||||
                                               barrier->priv->y1,
 | 
			
		||||
                                               barrier->priv->x2,
 | 
			
		||||
                                               barrier->priv->y2,
 | 
			
		||||
                                               barrier->priv->directions,
 | 
			
		||||
                                               0, NULL);
 | 
			
		||||
 | 
			
		||||
  g_hash_table_insert (display->xids, &priv->xbarrier, barrier);
 | 
			
		||||
 | 
			
		||||
  return META_BARRIER_IMPL (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_barrier_fire_xevent (MetaBarrier    *barrier,
 | 
			
		||||
                          XIBarrierEvent *xevent)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierEvent *event = g_slice_new0 (MetaBarrierEvent);
 | 
			
		||||
 | 
			
		||||
  event->ref_count = 1;
 | 
			
		||||
  event->event_id = xevent->eventid;
 | 
			
		||||
  event->time = xevent->time;
 | 
			
		||||
  event->dt = xevent->dtime;
 | 
			
		||||
 | 
			
		||||
  event->x = xevent->root_x;
 | 
			
		||||
  event->y = xevent->root_y;
 | 
			
		||||
  event->dx = xevent->dx;
 | 
			
		||||
  event->dy = xevent->dy;
 | 
			
		||||
 | 
			
		||||
  event->released = (xevent->flags & XIBarrierPointerReleased) != 0;
 | 
			
		||||
  event->grabbed = (xevent->flags & XIBarrierDeviceIsGrabbed) != 0;
 | 
			
		||||
 | 
			
		||||
  switch (xevent->evtype)
 | 
			
		||||
    {
 | 
			
		||||
    case XI_BarrierHit:
 | 
			
		||||
      _meta_barrier_emit_hit_signal (barrier, event);
 | 
			
		||||
      break;
 | 
			
		||||
    case XI_BarrierLeave:
 | 
			
		||||
      _meta_barrier_emit_left_signal (barrier, event);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_barrier_event_unref (event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_display_process_barrier_xevent (MetaDisplay *display,
 | 
			
		||||
                                     XIEvent     *event)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrier *barrier;
 | 
			
		||||
  XIBarrierEvent *xev;
 | 
			
		||||
 | 
			
		||||
  if (event == NULL)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  switch (event->evtype)
 | 
			
		||||
    {
 | 
			
		||||
    case XI_BarrierHit:
 | 
			
		||||
    case XI_BarrierLeave:
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  xev = (XIBarrierEvent *) event;
 | 
			
		||||
  barrier = g_hash_table_lookup (display->xids, &xev->barrier);
 | 
			
		||||
  if (barrier != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      meta_barrier_fire_xevent (barrier, xev);
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_barrier_impl_x11_class_init (MetaBarrierImplX11Class *klass)
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierImplClass *impl_class = META_BARRIER_IMPL_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  impl_class->is_active = _meta_barrier_impl_x11_is_active;
 | 
			
		||||
  impl_class->release = _meta_barrier_impl_x11_release;
 | 
			
		||||
  impl_class->destroy = _meta_barrier_impl_x11_destroy;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_barrier_impl_x11_init (MetaBarrierImplX11 *self)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* HAVE_XI23 */
 | 
			
		||||
							
								
								
									
										59
									
								
								src/backends/x11/meta-barrier-x11.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/backends/x11/meta-barrier-x11.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2015 Red Hat
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
 * published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 | 
			
		||||
 * 02111-1307, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * Written by:
 | 
			
		||||
 *     Jonas Ådahl <jadahl@gmail.com>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef META_BARRIER_X11_H
 | 
			
		||||
#define META_BARRIER_X11_H
 | 
			
		||||
 | 
			
		||||
#include "backends/meta-barrier-private.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_BARRIER_IMPL_X11            (meta_barrier_impl_x11_get_type ())
 | 
			
		||||
#define META_BARRIER_IMPL_X11(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BARRIER_IMPL_X11, MetaBarrierImplX11))
 | 
			
		||||
#define META_BARRIER_IMPL_X11_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_BARRIER_IMPL_X11, MetaBarrierImplX11Class))
 | 
			
		||||
#define META_IS_BARRIER_IMPL_X11(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BARRIER_IMPL_X11))
 | 
			
		||||
#define META_IS_BARRIER_IMPL_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_BARRIER_IMPL_X11))
 | 
			
		||||
#define META_BARRIER_IMPL_X11_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_BARRIER_IMPL_X11, MetaBarrierImplX11Class))
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaBarrierImplX11        MetaBarrierImplX11;
 | 
			
		||||
typedef struct _MetaBarrierImplX11Class   MetaBarrierImplX11Class;
 | 
			
		||||
typedef struct _MetaBarrierImplX11Private MetaBarrierImplX11Private;
 | 
			
		||||
 | 
			
		||||
struct _MetaBarrierImplX11
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierImpl parent;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaBarrierImplX11Class
 | 
			
		||||
{
 | 
			
		||||
  MetaBarrierImplClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType meta_barrier_impl_x11_get_type (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
MetaBarrierImpl *meta_barrier_impl_x11_new (MetaBarrier *barrier);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* META_BARRIER_X11_H1 */
 | 
			
		||||
@@ -26,6 +26,8 @@
 | 
			
		||||
 | 
			
		||||
#include "meta-cursor-renderer-x11.h"
 | 
			
		||||
 | 
			
		||||
#include <X11/extensions/Xfixes.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-backend-x11.h"
 | 
			
		||||
#include "meta-stage.h"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										226
									
								
								src/backends/x11/meta-input-settings-x11.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										226
									
								
								src/backends/x11/meta-input-settings-x11.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,226 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014 Red Hat
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
 * published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 | 
			
		||||
 * 02111-1307, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Carlos Garnacho <carlosg@gnome.org>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-backend-x11.h"
 | 
			
		||||
#include "meta-input-settings-x11.h"
 | 
			
		||||
 | 
			
		||||
#include <gdk/gdkx.h>
 | 
			
		||||
#include <X11/Xatom.h>
 | 
			
		||||
#include <X11/extensions/XInput2.h>
 | 
			
		||||
#include <X11/XKBlib.h>
 | 
			
		||||
 | 
			
		||||
#include <meta/errors.h>
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaInputSettingsX11, meta_input_settings_x11, META_TYPE_INPUT_SETTINGS)
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
change_property (ClutterInputDevice *device,
 | 
			
		||||
                 const gchar        *property,
 | 
			
		||||
                 Atom                type,
 | 
			
		||||
                 int                 format,
 | 
			
		||||
                 void               *data,
 | 
			
		||||
                 gulong              nitems)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackend *backend = meta_get_backend ();
 | 
			
		||||
  Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
 | 
			
		||||
  gulong nitems_ret, bytes_after_ret;
 | 
			
		||||
  int rc, device_id, format_ret;
 | 
			
		||||
  Atom property_atom, type_ret;
 | 
			
		||||
  guchar *data_ret;
 | 
			
		||||
 | 
			
		||||
  property_atom = XInternAtom (xdisplay, property, False);
 | 
			
		||||
  device_id = clutter_input_device_get_device_id (device);
 | 
			
		||||
 | 
			
		||||
  rc = XIGetProperty (xdisplay, device_id, property_atom,
 | 
			
		||||
                      0, 0, False, type, &type_ret, &format_ret,
 | 
			
		||||
                      &nitems_ret, &bytes_after_ret, &data_ret);
 | 
			
		||||
 | 
			
		||||
  meta_XFree (data_ret);
 | 
			
		||||
 | 
			
		||||
  if (rc == Success && type_ret == type && format_ret == format)
 | 
			
		||||
    XIChangeProperty (xdisplay, device_id, property_atom, type,
 | 
			
		||||
                      format, XIPropModeReplace, data, nitems);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_x11_set_send_events (MetaInputSettings        *settings,
 | 
			
		||||
                                         ClutterInputDevice       *device,
 | 
			
		||||
                                         GDesktopDeviceSendEvents  mode)
 | 
			
		||||
{
 | 
			
		||||
  guchar values[2] = { 0 }; /* disabled, disabled-on-external-mouse */
 | 
			
		||||
 | 
			
		||||
  switch (mode)
 | 
			
		||||
    {
 | 
			
		||||
    case G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED:
 | 
			
		||||
      values[0] = 1;
 | 
			
		||||
      break;
 | 
			
		||||
    case G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE:
 | 
			
		||||
      values[1] = 1;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  change_property (device, "libinput Send Events Mode Enabled",
 | 
			
		||||
                   XA_INTEGER, 8, &values, 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_x11_set_matrix (MetaInputSettings  *settings,
 | 
			
		||||
                                    ClutterInputDevice *device,
 | 
			
		||||
                                    gfloat              matrix[6])
 | 
			
		||||
{
 | 
			
		||||
  MetaBackend *backend = meta_get_backend ();
 | 
			
		||||
  Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
 | 
			
		||||
  gfloat full_matrix[9] = { matrix[0], matrix[1], matrix[2],
 | 
			
		||||
                            matrix[3], matrix[4], matrix[5],
 | 
			
		||||
                            0, 0, 1 };
 | 
			
		||||
 | 
			
		||||
  change_property (device, "Coordinate Transformation Matrix",
 | 
			
		||||
                   XInternAtom (xdisplay, "FLOAT", False),
 | 
			
		||||
                   32, &full_matrix, 9);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_x11_set_speed (MetaInputSettings  *settings,
 | 
			
		||||
                                   ClutterInputDevice *device,
 | 
			
		||||
                                   gdouble             speed)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackend *backend = meta_get_backend ();
 | 
			
		||||
  Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
 | 
			
		||||
  gfloat value = speed;
 | 
			
		||||
 | 
			
		||||
  change_property (device, "libinput Accel Speed",
 | 
			
		||||
                   XInternAtom (xdisplay, "FLOAT", False),
 | 
			
		||||
                   32, &value, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_x11_set_left_handed (MetaInputSettings  *settings,
 | 
			
		||||
                                         ClutterInputDevice *device,
 | 
			
		||||
                                         gboolean            enabled)
 | 
			
		||||
{
 | 
			
		||||
  guchar value = (enabled) ? 1 : 0;
 | 
			
		||||
 | 
			
		||||
  change_property (device, "libinput Left Handed Enabled",
 | 
			
		||||
                   XA_INTEGER, 8, &value, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_x11_set_tap_enabled (MetaInputSettings  *settings,
 | 
			
		||||
                                         ClutterInputDevice *device,
 | 
			
		||||
                                         gboolean            enabled)
 | 
			
		||||
{
 | 
			
		||||
  guchar value = (enabled) ? 1 : 0;
 | 
			
		||||
 | 
			
		||||
  change_property (device, "libinput Tapping Enabled",
 | 
			
		||||
                   XA_INTEGER, 8, &value, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_x11_set_invert_scroll (MetaInputSettings  *settings,
 | 
			
		||||
                                           ClutterInputDevice *device,
 | 
			
		||||
                                           gboolean            inverted)
 | 
			
		||||
{
 | 
			
		||||
  guchar value = (inverted) ? 1 : 0;
 | 
			
		||||
 | 
			
		||||
  change_property (device, "libinput Natural Scrolling Enabled",
 | 
			
		||||
                   XA_INTEGER, 8, &value, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_x11_set_scroll_method (MetaInputSettings            *settings,
 | 
			
		||||
                                           ClutterInputDevice           *device,
 | 
			
		||||
                                           GDesktopTouchpadScrollMethod  mode)
 | 
			
		||||
{
 | 
			
		||||
  guchar values[3] = { 0 }; /* 2fg, edge, button. The last value is unused */
 | 
			
		||||
 | 
			
		||||
  switch (mode)
 | 
			
		||||
    {
 | 
			
		||||
    case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_DISABLED:
 | 
			
		||||
      break;
 | 
			
		||||
    case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_EDGE_SCROLLING:
 | 
			
		||||
      values[1] = 1;
 | 
			
		||||
      break;
 | 
			
		||||
    case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_TWO_FINGER_SCROLLING:
 | 
			
		||||
      values[0] = 1;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  change_property (device, "libinput Scroll Method Enabled",
 | 
			
		||||
                   XA_INTEGER, 8, &values, 3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_x11_set_scroll_button (MetaInputSettings  *settings,
 | 
			
		||||
                                           ClutterInputDevice *device,
 | 
			
		||||
                                           guint               button)
 | 
			
		||||
{
 | 
			
		||||
  change_property (device, "libinput Scroll Method Enabled",
 | 
			
		||||
                   XA_INTEGER, 32, &button, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_x11_set_keyboard_repeat (MetaInputSettings *settings,
 | 
			
		||||
                                             gboolean           enabled,
 | 
			
		||||
                                             guint              delay,
 | 
			
		||||
                                             guint              interval)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackend *backend = meta_get_backend ();
 | 
			
		||||
  Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
 | 
			
		||||
 | 
			
		||||
  if (enabled)
 | 
			
		||||
    {
 | 
			
		||||
      XAutoRepeatOn (xdisplay);
 | 
			
		||||
      XkbSetAutoRepeatRate (xdisplay, XkbUseCoreKbd, delay, interval);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      XAutoRepeatOff (xdisplay);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_x11_class_init (MetaInputSettingsX11Class *klass)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsClass *input_settings_class = META_INPUT_SETTINGS_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  input_settings_class->set_send_events = meta_input_settings_x11_set_send_events;
 | 
			
		||||
  input_settings_class->set_matrix = meta_input_settings_x11_set_matrix;
 | 
			
		||||
  input_settings_class->set_speed = meta_input_settings_x11_set_speed;
 | 
			
		||||
  input_settings_class->set_left_handed = meta_input_settings_x11_set_left_handed;
 | 
			
		||||
  input_settings_class->set_tap_enabled = meta_input_settings_x11_set_tap_enabled;
 | 
			
		||||
  input_settings_class->set_invert_scroll = meta_input_settings_x11_set_invert_scroll;
 | 
			
		||||
  input_settings_class->set_scroll_method = meta_input_settings_x11_set_scroll_method;
 | 
			
		||||
  input_settings_class->set_scroll_button = meta_input_settings_x11_set_scroll_button;
 | 
			
		||||
  input_settings_class->set_keyboard_repeat = meta_input_settings_x11_set_keyboard_repeat;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_x11_init (MetaInputSettingsX11 *settings)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								src/backends/x11/meta-input-settings-x11.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/backends/x11/meta-input-settings-x11.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2014 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 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Carlos Garnacho <carlosg@gnome.org>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef META_INPUT_SETTINGS_X11_H
 | 
			
		||||
#define META_INPUT_SETTINGS_X11_H
 | 
			
		||||
 | 
			
		||||
#include "meta-input-settings-private.h"
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_INPUT_SETTINGS_X11             (meta_input_settings_x11_get_type ())
 | 
			
		||||
#define META_INPUT_SETTINGS_X11(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_INPUT_SETTINGS_X11, MetaInputSettingsX11))
 | 
			
		||||
#define META_INPUT_SETTINGS_X11_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_INPUT_SETTINGS_X11, MetaInputSettingsX11Class))
 | 
			
		||||
#define META_IS_INPUT_SETTINGS_X11(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_INPUT_SETTINGS_X11))
 | 
			
		||||
#define META_IS_INPUT_SETTINGS_X11_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_INPUT_SETTINGS_X11))
 | 
			
		||||
#define META_INPUT_SETTINGS_X11_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_INPUT_SETTINGS_X11, MetaInputSettingsX11Class))
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaInputSettingsX11 MetaInputSettingsX11;
 | 
			
		||||
typedef struct _MetaInputSettingsX11Class MetaInputSettingsX11Class;
 | 
			
		||||
 | 
			
		||||
struct _MetaInputSettingsX11
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettings parent_instance;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaInputSettingsX11Class
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType meta_input_settings_x11_get_type (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
#endif /* META_INPUT_SETTINGS_X11_H */
 | 
			
		||||
@@ -41,7 +41,6 @@
 | 
			
		||||
#include "meta-backend-x11.h"
 | 
			
		||||
#include <meta/main.h>
 | 
			
		||||
#include <meta/errors.h>
 | 
			
		||||
#include "edid.h"
 | 
			
		||||
#include "meta-monitor-config.h"
 | 
			
		||||
 | 
			
		||||
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
 | 
			
		||||
@@ -57,7 +56,6 @@ struct _MetaMonitorManagerXrandr
 | 
			
		||||
 | 
			
		||||
  Display *xdisplay;
 | 
			
		||||
  XRRScreenResources *resources;
 | 
			
		||||
  int time;
 | 
			
		||||
  int rr_event_base;
 | 
			
		||||
  int rr_error_base;
 | 
			
		||||
};
 | 
			
		||||
@@ -140,11 +138,63 @@ meta_monitor_transform_from_xrandr_all (Rotation rotation)
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
output_get_integer_property (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                             MetaOutput *output, const char *propname,
 | 
			
		||||
                             gint *value)
 | 
			
		||||
{
 | 
			
		||||
  gboolean exists = FALSE;
 | 
			
		||||
  Atom atom, actual_type;
 | 
			
		||||
  int actual_format;
 | 
			
		||||
  unsigned long nitems, bytes_after;
 | 
			
		||||
  unsigned char *buffer;
 | 
			
		||||
 | 
			
		||||
  atom = XInternAtom (manager_xrandr->xdisplay, propname, False);
 | 
			
		||||
  XRRGetOutputProperty (manager_xrandr->xdisplay,
 | 
			
		||||
                        (XID)output->winsys_id,
 | 
			
		||||
                        atom,
 | 
			
		||||
                        0, G_MAXLONG, False, False, XA_INTEGER,
 | 
			
		||||
                        &actual_type, &actual_format,
 | 
			
		||||
                        &nitems, &bytes_after, &buffer);
 | 
			
		||||
 | 
			
		||||
  exists = (actual_type == XA_INTEGER && actual_format == 32 && nitems == 1);
 | 
			
		||||
 | 
			
		||||
  if (exists && value != NULL)
 | 
			
		||||
    *value = ((int*)buffer)[0];
 | 
			
		||||
 | 
			
		||||
  XFree (buffer);
 | 
			
		||||
  return exists;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
output_get_property_exists (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                            MetaOutput *output, const char *propname)
 | 
			
		||||
{
 | 
			
		||||
  gboolean exists = FALSE;
 | 
			
		||||
  Atom atom, actual_type;
 | 
			
		||||
  int actual_format;
 | 
			
		||||
  unsigned long nitems, bytes_after;
 | 
			
		||||
  unsigned char *buffer;
 | 
			
		||||
 | 
			
		||||
  atom = XInternAtom (manager_xrandr->xdisplay, propname, False);
 | 
			
		||||
  XRRGetOutputProperty (manager_xrandr->xdisplay,
 | 
			
		||||
                        (XID)output->winsys_id,
 | 
			
		||||
                        atom,
 | 
			
		||||
                        0, G_MAXLONG, False, False, AnyPropertyType,
 | 
			
		||||
                        &actual_type, &actual_format,
 | 
			
		||||
                        &nitems, &bytes_after, &buffer);
 | 
			
		||||
 | 
			
		||||
  exists = (actual_type != None);
 | 
			
		||||
 | 
			
		||||
  XFree (buffer);
 | 
			
		||||
  return exists;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                             MetaOutput *output, const char *propname)
 | 
			
		||||
{
 | 
			
		||||
  gboolean value;
 | 
			
		||||
  gboolean value = FALSE;
 | 
			
		||||
  Atom atom, actual_type;
 | 
			
		||||
  int actual_format;
 | 
			
		||||
  unsigned long nitems, bytes_after;
 | 
			
		||||
@@ -158,12 +208,12 @@ output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                        &actual_type, &actual_format,
 | 
			
		||||
                        &nitems, &bytes_after, &buffer);
 | 
			
		||||
 | 
			
		||||
  if (actual_type != XA_CARDINAL || actual_format != 32 ||
 | 
			
		||||
      nitems < 1)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
  if (actual_type != XA_CARDINAL || actual_format != 32 || nitems < 1)
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  value = ((int*)buffer)[0];
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  XFree (buffer);
 | 
			
		||||
  return value;
 | 
			
		||||
}
 | 
			
		||||
@@ -187,7 +237,7 @@ static int
 | 
			
		||||
output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                             MetaOutput               *output)
 | 
			
		||||
{
 | 
			
		||||
  gboolean value;
 | 
			
		||||
  int value = -1;
 | 
			
		||||
  Atom atom, actual_type;
 | 
			
		||||
  int actual_format;
 | 
			
		||||
  unsigned long nitems, bytes_after;
 | 
			
		||||
@@ -201,14 +251,17 @@ output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                        &actual_type, &actual_format,
 | 
			
		||||
                        &nitems, &bytes_after, &buffer);
 | 
			
		||||
 | 
			
		||||
  if (actual_type != XA_INTEGER || actual_format != 32 ||
 | 
			
		||||
      nitems < 1)
 | 
			
		||||
    return -1;
 | 
			
		||||
  if (actual_type != XA_INTEGER || actual_format != 32 || nitems < 1)
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  value = ((int*)buffer)[0];
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  XFree (buffer);
 | 
			
		||||
  return normalize_backlight (output, value);
 | 
			
		||||
  if (value > 0)
 | 
			
		||||
    return normalize_backlight (output, value);
 | 
			
		||||
  else
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -327,7 +380,170 @@ static gboolean
 | 
			
		||||
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                                MetaOutput               *output)
 | 
			
		||||
{
 | 
			
		||||
  return output_get_boolean_property (manager_xrandr, output, "hotplug_mode_update");
 | 
			
		||||
  return output_get_property_exists (manager_xrandr, output, "hotplug_mode_update");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gint
 | 
			
		||||
output_get_suggested_x (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                        MetaOutput               *output)
 | 
			
		||||
{
 | 
			
		||||
  gint val;
 | 
			
		||||
  if (output_get_integer_property (manager_xrandr, output, "suggested X", &val))
 | 
			
		||||
    return val;
 | 
			
		||||
 | 
			
		||||
  return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gint
 | 
			
		||||
output_get_suggested_y (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                        MetaOutput               *output)
 | 
			
		||||
{
 | 
			
		||||
  gint val;
 | 
			
		||||
  if (output_get_integer_property (manager_xrandr, output, "suggested Y", &val))
 | 
			
		||||
    return val;
 | 
			
		||||
 | 
			
		||||
  return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaConnectorType
 | 
			
		||||
connector_type_from_atom (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                          Atom                      atom)
 | 
			
		||||
{
 | 
			
		||||
  Display *xdpy = manager_xrandr->xdisplay;
 | 
			
		||||
 | 
			
		||||
  if (atom == XInternAtom (xdpy, "HDMI", True))
 | 
			
		||||
    return META_CONNECTOR_TYPE_HDMIA;
 | 
			
		||||
  if (atom == XInternAtom (xdpy, "VGA", True))
 | 
			
		||||
    return META_CONNECTOR_TYPE_VGA;
 | 
			
		||||
  /* Doesn't have a DRM equivalent, but means an internal panel.
 | 
			
		||||
   * We could pick either LVDS or eDP here. */
 | 
			
		||||
  if (atom == XInternAtom (xdpy, "Panel", True))
 | 
			
		||||
    return META_CONNECTOR_TYPE_LVDS;
 | 
			
		||||
  if (atom == XInternAtom (xdpy, "DVI", True) || atom == XInternAtom (xdpy, "DVI-I", True))
 | 
			
		||||
    return META_CONNECTOR_TYPE_DVII;
 | 
			
		||||
  if (atom == XInternAtom (xdpy, "DVI-A", True))
 | 
			
		||||
    return META_CONNECTOR_TYPE_DVIA;
 | 
			
		||||
  if (atom == XInternAtom (xdpy, "DVI-D", True))
 | 
			
		||||
    return META_CONNECTOR_TYPE_DVID;
 | 
			
		||||
  if (atom == XInternAtom (xdpy, "DisplayPort", True))
 | 
			
		||||
    return META_CONNECTOR_TYPE_DisplayPort;
 | 
			
		||||
 | 
			
		||||
  if (atom == XInternAtom (xdpy, "TV", True))
 | 
			
		||||
    return META_CONNECTOR_TYPE_TV;
 | 
			
		||||
  if (atom == XInternAtom (xdpy, "TV-Composite", True))
 | 
			
		||||
    return META_CONNECTOR_TYPE_Composite;
 | 
			
		||||
  if (atom == XInternAtom (xdpy, "TV-SVideo", True))
 | 
			
		||||
    return META_CONNECTOR_TYPE_SVIDEO;
 | 
			
		||||
  /* Another set of mismatches. */
 | 
			
		||||
  if (atom == XInternAtom (xdpy, "TV-SCART", True))
 | 
			
		||||
    return META_CONNECTOR_TYPE_TV;
 | 
			
		||||
  if (atom == XInternAtom (xdpy, "TV-C4", True))
 | 
			
		||||
    return META_CONNECTOR_TYPE_TV;
 | 
			
		||||
 | 
			
		||||
  return META_CONNECTOR_TYPE_Unknown;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaConnectorType
 | 
			
		||||
output_get_connector_type_from_prop (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                                     MetaOutput               *output)
 | 
			
		||||
{
 | 
			
		||||
  MetaConnectorType ret = META_CONNECTOR_TYPE_Unknown;
 | 
			
		||||
  Atom atom, actual_type, connector_type_atom;
 | 
			
		||||
  int actual_format;
 | 
			
		||||
  unsigned long nitems, bytes_after;
 | 
			
		||||
  unsigned char *buffer;
 | 
			
		||||
 | 
			
		||||
  atom = XInternAtom (manager_xrandr->xdisplay, "ConnectorType", False);
 | 
			
		||||
  XRRGetOutputProperty (manager_xrandr->xdisplay,
 | 
			
		||||
                        (XID)output->winsys_id,
 | 
			
		||||
                        atom,
 | 
			
		||||
                        0, G_MAXLONG, False, False, XA_ATOM,
 | 
			
		||||
                        &actual_type, &actual_format,
 | 
			
		||||
                        &nitems, &bytes_after, &buffer);
 | 
			
		||||
 | 
			
		||||
  if (actual_type != XA_ATOM || actual_format != 32 || nitems < 1)
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  connector_type_atom = ((Atom *) buffer)[0];
 | 
			
		||||
  ret = connector_type_from_atom (manager_xrandr, connector_type_atom);
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  meta_XFree (buffer);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaConnectorType
 | 
			
		||||
output_get_connector_type_from_name (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                                     MetaOutput               *output)
 | 
			
		||||
{
 | 
			
		||||
  const char *name = output->name;
 | 
			
		||||
 | 
			
		||||
  /* drmmode_display.c, which was copy/pasted across all the FOSS
 | 
			
		||||
   * xf86-video-* drivers, seems to name its outputs based on the
 | 
			
		||||
   * connector type, so look for that....
 | 
			
		||||
   *
 | 
			
		||||
   * SNA has its own naming scheme, because what else did you expect
 | 
			
		||||
   * from SNA, but it's not too different, so we can thankfully use
 | 
			
		||||
   * that with minor changes.
 | 
			
		||||
   *
 | 
			
		||||
   * http://cgit.freedesktop.org/xorg/xserver/tree/hw/xfree86/drivers/modesetting/drmmode_display.c#n953
 | 
			
		||||
   * http://cgit.freedesktop.org/xorg/driver/xf86-video-intel/tree/src/sna/sna_display.c#n3486
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  if (g_str_has_prefix (name, "DVI"))
 | 
			
		||||
    return META_CONNECTOR_TYPE_DVII;
 | 
			
		||||
  if (g_str_has_prefix (name, "LVDS"))
 | 
			
		||||
    return META_CONNECTOR_TYPE_LVDS;
 | 
			
		||||
  if (g_str_has_prefix (name, "HDMI"))
 | 
			
		||||
    return META_CONNECTOR_TYPE_HDMIA;
 | 
			
		||||
  if (g_str_has_prefix (name, "VGA"))
 | 
			
		||||
    return META_CONNECTOR_TYPE_VGA;
 | 
			
		||||
  /* SNA uses DP, not DisplayPort. Test for both. */
 | 
			
		||||
  if (g_str_has_prefix (name, "DP") || g_str_has_prefix (name, "DisplayPort"))
 | 
			
		||||
    return META_CONNECTOR_TYPE_DisplayPort;
 | 
			
		||||
  if (g_str_has_prefix (name, "eDP"))
 | 
			
		||||
    return META_CONNECTOR_TYPE_eDP;
 | 
			
		||||
  if (g_str_has_prefix (name, "Virtual"))
 | 
			
		||||
    return META_CONNECTOR_TYPE_VIRTUAL;
 | 
			
		||||
  if (g_str_has_prefix (name, "Composite"))
 | 
			
		||||
    return META_CONNECTOR_TYPE_VGA;
 | 
			
		||||
  if (g_str_has_prefix (name, "S-video"))
 | 
			
		||||
    return META_CONNECTOR_TYPE_SVIDEO;
 | 
			
		||||
  if (g_str_has_prefix (name, "TV"))
 | 
			
		||||
    return META_CONNECTOR_TYPE_TV;
 | 
			
		||||
  if (g_str_has_prefix (name, "CTV"))
 | 
			
		||||
    return META_CONNECTOR_TYPE_Composite;
 | 
			
		||||
  if (g_str_has_prefix (name, "DSI"))
 | 
			
		||||
    return META_CONNECTOR_TYPE_DSI;
 | 
			
		||||
  if (g_str_has_prefix (name, "DIN"))
 | 
			
		||||
    return META_CONNECTOR_TYPE_9PinDIN;
 | 
			
		||||
 | 
			
		||||
  return META_CONNECTOR_TYPE_Unknown;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaConnectorType
 | 
			
		||||
output_get_connector_type (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                           MetaOutput               *output)
 | 
			
		||||
{
 | 
			
		||||
  MetaConnectorType ret;
 | 
			
		||||
 | 
			
		||||
  /* The "ConnectorType" property is considered mandatory since RandR 1.3,
 | 
			
		||||
   * but none of the FOSS drivers support it, because we're a bunch of
 | 
			
		||||
   * professional software developers.
 | 
			
		||||
   *
 | 
			
		||||
   * Try poking it first, without any expectations that it will work.
 | 
			
		||||
   * If it's not there, we thankfully have other bonghits to try next.
 | 
			
		||||
   */
 | 
			
		||||
  ret = output_get_connector_type_from_prop (manager_xrandr, output);
 | 
			
		||||
  if (ret != META_CONNECTOR_TYPE_Unknown)
 | 
			
		||||
    return ret;
 | 
			
		||||
 | 
			
		||||
  /* Fall back to heuristics based on the output name. */
 | 
			
		||||
  ret = output_get_connector_type_from_name (manager_xrandr, output);
 | 
			
		||||
  if (ret != META_CONNECTOR_TYPE_Unknown)
 | 
			
		||||
    return ret;
 | 
			
		||||
 | 
			
		||||
  return META_CONNECTOR_TYPE_Unknown;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *
 | 
			
		||||
@@ -336,12 +552,6 @@ get_xmode_name (XRRModeInfo *xmode)
 | 
			
		||||
  int width = xmode->width;
 | 
			
		||||
  int height = xmode->height;
 | 
			
		||||
 | 
			
		||||
  if (xmode->hSkew != 0)
 | 
			
		||||
    {
 | 
			
		||||
      width += 2 * (xmode->hSkew >> 8);
 | 
			
		||||
      height += 2 * (xmode->hSkew & 0xff);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return g_strdup_printf ("%dx%d", width, height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -410,7 +620,6 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  manager_xrandr->resources = resources;
 | 
			
		||||
  manager_xrandr->time = resources->configTimestamp;
 | 
			
		||||
  manager->n_outputs = resources->noutput;
 | 
			
		||||
  manager->n_crtcs = resources->ncrtc;
 | 
			
		||||
  manager->n_modes = resources->nmode;
 | 
			
		||||
@@ -479,45 +688,21 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
 | 
			
		||||
      if (output->connection != RR_Disconnected)
 | 
			
		||||
	{
 | 
			
		||||
          GBytes *edid;
 | 
			
		||||
          MonitorInfo *parsed_edid;
 | 
			
		||||
 | 
			
		||||
	  meta_output->winsys_id = resources->outputs[i];
 | 
			
		||||
	  meta_output->name = g_strdup (output->name);
 | 
			
		||||
 | 
			
		||||
          edid = read_output_edid (manager_xrandr, meta_output->winsys_id);
 | 
			
		||||
          if (edid)
 | 
			
		||||
            {
 | 
			
		||||
              gsize len;
 | 
			
		||||
          meta_output_parse_edid (meta_output, edid);
 | 
			
		||||
          g_bytes_unref (edid);
 | 
			
		||||
 | 
			
		||||
              parsed_edid = decode_edid (g_bytes_get_data (edid, &len));
 | 
			
		||||
              if (parsed_edid)
 | 
			
		||||
                {
 | 
			
		||||
                  meta_output->vendor = g_strndup (parsed_edid->manufacturer_code, 4);
 | 
			
		||||
                  if (parsed_edid->dsc_product_name[0])
 | 
			
		||||
                    meta_output->product = g_strndup (parsed_edid->dsc_product_name, 14);
 | 
			
		||||
                  else
 | 
			
		||||
                    meta_output->product = g_strdup_printf ("0x%04x", (unsigned)parsed_edid->product_code);
 | 
			
		||||
                  if (parsed_edid->dsc_serial_number[0])
 | 
			
		||||
                    meta_output->serial = g_strndup (parsed_edid->dsc_serial_number, 14);
 | 
			
		||||
                  else
 | 
			
		||||
                    meta_output->serial = g_strdup_printf ("0x%08x", parsed_edid->serial_number);
 | 
			
		||||
 | 
			
		||||
                  g_free (parsed_edid);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
              g_bytes_unref (edid);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          if (!meta_output->vendor)
 | 
			
		||||
            {
 | 
			
		||||
              meta_output->vendor = g_strdup ("unknown");
 | 
			
		||||
              meta_output->product = g_strdup ("unknown");
 | 
			
		||||
              meta_output->serial = g_strdup ("unknown");
 | 
			
		||||
            }
 | 
			
		||||
	  meta_output->width_mm = output->mm_width;
 | 
			
		||||
	  meta_output->height_mm = output->mm_height;
 | 
			
		||||
	  meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
 | 
			
		||||
          meta_output->hotplug_mode_update = output_get_hotplug_mode_update (manager_xrandr, meta_output);
 | 
			
		||||
	  meta_output->suggested_x = output_get_suggested_x (manager_xrandr, meta_output);
 | 
			
		||||
	  meta_output->suggested_y = output_get_suggested_y (manager_xrandr, meta_output);
 | 
			
		||||
          meta_output->connector_type = output_get_connector_type (manager_xrandr, meta_output);
 | 
			
		||||
 | 
			
		||||
	  meta_output->n_modes = output->nmode;
 | 
			
		||||
	  meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
 | 
			
		||||
@@ -744,7 +929,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
 | 
			
		||||
          XRRSetCrtcConfig (manager_xrandr->xdisplay,
 | 
			
		||||
                            manager_xrandr->resources,
 | 
			
		||||
                            (XID)crtc->crtc_id,
 | 
			
		||||
                            manager_xrandr->time,
 | 
			
		||||
                            CurrentTime,
 | 
			
		||||
                            0, 0,
 | 
			
		||||
                            None,
 | 
			
		||||
                            RR_Rotate_0,
 | 
			
		||||
@@ -774,7 +959,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
 | 
			
		||||
      XRRSetCrtcConfig (manager_xrandr->xdisplay,
 | 
			
		||||
                        manager_xrandr->resources,
 | 
			
		||||
                        (XID)crtc->crtc_id,
 | 
			
		||||
                        manager_xrandr->time,
 | 
			
		||||
                        CurrentTime,
 | 
			
		||||
                        0, 0,
 | 
			
		||||
                        None,
 | 
			
		||||
                        RR_Rotate_0,
 | 
			
		||||
@@ -811,26 +996,12 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
 | 
			
		||||
          unsigned int j, n_outputs;
 | 
			
		||||
          int width, height;
 | 
			
		||||
          Status ok;
 | 
			
		||||
          unsigned long old_controlled_mask;
 | 
			
		||||
          unsigned long new_controlled_mask;
 | 
			
		||||
 | 
			
		||||
          mode = crtc_info->mode;
 | 
			
		||||
 | 
			
		||||
          n_outputs = crtc_info->outputs->len;
 | 
			
		||||
          outputs = g_new (XID, n_outputs);
 | 
			
		||||
 | 
			
		||||
          old_controlled_mask = 0;
 | 
			
		||||
          for (j = 0; j < manager->n_outputs; j++)
 | 
			
		||||
            {
 | 
			
		||||
              MetaOutput *output;
 | 
			
		||||
 | 
			
		||||
              output = &manager->outputs[j];
 | 
			
		||||
 | 
			
		||||
              if (output->crtc == crtc)
 | 
			
		||||
                old_controlled_mask |= 1UL << j;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          new_controlled_mask = 0;
 | 
			
		||||
          for (j = 0; j < n_outputs; j++)
 | 
			
		||||
            {
 | 
			
		||||
              MetaOutput *output;
 | 
			
		||||
@@ -839,25 +1010,14 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
 | 
			
		||||
 | 
			
		||||
              output->is_dirty = TRUE;
 | 
			
		||||
              output->crtc = crtc;
 | 
			
		||||
              new_controlled_mask |= 1UL << j;
 | 
			
		||||
 | 
			
		||||
              outputs[j] = output->winsys_id;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          if (crtc->current_mode == mode &&
 | 
			
		||||
              crtc->rect.x == crtc_info->x &&
 | 
			
		||||
              crtc->rect.y == crtc_info->y &&
 | 
			
		||||
              crtc->transform == crtc_info->transform &&
 | 
			
		||||
              old_controlled_mask == new_controlled_mask)
 | 
			
		||||
            {
 | 
			
		||||
              /* No change */
 | 
			
		||||
              goto next;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
 | 
			
		||||
                                 manager_xrandr->resources,
 | 
			
		||||
                                 (XID)crtc->crtc_id,
 | 
			
		||||
                                 manager_xrandr->time,
 | 
			
		||||
                                 CurrentTime,
 | 
			
		||||
                                 crtc_info->x, crtc_info->y,
 | 
			
		||||
                                 (XID)mode->mode_id,
 | 
			
		||||
                                 meta_monitor_transform_to_xrandr (crtc_info->transform),
 | 
			
		||||
@@ -865,7 +1025,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
 | 
			
		||||
 | 
			
		||||
          if (ok != Success)
 | 
			
		||||
            {
 | 
			
		||||
              meta_warning ("Configuring CRTC %d with mode %d (%d x %d @ %f) at position %d, %d and transfrom %u failed\n",
 | 
			
		||||
              meta_warning ("Configuring CRTC %d with mode %d (%d x %d @ %f) at position %d, %d and transform %u failed\n",
 | 
			
		||||
                            (unsigned)(crtc->crtc_id), (unsigned)(mode->mode_id),
 | 
			
		||||
                            mode->width, mode->height, (float)mode->refresh_rate,
 | 
			
		||||
                            crtc_info->x, crtc_info->y, crtc_info->transform);
 | 
			
		||||
@@ -998,16 +1158,6 @@ meta_monitor_manager_xrandr_set_crtc_gamma (MetaMonitorManager *manager,
 | 
			
		||||
  XRRFreeGamma (gamma);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_xrandr_rebuild_derived (MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
  /* This will be a no-op if the change was from our side, as
 | 
			
		||||
     we already called it in the DBus method handler */
 | 
			
		||||
  meta_monitor_config_update_current (manager->config, manager);
 | 
			
		||||
 | 
			
		||||
  meta_monitor_manager_rebuild_derived (manager);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
 | 
			
		||||
{
 | 
			
		||||
@@ -1067,63 +1217,26 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
 | 
			
		||||
					   XEvent                   *event)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
 | 
			
		||||
  MetaOutput *old_outputs;
 | 
			
		||||
  MetaCRTC *old_crtcs;
 | 
			
		||||
  MetaMonitorMode *old_modes;
 | 
			
		||||
  unsigned int n_old_outputs, n_old_modes;
 | 
			
		||||
  gboolean new_config;
 | 
			
		||||
  gboolean hotplug;
 | 
			
		||||
 | 
			
		||||
  if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  XRRUpdateConfiguration (event);
 | 
			
		||||
 | 
			
		||||
  /* Save the old structures, so they stay valid during the update */
 | 
			
		||||
  old_outputs = manager->outputs;
 | 
			
		||||
  n_old_outputs = manager->n_outputs;
 | 
			
		||||
  old_modes = manager->modes;
 | 
			
		||||
  n_old_modes = manager->n_modes;
 | 
			
		||||
  old_crtcs = manager->crtcs;
 | 
			
		||||
 | 
			
		||||
  manager->serial++;
 | 
			
		||||
  meta_monitor_manager_xrandr_read_current (manager);
 | 
			
		||||
 | 
			
		||||
  new_config = manager_xrandr->resources->timestamp >=
 | 
			
		||||
    manager_xrandr->resources->configTimestamp;
 | 
			
		||||
  if (meta_monitor_manager_has_hotplug_mode_update (manager))
 | 
			
		||||
  meta_monitor_manager_read_current_config (manager);
 | 
			
		||||
 | 
			
		||||
  hotplug = manager_xrandr->resources->timestamp < manager_xrandr->resources->configTimestamp;
 | 
			
		||||
  if (hotplug)
 | 
			
		||||
    {
 | 
			
		||||
      /* Check if the current intended configuration is a result of an
 | 
			
		||||
         XRandR call.  Otherwise, hotplug_mode_update tells us to get
 | 
			
		||||
         a new preferred mode on hotplug events to handle dynamic
 | 
			
		||||
         guest resizing. */
 | 
			
		||||
      if (new_config)
 | 
			
		||||
        meta_monitor_manager_xrandr_rebuild_derived (manager);
 | 
			
		||||
      else
 | 
			
		||||
        meta_monitor_config_make_default (manager->config, manager);
 | 
			
		||||
      /* This is a hotplug event, so go ahead and build a new configuration. */
 | 
			
		||||
      meta_monitor_manager_on_hotplug (manager);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      /* Check if the current intended configuration has the same outputs
 | 
			
		||||
         as the new real one, or if the event is a result of an XRandR call.
 | 
			
		||||
         If so, we can go straight to rebuild the logical config and tell
 | 
			
		||||
         the outside world.
 | 
			
		||||
         Otherwise, this event was caused by hotplug, so give a chance to
 | 
			
		||||
         MetaMonitorConfig.
 | 
			
		||||
 | 
			
		||||
         Note that we need to check both the timestamps and the list of
 | 
			
		||||
         outputs, because the X server might emit spurious events with new
 | 
			
		||||
         configTimestamps (bug 702804), and the driver may have changed
 | 
			
		||||
         the EDID for some other reason (old qxl and vbox drivers). */
 | 
			
		||||
      if (new_config || meta_monitor_config_match_current (manager->config, manager))
 | 
			
		||||
        meta_monitor_manager_xrandr_rebuild_derived (manager);
 | 
			
		||||
      else if (!meta_monitor_config_apply_stored (manager->config, manager))
 | 
			
		||||
        meta_monitor_config_make_default (manager->config, manager);
 | 
			
		||||
      /* Something else changed -- tell the world about it. */
 | 
			
		||||
      meta_monitor_manager_rebuild_derived (manager);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
 | 
			
		||||
  meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
 | 
			
		||||
  g_free (old_crtcs);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@
 | 
			
		||||
#ifndef META_MONITOR_MANAGER_XRANDR_H
 | 
			
		||||
#define META_MONITOR_MANAGER_XRANDR_H
 | 
			
		||||
 | 
			
		||||
#include "meta-monitor-manager.h"
 | 
			
		||||
#include "meta-monitor-manager-private.h"
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_MONITOR_MANAGER_XRANDR            (meta_monitor_manager_xrandr_get_type ())
 | 
			
		||||
#define META_MONITOR_MANAGER_XRANDR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandr))
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ struct _MetaCompositor
 | 
			
		||||
  guint           server_time_is_monotonic_time : 1;
 | 
			
		||||
  guint           no_mipmaps  : 1;
 | 
			
		||||
 | 
			
		||||
  ClutterActor          *stage, *window_group, *top_window_group;
 | 
			
		||||
  ClutterActor          *stage, *window_group, *top_window_group, *feedback_group;
 | 
			
		||||
  ClutterActor          *background_actor;
 | 
			
		||||
  GList                 *windows;
 | 
			
		||||
  Window                 output;
 | 
			
		||||
 
 | 
			
		||||
@@ -185,6 +185,19 @@ meta_get_top_window_group_for_screen (MetaScreen *screen)
 | 
			
		||||
  return compositor->top_window_group;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_get_feedback_group_for_screen:
 | 
			
		||||
 * @screen: a #MetaScreen
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: (transfer none): The feedback group corresponding to @screen
 | 
			
		||||
 */
 | 
			
		||||
ClutterActor *
 | 
			
		||||
meta_get_feedback_group_for_screen (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  MetaCompositor *compositor = get_compositor_for_screen (screen);
 | 
			
		||||
  return compositor->feedback_group;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_get_window_actors:
 | 
			
		||||
 * @screen: a #MetaScreen
 | 
			
		||||
@@ -478,9 +491,11 @@ meta_compositor_manage (MetaCompositor *compositor)
 | 
			
		||||
 | 
			
		||||
  compositor->window_group = meta_window_group_new (screen);
 | 
			
		||||
  compositor->top_window_group = meta_window_group_new (screen);
 | 
			
		||||
  compositor->feedback_group = meta_window_group_new (screen);
 | 
			
		||||
 | 
			
		||||
  clutter_actor_add_child (compositor->stage, compositor->window_group);
 | 
			
		||||
  clutter_actor_add_child (compositor->stage, compositor->top_window_group);
 | 
			
		||||
  clutter_actor_add_child (compositor->stage, compositor->feedback_group);
 | 
			
		||||
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
    {
 | 
			
		||||
@@ -599,6 +614,7 @@ set_unredirected_window (MetaCompositor *compositor,
 | 
			
		||||
      meta_window_actor_set_unredirected (window_actor, FALSE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_shape_cow_for_window (compositor, window);
 | 
			
		||||
  compositor->unredirected_window = window;
 | 
			
		||||
 | 
			
		||||
  if (compositor->unredirected_window != NULL)
 | 
			
		||||
@@ -606,8 +622,6 @@ set_unredirected_window (MetaCompositor *compositor,
 | 
			
		||||
      MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (compositor->unredirected_window));
 | 
			
		||||
      meta_window_actor_set_unredirected (window_actor, TRUE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_shape_cow_for_window (compositor, compositor->unredirected_window);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
 
 | 
			
		||||
@@ -708,6 +708,7 @@ on_background_changed (MetaBackground      *background,
 | 
			
		||||
                       MetaBackgroundActor *self)
 | 
			
		||||
{
 | 
			
		||||
  invalidate_pipeline (self, CHANGED_BACKGROUND);
 | 
			
		||||
  clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
 
 | 
			
		||||
@@ -53,7 +53,7 @@ struct _MetaBackgroundImageCacheClass
 | 
			
		||||
struct _MetaBackgroundImage
 | 
			
		||||
{
 | 
			
		||||
  GObject parent_instance;
 | 
			
		||||
  char *filename;
 | 
			
		||||
  GFile *file;
 | 
			
		||||
  MetaBackgroundImageCache *cache;
 | 
			
		||||
  gboolean in_cache;
 | 
			
		||||
  gboolean loaded;
 | 
			
		||||
@@ -70,7 +70,7 @@ G_DEFINE_TYPE (MetaBackgroundImageCache, meta_background_image_cache, G_TYPE_OBJ
 | 
			
		||||
static void
 | 
			
		||||
meta_background_image_cache_init (MetaBackgroundImageCache *cache)
 | 
			
		||||
{
 | 
			
		||||
  cache->images = g_hash_table_new (g_str_hash, g_str_equal);
 | 
			
		||||
  cache->images = g_hash_table_new (g_file_hash, (GEqualFunc) g_file_equal);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -124,9 +124,17 @@ load_file (GTask               *task,
 | 
			
		||||
{
 | 
			
		||||
  GError *error = NULL;
 | 
			
		||||
  GdkPixbuf *pixbuf;
 | 
			
		||||
  GFileInputStream *stream;
 | 
			
		||||
 | 
			
		||||
  pixbuf = gdk_pixbuf_new_from_file (image->filename,
 | 
			
		||||
                                     &error);
 | 
			
		||||
  stream = g_file_read (image->file, NULL, &error);
 | 
			
		||||
  if (stream == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      g_task_return_error (task, error);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  pixbuf = gdk_pixbuf_new_from_stream (G_INPUT_STREAM (stream), NULL, &error);
 | 
			
		||||
  g_object_unref (stream);
 | 
			
		||||
 | 
			
		||||
  if (pixbuf == NULL)
 | 
			
		||||
    {
 | 
			
		||||
@@ -156,9 +164,11 @@ file_loaded (GObject      *source_object,
 | 
			
		||||
 | 
			
		||||
  if (pixbuf == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      char *uri = g_file_get_uri (image->file);
 | 
			
		||||
      g_warning ("Failed to load background '%s': %s",
 | 
			
		||||
                 image->filename, error->message);
 | 
			
		||||
                 uri, error->message);
 | 
			
		||||
      g_clear_error (&error);
 | 
			
		||||
      g_free (uri);
 | 
			
		||||
      goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -185,6 +195,9 @@ file_loaded (GObject      *source_object,
 | 
			
		||||
  image->texture = texture;
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
  if (pixbuf != NULL)
 | 
			
		||||
    g_object_unref (pixbuf);
 | 
			
		||||
 | 
			
		||||
  image->loaded = TRUE;
 | 
			
		||||
  g_signal_emit (image, signals[LOADED], 0);
 | 
			
		||||
}
 | 
			
		||||
@@ -192,7 +205,7 @@ out:
 | 
			
		||||
/**
 | 
			
		||||
 * meta_background_image_cache_load:
 | 
			
		||||
 * @cache: a #MetaBackgroundImageCache
 | 
			
		||||
 * @filename: filename to load
 | 
			
		||||
 * @file: #GFile to load
 | 
			
		||||
 *
 | 
			
		||||
 * Loads an image to use as a background, or returns a reference to an
 | 
			
		||||
 * image that is already in the process of loading or loaded. In either
 | 
			
		||||
@@ -206,23 +219,23 @@ out:
 | 
			
		||||
 */
 | 
			
		||||
MetaBackgroundImage *
 | 
			
		||||
meta_background_image_cache_load (MetaBackgroundImageCache *cache,
 | 
			
		||||
                                  const char               *filename)
 | 
			
		||||
                                  GFile                    *file)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackgroundImage *image;
 | 
			
		||||
  GTask *task;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (META_IS_BACKGROUND_IMAGE_CACHE (cache), NULL);
 | 
			
		||||
  g_return_val_if_fail (filename != NULL, NULL);
 | 
			
		||||
  g_return_val_if_fail (file != NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  image = g_hash_table_lookup (cache->images, filename);
 | 
			
		||||
  image = g_hash_table_lookup (cache->images, file);
 | 
			
		||||
  if (image != NULL)
 | 
			
		||||
    return g_object_ref (image);
 | 
			
		||||
 | 
			
		||||
  image = g_object_new (META_TYPE_BACKGROUND_IMAGE, NULL);
 | 
			
		||||
  image->cache = cache;
 | 
			
		||||
  image->in_cache = TRUE;
 | 
			
		||||
  image->filename = g_strdup (filename);
 | 
			
		||||
  g_hash_table_insert (cache->images, image->filename, image);
 | 
			
		||||
  image->file = g_object_ref (file);
 | 
			
		||||
  g_hash_table_insert (cache->images, image->file, image);
 | 
			
		||||
 | 
			
		||||
  task = g_task_new (image, NULL, file_loaded, NULL);
 | 
			
		||||
 | 
			
		||||
@@ -235,25 +248,25 @@ meta_background_image_cache_load (MetaBackgroundImageCache *cache,
 | 
			
		||||
/**
 | 
			
		||||
 * meta_background_image_cache_purge:
 | 
			
		||||
 * @cache: a #MetaBackgroundImageCache
 | 
			
		||||
 * @filename: filename to remove from the cache
 | 
			
		||||
 * @file: file to remove from the cache
 | 
			
		||||
 *
 | 
			
		||||
 * Remove an entry from the cache; this would be used if monitoring
 | 
			
		||||
 * showed that the file changed.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
meta_background_image_cache_purge (MetaBackgroundImageCache *cache,
 | 
			
		||||
                                   const char               *filename)
 | 
			
		||||
                                   GFile                    *file)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackgroundImage *image;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (META_IS_BACKGROUND_IMAGE_CACHE (cache));
 | 
			
		||||
  g_return_if_fail (filename != NULL);
 | 
			
		||||
  g_return_if_fail (file != NULL);
 | 
			
		||||
 | 
			
		||||
  image = g_hash_table_lookup (cache->images, filename);
 | 
			
		||||
  image = g_hash_table_lookup (cache->images, file);
 | 
			
		||||
  if (image == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  g_hash_table_remove (cache->images, image->filename);
 | 
			
		||||
  g_hash_table_remove (cache->images, image->file);
 | 
			
		||||
  image->in_cache = FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -270,12 +283,12 @@ meta_background_image_finalize (GObject *object)
 | 
			
		||||
  MetaBackgroundImage *image = META_BACKGROUND_IMAGE (object);
 | 
			
		||||
 | 
			
		||||
  if (image->in_cache)
 | 
			
		||||
    g_hash_table_remove (image->cache->images, image->filename);
 | 
			
		||||
    g_hash_table_remove (image->cache->images, image->file);
 | 
			
		||||
 | 
			
		||||
  if (image->texture)
 | 
			
		||||
    cogl_object_unref (image->texture);
 | 
			
		||||
  if (image->filename)
 | 
			
		||||
    g_free (image->filename);
 | 
			
		||||
  if (image->file)
 | 
			
		||||
    g_object_unref (image->file);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_background_image_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -50,9 +50,9 @@ struct _MetaBackgroundPrivate
 | 
			
		||||
  ClutterColor              color;
 | 
			
		||||
  ClutterColor              second_color;
 | 
			
		||||
 | 
			
		||||
  char *filename1;
 | 
			
		||||
  GFile *file1;
 | 
			
		||||
  MetaBackgroundImage *background_image1;
 | 
			
		||||
  char *filename2;
 | 
			
		||||
  GFile *file2;
 | 
			
		||||
  MetaBackgroundImage *background_image2;
 | 
			
		||||
 | 
			
		||||
  CoglTexture *color_texture;
 | 
			
		||||
@@ -241,16 +241,28 @@ on_background_loaded (MetaBackgroundImage *image,
 | 
			
		||||
  mark_changed (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
set_filename (MetaBackground       *self,
 | 
			
		||||
              char                **filenamep,
 | 
			
		||||
              MetaBackgroundImage **imagep,
 | 
			
		||||
              const char           *filename)
 | 
			
		||||
static gboolean
 | 
			
		||||
file_equal0 (GFile *file1,
 | 
			
		||||
             GFile *file2)
 | 
			
		||||
{
 | 
			
		||||
  if (g_strcmp0 (filename, *filenamep) != 0)
 | 
			
		||||
  if (file1 == file2)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  if ((file1 == NULL) || (file2 == NULL))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  return g_file_equal (file1, file2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
set_file (MetaBackground       *self,
 | 
			
		||||
          GFile               **filep,
 | 
			
		||||
          MetaBackgroundImage **imagep,
 | 
			
		||||
          GFile                *file)
 | 
			
		||||
{
 | 
			
		||||
  if (!file_equal0 (*filep, file))
 | 
			
		||||
    {
 | 
			
		||||
      g_free (*filenamep);
 | 
			
		||||
      *filenamep = g_strdup (filename);
 | 
			
		||||
      g_clear_object (filep);
 | 
			
		||||
 | 
			
		||||
      if (*imagep)
 | 
			
		||||
        {
 | 
			
		||||
@@ -261,10 +273,12 @@ set_filename (MetaBackground       *self,
 | 
			
		||||
          *imagep = NULL;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (filename)
 | 
			
		||||
      if (file)
 | 
			
		||||
        {
 | 
			
		||||
          MetaBackgroundImageCache *cache = meta_background_image_cache_get_default ();
 | 
			
		||||
          *imagep = meta_background_image_cache_load (cache, filename);
 | 
			
		||||
 | 
			
		||||
          *filep = g_object_ref (file);
 | 
			
		||||
          *imagep = meta_background_image_cache_load (cache, file);
 | 
			
		||||
          g_signal_connect (*imagep, "loaded",
 | 
			
		||||
                            G_CALLBACK (on_background_loaded), self);
 | 
			
		||||
        }
 | 
			
		||||
@@ -280,8 +294,8 @@ meta_background_dispose (GObject *object)
 | 
			
		||||
  free_color_texture (self);
 | 
			
		||||
  free_wallpaper_texture (self);
 | 
			
		||||
 | 
			
		||||
  set_filename (self, &priv->filename1, &priv->background_image1, NULL);
 | 
			
		||||
  set_filename (self, &priv->filename2, &priv->background_image2, NULL);
 | 
			
		||||
  set_file (self, &priv->file1, &priv->background_image1, NULL);
 | 
			
		||||
  set_file (self, &priv->file2, &priv->background_image2, NULL);
 | 
			
		||||
 | 
			
		||||
  set_screen (self, NULL);
 | 
			
		||||
 | 
			
		||||
@@ -867,19 +881,19 @@ meta_background_set_gradient (MetaBackground            *self,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_background_set_filename (MetaBackground            *self,
 | 
			
		||||
                              const char                *filename,
 | 
			
		||||
                              GDesktopBackgroundStyle    style)
 | 
			
		||||
meta_background_set_file (MetaBackground            *self,
 | 
			
		||||
                          GFile                     *file,
 | 
			
		||||
                          GDesktopBackgroundStyle    style)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (META_IS_BACKGROUND (self));
 | 
			
		||||
 | 
			
		||||
  meta_background_set_blend (self, filename, NULL, 0.0, style);
 | 
			
		||||
  meta_background_set_blend (self, file, NULL, 0.0, style);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_background_set_blend (MetaBackground          *self,
 | 
			
		||||
                           const char              *filename1,
 | 
			
		||||
                           const char              *filename2,
 | 
			
		||||
                           GFile                   *file1,
 | 
			
		||||
                           GFile                   *file2,
 | 
			
		||||
                           double                   blend_factor,
 | 
			
		||||
                           GDesktopBackgroundStyle  style)
 | 
			
		||||
{
 | 
			
		||||
@@ -890,8 +904,8 @@ meta_background_set_blend (MetaBackground          *self,
 | 
			
		||||
 | 
			
		||||
  priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  set_filename (self, &priv->filename1, &priv->background_image1, filename1);
 | 
			
		||||
  set_filename (self, &priv->filename2, &priv->background_image2, filename2);
 | 
			
		||||
  set_file (self, &priv->file1, &priv->background_image1, file1);
 | 
			
		||||
  set_file (self, &priv->file2, &priv->background_image2, file2);
 | 
			
		||||
 | 
			
		||||
  priv->blend_factor = blend_factor;
 | 
			
		||||
  priv->style = style;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										64
									
								
								src/compositor/meta-dnd-actor-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								src/compositor/meta-dnd-actor-private.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * meta-dnd-actor-private.h: Actor for painting the DnD surface
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2014 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 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Carlos Garnacho <carlosg@gnome.org>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef META_DND_ACTOR_PRIVATE_H
 | 
			
		||||
#define META_DND_ACTOR_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include "meta-feedback-actor-private.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MetaDnDActor:
 | 
			
		||||
 *
 | 
			
		||||
 * This class handles the rendering of the DnD surface
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_DND_ACTOR            (meta_dnd_actor_get_type ())
 | 
			
		||||
#define META_DND_ACTOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DND_ACTOR, MetaDnDActor))
 | 
			
		||||
#define META_DND_ACTOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DND_ACTOR, MetaDnDActorClass))
 | 
			
		||||
#define META_IS_DND_ACTOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DND_ACTOR))
 | 
			
		||||
#define META_IS_DND_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DND_ACTOR))
 | 
			
		||||
#define META_DND_ACTOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DND_ACTOR, MetaDnDActorClass))
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaDnDActor        MetaDnDActor;
 | 
			
		||||
typedef struct _MetaDnDActorClass   MetaDnDActorClass;
 | 
			
		||||
 | 
			
		||||
struct _MetaDnDActorClass
 | 
			
		||||
{
 | 
			
		||||
  /*< private >*/
 | 
			
		||||
  MetaFeedbackActorClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaDnDActor
 | 
			
		||||
{
 | 
			
		||||
  MetaFeedbackActor parent;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType         meta_dnd_actor_get_type (void);
 | 
			
		||||
 | 
			
		||||
ClutterActor *meta_dnd_actor_new (ClutterActor *drag_origin,
 | 
			
		||||
                                  int           start_x,
 | 
			
		||||
                                  int           start_y);
 | 
			
		||||
 | 
			
		||||
void          meta_dnd_actor_drag_finish (MetaDnDActor *self,
 | 
			
		||||
                                          gboolean      success);
 | 
			
		||||
 | 
			
		||||
#endif /* META_DND_ACTOR_PRIVATE_H */
 | 
			
		||||
							
								
								
									
										231
									
								
								src/compositor/meta-dnd-actor.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								src/compositor/meta-dnd-actor.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,231 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2014 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 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Carlos Garnacho <carlosg@gnome.org>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SECTION:meta-dnd-actor
 | 
			
		||||
 * @title: MetaDnDActor
 | 
			
		||||
 * @short_description: Actor for painting the drag and drop surface
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <config.h>
 | 
			
		||||
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-dnd-actor-private.h"
 | 
			
		||||
 | 
			
		||||
#define DRAG_FAILED_DURATION 500
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
  PROP_DRAG_ORIGIN = 1,
 | 
			
		||||
  PROP_DRAG_START_X,
 | 
			
		||||
  PROP_DRAG_START_Y
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaDnDActorPrivate MetaDnDActorPrivate;
 | 
			
		||||
 | 
			
		||||
struct _MetaDnDActorPrivate
 | 
			
		||||
{
 | 
			
		||||
  ClutterActor *drag_origin;
 | 
			
		||||
  int drag_start_x;
 | 
			
		||||
  int drag_start_y;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaDnDActor, meta_dnd_actor, META_TYPE_FEEDBACK_ACTOR)
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_dnd_actor_set_property (GObject      *object,
 | 
			
		||||
                             guint         prop_id,
 | 
			
		||||
                             const GValue *value,
 | 
			
		||||
                             GParamSpec   *pspec)
 | 
			
		||||
{
 | 
			
		||||
  MetaDnDActor *self = META_DND_ACTOR (object);
 | 
			
		||||
  MetaDnDActorPrivate *priv = meta_dnd_actor_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
  switch (prop_id)
 | 
			
		||||
    {
 | 
			
		||||
    case PROP_DRAG_ORIGIN:
 | 
			
		||||
      priv->drag_origin = g_value_get_object (value);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_DRAG_START_X:
 | 
			
		||||
      priv->drag_start_x = g_value_get_int (value);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_DRAG_START_Y:
 | 
			
		||||
      priv->drag_start_y = g_value_get_int (value);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_dnd_actor_get_property (GObject      *object,
 | 
			
		||||
                             guint         prop_id,
 | 
			
		||||
                             GValue       *value,
 | 
			
		||||
                             GParamSpec   *pspec)
 | 
			
		||||
{
 | 
			
		||||
  MetaDnDActor *self = META_DND_ACTOR (object);
 | 
			
		||||
  MetaDnDActorPrivate *priv = meta_dnd_actor_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
  switch (prop_id)
 | 
			
		||||
    {
 | 
			
		||||
    case PROP_DRAG_ORIGIN:
 | 
			
		||||
      g_value_set_object (value, priv->drag_origin);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_DRAG_START_X:
 | 
			
		||||
      g_value_set_int (value, priv->drag_start_x);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_DRAG_START_Y:
 | 
			
		||||
      g_value_set_int (value, priv->drag_start_y);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_dnd_actor_class_init (MetaDnDActorClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
  GParamSpec *pspec;
 | 
			
		||||
 | 
			
		||||
  object_class->set_property = meta_dnd_actor_set_property;
 | 
			
		||||
  object_class->get_property = meta_dnd_actor_get_property;
 | 
			
		||||
 | 
			
		||||
  pspec = g_param_spec_object ("drag-origin",
 | 
			
		||||
                               "Drag origin",
 | 
			
		||||
                               "The origin of the DnD operation",
 | 
			
		||||
                               CLUTTER_TYPE_ACTOR,
 | 
			
		||||
                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (object_class,
 | 
			
		||||
                                   PROP_DRAG_ORIGIN,
 | 
			
		||||
                                   pspec);
 | 
			
		||||
 | 
			
		||||
  pspec = g_param_spec_int ("drag-start-x",
 | 
			
		||||
                            "Drag start X",
 | 
			
		||||
                            "The X axis of the drag start point",
 | 
			
		||||
                            0, G_MAXINT, 0,
 | 
			
		||||
                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (object_class,
 | 
			
		||||
                                   PROP_DRAG_START_X,
 | 
			
		||||
                                   pspec);
 | 
			
		||||
 | 
			
		||||
  pspec = g_param_spec_int ("drag-start-y",
 | 
			
		||||
                            "Drag start Y",
 | 
			
		||||
                            "The Y axis of the drag start point",
 | 
			
		||||
                            0, G_MAXINT, 0,
 | 
			
		||||
                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (object_class,
 | 
			
		||||
                                   PROP_DRAG_START_Y,
 | 
			
		||||
                                   pspec);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_dnd_actor_init (MetaDnDActor *self)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_dnd_actor_new:
 | 
			
		||||
 *
 | 
			
		||||
 * Creates a new actor to draw the current drag and drop surface.
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: the newly created background actor
 | 
			
		||||
 */
 | 
			
		||||
ClutterActor *
 | 
			
		||||
meta_dnd_actor_new (ClutterActor *drag_origin,
 | 
			
		||||
                    int           drag_start_x,
 | 
			
		||||
                    int           drag_start_y)
 | 
			
		||||
{
 | 
			
		||||
  MetaDnDActor *self;
 | 
			
		||||
 | 
			
		||||
  self = g_object_new (META_TYPE_DND_ACTOR,
 | 
			
		||||
                       "drag-origin", drag_origin,
 | 
			
		||||
                       "drag-start-x", drag_start_x,
 | 
			
		||||
                       "drag-start-y", drag_start_y,
 | 
			
		||||
                       NULL);
 | 
			
		||||
 | 
			
		||||
  return CLUTTER_ACTOR (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
drag_failed_complete (ClutterTimeline *timeline,
 | 
			
		||||
                      gboolean         is_finished,
 | 
			
		||||
                      gpointer         user_data)
 | 
			
		||||
{
 | 
			
		||||
  ClutterActor *self = user_data;
 | 
			
		||||
 | 
			
		||||
  clutter_actor_remove_all_children (self);
 | 
			
		||||
  clutter_actor_destroy (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_dnd_actor_drag_finish (MetaDnDActor *self,
 | 
			
		||||
                            gboolean      success)
 | 
			
		||||
{
 | 
			
		||||
  MetaDnDActorPrivate *priv;
 | 
			
		||||
  ClutterActor *actor;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (META_IS_DND_ACTOR (self));
 | 
			
		||||
 | 
			
		||||
  actor = CLUTTER_ACTOR (self);
 | 
			
		||||
  priv = meta_dnd_actor_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      clutter_actor_remove_all_children (CLUTTER_ACTOR (self));
 | 
			
		||||
      clutter_actor_destroy (CLUTTER_ACTOR (self));
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      ClutterTransition *transition;
 | 
			
		||||
 | 
			
		||||
      clutter_actor_save_easing_state (actor);
 | 
			
		||||
      clutter_actor_set_easing_mode (actor, CLUTTER_EASE_OUT_CUBIC);
 | 
			
		||||
      clutter_actor_set_easing_duration (actor, DRAG_FAILED_DURATION);
 | 
			
		||||
      clutter_actor_set_opacity (actor, 0);
 | 
			
		||||
 | 
			
		||||
      if (CLUTTER_ACTOR_IS_VISIBLE (priv->drag_origin))
 | 
			
		||||
        {
 | 
			
		||||
          int anchor_x, anchor_y;
 | 
			
		||||
          ClutterPoint dest;
 | 
			
		||||
 | 
			
		||||
          clutter_actor_get_transformed_position (priv->drag_origin,
 | 
			
		||||
                                                  &dest.x, &dest.y);
 | 
			
		||||
          meta_feedback_actor_get_anchor (META_FEEDBACK_ACTOR (self),
 | 
			
		||||
                                          &anchor_x, &anchor_y);
 | 
			
		||||
 | 
			
		||||
          dest.x += priv->drag_start_x - anchor_x;
 | 
			
		||||
          dest.y += priv->drag_start_y - anchor_y;
 | 
			
		||||
          clutter_actor_set_position (actor, dest.x, dest.y);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      transition = clutter_actor_get_transition (actor, "opacity");
 | 
			
		||||
      g_signal_connect (transition, "stopped",
 | 
			
		||||
                        G_CALLBACK (drag_failed_complete), self);
 | 
			
		||||
 | 
			
		||||
      clutter_actor_restore_easing_state (actor);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										74
									
								
								src/compositor/meta-feedback-actor-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/compositor/meta-feedback-actor-private.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * meta-feedback-actor-private.h: Actor for painting user interaction feedback
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2014 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 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Carlos Garnacho <carlosg@gnome.org>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef META_FEEDBACK_ACTOR_PRIVATE_H
 | 
			
		||||
#define META_FEEDBACK_ACTOR_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MetaFeedbackActor:
 | 
			
		||||
 *
 | 
			
		||||
 * This class handles the rendering of user interaction feedback
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_FEEDBACK_ACTOR            (meta_feedback_actor_get_type ())
 | 
			
		||||
#define META_FEEDBACK_ACTOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_FEEDBACK_ACTOR, MetaFeedbackActor))
 | 
			
		||||
#define META_FEEDBACK_ACTOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_FEEDBACK_ACTOR, MetaFeedbackActorClass))
 | 
			
		||||
#define META_IS_FEEDBACK_ACTOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_FEEDBACK_ACTOR))
 | 
			
		||||
#define META_IS_FEEDBACK_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_FEEDBACK_ACTOR))
 | 
			
		||||
#define META_FEEDBACK_ACTOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_FEEDBACK_ACTOR, MetaFeedbackActorClass))
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaFeedbackActor        MetaFeedbackActor;
 | 
			
		||||
typedef struct _MetaFeedbackActorClass   MetaFeedbackActorClass;
 | 
			
		||||
 | 
			
		||||
struct _MetaFeedbackActorClass
 | 
			
		||||
{
 | 
			
		||||
  /*< private >*/
 | 
			
		||||
  ClutterActorClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaFeedbackActor
 | 
			
		||||
{
 | 
			
		||||
  ClutterActor parent;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType meta_feedback_actor_get_type (void);
 | 
			
		||||
 | 
			
		||||
ClutterActor *meta_feedback_actor_new (int anchor_x,
 | 
			
		||||
                                       int anchor_y);
 | 
			
		||||
 | 
			
		||||
void meta_feedback_actor_set_anchor (MetaFeedbackActor *actor,
 | 
			
		||||
                                     int                anchor_x,
 | 
			
		||||
                                     int                anchor_y);
 | 
			
		||||
void meta_feedback_actor_get_anchor (MetaFeedbackActor *actor,
 | 
			
		||||
                                     int               *anchor_x,
 | 
			
		||||
                                     int               *anchor_y);
 | 
			
		||||
 | 
			
		||||
void meta_feedback_actor_set_position (MetaFeedbackActor  *self,
 | 
			
		||||
                                       int                 x,
 | 
			
		||||
                                       int                 y);
 | 
			
		||||
 | 
			
		||||
void meta_feedback_actor_update (MetaFeedbackActor  *self,
 | 
			
		||||
                                 const ClutterEvent *event);
 | 
			
		||||
 | 
			
		||||
#endif /* META_FEEDBACK_ACTOR_PRIVATE_H */
 | 
			
		||||
							
								
								
									
										249
									
								
								src/compositor/meta-feedback-actor.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								src/compositor/meta-feedback-actor.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,249 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2014 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 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Carlos Garnacho <carlosg@gnome.org>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SECTION:meta-feedback-actor
 | 
			
		||||
 * @title: MetaFeedbackActor
 | 
			
		||||
 * @short_description: Actor for painting user interaction feedback
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <config.h>
 | 
			
		||||
 | 
			
		||||
#include "display-private.h"
 | 
			
		||||
#include "compositor-private.h"
 | 
			
		||||
#include "meta-feedback-actor-private.h"
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
  PROP_ANCHOR_X = 1,
 | 
			
		||||
  PROP_ANCHOR_Y
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaFeedbackActorPrivate MetaFeedbackActorPrivate;
 | 
			
		||||
 | 
			
		||||
struct _MetaFeedbackActorPrivate
 | 
			
		||||
{
 | 
			
		||||
  int anchor_x;
 | 
			
		||||
  int anchor_y;
 | 
			
		||||
  int pos_x;
 | 
			
		||||
  int pos_y;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaFeedbackActor, meta_feedback_actor, CLUTTER_TYPE_ACTOR)
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_feedback_actor_constructed (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display;
 | 
			
		||||
 | 
			
		||||
  display = meta_get_display ();
 | 
			
		||||
  clutter_actor_add_child (display->compositor->feedback_group,
 | 
			
		||||
                           CLUTTER_ACTOR (object));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_feedback_actor_update_position (MetaFeedbackActor *self)
 | 
			
		||||
{
 | 
			
		||||
  MetaFeedbackActorPrivate *priv = meta_feedback_actor_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
  clutter_actor_set_position (CLUTTER_ACTOR (self),
 | 
			
		||||
                              priv->pos_x - priv->anchor_x,
 | 
			
		||||
                              priv->pos_y - priv->anchor_y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_feedback_actor_set_property (GObject      *object,
 | 
			
		||||
                                  guint         prop_id,
 | 
			
		||||
                                  const GValue *value,
 | 
			
		||||
                                  GParamSpec   *pspec)
 | 
			
		||||
{
 | 
			
		||||
  MetaFeedbackActor *self = META_FEEDBACK_ACTOR (object);
 | 
			
		||||
  MetaFeedbackActorPrivate *priv = meta_feedback_actor_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
  switch (prop_id)
 | 
			
		||||
    {
 | 
			
		||||
    case PROP_ANCHOR_X:
 | 
			
		||||
      priv->anchor_x = g_value_get_int (value);
 | 
			
		||||
      meta_feedback_actor_update_position (self);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_ANCHOR_Y:
 | 
			
		||||
      priv->anchor_y = g_value_get_int (value);
 | 
			
		||||
      meta_feedback_actor_update_position (self);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_feedback_actor_get_property (GObject      *object,
 | 
			
		||||
                                  guint         prop_id,
 | 
			
		||||
                                  GValue       *value,
 | 
			
		||||
                                  GParamSpec   *pspec)
 | 
			
		||||
{
 | 
			
		||||
  MetaFeedbackActor *self = META_FEEDBACK_ACTOR (object);
 | 
			
		||||
  MetaFeedbackActorPrivate *priv = meta_feedback_actor_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
  switch (prop_id)
 | 
			
		||||
    {
 | 
			
		||||
    case PROP_ANCHOR_X:
 | 
			
		||||
      g_value_set_int (value, priv->anchor_x);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_ANCHOR_Y:
 | 
			
		||||
      g_value_set_int (value, priv->anchor_y);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_feedback_actor_class_init (MetaFeedbackActorClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
  GParamSpec *pspec;
 | 
			
		||||
 | 
			
		||||
  object_class->constructed = meta_feedback_actor_constructed;
 | 
			
		||||
  object_class->set_property = meta_feedback_actor_set_property;
 | 
			
		||||
  object_class->get_property = meta_feedback_actor_get_property;
 | 
			
		||||
 | 
			
		||||
  pspec = g_param_spec_int ("anchor-x",
 | 
			
		||||
                            "Anchor X",
 | 
			
		||||
                            "The X axis of the anchor point",
 | 
			
		||||
                            0, G_MAXINT, 0,
 | 
			
		||||
                            G_PARAM_READWRITE);
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (object_class,
 | 
			
		||||
                                   PROP_ANCHOR_X,
 | 
			
		||||
                                   pspec);
 | 
			
		||||
 | 
			
		||||
  pspec = g_param_spec_int ("anchor-y",
 | 
			
		||||
                            "Anchor Y",
 | 
			
		||||
                            "The Y axis of the anchor point",
 | 
			
		||||
                            0, G_MAXINT, 0,
 | 
			
		||||
                            G_PARAM_READWRITE);
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (object_class,
 | 
			
		||||
                                   PROP_ANCHOR_Y,
 | 
			
		||||
                                   pspec);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_feedback_actor_init (MetaFeedbackActor *self)
 | 
			
		||||
{
 | 
			
		||||
  clutter_actor_set_reactive (CLUTTER_ACTOR (self), FALSE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_feedback_actor_new:
 | 
			
		||||
 *
 | 
			
		||||
 * Creates a new actor to draw the current drag and drop surface.
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: the newly created background actor
 | 
			
		||||
 */
 | 
			
		||||
ClutterActor *
 | 
			
		||||
meta_feedback_actor_new (int anchor_x,
 | 
			
		||||
                         int anchor_y)
 | 
			
		||||
{
 | 
			
		||||
  MetaFeedbackActor *self;
 | 
			
		||||
 | 
			
		||||
  self = g_object_new (META_TYPE_FEEDBACK_ACTOR,
 | 
			
		||||
                       "anchor-x", anchor_x,
 | 
			
		||||
                       "anchor-y", anchor_y,
 | 
			
		||||
                       NULL);
 | 
			
		||||
 | 
			
		||||
  return CLUTTER_ACTOR (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_feedback_actor_set_anchor (MetaFeedbackActor *self,
 | 
			
		||||
                                int                anchor_x,
 | 
			
		||||
                                int                anchor_y)
 | 
			
		||||
{
 | 
			
		||||
  MetaFeedbackActorPrivate *priv;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (META_IS_FEEDBACK_ACTOR (self));
 | 
			
		||||
 | 
			
		||||
  priv = meta_feedback_actor_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
  if (priv->anchor_x == anchor_x && priv->anchor_y == anchor_y)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (priv->anchor_x != anchor_y)
 | 
			
		||||
    {
 | 
			
		||||
      priv->anchor_x = anchor_x;
 | 
			
		||||
      g_object_notify (G_OBJECT (self), "anchor-x");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (priv->anchor_y != anchor_y)
 | 
			
		||||
    {
 | 
			
		||||
      priv->anchor_y = anchor_y;
 | 
			
		||||
      g_object_notify (G_OBJECT (self), "anchor-y");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_feedback_actor_update_position (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_feedback_actor_get_anchor (MetaFeedbackActor *self,
 | 
			
		||||
                                int               *anchor_x,
 | 
			
		||||
                                int               *anchor_y)
 | 
			
		||||
{
 | 
			
		||||
  MetaFeedbackActorPrivate *priv;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (META_IS_FEEDBACK_ACTOR (self));
 | 
			
		||||
 | 
			
		||||
  priv = meta_feedback_actor_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
  if (anchor_x)
 | 
			
		||||
    *anchor_x = priv->anchor_x;
 | 
			
		||||
  if (anchor_y)
 | 
			
		||||
    *anchor_y = priv->anchor_y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_feedback_actor_set_position (MetaFeedbackActor  *self,
 | 
			
		||||
                                  int                 x,
 | 
			
		||||
                                  int                 y)
 | 
			
		||||
{
 | 
			
		||||
  MetaFeedbackActorPrivate *priv;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (META_IS_FEEDBACK_ACTOR (self));
 | 
			
		||||
 | 
			
		||||
  priv = meta_feedback_actor_get_instance_private (self);
 | 
			
		||||
  priv->pos_x = x;
 | 
			
		||||
  priv->pos_y = y;
 | 
			
		||||
 | 
			
		||||
  meta_feedback_actor_update_position (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_feedback_actor_update (MetaFeedbackActor  *self,
 | 
			
		||||
                            const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  ClutterPoint point;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (META_IS_FEEDBACK_ACTOR (self));
 | 
			
		||||
  g_return_if_fail (event != NULL);
 | 
			
		||||
 | 
			
		||||
  clutter_event_get_position (event, &point);
 | 
			
		||||
  meta_feedback_actor_set_position (self, point.x, point.y);
 | 
			
		||||
}
 | 
			
		||||
@@ -40,7 +40,7 @@
 | 
			
		||||
 | 
			
		||||
#include "compositor-private.h"
 | 
			
		||||
#include "meta-window-actor-private.h"
 | 
			
		||||
#include "meta-monitor-manager.h"
 | 
			
		||||
#include "meta-monitor-manager-private.h"
 | 
			
		||||
 | 
			
		||||
G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -193,8 +193,8 @@ meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor,
 | 
			
		||||
      MetaRectangle window_rect;
 | 
			
		||||
      meta_window_get_frame_rect (priv->window, &window_rect);
 | 
			
		||||
 | 
			
		||||
      if (window_rect.x == x &&
 | 
			
		||||
          window_rect.y == y &&
 | 
			
		||||
      if (x == 0 &&
 | 
			
		||||
          y == 0 &&
 | 
			
		||||
          window_rect.width == width &&
 | 
			
		||||
          window_rect.height == height)
 | 
			
		||||
        priv->full_damage_frames_count++;
 | 
			
		||||
@@ -383,6 +383,7 @@ window_decorated_notify (MetaWindow *window,
 | 
			
		||||
{
 | 
			
		||||
  MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (user_data);
 | 
			
		||||
 | 
			
		||||
  detach_pixmap (self);
 | 
			
		||||
  free_damage (self);
 | 
			
		||||
  create_damage (self);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -49,6 +49,8 @@ meta_surface_actor_pick (ClutterActor       *actor,
 | 
			
		||||
{
 | 
			
		||||
  MetaSurfaceActor *self = META_SURFACE_ACTOR (actor);
 | 
			
		||||
  MetaSurfaceActorPrivate *priv = self->priv;
 | 
			
		||||
  ClutterActorIter iter;
 | 
			
		||||
  ClutterActor *child;
 | 
			
		||||
 | 
			
		||||
  if (!clutter_actor_should_pick_paint (actor))
 | 
			
		||||
    return;
 | 
			
		||||
@@ -92,6 +94,11 @@ meta_surface_actor_pick (ClutterActor       *actor,
 | 
			
		||||
      cogl_framebuffer_draw_rectangles (fb, pipeline, rectangles, n_rects);
 | 
			
		||||
      cogl_object_unref (pipeline);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  clutter_actor_iter_init (&iter, actor);
 | 
			
		||||
 | 
			
		||||
  while (clutter_actor_iter_next (&iter, &child))
 | 
			
		||||
    clutter_actor_paint (child);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,7 @@
 | 
			
		||||
#include "meta-window-actor-private.h"
 | 
			
		||||
#include "meta-texture-rectangle.h"
 | 
			
		||||
#include "region-utils.h"
 | 
			
		||||
#include "meta-monitor-manager.h"
 | 
			
		||||
#include "meta-monitor-manager-private.h"
 | 
			
		||||
#include "meta-cullable.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-surface-actor.h"
 | 
			
		||||
@@ -100,7 +100,7 @@ struct _MetaWindowActorPrivate
 | 
			
		||||
  guint		    disposed               : 1;
 | 
			
		||||
 | 
			
		||||
  /* If set, the client needs to be sent a _NET_WM_FRAME_DRAWN
 | 
			
		||||
   * client message using the most recent frame in ->frames */
 | 
			
		||||
   * client message for one or more messages in ->frames */
 | 
			
		||||
  guint             needs_frame_drawn      : 1;
 | 
			
		||||
  guint             repaint_scheduled      : 1;
 | 
			
		||||
 | 
			
		||||
@@ -118,10 +118,21 @@ struct _MetaWindowActorPrivate
 | 
			
		||||
 | 
			
		||||
typedef struct _FrameData FrameData;
 | 
			
		||||
 | 
			
		||||
/* Each time the application updates the sync request counter to a new even value
 | 
			
		||||
 * value, we queue a frame into the windows list of frames. Once we're painting
 | 
			
		||||
 * an update "in response" to the window, we fill in frame_counter with the
 | 
			
		||||
 * Cogl counter for that frame, and send _NET_WM_FRAME_DRAWN at the end of the
 | 
			
		||||
 * frame. _NET_WM_FRAME_TIMINGS is sent when we get a frame_complete callback.
 | 
			
		||||
 *
 | 
			
		||||
 * As an exception, if a window is completely obscured, we try to throttle drawning
 | 
			
		||||
 * to a slower frame rate. In this case, frame_counter stays -1 until
 | 
			
		||||
 * send_frame_message_timeout() runs, at which point we send both the
 | 
			
		||||
 * _NET_WM_FRAME_DRAWN and _NET_WM_FRAME_TIMINGS messages.
 | 
			
		||||
 */
 | 
			
		||||
struct _FrameData
 | 
			
		||||
{
 | 
			
		||||
  int64_t frame_counter;
 | 
			
		||||
  guint64 sync_request_serial;
 | 
			
		||||
  int64_t frame_counter;
 | 
			
		||||
  gint64 frame_drawn_time;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -655,6 +666,30 @@ clip_shadow_under_window (MetaWindowActor *self)
 | 
			
		||||
  return is_non_opaque (self) && priv->window->frame;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
assign_frame_counter_to_frames (MetaWindowActor *self)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
  GList *l;
 | 
			
		||||
 | 
			
		||||
  /* If the window is obscured, then we're expecting to deal with sending
 | 
			
		||||
   * frame messages in a timeout, rather than in this paint cycle.
 | 
			
		||||
   */
 | 
			
		||||
  if (priv->send_frame_messages_timer != 0)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  for (l = priv->frames; l; l = l->next)
 | 
			
		||||
    {
 | 
			
		||||
      FrameData *frame = l->data;
 | 
			
		||||
 | 
			
		||||
      if (frame->frame_counter == -1)
 | 
			
		||||
        {
 | 
			
		||||
          CoglOnscreen *onscreen = COGL_ONSCREEN (cogl_get_draw_framebuffer());
 | 
			
		||||
          frame->frame_counter = cogl_onscreen_get_frame_counter (onscreen);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_window_actor_paint (ClutterActor *actor)
 | 
			
		||||
{
 | 
			
		||||
@@ -671,6 +706,8 @@ meta_window_actor_paint (ClutterActor *actor)
 | 
			
		||||
    {
 | 
			
		||||
      g_source_remove (priv->send_frame_messages_timer);
 | 
			
		||||
      priv->send_frame_messages_timer = 0;
 | 
			
		||||
 | 
			
		||||
      assign_frame_counter_to_frames (self);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (shadow != NULL)
 | 
			
		||||
@@ -873,16 +910,27 @@ send_frame_messages_timeout (gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActor *self = (MetaWindowActor *) data;
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
  FrameData *frame = g_slice_new0 (FrameData);
 | 
			
		||||
  GList *l;
 | 
			
		||||
 | 
			
		||||
  frame->sync_request_serial = priv->window->sync_request_serial;
 | 
			
		||||
  for (l = priv->frames; l;)
 | 
			
		||||
    {
 | 
			
		||||
      GList *l_next = l->next;
 | 
			
		||||
      FrameData *frame = l->data;
 | 
			
		||||
 | 
			
		||||
  do_send_frame_drawn (self, frame);
 | 
			
		||||
  do_send_frame_timings (self, frame, 0, 0);
 | 
			
		||||
      if (frame->frame_counter == -1)
 | 
			
		||||
        {
 | 
			
		||||
          do_send_frame_drawn (self, frame);
 | 
			
		||||
          do_send_frame_timings (self, frame, 0, 0);
 | 
			
		||||
 | 
			
		||||
          priv->frames = g_list_delete_link (priv->frames, l);
 | 
			
		||||
          frame_data_free (frame);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      l = l_next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  priv->needs_frame_drawn = FALSE;
 | 
			
		||||
  priv->send_frame_messages_timer = 0;
 | 
			
		||||
  frame_data_free (frame);
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
@@ -891,6 +939,10 @@ static void
 | 
			
		||||
queue_send_frame_messages_timeout (MetaWindowActor *self)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  if (priv->send_frame_messages_timer != 0)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  MetaDisplay *display = meta_window_get_display (priv->window);
 | 
			
		||||
  gint64 current_time = meta_compositor_monotonic_time_to_server_time (display, g_get_monotonic_time ());
 | 
			
		||||
  MetaMonitorManager *monitor_manager = meta_monitor_manager_get ();
 | 
			
		||||
@@ -933,6 +985,7 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  frame = g_slice_new0 (FrameData);
 | 
			
		||||
  frame->frame_counter = -1;
 | 
			
		||||
 | 
			
		||||
  priv->needs_frame_drawn = TRUE;
 | 
			
		||||
 | 
			
		||||
@@ -1155,7 +1208,7 @@ gboolean
 | 
			
		||||
meta_window_actor_should_unredirect (MetaWindowActor *self)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
  if (priv->surface)
 | 
			
		||||
  if (!meta_window_actor_is_destroyed (self) && priv->surface)
 | 
			
		||||
    return meta_surface_actor_should_unredirect (priv->surface);
 | 
			
		||||
  else
 | 
			
		||||
    return FALSE;
 | 
			
		||||
@@ -1905,24 +1958,12 @@ meta_window_actor_handle_updates (MetaWindowActor *self)
 | 
			
		||||
void
 | 
			
		||||
meta_window_actor_pre_paint (MetaWindowActor *self)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
  GList *l;
 | 
			
		||||
 | 
			
		||||
  if (meta_window_actor_is_destroyed (self))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  meta_window_actor_handle_updates (self);
 | 
			
		||||
 | 
			
		||||
  for (l = priv->frames; l != NULL; l = l->next)
 | 
			
		||||
    {
 | 
			
		||||
      FrameData *frame = l->data;
 | 
			
		||||
 | 
			
		||||
      if (frame->frame_counter == 0)
 | 
			
		||||
        {
 | 
			
		||||
          CoglOnscreen *onscreen = COGL_ONSCREEN (cogl_get_draw_framebuffer());
 | 
			
		||||
          frame->frame_counter = cogl_onscreen_get_frame_counter (onscreen);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  assign_frame_counter_to_frames (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -1963,16 +2004,23 @@ meta_window_actor_post_paint (MetaWindowActor *self)
 | 
			
		||||
  if (meta_window_actor_is_destroyed (self))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
 /* This window had damage, but wasn't actually redrawn because
 | 
			
		||||
  * it is obscured. So we should wait until timer expiration
 | 
			
		||||
  * before sending _NET_WM_FRAME_* messages.
 | 
			
		||||
  */
 | 
			
		||||
  if (priv->send_frame_messages_timer != 0)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (priv->needs_frame_drawn)
 | 
			
		||||
  /* If the window had damage, but wasn't actually redrawn because
 | 
			
		||||
   * it is obscured, we should wait until timer expiration before
 | 
			
		||||
   * sending _NET_WM_FRAME_* messages.
 | 
			
		||||
   */
 | 
			
		||||
  if (priv->send_frame_messages_timer == 0 &&
 | 
			
		||||
      priv->needs_frame_drawn)
 | 
			
		||||
    {
 | 
			
		||||
      do_send_frame_drawn (self, priv->frames->data);
 | 
			
		||||
      GList *l;
 | 
			
		||||
 | 
			
		||||
      for (l = priv->frames; l; l = l->next)
 | 
			
		||||
        {
 | 
			
		||||
          FrameData *frame = l->data;
 | 
			
		||||
 | 
			
		||||
          if (frame->frame_drawn_time == 0)
 | 
			
		||||
            do_send_frame_drawn (self, frame);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      priv->needs_frame_drawn = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -2057,15 +2105,20 @@ meta_window_actor_frame_complete (MetaWindowActor *self,
 | 
			
		||||
    {
 | 
			
		||||
      GList *l_next = l->next;
 | 
			
		||||
      FrameData *frame = l->data;
 | 
			
		||||
      gint64 frame_counter = cogl_frame_info_get_frame_counter (frame_info);
 | 
			
		||||
 | 
			
		||||
      if (frame->frame_counter == cogl_frame_info_get_frame_counter (frame_info))
 | 
			
		||||
      if (frame->frame_counter != -1 && frame->frame_counter <= frame_counter)
 | 
			
		||||
        {
 | 
			
		||||
          if (frame->frame_drawn_time != 0)
 | 
			
		||||
            {
 | 
			
		||||
              priv->frames = g_list_delete_link (priv->frames, l);
 | 
			
		||||
              send_frame_timings (self, frame, frame_info, presentation_time);
 | 
			
		||||
              frame_data_free (frame);
 | 
			
		||||
            }
 | 
			
		||||
          if (G_UNLIKELY (frame->frame_drawn_time == 0))
 | 
			
		||||
            g_warning ("%s: Frame has assigned frame counter but no frame drawn time",
 | 
			
		||||
                       priv->window->desc);
 | 
			
		||||
          if (G_UNLIKELY (frame->frame_counter < frame_counter))
 | 
			
		||||
            g_warning ("%s: frame_complete callback never occurred for frame %" G_GINT64_FORMAT,
 | 
			
		||||
                       priv->window->desc, frame->frame_counter);
 | 
			
		||||
 | 
			
		||||
          priv->frames = g_list_delete_link (priv->frames, l);
 | 
			
		||||
          send_frame_timings (self, frame, frame_info, presentation_time);
 | 
			
		||||
          frame_data_free (frame);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      l = l_next;
 | 
			
		||||
 
 | 
			
		||||
@@ -24,8 +24,8 @@ pkglib_LTLIBRARIES = default.la
 | 
			
		||||
# (There is no way to stop libtool generating static libs locally, and we
 | 
			
		||||
# cannot do this globally because of libmutter-private.so).
 | 
			
		||||
install-exec-hook:
 | 
			
		||||
	-rm $(DESTDIR)$(pkglibdir)/*.a
 | 
			
		||||
	-rm $(DESTDIR)$(pkglibdir)/*.la
 | 
			
		||||
	-rm -f $(DESTDIR)$(pkglibdir)/*.a
 | 
			
		||||
	-rm -f $(DESTDIR)$(pkglibdir)/*.la
 | 
			
		||||
 | 
			
		||||
# Since we removed the .la file, 'make uninstall' doesn't work properly,
 | 
			
		||||
# since it counts on libtool to remove the .la files, so just kill the
 | 
			
		||||
 
 | 
			
		||||
@@ -295,7 +295,7 @@ on_monitors_changed (MetaScreen *screen,
 | 
			
		||||
{
 | 
			
		||||
  MetaDefaultPlugin *self = META_DEFAULT_PLUGIN (plugin);
 | 
			
		||||
  int i, n;
 | 
			
		||||
  GRand *rand = g_rand_new_with_seed (12345);
 | 
			
		||||
  GRand *rand = g_rand_new_with_seed (123456);
 | 
			
		||||
 | 
			
		||||
  clutter_actor_destroy_all_children (self->priv->background_group);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -328,17 +328,17 @@ setup_constraint_info (ConstraintInfo      *info,
 | 
			
		||||
  info->orig    = *orig;
 | 
			
		||||
  info->current = *new;
 | 
			
		||||
 | 
			
		||||
  if (flags & META_IS_MOVE_ACTION && flags & META_IS_RESIZE_ACTION)
 | 
			
		||||
  if (flags & META_MOVE_RESIZE_MOVE_ACTION && flags & META_MOVE_RESIZE_RESIZE_ACTION)
 | 
			
		||||
    info->action_type = ACTION_MOVE_AND_RESIZE;
 | 
			
		||||
  else if (flags & META_IS_RESIZE_ACTION)
 | 
			
		||||
  else if (flags & META_MOVE_RESIZE_RESIZE_ACTION)
 | 
			
		||||
    info->action_type = ACTION_RESIZE;
 | 
			
		||||
  else if (flags & META_IS_MOVE_ACTION)
 | 
			
		||||
  else if (flags & META_MOVE_RESIZE_MOVE_ACTION)
 | 
			
		||||
    info->action_type = ACTION_MOVE;
 | 
			
		||||
  else
 | 
			
		||||
    g_error ("BAD, BAD developer!  No treat for you!  (Fix your calls to "
 | 
			
		||||
             "meta_window_move_resize_internal()).\n");
 | 
			
		||||
 | 
			
		||||
  info->is_user_action = (flags & META_IS_USER_ACTION);
 | 
			
		||||
  info->is_user_action = (flags & META_MOVE_RESIZE_USER_ACTION);
 | 
			
		||||
 | 
			
		||||
  info->resize_gravity = resize_gravity;
 | 
			
		||||
 | 
			
		||||
@@ -612,9 +612,14 @@ update_onscreen_requirements (MetaWindow     *window,
 | 
			
		||||
   */
 | 
			
		||||
  if (window->frame && window->decorated)
 | 
			
		||||
    {
 | 
			
		||||
      MetaRectangle titlebar_rect;
 | 
			
		||||
      MetaRectangle titlebar_rect, frame_rect;
 | 
			
		||||
 | 
			
		||||
      meta_window_get_titlebar_rect (window, &titlebar_rect);
 | 
			
		||||
      meta_window_get_frame_rect (window, &frame_rect);
 | 
			
		||||
 | 
			
		||||
      /* translate into screen coordinates */
 | 
			
		||||
      titlebar_rect.x = frame_rect.x;
 | 
			
		||||
      titlebar_rect.y = frame_rect.y;
 | 
			
		||||
 | 
			
		||||
      old = window->require_titlebar_visible;
 | 
			
		||||
      window->require_titlebar_visible =
 | 
			
		||||
@@ -1012,6 +1017,7 @@ constrain_aspect_ratio (MetaWindow         *window,
 | 
			
		||||
  double best_width, best_height;
 | 
			
		||||
  double alt_width, alt_height;
 | 
			
		||||
  MetaRectangle *start_rect;
 | 
			
		||||
  MetaRectangle client_rect;
 | 
			
		||||
 | 
			
		||||
  if (priority > PRIORITY_ASPECT_RATIO)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
@@ -1063,15 +1069,18 @@ constrain_aspect_ratio (MetaWindow         *window,
 | 
			
		||||
      fudge = 1;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_window_frame_rect_to_client_rect (window, &info->current, &client_rect);
 | 
			
		||||
 | 
			
		||||
  constraint_already_satisfied =
 | 
			
		||||
    info->current.width - (info->current.height * minr ) > -minr*fudge &&
 | 
			
		||||
    info->current.width - (info->current.height * maxr ) <  maxr*fudge;
 | 
			
		||||
    client_rect.width - (client_rect.height * minr ) > -minr*fudge &&
 | 
			
		||||
    client_rect.width - (client_rect.height * maxr ) <  maxr*fudge;
 | 
			
		||||
  if (check_only || constraint_already_satisfied)
 | 
			
		||||
    return constraint_already_satisfied;
 | 
			
		||||
 | 
			
		||||
  /*** Enforce constraint ***/
 | 
			
		||||
  new_width = info->current.width;
 | 
			
		||||
  new_height = info->current.height;
 | 
			
		||||
  new_width = client_rect.width;
 | 
			
		||||
  new_height = client_rect.height;
 | 
			
		||||
 | 
			
		||||
  switch (info->resize_gravity)
 | 
			
		||||
    {
 | 
			
		||||
@@ -1118,6 +1127,14 @@ constrain_aspect_ratio (MetaWindow         *window,
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    client_rect.width = new_width;
 | 
			
		||||
    client_rect.height = new_height;
 | 
			
		||||
    meta_window_client_rect_to_frame_rect (window, &client_rect, &client_rect);
 | 
			
		||||
    new_width = client_rect.width;
 | 
			
		||||
    new_height = client_rect.height;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Figure out what original rect to pass to meta_rectangle_resize_with_gravity
 | 
			
		||||
   * See bug 448183
 | 
			
		||||
   */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										200
									
								
								src/core/core.c
									
									
									
									
									
								
							
							
						
						
									
										200
									
								
								src/core/core.c
									
									
									
									
									
								
							@@ -62,87 +62,6 @@ get_window (Display *xdisplay,
 | 
			
		||||
  return window;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_core_get (Display *xdisplay,
 | 
			
		||||
    Window xwindow,
 | 
			
		||||
    ...)
 | 
			
		||||
{
 | 
			
		||||
  va_list args;
 | 
			
		||||
  MetaCoreGetType request;
 | 
			
		||||
 | 
			
		||||
  MetaDisplay *display = meta_display_for_x_display (xdisplay);
 | 
			
		||||
  MetaWindow *window = meta_display_lookup_x_window (display, xwindow);
 | 
			
		||||
  MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
 | 
			
		||||
  MetaWindowX11Private *priv = window_x11->priv;
 | 
			
		||||
 | 
			
		||||
  va_start (args, xwindow);
 | 
			
		||||
 | 
			
		||||
  request = va_arg (args, MetaCoreGetType);
 | 
			
		||||
 | 
			
		||||
  /* Now, we special-case the first request slightly. Mostly, requests
 | 
			
		||||
   * for information on windows which have no frame are errors.
 | 
			
		||||
   * But sometimes we may want to know *whether* a window has a frame.
 | 
			
		||||
   * In this case, pass the key META_CORE_WINDOW_HAS_FRAME
 | 
			
		||||
   * as the *first* request, with a pointer to a boolean; if the window
 | 
			
		||||
   * has no frame, this will be set to False and meta_core_get will
 | 
			
		||||
   * exit immediately (so the values of any other requests will be
 | 
			
		||||
   * undefined). Otherwise it will be set to True and meta_core_get will
 | 
			
		||||
   * continue happily on its way.
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  if (request != META_CORE_WINDOW_HAS_FRAME &&
 | 
			
		||||
      (window == NULL || window->frame == NULL))
 | 
			
		||||
    {
 | 
			
		||||
      meta_bug ("No such frame window 0x%lx!\n", xwindow);
 | 
			
		||||
      goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  while (request != META_CORE_GET_END)
 | 
			
		||||
    {
 | 
			
		||||
      gpointer answer = va_arg (args, gpointer);
 | 
			
		||||
 | 
			
		||||
      switch (request)
 | 
			
		||||
        {
 | 
			
		||||
        case META_CORE_WINDOW_HAS_FRAME:
 | 
			
		||||
          *((gboolean*)answer) = window != NULL && window->frame != NULL;
 | 
			
		||||
          if (!*((gboolean*)answer)) goto out; /* see above */
 | 
			
		||||
          break;
 | 
			
		||||
        case META_CORE_GET_CLIENT_WIDTH:
 | 
			
		||||
          *((gint*)answer) = priv->client_rect.width;
 | 
			
		||||
          break;
 | 
			
		||||
        case META_CORE_GET_CLIENT_HEIGHT:
 | 
			
		||||
          *((gint*)answer) = priv->client_rect.height;
 | 
			
		||||
          break;
 | 
			
		||||
        case META_CORE_GET_FRAME_FLAGS:
 | 
			
		||||
          *((MetaFrameFlags*)answer) = meta_frame_get_flags (window->frame);
 | 
			
		||||
          break;
 | 
			
		||||
        case META_CORE_GET_FRAME_TYPE:
 | 
			
		||||
          *((MetaFrameType*)answer) = meta_window_get_frame_type (window);
 | 
			
		||||
          break;
 | 
			
		||||
        case META_CORE_GET_MINI_ICON:
 | 
			
		||||
          *((GdkPixbuf**)answer) = window->mini_icon;
 | 
			
		||||
          break;
 | 
			
		||||
        case META_CORE_GET_ICON:
 | 
			
		||||
          *((GdkPixbuf**)answer) = window->icon;
 | 
			
		||||
          break;
 | 
			
		||||
        case META_CORE_GET_FRAME_RECT:
 | 
			
		||||
          meta_window_get_frame_rect (window, ((MetaRectangle*)answer));
 | 
			
		||||
          break;
 | 
			
		||||
        case META_CORE_GET_THEME_VARIANT:
 | 
			
		||||
          *((char**)answer) = window->gtk_theme_variant;
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        default:
 | 
			
		||||
          meta_warning("Unknown window information request: %d\n", request);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      request = va_arg (args, MetaCoreGetType);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  va_end (args);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_core_queue_frame_resize (Display *xdisplay,
 | 
			
		||||
                              Window   frame_xwindow)
 | 
			
		||||
@@ -161,8 +80,7 @@ lower_window_and_transients (MetaWindow *window,
 | 
			
		||||
 | 
			
		||||
  meta_window_foreach_transient (window, lower_window_and_transients, NULL);
 | 
			
		||||
 | 
			
		||||
  if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK &&
 | 
			
		||||
      meta_prefs_get_raise_on_click ())
 | 
			
		||||
  if (meta_prefs_get_raise_on_click ())
 | 
			
		||||
    {
 | 
			
		||||
      /* Move window to the back of the focusing workspace's MRU list.
 | 
			
		||||
       * Do extra sanity checks to avoid possible race conditions.
 | 
			
		||||
@@ -209,37 +127,6 @@ meta_core_user_lower_and_unfocus (Display *xdisplay,
 | 
			
		||||
                                       timestamp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_core_user_focus (Display *xdisplay,
 | 
			
		||||
                      Window   frame_xwindow,
 | 
			
		||||
                      guint32  timestamp)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindow *window = get_window (xdisplay, frame_xwindow);
 | 
			
		||||
 | 
			
		||||
  meta_window_focus (window, timestamp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_core_minimize (Display *xdisplay,
 | 
			
		||||
                    Window   frame_xwindow)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindow *window = get_window (xdisplay, frame_xwindow);
 | 
			
		||||
 | 
			
		||||
  meta_window_minimize (window);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_core_maximize (Display *xdisplay,
 | 
			
		||||
                    Window   frame_xwindow)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindow *window = get_window (xdisplay, frame_xwindow);
 | 
			
		||||
 | 
			
		||||
  if (meta_prefs_get_raise_on_click ())
 | 
			
		||||
    meta_window_raise (window);
 | 
			
		||||
 | 
			
		||||
  meta_window_maximize (window, META_MAXIMIZE_BOTH);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_core_toggle_maximize_vertically (Display *xdisplay,
 | 
			
		||||
				      Window   frame_xwindow)
 | 
			
		||||
@@ -285,84 +172,6 @@ meta_core_toggle_maximize (Display *xdisplay,
 | 
			
		||||
    meta_window_maximize (window, META_MAXIMIZE_BOTH);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_core_unmaximize (Display *xdisplay,
 | 
			
		||||
                      Window   frame_xwindow)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindow *window = get_window (xdisplay, frame_xwindow);
 | 
			
		||||
 | 
			
		||||
  if (meta_prefs_get_raise_on_click ())
 | 
			
		||||
    meta_window_raise (window);
 | 
			
		||||
 | 
			
		||||
  meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_core_delete (Display *xdisplay,
 | 
			
		||||
                  Window   frame_xwindow,
 | 
			
		||||
                  guint32  timestamp)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindow *window = get_window (xdisplay, frame_xwindow);
 | 
			
		||||
 | 
			
		||||
  meta_window_delete (window, timestamp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_core_unshade (Display *xdisplay,
 | 
			
		||||
                   Window   frame_xwindow,
 | 
			
		||||
                   guint32  timestamp)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindow *window = get_window (xdisplay, frame_xwindow);
 | 
			
		||||
 | 
			
		||||
  meta_window_unshade (window, timestamp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_core_shade (Display *xdisplay,
 | 
			
		||||
                 Window   frame_xwindow,
 | 
			
		||||
                 guint32  timestamp)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindow *window = get_window (xdisplay, frame_xwindow);
 | 
			
		||||
 | 
			
		||||
  meta_window_shade (window, timestamp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_core_unstick (Display *xdisplay,
 | 
			
		||||
                   Window   frame_xwindow)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindow *window = get_window (xdisplay, frame_xwindow);
 | 
			
		||||
 | 
			
		||||
  meta_window_unstick (window);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_core_make_above (Display *xdisplay,
 | 
			
		||||
                      Window   frame_xwindow)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindow *window = get_window (xdisplay, frame_xwindow);
 | 
			
		||||
 | 
			
		||||
  meta_window_make_above (window);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_core_unmake_above (Display *xdisplay,
 | 
			
		||||
                        Window   frame_xwindow)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindow *window = get_window (xdisplay, frame_xwindow);
 | 
			
		||||
 | 
			
		||||
  meta_window_unmake_above (window);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_core_stick (Display *xdisplay,
 | 
			
		||||
                 Window   frame_xwindow)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindow *window = get_window (xdisplay, frame_xwindow);
 | 
			
		||||
 | 
			
		||||
  meta_window_stick (window);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_core_change_workspace (Display *xdisplay,
 | 
			
		||||
                            Window   frame_xwindow,
 | 
			
		||||
@@ -497,3 +306,10 @@ meta_invalidate_default_icons (void)
 | 
			
		||||
{
 | 
			
		||||
  /* XXX: Actually invalidate the icons when they're used. */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_retheme_all (void)
 | 
			
		||||
{
 | 
			
		||||
  if (meta_get_display ())
 | 
			
		||||
    meta_display_retheme_all ();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -28,60 +28,6 @@
 | 
			
		||||
#include <meta/common.h>
 | 
			
		||||
#include <meta/boxes.h>
 | 
			
		||||
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
  META_CORE_GET_END = 0,
 | 
			
		||||
  META_CORE_WINDOW_HAS_FRAME,
 | 
			
		||||
  META_CORE_GET_CLIENT_WIDTH,
 | 
			
		||||
  META_CORE_GET_CLIENT_HEIGHT,
 | 
			
		||||
  META_CORE_GET_FRAME_FLAGS,
 | 
			
		||||
  META_CORE_GET_FRAME_TYPE,
 | 
			
		||||
  META_CORE_GET_MINI_ICON,
 | 
			
		||||
  META_CORE_GET_ICON,
 | 
			
		||||
  META_CORE_GET_FRAME_RECT,
 | 
			
		||||
  META_CORE_GET_THEME_VARIANT,
 | 
			
		||||
} MetaCoreGetType;
 | 
			
		||||
 | 
			
		||||
/* General information function about the given window. Pass in a sequence of
 | 
			
		||||
 * pairs of MetaCoreGetTypes and pointers to variables; the variables will be
 | 
			
		||||
 * filled with the requested values. End the list with META_CORE_GET_END.
 | 
			
		||||
 * For example:
 | 
			
		||||
 *
 | 
			
		||||
 *   meta_core_get (my_display, my_window,
 | 
			
		||||
 *                  META_CORE_GET_FRAME_WIDTH, &width,
 | 
			
		||||
 *                  META_CORE_GET_FRAME_HEIGHT, &height,
 | 
			
		||||
 *                  META_CORE_GET_END);
 | 
			
		||||
 *
 | 
			
		||||
 * If the window doesn't have a frame, this will raise a meta_bug. To suppress
 | 
			
		||||
 * this behaviour, ask META_CORE_WINDOW_HAS_FRAME as the *first* question in
 | 
			
		||||
 * the list. If the window has no frame, the answer to this question will be
 | 
			
		||||
 * False, and anything else you asked will be undefined. Otherwise, the answer
 | 
			
		||||
 * will be True. The answer will necessarily be True if you ask the question
 | 
			
		||||
 * in any other position. The positions of all other questions don't matter.
 | 
			
		||||
 *
 | 
			
		||||
 * The reason for this function is that some parts of the program don't know
 | 
			
		||||
 * about MetaWindows. But they *can* see core.h. So we used to have a whole
 | 
			
		||||
 * load of functions which took a display and an X window, looked up the
 | 
			
		||||
 * relevant MetaWindow, and returned information about it. The trouble with
 | 
			
		||||
 * that is that looking up the MetaWindow is a nontrivial operation, and
 | 
			
		||||
 * consolidating the calls in this way makes (for example) frame exposes
 | 
			
		||||
 * 33% faster, according to valgrind.
 | 
			
		||||
 *
 | 
			
		||||
 * This function would perhaps be slightly better if the questions were
 | 
			
		||||
 * represented by pointers, perhaps gchar*s, because then we could take
 | 
			
		||||
 * advantage of gcc's automatic sentinel checking. On the other hand, this
 | 
			
		||||
 * immediately suggests string comparison, and that's slow.
 | 
			
		||||
 *
 | 
			
		||||
 * Another possible improvement is that core.h still has a bunch of
 | 
			
		||||
 * functions which can't be described by the formula "give a display and
 | 
			
		||||
 * an X window, get a single value" (meta_core_user_move, for example), but
 | 
			
		||||
 * which could theoretically be handled by this function if we relaxed the
 | 
			
		||||
 * requirement that all questions should have exactly one argument.
 | 
			
		||||
 */
 | 
			
		||||
void meta_core_get (Display *xdisplay,
 | 
			
		||||
                    Window window,
 | 
			
		||||
                    ...);
 | 
			
		||||
 | 
			
		||||
void meta_core_queue_frame_resize (Display *xdisplay,
 | 
			
		||||
                                   Window frame_xwindow);
 | 
			
		||||
 | 
			
		||||
@@ -89,39 +35,12 @@ void meta_core_user_lower_and_unfocus (Display *xdisplay,
 | 
			
		||||
                                       Window   frame_xwindow,
 | 
			
		||||
                                       guint32  timestamp);
 | 
			
		||||
 | 
			
		||||
void meta_core_user_focus   (Display *xdisplay,
 | 
			
		||||
                             Window   frame_xwindow,
 | 
			
		||||
                             guint32  timestamp);
 | 
			
		||||
 | 
			
		||||
void meta_core_minimize         (Display *xdisplay,
 | 
			
		||||
                                 Window   frame_xwindow);
 | 
			
		||||
void meta_core_toggle_maximize  (Display *xdisplay,
 | 
			
		||||
                                 Window   frame_xwindow);
 | 
			
		||||
void meta_core_toggle_maximize_horizontally  (Display *xdisplay,
 | 
			
		||||
                                              Window   frame_xwindow);
 | 
			
		||||
void meta_core_toggle_maximize_vertically    (Display *xdisplay,
 | 
			
		||||
                                              Window   frame_xwindow);
 | 
			
		||||
void meta_core_unmaximize       (Display *xdisplay,
 | 
			
		||||
                                 Window   frame_xwindow);
 | 
			
		||||
void meta_core_maximize         (Display *xdisplay,
 | 
			
		||||
                                 Window   frame_xwindow);
 | 
			
		||||
void meta_core_delete           (Display *xdisplay,
 | 
			
		||||
                                 Window   frame_xwindow,
 | 
			
		||||
                                 guint32  timestamp);
 | 
			
		||||
void meta_core_unshade          (Display *xdisplay,
 | 
			
		||||
                                 Window   frame_xwindow,
 | 
			
		||||
                                 guint32  timestamp);
 | 
			
		||||
void meta_core_shade            (Display *xdisplay,
 | 
			
		||||
                                 Window   frame_xwindow,
 | 
			
		||||
                                 guint32  timestamp);
 | 
			
		||||
void meta_core_unstick          (Display *xdisplay,
 | 
			
		||||
                                 Window   frame_xwindow);
 | 
			
		||||
void meta_core_stick            (Display *xdisplay,
 | 
			
		||||
                                 Window   frame_xwindow);
 | 
			
		||||
void meta_core_unmake_above     (Display *xdisplay,
 | 
			
		||||
                                 Window   frame_xwindow);
 | 
			
		||||
void meta_core_make_above       (Display *xdisplay,
 | 
			
		||||
                                 Window   frame_xwindow);
 | 
			
		||||
void meta_core_change_workspace (Display *xdisplay,
 | 
			
		||||
                                 Window   frame_xwindow,
 | 
			
		||||
                                 int      new_workspace);
 | 
			
		||||
@@ -168,5 +87,6 @@ void       meta_core_set_screen_cursor (Display *xdisplay,
 | 
			
		||||
                                        MetaCursor cursor);
 | 
			
		||||
 | 
			
		||||
void meta_invalidate_default_icons (void);
 | 
			
		||||
void meta_retheme_all (void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -57,6 +57,7 @@ typedef struct MetaEdgeResistanceData MetaEdgeResistanceData;
 | 
			
		||||
typedef enum {
 | 
			
		||||
  META_LIST_DEFAULT                   = 0,      /* normal windows */
 | 
			
		||||
  META_LIST_INCLUDE_OVERRIDE_REDIRECT = 1 << 0, /* normal and O-R */
 | 
			
		||||
  META_LIST_SORTED                    = 1 << 1, /* sort list by mru */
 | 
			
		||||
} MetaListWindowsFlags;
 | 
			
		||||
 | 
			
		||||
#define _NET_WM_STATE_REMOVE        0    /* remove/unset property */
 | 
			
		||||
@@ -84,6 +85,10 @@ typedef enum {
 | 
			
		||||
   * Events go to windows normally. */
 | 
			
		||||
  META_EVENT_ROUTE_NORMAL,
 | 
			
		||||
 | 
			
		||||
  /* In a window operation like moving or resizing. All events
 | 
			
		||||
   * goes to MetaWindow, but not to the actual client window. */
 | 
			
		||||
  META_EVENT_ROUTE_WINDOW_OP,
 | 
			
		||||
 | 
			
		||||
  /* In a compositor grab operation. All events go to the
 | 
			
		||||
   * compositor plugin. */
 | 
			
		||||
  META_EVENT_ROUTE_COMPOSITOR_GRAB,
 | 
			
		||||
@@ -92,9 +97,8 @@ typedef enum {
 | 
			
		||||
   * the Wayland application. */
 | 
			
		||||
  META_EVENT_ROUTE_WAYLAND_POPUP,
 | 
			
		||||
 | 
			
		||||
  /* In a window operation like moving or resizing. All events
 | 
			
		||||
   * goes to MetaWindow, but not to the actual client window. */
 | 
			
		||||
  META_EVENT_ROUTE_WINDOW_OP,
 | 
			
		||||
  /* The user is clicking on a window button. */
 | 
			
		||||
  META_EVENT_ROUTE_FRAME_BUTTON,
 | 
			
		||||
} MetaEventRoute;
 | 
			
		||||
 | 
			
		||||
typedef gboolean (*MetaAlarmFilter) (MetaDisplay           *display,
 | 
			
		||||
@@ -174,7 +178,6 @@ struct _MetaDisplay
 | 
			
		||||
   * ignore
 | 
			
		||||
   */
 | 
			
		||||
  unsigned long ignored_crossing_serials[N_IGNORED_CROSSING_SERIALS];
 | 
			
		||||
  Window ungrab_should_not_cause_focus_window;
 | 
			
		||||
 | 
			
		||||
  guint32 current_time;
 | 
			
		||||
 | 
			
		||||
@@ -447,8 +450,8 @@ void meta_display_accelerator_activate (MetaDisplay     *display,
 | 
			
		||||
gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_XI23
 | 
			
		||||
gboolean meta_display_process_barrier_event (MetaDisplay *display,
 | 
			
		||||
                                             XIEvent     *event);
 | 
			
		||||
gboolean meta_display_process_barrier_xevent (MetaDisplay *display,
 | 
			
		||||
                                              XIEvent     *event);
 | 
			
		||||
#endif /* HAVE_XI23 */
 | 
			
		||||
 | 
			
		||||
void meta_display_set_input_focus_xwindow (MetaDisplay *display,
 | 
			
		||||
@@ -477,6 +480,12 @@ gboolean meta_display_show_restart_message (MetaDisplay *display,
 | 
			
		||||
                                            const char  *message);
 | 
			
		||||
gboolean meta_display_request_restart      (MetaDisplay *display);
 | 
			
		||||
 | 
			
		||||
gboolean meta_display_show_resize_popup (MetaDisplay *display,
 | 
			
		||||
                                         gboolean show,
 | 
			
		||||
                                         MetaRectangle *rect,
 | 
			
		||||
                                         int display_w,
 | 
			
		||||
                                         int display_h);
 | 
			
		||||
 | 
			
		||||
void meta_restart_init (void);
 | 
			
		||||
void meta_restart_finish (void);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -50,6 +50,7 @@
 | 
			
		||||
#include "meta-idle-monitor-dbus.h"
 | 
			
		||||
#include "meta-cursor-tracker-private.h"
 | 
			
		||||
#include <meta/meta-backend.h>
 | 
			
		||||
#include "backends/native/meta-backend-native.h"
 | 
			
		||||
#include "backends/x11/meta-backend-x11.h"
 | 
			
		||||
#include <clutter/x11/clutter-x11.h>
 | 
			
		||||
 | 
			
		||||
@@ -122,6 +123,7 @@ enum
 | 
			
		||||
  GRAB_OP_END,
 | 
			
		||||
  SHOW_RESTART_MESSAGE,
 | 
			
		||||
  RESTART,
 | 
			
		||||
  SHOW_RESIZE_POPUP,
 | 
			
		||||
  LAST_SIGNAL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -150,6 +152,9 @@ static void update_cursor_theme (void);
 | 
			
		||||
static void    prefs_changed_callback    (MetaPreference pref,
 | 
			
		||||
                                          void          *data);
 | 
			
		||||
 | 
			
		||||
static int mru_cmp (gconstpointer a,
 | 
			
		||||
                    gconstpointer b);
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_display_get_property(GObject         *object,
 | 
			
		||||
                          guint            prop_id,
 | 
			
		||||
@@ -326,6 +331,16 @@ meta_display_class_init (MetaDisplayClass *klass)
 | 
			
		||||
                  NULL, NULL,
 | 
			
		||||
                  G_TYPE_BOOLEAN, 0);
 | 
			
		||||
 | 
			
		||||
  display_signals[SHOW_RESIZE_POPUP] =
 | 
			
		||||
    g_signal_new ("show-resize-popup",
 | 
			
		||||
                  G_TYPE_FROM_CLASS (klass),
 | 
			
		||||
                  G_SIGNAL_RUN_LAST,
 | 
			
		||||
                  0,
 | 
			
		||||
                  g_signal_accumulator_true_handled,
 | 
			
		||||
                  NULL, NULL,
 | 
			
		||||
                  G_TYPE_BOOLEAN, 4,
 | 
			
		||||
                  G_TYPE_BOOLEAN, META_TYPE_RECTANGLE, G_TYPE_INT, G_TYPE_INT);
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (object_class,
 | 
			
		||||
                                   PROP_FOCUS_WINDOW,
 | 
			
		||||
                                   g_param_spec_object ("focus-window",
 | 
			
		||||
@@ -637,7 +652,6 @@ meta_display_open (void)
 | 
			
		||||
      display->ignored_crossing_serials[i] = 0;
 | 
			
		||||
      ++i;
 | 
			
		||||
    }
 | 
			
		||||
  display->ungrab_should_not_cause_focus_window = None;
 | 
			
		||||
 | 
			
		||||
  display->current_time = CurrentTime;
 | 
			
		||||
  display->sentinel_counter = 0;
 | 
			
		||||
@@ -1004,7 +1018,7 @@ meta_display_list_windows (MetaDisplay          *display,
 | 
			
		||||
    {
 | 
			
		||||
      MetaWindow *window = value;
 | 
			
		||||
 | 
			
		||||
      if (!META_IS_WINDOW (window))
 | 
			
		||||
      if (!META_IS_WINDOW (window) || window->unmanaging)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (!window->override_redirect ||
 | 
			
		||||
@@ -1017,7 +1031,7 @@ meta_display_list_windows (MetaDisplay          *display,
 | 
			
		||||
    {
 | 
			
		||||
      MetaWindow *window = value;
 | 
			
		||||
 | 
			
		||||
      if (!META_IS_WINDOW (window))
 | 
			
		||||
      if (!META_IS_WINDOW (window) || window->unmanaging)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (!window->override_redirect ||
 | 
			
		||||
@@ -1061,6 +1075,9 @@ meta_display_list_windows (MetaDisplay          *display,
 | 
			
		||||
      tmp = next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (flags & META_LIST_SORTED)
 | 
			
		||||
    winlist = g_slist_sort (winlist, mru_cmp);
 | 
			
		||||
 | 
			
		||||
  return winlist;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1199,7 +1216,7 @@ meta_grab_op_is_resizing (MetaGrabOp op)
 | 
			
		||||
  if (!grab_op_is_window (op))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  return (op & META_GRAB_OP_WINDOW_DIR_MASK) != 0;
 | 
			
		||||
  return (op & META_GRAB_OP_WINDOW_DIR_MASK) != 0 || op == META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
@@ -1208,7 +1225,7 @@ meta_grab_op_is_moving (MetaGrabOp op)
 | 
			
		||||
  if (!grab_op_is_window (op))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  return (op & META_GRAB_OP_WINDOW_DIR_MASK) == 0;
 | 
			
		||||
  return !meta_grab_op_is_resizing (op);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -1785,6 +1802,9 @@ get_event_route_from_grab_op (MetaGrabOp op)
 | 
			
		||||
    case META_GRAB_OP_WAYLAND_POPUP:
 | 
			
		||||
      return META_EVENT_ROUTE_WAYLAND_POPUP;
 | 
			
		||||
 | 
			
		||||
    case META_GRAB_OP_FRAME_BUTTON:
 | 
			
		||||
      return META_EVENT_ROUTE_FRAME_BUTTON;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
    }
 | 
			
		||||
@@ -1947,6 +1967,11 @@ meta_display_end_grab_op (MetaDisplay *display,
 | 
			
		||||
  g_signal_emit (display, display_signals[GRAB_OP_END], 0,
 | 
			
		||||
                 display->screen, grab_window, grab_op);
 | 
			
		||||
 | 
			
		||||
  /* We need to reset this early, since the
 | 
			
		||||
   * meta_window_grab_op_ended callback relies on this being
 | 
			
		||||
   * up to date. */
 | 
			
		||||
  display->grab_op = META_GRAB_OP_NONE;
 | 
			
		||||
 | 
			
		||||
  if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
 | 
			
		||||
    {
 | 
			
		||||
      /* Clear out the edge cache */
 | 
			
		||||
@@ -1959,7 +1984,7 @@ meta_display_end_grab_op (MetaDisplay *display,
 | 
			
		||||
       * beginning of the grab_op.
 | 
			
		||||
       */
 | 
			
		||||
      if (!meta_prefs_get_raise_on_click () &&
 | 
			
		||||
          display->grab_threshold_movement_reached)
 | 
			
		||||
          !display->grab_threshold_movement_reached)
 | 
			
		||||
        meta_window_raise (display->grab_window);
 | 
			
		||||
 | 
			
		||||
      meta_window_grab_op_ended (grab_window, grab_op);
 | 
			
		||||
@@ -1979,7 +2004,6 @@ meta_display_end_grab_op (MetaDisplay *display,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  display->event_route = META_EVENT_ROUTE_NORMAL;
 | 
			
		||||
  display->grab_op = META_GRAB_OP_NONE;
 | 
			
		||||
  display->grab_window = NULL;
 | 
			
		||||
  display->grab_tile_mode = META_TILE_NONE;
 | 
			
		||||
  display->grab_tile_monitor_number = -1;
 | 
			
		||||
@@ -2434,13 +2458,22 @@ meta_display_get_tab_list (MetaDisplay   *display,
 | 
			
		||||
 | 
			
		||||
  mru_list = workspace ? workspace->mru_list : global_mru_list;
 | 
			
		||||
 | 
			
		||||
  /* Windows sellout mode - MRU order.
 | 
			
		||||
  /* Windows sellout mode - MRU order. Collect unminimized windows
 | 
			
		||||
   * then minimized so minimized windows aren't in the way so much.
 | 
			
		||||
   */
 | 
			
		||||
  for (tmp = mru_list; tmp; tmp = tmp->next)
 | 
			
		||||
    {
 | 
			
		||||
      MetaWindow *window = tmp->data;
 | 
			
		||||
 | 
			
		||||
      if (IN_TAB_CHAIN (window, type))
 | 
			
		||||
      if (!window->minimized && IN_TAB_CHAIN (window, type))
 | 
			
		||||
        tab_list = g_list_prepend (tab_list, window);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  for (tmp = mru_list; tmp; tmp = tmp->next)
 | 
			
		||||
    {
 | 
			
		||||
      MetaWindow *window = tmp->data;
 | 
			
		||||
 | 
			
		||||
      if (window->minimized && IN_TAB_CHAIN (window, type))
 | 
			
		||||
        tab_list = g_list_prepend (tab_list, window);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -2877,9 +2910,11 @@ meta_display_get_xinput_opcode (MetaDisplay *display)
 | 
			
		||||
 * meta_display_supports_extended_barriers:
 | 
			
		||||
 * @display: a #MetaDisplay
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: whether the X server supports extended barrier
 | 
			
		||||
 * features as defined in version 2.3 of the XInput 2
 | 
			
		||||
 * specification.
 | 
			
		||||
 * Returns: whether pointer barriers can be supported.
 | 
			
		||||
 *
 | 
			
		||||
 * When running as an X compositor the X server needs XInput 2
 | 
			
		||||
 * version 2.3. When running as a display server it is supported
 | 
			
		||||
 * when running on the native backend.
 | 
			
		||||
 *
 | 
			
		||||
 * Clients should use this method to determine whether their
 | 
			
		||||
 * interfaces should depend on new barrier features.
 | 
			
		||||
@@ -2887,7 +2922,18 @@ meta_display_get_xinput_opcode (MetaDisplay *display)
 | 
			
		||||
gboolean
 | 
			
		||||
meta_display_supports_extended_barriers (MetaDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
  return META_DISPLAY_HAS_XINPUT_23 (display) && !meta_is_wayland_compositor ();
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
  if (META_IS_BACKEND_NATIVE (meta_get_backend ()))
 | 
			
		||||
    return TRUE;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  if (META_IS_BACKEND_X11 (meta_get_backend ()))
 | 
			
		||||
    {
 | 
			
		||||
      return (META_DISPLAY_HAS_XINPUT_23 (display) &&
 | 
			
		||||
              !meta_is_wayland_compositor());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_assert_not_reached ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -2999,6 +3045,22 @@ meta_display_request_restart (MetaDisplay *display)
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_display_show_resize_popup (MetaDisplay *display,
 | 
			
		||||
                                gboolean show,
 | 
			
		||||
                                MetaRectangle *rect,
 | 
			
		||||
                                int display_w,
 | 
			
		||||
                                int display_h)
 | 
			
		||||
{
 | 
			
		||||
  gboolean result = FALSE;
 | 
			
		||||
 | 
			
		||||
  g_signal_emit (display,
 | 
			
		||||
                 display_signals[SHOW_RESIZE_POPUP], 0,
 | 
			
		||||
                 show, rect, display_w, display_h, &result);
 | 
			
		||||
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_display_is_pointer_emulating_sequence:
 | 
			
		||||
 * @display: the display
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,7 @@
 | 
			
		||||
#include "display-private.h"
 | 
			
		||||
#include "window-private.h"
 | 
			
		||||
#include "backends/x11/meta-backend-x11.h"
 | 
			
		||||
#include "backends/meta-cursor-tracker-private.h"
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
#include "backends/native/meta-backend-native.h"
 | 
			
		||||
@@ -35,7 +36,6 @@
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_WAYLAND
 | 
			
		||||
#include "backends/meta-cursor-tracker-private.h"
 | 
			
		||||
#include "wayland/meta-wayland-private.h"
 | 
			
		||||
#endif
 | 
			
		||||
#include "meta-surface-actor.h"
 | 
			
		||||
@@ -66,9 +66,10 @@ get_window_for_event (MetaDisplay        *display,
 | 
			
		||||
        else
 | 
			
		||||
          return NULL;
 | 
			
		||||
      }
 | 
			
		||||
    case META_EVENT_ROUTE_WAYLAND_POPUP:
 | 
			
		||||
    case META_EVENT_ROUTE_WINDOW_OP:
 | 
			
		||||
    case META_EVENT_ROUTE_COMPOSITOR_GRAB:
 | 
			
		||||
    case META_EVENT_ROUTE_WAYLAND_POPUP:
 | 
			
		||||
    case META_EVENT_ROUTE_FRAME_BUTTON:
 | 
			
		||||
      return display->grab_window;
 | 
			
		||||
    default:
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
@@ -151,23 +152,6 @@ sequence_is_pointer_emulated (MetaDisplay        *display,
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_display_update_pointer_emulating_sequence (MetaDisplay        *display,
 | 
			
		||||
                                                const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  ClutterEventSequence *sequence;
 | 
			
		||||
 | 
			
		||||
  sequence = clutter_event_get_event_sequence (event);
 | 
			
		||||
 | 
			
		||||
  if (event->type == CLUTTER_TOUCH_BEGIN &&
 | 
			
		||||
      !display->pointer_emulating_sequence &&
 | 
			
		||||
      sequence_is_pointer_emulated (display, event))
 | 
			
		||||
    display->pointer_emulating_sequence = sequence;
 | 
			
		||||
  else if (event->type == CLUTTER_TOUCH_END &&
 | 
			
		||||
           display->pointer_emulating_sequence == sequence)
 | 
			
		||||
    display->pointer_emulating_sequence = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_display_handle_event (MetaDisplay        *display,
 | 
			
		||||
                           const ClutterEvent *event)
 | 
			
		||||
@@ -176,8 +160,15 @@ meta_display_handle_event (MetaDisplay        *display,
 | 
			
		||||
  gboolean bypass_clutter = FALSE;
 | 
			
		||||
  G_GNUC_UNUSED gboolean bypass_wayland = FALSE;
 | 
			
		||||
  MetaGestureTracker *tracker;
 | 
			
		||||
  ClutterEventSequence *sequence;
 | 
			
		||||
 | 
			
		||||
  meta_display_update_pointer_emulating_sequence (display, event);
 | 
			
		||||
  sequence = clutter_event_get_event_sequence (event);
 | 
			
		||||
 | 
			
		||||
  /* Set the pointer emulating sequence on touch begin, if eligible */
 | 
			
		||||
  if (event->type == CLUTTER_TOUCH_BEGIN &&
 | 
			
		||||
      !display->pointer_emulating_sequence &&
 | 
			
		||||
      sequence_is_pointer_emulated (display, event))
 | 
			
		||||
    display->pointer_emulating_sequence = sequence;
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_WAYLAND
 | 
			
		||||
  MetaWaylandCompositor *compositor = NULL;
 | 
			
		||||
@@ -271,7 +262,8 @@ meta_display_handle_event (MetaDisplay        *display,
 | 
			
		||||
       * event, and if it doesn't, replay the event to release our
 | 
			
		||||
       * own sync grab. */
 | 
			
		||||
 | 
			
		||||
      if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
 | 
			
		||||
      if (display->event_route == META_EVENT_ROUTE_WINDOW_OP ||
 | 
			
		||||
          display->event_route == META_EVENT_ROUTE_FRAME_BUTTON)
 | 
			
		||||
        {
 | 
			
		||||
          bypass_clutter = TRUE;
 | 
			
		||||
          bypass_wayland = TRUE;
 | 
			
		||||
@@ -314,6 +306,11 @@ meta_display_handle_event (MetaDisplay        *display,
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  /* Unset the pointer emulating sequence after its end event is processed */
 | 
			
		||||
  if (event->type == CLUTTER_TOUCH_END &&
 | 
			
		||||
      display->pointer_emulating_sequence == sequence)
 | 
			
		||||
    display->pointer_emulating_sequence = NULL;
 | 
			
		||||
 | 
			
		||||
  display->current_time = CurrentTime;
 | 
			
		||||
  return bypass_clutter;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										107
									
								
								src/core/frame.c
									
									
									
									
									
								
							
							
						
						
									
										107
									
								
								src/core/frame.c
									
									
									
									
									
								
							@@ -85,15 +85,18 @@ meta_window_ensure_frame (MetaWindow *window)
 | 
			
		||||
  else
 | 
			
		||||
    visual = NULL;
 | 
			
		||||
 | 
			
		||||
  frame->xwindow = meta_ui_create_frame_window (window->screen->ui,
 | 
			
		||||
                                                window->display->xdisplay,
 | 
			
		||||
                                                visual,
 | 
			
		||||
                                                frame->rect.x,
 | 
			
		||||
                                                frame->rect.y,
 | 
			
		||||
						frame->rect.width,
 | 
			
		||||
						frame->rect.height,
 | 
			
		||||
						frame->window->screen->number,
 | 
			
		||||
                                                &create_serial);
 | 
			
		||||
  frame->ui_frame = meta_ui_create_frame (window->screen->ui,
 | 
			
		||||
                                          window->display->xdisplay,
 | 
			
		||||
                                          frame->window,
 | 
			
		||||
                                          visual,
 | 
			
		||||
                                          frame->rect.x,
 | 
			
		||||
                                          frame->rect.y,
 | 
			
		||||
                                          frame->rect.width,
 | 
			
		||||
                                          frame->rect.height,
 | 
			
		||||
                                          frame->window->screen->number,
 | 
			
		||||
                                          &create_serial);
 | 
			
		||||
  frame->xwindow = frame->ui_frame->xwindow;
 | 
			
		||||
 | 
			
		||||
  meta_stack_tracker_record_add (window->screen->stack_tracker,
 | 
			
		||||
                                 frame->xwindow,
 | 
			
		||||
                                 create_serial);
 | 
			
		||||
@@ -103,19 +106,6 @@ meta_window_ensure_frame (MetaWindow *window)
 | 
			
		||||
  XChangeWindowAttributes (window->display->xdisplay,
 | 
			
		||||
			   frame->xwindow, CWEventMask, &attrs);
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
 | 
			
		||||
    XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
 | 
			
		||||
 | 
			
		||||
    XISetMask (mask.mask, XI_ButtonPress);
 | 
			
		||||
    XISetMask (mask.mask, XI_ButtonRelease);
 | 
			
		||||
    XISetMask (mask.mask, XI_Motion);
 | 
			
		||||
    XISetMask (mask.mask, XI_Enter);
 | 
			
		||||
    XISetMask (mask.mask, XI_Leave);
 | 
			
		||||
 | 
			
		||||
    XISelectEvents (window->display->xdisplay, frame->xwindow, &mask, 1);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  meta_display_register_x_window (window->display, &frame->xwindow, window);
 | 
			
		||||
 | 
			
		||||
  meta_error_trap_push (window->display);
 | 
			
		||||
@@ -146,12 +136,8 @@ meta_window_ensure_frame (MetaWindow *window)
 | 
			
		||||
  /* Now that frame->xwindow is registered with window, we can set its
 | 
			
		||||
   * style and background.
 | 
			
		||||
   */
 | 
			
		||||
  meta_ui_update_frame_style (window->screen->ui, frame->xwindow);
 | 
			
		||||
 | 
			
		||||
  if (window->title)
 | 
			
		||||
    meta_ui_set_frame_title (window->screen->ui,
 | 
			
		||||
                             window->frame->xwindow,
 | 
			
		||||
                             window->title);
 | 
			
		||||
  meta_frame_update_style (frame);
 | 
			
		||||
  meta_frame_update_title (frame);
 | 
			
		||||
 | 
			
		||||
  meta_ui_map_frame (frame->window->screen->ui, frame->xwindow);
 | 
			
		||||
 | 
			
		||||
@@ -159,10 +145,23 @@ meta_window_ensure_frame (MetaWindow *window)
 | 
			
		||||
    MetaBackend *backend = meta_get_backend ();
 | 
			
		||||
    if (META_IS_BACKEND_X11 (backend))
 | 
			
		||||
      {
 | 
			
		||||
        /* Since the backend takes keygrabs on another connection, make sure
 | 
			
		||||
         * to sync the GTK+ connection to ensure that the frame window has
 | 
			
		||||
         * been created on the server at this point. */
 | 
			
		||||
        Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
 | 
			
		||||
 | 
			
		||||
        /* Since the backend selects for events on another connection,
 | 
			
		||||
         * make sure to sync the GTK+ connection to ensure that the
 | 
			
		||||
         * frame window has been created on the server at this point. */
 | 
			
		||||
        XSync (window->display->xdisplay, False);
 | 
			
		||||
 | 
			
		||||
        unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
 | 
			
		||||
        XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
 | 
			
		||||
 | 
			
		||||
        XISetMask (mask.mask, XI_ButtonPress);
 | 
			
		||||
        XISetMask (mask.mask, XI_ButtonRelease);
 | 
			
		||||
        XISetMask (mask.mask, XI_Motion);
 | 
			
		||||
        XISetMask (mask.mask, XI_Enter);
 | 
			
		||||
        XISetMask (mask.mask, XI_Leave);
 | 
			
		||||
 | 
			
		||||
        XISelectEvents (xdisplay, frame->xwindow, &mask, 1);
 | 
			
		||||
      }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -215,7 +214,7 @@ meta_window_destroy_frame (MetaWindow *window)
 | 
			
		||||
                   window->frame->rect.y + borders.invisible.top);
 | 
			
		||||
  meta_error_trap_pop (window->display);
 | 
			
		||||
 | 
			
		||||
  meta_ui_destroy_frame_window (window->screen->ui, frame->xwindow);
 | 
			
		||||
  meta_ui_frame_unmanage (frame->ui_frame);
 | 
			
		||||
 | 
			
		||||
  meta_display_unregister_x_window (window->display,
 | 
			
		||||
                                    frame->xwindow);
 | 
			
		||||
@@ -335,9 +334,7 @@ meta_frame_calc_borders (MetaFrame        *frame,
 | 
			
		||||
    {
 | 
			
		||||
      if (!frame->borders_cached)
 | 
			
		||||
        {
 | 
			
		||||
          meta_ui_get_frame_borders (frame->window->screen->ui,
 | 
			
		||||
                                     frame->xwindow,
 | 
			
		||||
                                     &frame->cached_borders);
 | 
			
		||||
          meta_ui_frame_get_borders (frame->ui_frame, &frame->cached_borders);
 | 
			
		||||
          frame->borders_cached = TRUE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -353,8 +350,6 @@ meta_frame_clear_cached_borders (MetaFrame *frame)
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_frame_sync_to_window (MetaFrame *frame,
 | 
			
		||||
                           int        resize_gravity,
 | 
			
		||||
                           gboolean   need_move,
 | 
			
		||||
                           gboolean   need_resize)
 | 
			
		||||
{
 | 
			
		||||
  meta_topic (META_DEBUG_GEOMETRY,
 | 
			
		||||
@@ -364,49 +359,32 @@ meta_frame_sync_to_window (MetaFrame *frame,
 | 
			
		||||
              frame->rect.x + frame->rect.width,
 | 
			
		||||
              frame->rect.y + frame->rect.height);
 | 
			
		||||
 | 
			
		||||
  meta_ui_move_resize_frame (frame->window->screen->ui,
 | 
			
		||||
			     frame->xwindow,
 | 
			
		||||
  meta_ui_frame_move_resize (frame->ui_frame,
 | 
			
		||||
			     frame->rect.x,
 | 
			
		||||
			     frame->rect.y,
 | 
			
		||||
			     frame->rect.width,
 | 
			
		||||
			     frame->rect.height);
 | 
			
		||||
 | 
			
		||||
  if (need_resize)
 | 
			
		||||
    {
 | 
			
		||||
      /* If we're interactively resizing the frame, repaint
 | 
			
		||||
       * it immediately so we don't start to lag.
 | 
			
		||||
       */
 | 
			
		||||
      if (frame->window->display->grab_window ==
 | 
			
		||||
          frame->window)
 | 
			
		||||
        meta_ui_repaint_frame (frame->window->screen->ui,
 | 
			
		||||
                               frame->xwindow);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return need_resize;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cairo_region_t *
 | 
			
		||||
meta_frame_get_frame_bounds (MetaFrame *frame)
 | 
			
		||||
{
 | 
			
		||||
  return meta_ui_get_frame_bounds (frame->window->screen->ui,
 | 
			
		||||
                                   frame->xwindow,
 | 
			
		||||
                                   frame->rect.width,
 | 
			
		||||
                                   frame->rect.height);
 | 
			
		||||
  return meta_ui_frame_get_bounds (frame->ui_frame);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_frame_get_mask (MetaFrame                    *frame,
 | 
			
		||||
                     cairo_t                      *cr)
 | 
			
		||||
{
 | 
			
		||||
  meta_ui_get_frame_mask (frame->window->screen->ui, frame->xwindow,
 | 
			
		||||
                          frame->rect.width, frame->rect.height, cr);
 | 
			
		||||
  meta_ui_frame_get_mask (frame->ui_frame, cr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_frame_queue_draw (MetaFrame *frame)
 | 
			
		||||
{
 | 
			
		||||
  meta_ui_queue_frame_draw (frame->window->screen->ui,
 | 
			
		||||
                            frame->xwindow);
 | 
			
		||||
  meta_ui_frame_queue_draw (frame->ui_frame);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -433,3 +411,16 @@ meta_frame_get_xwindow (MetaFrame *frame)
 | 
			
		||||
{
 | 
			
		||||
  return frame->xwindow;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_frame_update_style (MetaFrame *frame)
 | 
			
		||||
{
 | 
			
		||||
  meta_ui_frame_update_style (frame->ui_frame);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_frame_update_title (MetaFrame *frame)
 | 
			
		||||
{
 | 
			
		||||
  if (frame->window->title)
 | 
			
		||||
    meta_ui_frame_set_title (frame->ui_frame, frame->window->title);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,8 @@
 | 
			
		||||
 | 
			
		||||
#include "window-private.h"
 | 
			
		||||
 | 
			
		||||
#include "ui/frames.h"
 | 
			
		||||
 | 
			
		||||
struct _MetaFrame
 | 
			
		||||
{
 | 
			
		||||
  /* window we frame */
 | 
			
		||||
@@ -50,6 +52,8 @@ struct _MetaFrame
 | 
			
		||||
  guint need_reapply_frame_shape : 1;
 | 
			
		||||
  guint is_flashing : 1; /* used by the visual bell flash */
 | 
			
		||||
  guint borders_cached : 1;
 | 
			
		||||
 | 
			
		||||
  MetaUIFrame *ui_frame;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void     meta_window_ensure_frame           (MetaWindow *window);
 | 
			
		||||
@@ -64,8 +68,6 @@ void meta_frame_calc_borders      (MetaFrame        *frame,
 | 
			
		||||
                                   MetaFrameBorders *borders);
 | 
			
		||||
 | 
			
		||||
gboolean meta_frame_sync_to_window (MetaFrame         *frame,
 | 
			
		||||
                                    int                gravity,
 | 
			
		||||
                                    gboolean           need_move,
 | 
			
		||||
                                    gboolean           need_resize);
 | 
			
		||||
 | 
			
		||||
void meta_frame_clear_cached_borders (MetaFrame *frame);
 | 
			
		||||
@@ -78,8 +80,7 @@ void meta_frame_get_mask (MetaFrame *frame,
 | 
			
		||||
void meta_frame_set_screen_cursor (MetaFrame	*frame,
 | 
			
		||||
				   MetaCursor	cursor);
 | 
			
		||||
 | 
			
		||||
void meta_frame_update_style (MetaFrame *frame);
 | 
			
		||||
void meta_frame_update_title (MetaFrame *frame);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -42,16 +42,10 @@ struct _MetaKeyHandler
 | 
			
		||||
  GDestroyNotify user_data_free_func;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaKeyBinding
 | 
			
		||||
{
 | 
			
		||||
  const char *name;
 | 
			
		||||
  KeySym keysym;
 | 
			
		||||
  KeyCode keycode;
 | 
			
		||||
  unsigned int mask;
 | 
			
		||||
  MetaVirtualModifier modifiers;
 | 
			
		||||
  gint flags;
 | 
			
		||||
  MetaKeyHandler *handler;
 | 
			
		||||
};
 | 
			
		||||
typedef struct _MetaResolvedKeyCombo {
 | 
			
		||||
  xkb_keycode_t keycode;
 | 
			
		||||
  xkb_mod_mask_t mask;
 | 
			
		||||
} MetaResolvedKeyCombo;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MetaKeyCombo:
 | 
			
		||||
@@ -67,6 +61,15 @@ struct _MetaKeyCombo
 | 
			
		||||
  MetaVirtualModifier modifiers;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaKeyBinding
 | 
			
		||||
{
 | 
			
		||||
  const char *name;
 | 
			
		||||
  MetaKeyCombo combo;
 | 
			
		||||
  MetaResolvedKeyCombo resolved_combo;
 | 
			
		||||
  gint flags;
 | 
			
		||||
  MetaKeyHandler *handler;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  char *name;
 | 
			
		||||
@@ -81,9 +84,6 @@ typedef struct
 | 
			
		||||
   */
 | 
			
		||||
  GSList *combos;
 | 
			
		||||
 | 
			
		||||
  /* for keybindings that apply only to a window */
 | 
			
		||||
  gboolean      per_window:1;
 | 
			
		||||
 | 
			
		||||
  /* for keybindings not added with meta_display_add_keybinding() */
 | 
			
		||||
  gboolean      builtin:1;
 | 
			
		||||
} MetaKeyPref;
 | 
			
		||||
@@ -97,10 +97,13 @@ typedef struct
 | 
			
		||||
  xkb_mod_mask_t super_mask;
 | 
			
		||||
  xkb_mod_mask_t meta_mask;
 | 
			
		||||
  MetaKeyCombo overlay_key_combo;
 | 
			
		||||
  MetaResolvedKeyCombo overlay_resolved_key_combo;
 | 
			
		||||
  gboolean overlay_key_only_pressed;
 | 
			
		||||
  MetaKeyCombo *iso_next_group_combos;
 | 
			
		||||
  MetaResolvedKeyCombo *iso_next_group_combos;
 | 
			
		||||
  int n_iso_next_group_combos;
 | 
			
		||||
 | 
			
		||||
  xkb_level_index_t keymap_num_levels;
 | 
			
		||||
 | 
			
		||||
  /* Alt+click button grabs */
 | 
			
		||||
  ClutterModifierType window_grab_modifiers;
 | 
			
		||||
} MetaKeyBindingManager;
 | 
			
		||||
 
 | 
			
		||||
@@ -40,7 +40,11 @@
 | 
			
		||||
#include <meta/prefs.h>
 | 
			
		||||
#include "meta-accel-parse.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __linux__
 | 
			
		||||
#include <linux/input.h>
 | 
			
		||||
#elif !defined KEY_GRAVE
 | 
			
		||||
#define KEY_GRAVE 0x29 /* assume the use of xf86-input-keyboard */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "backends/x11/meta-backend-x11.h"
 | 
			
		||||
#include "x11/window-x11.h"
 | 
			
		||||
@@ -87,7 +91,7 @@ meta_key_binding_get_name (MetaKeyBinding *binding)
 | 
			
		||||
MetaVirtualModifier
 | 
			
		||||
meta_key_binding_get_modifiers (MetaKeyBinding *binding)
 | 
			
		||||
{
 | 
			
		||||
  return binding->modifiers;
 | 
			
		||||
  return binding->combo.modifiers;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
@@ -99,7 +103,7 @@ meta_key_binding_is_reversed (MetaKeyBinding *binding)
 | 
			
		||||
guint
 | 
			
		||||
meta_key_binding_get_mask (MetaKeyBinding *binding)
 | 
			
		||||
{
 | 
			
		||||
  return binding->mask;
 | 
			
		||||
  return binding->resolved_combo.mask;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
@@ -149,20 +153,18 @@ typedef struct _MetaKeyGrab MetaKeyGrab;
 | 
			
		||||
struct _MetaKeyGrab {
 | 
			
		||||
  char *name;
 | 
			
		||||
  guint action;
 | 
			
		||||
  MetaKeyCombo *combo;
 | 
			
		||||
  MetaKeyCombo combo;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_key_grab_free (MetaKeyGrab *grab)
 | 
			
		||||
{
 | 
			
		||||
  g_free (grab->name);
 | 
			
		||||
  g_free (grab->combo);
 | 
			
		||||
  g_free (grab);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static guint32
 | 
			
		||||
key_binding_key (guint32 keycode,
 | 
			
		||||
                 guint32 mask)
 | 
			
		||||
key_combo_key (MetaResolvedKeyCombo *resolved_combo)
 | 
			
		||||
{
 | 
			
		||||
  /* On X, keycodes are only 8 bits while libxkbcommon supports 32 bit
 | 
			
		||||
     keycodes, but since we're using the same XKB keymaps that X uses,
 | 
			
		||||
@@ -172,16 +174,8 @@ key_binding_key (guint32 keycode,
 | 
			
		||||
     can use a 32 bit integer to safely concatenate both keycode and
 | 
			
		||||
     mask and thus making it easy to use them as an index in a
 | 
			
		||||
     GHashTable. */
 | 
			
		||||
  guint32 key = keycode & 0xffff;
 | 
			
		||||
  return (key << 16) | (mask & 0xffff);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *
 | 
			
		||||
keysym_name (xkb_keysym_t keysym)
 | 
			
		||||
{
 | 
			
		||||
  static char name[32] = "";
 | 
			
		||||
  xkb_keysym_get_name (keysym, name, sizeof (name));
 | 
			
		||||
  return name;
 | 
			
		||||
  guint32 key = resolved_combo->keycode & 0xffff;
 | 
			
		||||
  return (key << 16) | (resolved_combo->mask & 0xffff);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -236,29 +230,19 @@ reload_modmap (MetaKeyBindingManager *keys)
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
is_keycode_for_keysym (struct xkb_keymap *keymap,
 | 
			
		||||
                       xkb_layout_index_t layout,
 | 
			
		||||
                       xkb_level_index_t  level,
 | 
			
		||||
                       xkb_keycode_t      keycode,
 | 
			
		||||
                       xkb_keysym_t       keysym)
 | 
			
		||||
{
 | 
			
		||||
  xkb_layout_index_t num_layouts, i;
 | 
			
		||||
  const xkb_keysym_t *syms;
 | 
			
		||||
  int num_syms, k;
 | 
			
		||||
 | 
			
		||||
  num_layouts = xkb_keymap_num_layouts_for_key (keymap, keycode);
 | 
			
		||||
  for (i = 0; i < num_layouts; i++)
 | 
			
		||||
  num_syms = xkb_keymap_key_get_syms_by_level (keymap, keycode, layout, level, &syms);
 | 
			
		||||
  for (k = 0; k < num_syms; k++)
 | 
			
		||||
    {
 | 
			
		||||
      xkb_level_index_t num_levels, j;
 | 
			
		||||
 | 
			
		||||
      num_levels = xkb_keymap_num_levels_for_key (keymap, keycode, i);
 | 
			
		||||
      for (j = 0; j < num_levels; j++)
 | 
			
		||||
        {
 | 
			
		||||
          const xkb_keysym_t *syms;
 | 
			
		||||
          int num_syms, k;
 | 
			
		||||
 | 
			
		||||
          num_syms = xkb_keymap_key_get_syms_by_level (keymap, keycode, i, j, &syms);
 | 
			
		||||
          for (k = 0; k < num_syms; k++)
 | 
			
		||||
            {
 | 
			
		||||
              if (syms[k] == keysym)
 | 
			
		||||
                return TRUE;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
      if (syms[k] == keysym)
 | 
			
		||||
        return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
@@ -268,6 +252,8 @@ typedef struct
 | 
			
		||||
{
 | 
			
		||||
  GArray *keycodes;
 | 
			
		||||
  xkb_keysym_t keysym;
 | 
			
		||||
  xkb_layout_index_t layout;
 | 
			
		||||
  xkb_level_index_t level;
 | 
			
		||||
} FindKeysymData;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -278,8 +264,10 @@ get_keycodes_for_keysym_iter (struct xkb_keymap *keymap,
 | 
			
		||||
  FindKeysymData *search_data = data;
 | 
			
		||||
  GArray *keycodes = search_data->keycodes;
 | 
			
		||||
  xkb_keysym_t keysym = search_data->keysym;
 | 
			
		||||
  xkb_layout_index_t layout = search_data->layout;
 | 
			
		||||
  xkb_level_index_t level = search_data->level;
 | 
			
		||||
 | 
			
		||||
  if (is_keycode_for_keysym (keymap, keycode, keysym))
 | 
			
		||||
  if (is_keycode_for_keysym (keymap, layout, level, keycode, keysym))
 | 
			
		||||
    g_array_append_val (keycodes, keycode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -307,8 +295,15 @@ get_keycodes_for_keysym (MetaKeyBindingManager  *keys,
 | 
			
		||||
  {
 | 
			
		||||
    MetaBackend *backend = meta_get_backend ();
 | 
			
		||||
    struct xkb_keymap *keymap = meta_backend_get_keymap (backend);
 | 
			
		||||
    FindKeysymData search_data = { retval, keysym };
 | 
			
		||||
    xkb_keymap_key_for_each (keymap, get_keycodes_for_keysym_iter, &search_data);
 | 
			
		||||
    xkb_layout_index_t i;
 | 
			
		||||
    xkb_level_index_t j;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < xkb_keymap_num_layouts (keymap); i++)
 | 
			
		||||
      for (j = 0; j < keys->keymap_num_levels; j++)
 | 
			
		||||
        {
 | 
			
		||||
          FindKeysymData search_data = { retval, keysym, i, j };
 | 
			
		||||
          xkb_keymap_key_for_each (keymap, get_keycodes_for_keysym_iter, &search_data);
 | 
			
		||||
        }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
@@ -319,7 +314,7 @@ get_keycodes_for_keysym (MetaKeyBindingManager  *keys,
 | 
			
		||||
 | 
			
		||||
static guint
 | 
			
		||||
get_first_keycode_for_keysym (MetaKeyBindingManager *keys,
 | 
			
		||||
                              guint                   keysym)
 | 
			
		||||
                              guint                  keysym)
 | 
			
		||||
{
 | 
			
		||||
  int *keycodes;
 | 
			
		||||
  int n_keycodes;
 | 
			
		||||
@@ -336,11 +331,37 @@ get_first_keycode_for_keysym (MetaKeyBindingManager *keys,
 | 
			
		||||
  return keycode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
determine_keymap_num_levels_iter (struct xkb_keymap *keymap,
 | 
			
		||||
                                  xkb_keycode_t      keycode,
 | 
			
		||||
                                  void              *data)
 | 
			
		||||
{
 | 
			
		||||
  xkb_level_index_t *num_levels = data;
 | 
			
		||||
  xkb_layout_index_t i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < xkb_keymap_num_layouts_for_key (keymap, keycode); i++)
 | 
			
		||||
    {
 | 
			
		||||
      xkb_level_index_t level = xkb_keymap_num_levels_for_key (keymap, keycode, i);
 | 
			
		||||
      if (level > *num_levels)
 | 
			
		||||
        *num_levels = level;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
determine_keymap_num_levels (MetaKeyBindingManager *keys)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackend *backend = meta_get_backend ();
 | 
			
		||||
  struct xkb_keymap *keymap = meta_backend_get_keymap (backend);
 | 
			
		||||
 | 
			
		||||
  keys->keymap_num_levels = 0;
 | 
			
		||||
  xkb_keymap_key_for_each (keymap, determine_keymap_num_levels_iter, &keys->keymap_num_levels);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
reload_iso_next_group_combos (MetaKeyBindingManager *keys)
 | 
			
		||||
{
 | 
			
		||||
  const char *iso_next_group_option;
 | 
			
		||||
  MetaKeyCombo *combos;
 | 
			
		||||
  MetaResolvedKeyCombo *combos;
 | 
			
		||||
  int *keycodes;
 | 
			
		||||
  int n_keycodes;
 | 
			
		||||
  int n_combos;
 | 
			
		||||
@@ -368,39 +389,36 @@ reload_iso_next_group_combos (MetaKeyBindingManager *keys)
 | 
			
		||||
      g_str_equal (iso_next_group_option, "caps_toggle"))
 | 
			
		||||
    {
 | 
			
		||||
      n_combos = n_keycodes;
 | 
			
		||||
      combos = g_new (MetaKeyCombo, n_combos);
 | 
			
		||||
      combos = g_new (MetaResolvedKeyCombo, n_combos);
 | 
			
		||||
 | 
			
		||||
      for (i = 0; i < n_keycodes; ++i)
 | 
			
		||||
        {
 | 
			
		||||
          combos[i].keysym = XKB_KEY_ISO_Next_Group;
 | 
			
		||||
          combos[i].keycode = keycodes[i];
 | 
			
		||||
          combos[i].modifiers = 0;
 | 
			
		||||
          combos[i].mask = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else if (g_str_equal (iso_next_group_option, "shift_caps_toggle") ||
 | 
			
		||||
           g_str_equal (iso_next_group_option, "shifts_toggle"))
 | 
			
		||||
    {
 | 
			
		||||
      n_combos = n_keycodes;
 | 
			
		||||
      combos = g_new (MetaKeyCombo, n_combos);
 | 
			
		||||
      combos = g_new (MetaResolvedKeyCombo, n_combos);
 | 
			
		||||
 | 
			
		||||
      for (i = 0; i < n_keycodes; ++i)
 | 
			
		||||
        {
 | 
			
		||||
          combos[i].keysym = XKB_KEY_ISO_Next_Group;
 | 
			
		||||
          combos[i].keycode = keycodes[i];
 | 
			
		||||
          combos[i].modifiers = ShiftMask;
 | 
			
		||||
          combos[i].mask = ShiftMask;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else if (g_str_equal (iso_next_group_option, "alt_caps_toggle") ||
 | 
			
		||||
           g_str_equal (iso_next_group_option, "alt_space_toggle"))
 | 
			
		||||
    {
 | 
			
		||||
      n_combos = n_keycodes;
 | 
			
		||||
      combos = g_new (MetaKeyCombo, n_combos);
 | 
			
		||||
      combos = g_new (MetaResolvedKeyCombo, n_combos);
 | 
			
		||||
 | 
			
		||||
      for (i = 0; i < n_keycodes; ++i)
 | 
			
		||||
        {
 | 
			
		||||
          combos[i].keysym = XKB_KEY_ISO_Next_Group;
 | 
			
		||||
          combos[i].keycode = keycodes[i];
 | 
			
		||||
          combos[i].modifiers = Mod1Mask;
 | 
			
		||||
          combos[i].mask = Mod1Mask;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else if (g_str_equal (iso_next_group_option, "ctrl_shift_toggle") ||
 | 
			
		||||
@@ -408,50 +426,44 @@ reload_iso_next_group_combos (MetaKeyBindingManager *keys)
 | 
			
		||||
           g_str_equal (iso_next_group_option, "rctrl_rshift_toggle"))
 | 
			
		||||
    {
 | 
			
		||||
      n_combos = n_keycodes * 2;
 | 
			
		||||
      combos = g_new (MetaKeyCombo, n_combos);
 | 
			
		||||
      combos = g_new (MetaResolvedKeyCombo, n_combos);
 | 
			
		||||
 | 
			
		||||
      for (i = 0; i < n_keycodes; ++i)
 | 
			
		||||
        {
 | 
			
		||||
          combos[i].keysym = XKB_KEY_ISO_Next_Group;
 | 
			
		||||
          combos[i].keycode = keycodes[i];
 | 
			
		||||
          combos[i].modifiers = ShiftMask;
 | 
			
		||||
          combos[i].mask = ShiftMask;
 | 
			
		||||
 | 
			
		||||
          combos[i + n_keycodes].keysym = XKB_KEY_ISO_Next_Group;
 | 
			
		||||
          combos[i + n_keycodes].keycode = keycodes[i];
 | 
			
		||||
          combos[i + n_keycodes].modifiers = ControlMask;
 | 
			
		||||
          combos[i + n_keycodes].mask = ControlMask;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else if (g_str_equal (iso_next_group_option, "ctrl_alt_toggle"))
 | 
			
		||||
    {
 | 
			
		||||
      n_combos = n_keycodes * 2;
 | 
			
		||||
      combos = g_new (MetaKeyCombo, n_combos);
 | 
			
		||||
      combos = g_new (MetaResolvedKeyCombo, n_combos);
 | 
			
		||||
 | 
			
		||||
      for (i = 0; i < n_keycodes; ++i)
 | 
			
		||||
        {
 | 
			
		||||
          combos[i].keysym = XKB_KEY_ISO_Next_Group;
 | 
			
		||||
          combos[i].keycode = keycodes[i];
 | 
			
		||||
          combos[i].modifiers = Mod1Mask;
 | 
			
		||||
          combos[i].mask = Mod1Mask;
 | 
			
		||||
 | 
			
		||||
          combos[i + n_keycodes].keysym = XKB_KEY_ISO_Next_Group;
 | 
			
		||||
          combos[i + n_keycodes].keycode = keycodes[i];
 | 
			
		||||
          combos[i + n_keycodes].modifiers = ControlMask;
 | 
			
		||||
          combos[i + n_keycodes].mask = ControlMask;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else if (g_str_equal (iso_next_group_option, "alt_shift_toggle") ||
 | 
			
		||||
           g_str_equal (iso_next_group_option, "lalt_lshift_toggle"))
 | 
			
		||||
    {
 | 
			
		||||
      n_combos = n_keycodes * 2;
 | 
			
		||||
      combos = g_new (MetaKeyCombo, n_combos);
 | 
			
		||||
      combos = g_new (MetaResolvedKeyCombo, n_combos);
 | 
			
		||||
 | 
			
		||||
      for (i = 0; i < n_keycodes; ++i)
 | 
			
		||||
        {
 | 
			
		||||
          combos[i].keysym = XKB_KEY_ISO_Next_Group;
 | 
			
		||||
          combos[i].keycode = keycodes[i];
 | 
			
		||||
          combos[i].modifiers = Mod1Mask;
 | 
			
		||||
          combos[i].mask = Mod1Mask;
 | 
			
		||||
 | 
			
		||||
          combos[i + n_keycodes].keysym = XKB_KEY_ISO_Next_Group;
 | 
			
		||||
          combos[i + n_keycodes].keycode = keycodes[i];
 | 
			
		||||
          combos[i + n_keycodes].modifiers = ShiftMask;
 | 
			
		||||
          combos[i + n_keycodes].mask = ShiftMask;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
@@ -466,39 +478,6 @@ reload_iso_next_group_combos (MetaKeyBindingManager *keys)
 | 
			
		||||
  keys->iso_next_group_combos = combos;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
binding_reload_keycode_foreach (gpointer key,
 | 
			
		||||
                                gpointer value,
 | 
			
		||||
                                gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  MetaKeyBindingManager *keys = data;
 | 
			
		||||
  MetaKeyBinding *binding = value;
 | 
			
		||||
 | 
			
		||||
  if (binding->keysym)
 | 
			
		||||
    binding->keycode = get_first_keycode_for_keysym (keys, binding->keysym);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
reload_keycodes (MetaKeyBindingManager *keys)
 | 
			
		||||
{
 | 
			
		||||
  meta_topic (META_DEBUG_KEYBINDINGS,
 | 
			
		||||
              "Reloading keycodes for binding tables\n");
 | 
			
		||||
 | 
			
		||||
  if (keys->overlay_key_combo.keysym != 0)
 | 
			
		||||
    {
 | 
			
		||||
      keys->overlay_key_combo.keycode =
 | 
			
		||||
        get_first_keycode_for_keysym (keys, keys->overlay_key_combo.keysym);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      keys->overlay_key_combo.keycode = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  reload_iso_next_group_combos (keys);
 | 
			
		||||
 | 
			
		||||
  g_hash_table_foreach (keys->key_bindings, binding_reload_keycode_foreach, keys);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
devirtualize_modifiers (MetaKeyBindingManager *keys,
 | 
			
		||||
                        MetaVirtualModifier     modifiers,
 | 
			
		||||
@@ -528,58 +507,56 @@ devirtualize_modifiers (MetaKeyBindingManager *keys,
 | 
			
		||||
    *mask |= Mod5Mask;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
binding_reload_modifiers_foreach (gpointer key,
 | 
			
		||||
                                  gpointer value,
 | 
			
		||||
                                  gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  MetaKeyBindingManager *keys = data;
 | 
			
		||||
  MetaKeyBinding *binding = value;
 | 
			
		||||
 | 
			
		||||
  devirtualize_modifiers (keys, binding->modifiers, &binding->mask);
 | 
			
		||||
  meta_topic (META_DEBUG_KEYBINDINGS,
 | 
			
		||||
              " Devirtualized mods 0x%x -> 0x%x (%s)\n",
 | 
			
		||||
              binding->modifiers,
 | 
			
		||||
              binding->mask,
 | 
			
		||||
              binding->name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
reload_modifiers (MetaKeyBindingManager *keys)
 | 
			
		||||
{
 | 
			
		||||
  meta_topic (META_DEBUG_KEYBINDINGS,
 | 
			
		||||
              "Reloading keycodes for binding tables\n");
 | 
			
		||||
 | 
			
		||||
  g_hash_table_foreach (keys->key_bindings, binding_reload_modifiers_foreach, keys);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
index_binding (MetaKeyBindingManager *keys,
 | 
			
		||||
               MetaKeyBinding         *binding)
 | 
			
		||||
{
 | 
			
		||||
  guint32 index_key;
 | 
			
		||||
 | 
			
		||||
  index_key = key_binding_key (binding->keycode, binding->mask);
 | 
			
		||||
  index_key = key_combo_key (&binding->resolved_combo);
 | 
			
		||||
  g_hash_table_replace (keys->key_bindings_index,
 | 
			
		||||
                        GINT_TO_POINTER (index_key), binding);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
binding_index_foreach (gpointer key,
 | 
			
		||||
                       gpointer value,
 | 
			
		||||
                       gpointer data)
 | 
			
		||||
resolve_key_combo (MetaKeyBindingManager *keys,
 | 
			
		||||
                   MetaKeyCombo          *combo,
 | 
			
		||||
                   MetaResolvedKeyCombo  *resolved_combo)
 | 
			
		||||
{
 | 
			
		||||
  if (combo->keysym != 0)
 | 
			
		||||
    resolved_combo->keycode = get_first_keycode_for_keysym (keys, combo->keysym);
 | 
			
		||||
  else
 | 
			
		||||
    resolved_combo->keycode = combo->keycode;
 | 
			
		||||
 | 
			
		||||
  devirtualize_modifiers (keys, combo->modifiers, &resolved_combo->mask);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
binding_reload_combos_foreach (gpointer key,
 | 
			
		||||
                               gpointer value,
 | 
			
		||||
                               gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  MetaKeyBindingManager *keys = data;
 | 
			
		||||
  MetaKeyBinding *binding = value;
 | 
			
		||||
 | 
			
		||||
  resolve_key_combo (keys, &binding->combo, &binding->resolved_combo);
 | 
			
		||||
  index_binding (keys, binding);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
rebuild_binding_index (MetaKeyBindingManager *keys)
 | 
			
		||||
reload_combos (MetaKeyBindingManager *keys)
 | 
			
		||||
{
 | 
			
		||||
  g_hash_table_remove_all (keys->key_bindings_index);
 | 
			
		||||
  g_hash_table_foreach (keys->key_bindings, binding_index_foreach, keys);
 | 
			
		||||
 | 
			
		||||
  determine_keymap_num_levels (keys);
 | 
			
		||||
 | 
			
		||||
  resolve_key_combo (keys,
 | 
			
		||||
                     &keys->overlay_key_combo,
 | 
			
		||||
                     &keys->overlay_resolved_key_combo);
 | 
			
		||||
 | 
			
		||||
  reload_iso_next_group_combos (keys);
 | 
			
		||||
 | 
			
		||||
  g_hash_table_foreach (keys->key_bindings, binding_reload_combos_foreach, keys);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -606,15 +583,11 @@ rebuild_binding_table (MetaKeyBindingManager *keys,
 | 
			
		||||
            {
 | 
			
		||||
              MetaKeyHandler *handler = HANDLER (pref->name);
 | 
			
		||||
 | 
			
		||||
              b = g_malloc0 (sizeof (MetaKeyBinding));
 | 
			
		||||
 | 
			
		||||
              b = g_slice_new0 (MetaKeyBinding);
 | 
			
		||||
              b->name = pref->name;
 | 
			
		||||
              b->handler = handler;
 | 
			
		||||
              b->flags = handler->flags;
 | 
			
		||||
              b->keysym = combo->keysym;
 | 
			
		||||
              b->keycode = combo->keycode;
 | 
			
		||||
              b->modifiers = combo->modifiers;
 | 
			
		||||
              b->mask = 0;
 | 
			
		||||
              b->combo = *combo;
 | 
			
		||||
 | 
			
		||||
              g_hash_table_add (keys->key_bindings, b);
 | 
			
		||||
            }
 | 
			
		||||
@@ -629,19 +602,15 @@ rebuild_binding_table (MetaKeyBindingManager *keys,
 | 
			
		||||
  while (g)
 | 
			
		||||
    {
 | 
			
		||||
      MetaKeyGrab *grab = (MetaKeyGrab*)g->data;
 | 
			
		||||
      if (grab->combo && (grab->combo->keysym != None || grab->combo->keycode != 0))
 | 
			
		||||
      if (grab->combo.keysym != None || grab->combo.keycode != 0)
 | 
			
		||||
        {
 | 
			
		||||
          MetaKeyHandler *handler = HANDLER ("external-grab");
 | 
			
		||||
 | 
			
		||||
          b = g_malloc0 (sizeof (MetaKeyBinding));
 | 
			
		||||
 | 
			
		||||
          b = g_slice_new0 (MetaKeyBinding);
 | 
			
		||||
          b->name = grab->name;
 | 
			
		||||
          b->handler = handler;
 | 
			
		||||
          b->flags = handler->flags;
 | 
			
		||||
          b->keysym = grab->combo->keysym;
 | 
			
		||||
          b->keycode = grab->combo->keycode;
 | 
			
		||||
          b->modifiers = grab->combo->modifiers;
 | 
			
		||||
          b->mask = 0;
 | 
			
		||||
          b->combo = grab->combo;
 | 
			
		||||
 | 
			
		||||
          g_hash_table_add (keys->key_bindings, b);
 | 
			
		||||
        }
 | 
			
		||||
@@ -714,14 +683,10 @@ grab_key_bindings (MetaDisplay *display)
 | 
			
		||||
 | 
			
		||||
static MetaKeyBinding *
 | 
			
		||||
get_keybinding (MetaKeyBindingManager *keys,
 | 
			
		||||
                guint32                 keycode,
 | 
			
		||||
                guint32                 mask)
 | 
			
		||||
                MetaResolvedKeyCombo  *resolved_combo)
 | 
			
		||||
{
 | 
			
		||||
  guint32 key;
 | 
			
		||||
 | 
			
		||||
  mask = mask & 0xff & ~keys->ignored_modifier_mask;
 | 
			
		||||
  key = key_binding_key (keycode, mask);
 | 
			
		||||
 | 
			
		||||
  key = key_combo_key (resolved_combo);
 | 
			
		||||
  return g_hash_table_lookup (keys->key_bindings_index, GINT_TO_POINTER (key));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -840,6 +805,46 @@ meta_display_remove_keybinding (MetaDisplay *display,
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static guint
 | 
			
		||||
get_keybinding_action (MetaKeyBindingManager *keys,
 | 
			
		||||
                       MetaResolvedKeyCombo  *resolved_combo)
 | 
			
		||||
{
 | 
			
		||||
  MetaKeyBinding *binding;
 | 
			
		||||
 | 
			
		||||
  /* This is much more vague than the MetaDisplay::overlay-key signal,
 | 
			
		||||
   * which is only emitted if the overlay-key is the only key pressed;
 | 
			
		||||
   * as this method is primarily intended for plugins to allow processing
 | 
			
		||||
   * of mutter keybindings while holding a grab, the overlay-key-only-pressed
 | 
			
		||||
   * tracking is left to the plugin here.
 | 
			
		||||
   */
 | 
			
		||||
  if (resolved_combo->keycode == (unsigned int)keys->overlay_resolved_key_combo.keycode)
 | 
			
		||||
    return META_KEYBINDING_ACTION_OVERLAY_KEY;
 | 
			
		||||
 | 
			
		||||
  binding = get_keybinding (keys, resolved_combo);
 | 
			
		||||
  if (binding)
 | 
			
		||||
    {
 | 
			
		||||
      MetaKeyGrab *grab = g_hash_table_lookup (external_grabs, binding->name);
 | 
			
		||||
      if (grab)
 | 
			
		||||
        return grab->action;
 | 
			
		||||
      else
 | 
			
		||||
        return (guint) meta_prefs_get_keybinding_action (binding->name);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      return META_KEYBINDING_ACTION_NONE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
resolved_combo_from_event_params (MetaResolvedKeyCombo *resolved_combo,
 | 
			
		||||
                                  MetaKeyBindingManager *keys,
 | 
			
		||||
                                  unsigned int keycode,
 | 
			
		||||
                                  unsigned long mask)
 | 
			
		||||
{
 | 
			
		||||
  resolved_combo->keycode = keycode;
 | 
			
		||||
  resolved_combo->mask = mask & 0xff & ~keys->ignored_modifier_mask;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_display_get_keybinding_action:
 | 
			
		||||
 * @display: A #MetaDisplay
 | 
			
		||||
@@ -860,31 +865,9 @@ meta_display_get_keybinding_action (MetaDisplay  *display,
 | 
			
		||||
                                    unsigned long mask)
 | 
			
		||||
{
 | 
			
		||||
  MetaKeyBindingManager *keys = &display->key_binding_manager;
 | 
			
		||||
  MetaKeyBinding *binding;
 | 
			
		||||
 | 
			
		||||
  /* This is much more vague than the MetaDisplay::overlay-key signal,
 | 
			
		||||
   * which is only emitted if the overlay-key is the only key pressed;
 | 
			
		||||
   * as this method is primarily intended for plugins to allow processing
 | 
			
		||||
   * of mutter keybindings while holding a grab, the overlay-key-only-pressed
 | 
			
		||||
   * tracking is left to the plugin here.
 | 
			
		||||
   */
 | 
			
		||||
  if (keycode == (unsigned int)keys->overlay_key_combo.keycode)
 | 
			
		||||
    return META_KEYBINDING_ACTION_OVERLAY_KEY;
 | 
			
		||||
 | 
			
		||||
  binding = get_keybinding (keys, keycode, mask);
 | 
			
		||||
 | 
			
		||||
  if (binding)
 | 
			
		||||
    {
 | 
			
		||||
      MetaKeyGrab *grab = g_hash_table_lookup (external_grabs, binding->name);
 | 
			
		||||
      if (grab)
 | 
			
		||||
        return grab->action;
 | 
			
		||||
      else
 | 
			
		||||
        return (guint) meta_prefs_get_keybinding_action (binding->name);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      return META_KEYBINDING_ACTION_NONE;
 | 
			
		||||
    }
 | 
			
		||||
  MetaResolvedKeyCombo resolved_combo;
 | 
			
		||||
  resolved_combo_from_event_params (&resolved_combo, keys, keycode, mask);
 | 
			
		||||
  return get_keybinding_action (keys, &resolved_combo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -901,11 +884,7 @@ on_keymap_changed (MetaBackend *backend,
 | 
			
		||||
   * even when only the keymap changes */
 | 
			
		||||
  reload_modmap (keys);
 | 
			
		||||
 | 
			
		||||
  reload_keycodes (keys);
 | 
			
		||||
 | 
			
		||||
  reload_modifiers (keys);
 | 
			
		||||
 | 
			
		||||
  rebuild_binding_index (keys);
 | 
			
		||||
  reload_combos (keys);
 | 
			
		||||
 | 
			
		||||
  grab_key_bindings (display);
 | 
			
		||||
}
 | 
			
		||||
@@ -1125,9 +1104,7 @@ prefs_changed_callback (MetaPreference pref,
 | 
			
		||||
      ungrab_key_bindings (display);
 | 
			
		||||
      rebuild_key_binding_table (keys);
 | 
			
		||||
      rebuild_special_bindings (keys);
 | 
			
		||||
      reload_keycodes (keys);
 | 
			
		||||
      reload_modifiers (keys);
 | 
			
		||||
      rebuild_binding_index (keys);
 | 
			
		||||
      reload_combos (keys);
 | 
			
		||||
      grab_key_bindings (display);
 | 
			
		||||
      break;
 | 
			
		||||
    case META_PREF_MOUSE_BUTTON_MODS:
 | 
			
		||||
@@ -1172,11 +1149,9 @@ meta_display_shutdown_keys (MetaDisplay *display)
 | 
			
		||||
/* Grab/ungrab, ignoring all annoying modifiers like NumLock etc. */
 | 
			
		||||
static void
 | 
			
		||||
meta_change_keygrab (MetaKeyBindingManager *keys,
 | 
			
		||||
                     Window                  xwindow,
 | 
			
		||||
                     gboolean                grab,
 | 
			
		||||
                     int                     keysym,
 | 
			
		||||
                     unsigned int            keycode,
 | 
			
		||||
                     int                     modmask)
 | 
			
		||||
                     Window                 xwindow,
 | 
			
		||||
                     gboolean               grab,
 | 
			
		||||
                     MetaResolvedKeyCombo  *resolved_combo)
 | 
			
		||||
{
 | 
			
		||||
  unsigned int ignored_mask;
 | 
			
		||||
 | 
			
		||||
@@ -1195,10 +1170,9 @@ meta_change_keygrab (MetaKeyBindingManager *keys,
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  meta_topic (META_DEBUG_KEYBINDINGS,
 | 
			
		||||
              "%s keybinding %s keycode %d mask 0x%x on 0x%lx\n",
 | 
			
		||||
              "%s keybinding keycode %d mask 0x%x on 0x%lx\n",
 | 
			
		||||
              grab ? "Grabbing" : "Ungrabbing",
 | 
			
		||||
              keysym_name (keysym), keycode,
 | 
			
		||||
              modmask, xwindow);
 | 
			
		||||
              resolved_combo->keycode, resolved_combo->mask, xwindow);
 | 
			
		||||
 | 
			
		||||
  ignored_mask = 0;
 | 
			
		||||
  while (ignored_mask <= keys->ignored_modifier_mask)
 | 
			
		||||
@@ -1214,18 +1188,18 @@ meta_change_keygrab (MetaKeyBindingManager *keys,
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      mods = (XIGrabModifiers) { modmask | ignored_mask, 0 };
 | 
			
		||||
      mods = (XIGrabModifiers) { resolved_combo->mask | ignored_mask, 0 };
 | 
			
		||||
 | 
			
		||||
      if (grab)
 | 
			
		||||
        XIGrabKeycode (xdisplay,
 | 
			
		||||
                       META_VIRTUAL_CORE_KEYBOARD_ID,
 | 
			
		||||
                       keycode, xwindow,
 | 
			
		||||
                       resolved_combo->keycode, xwindow,
 | 
			
		||||
                       XIGrabModeSync, XIGrabModeAsync,
 | 
			
		||||
                       False, &mask, 1, &mods);
 | 
			
		||||
      else
 | 
			
		||||
        XIUngrabKeycode (xdisplay,
 | 
			
		||||
                         META_VIRTUAL_CORE_KEYBOARD_ID,
 | 
			
		||||
                         keycode, xwindow, 1, &mods);
 | 
			
		||||
                         resolved_combo->keycode, xwindow, 1, &mods);
 | 
			
		||||
 | 
			
		||||
      ++ignored_mask;
 | 
			
		||||
    }
 | 
			
		||||
@@ -1251,13 +1225,10 @@ change_keygrab_foreach (gpointer key,
 | 
			
		||||
  if (data->only_per_window != binding_is_per_window)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (binding->keycode == 0)
 | 
			
		||||
  if (binding->resolved_combo.keycode == 0)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  meta_change_keygrab (data->keys, data->xwindow, data->grab,
 | 
			
		||||
                       binding->keysym,
 | 
			
		||||
                       binding->keycode,
 | 
			
		||||
                       binding->mask);
 | 
			
		||||
  meta_change_keygrab (data->keys, data->xwindow, data->grab, &binding->resolved_combo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -1283,11 +1254,8 @@ meta_screen_change_keygrabs (MetaScreen *screen,
 | 
			
		||||
  MetaDisplay *display = screen->display;
 | 
			
		||||
  MetaKeyBindingManager *keys = &display->key_binding_manager;
 | 
			
		||||
 | 
			
		||||
  if (keys->overlay_key_combo.keycode != 0)
 | 
			
		||||
    meta_change_keygrab (keys, screen->xroot, grab,
 | 
			
		||||
                         keys->overlay_key_combo.keysym,
 | 
			
		||||
                         keys->overlay_key_combo.keycode,
 | 
			
		||||
                         keys->overlay_key_combo.modifiers);
 | 
			
		||||
  if (keys->overlay_resolved_key_combo.keycode != 0)
 | 
			
		||||
    meta_change_keygrab (keys, screen->xroot, grab, &keys->overlay_resolved_key_combo);
 | 
			
		||||
 | 
			
		||||
  if (keys->iso_next_group_combos)
 | 
			
		||||
    {
 | 
			
		||||
@@ -1295,12 +1263,8 @@ meta_screen_change_keygrabs (MetaScreen *screen,
 | 
			
		||||
      while (i < keys->n_iso_next_group_combos)
 | 
			
		||||
        {
 | 
			
		||||
          if (keys->iso_next_group_combos[i].keycode != 0)
 | 
			
		||||
            {
 | 
			
		||||
              meta_change_keygrab (keys, screen->xroot, grab,
 | 
			
		||||
                                   keys->iso_next_group_combos[i].keysym,
 | 
			
		||||
                                   keys->iso_next_group_combos[i].keycode,
 | 
			
		||||
                                   keys->iso_next_group_combos[i].modifiers);
 | 
			
		||||
            }
 | 
			
		||||
            meta_change_keygrab (keys, screen->xroot, grab, &keys->iso_next_group_combos[i]);
 | 
			
		||||
 | 
			
		||||
          ++i;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -1410,9 +1374,8 @@ handle_external_grab (MetaDisplay     *display,
 | 
			
		||||
                      MetaKeyBinding  *binding,
 | 
			
		||||
                      gpointer         user_data)
 | 
			
		||||
{
 | 
			
		||||
  guint action = meta_display_get_keybinding_action (display,
 | 
			
		||||
                                                     binding->keycode,
 | 
			
		||||
                                                     binding->mask);
 | 
			
		||||
  MetaKeyBindingManager *keys = &display->key_binding_manager;
 | 
			
		||||
  guint action = get_keybinding_action (keys, &binding->resolved_combo);
 | 
			
		||||
  meta_display_accelerator_activate (display, action, event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1425,12 +1388,10 @@ meta_display_grab_accelerator (MetaDisplay *display,
 | 
			
		||||
  MetaKeyBindingManager *keys = &display->key_binding_manager;
 | 
			
		||||
  MetaKeyBinding *binding;
 | 
			
		||||
  MetaKeyGrab *grab;
 | 
			
		||||
  guint keysym = 0;
 | 
			
		||||
  guint keycode = 0;
 | 
			
		||||
  guint mask = 0;
 | 
			
		||||
  MetaVirtualModifier modifiers = 0;
 | 
			
		||||
  MetaKeyCombo combo;
 | 
			
		||||
  MetaResolvedKeyCombo resolved_combo;
 | 
			
		||||
 | 
			
		||||
  if (!meta_parse_accelerator (accelerator, &keysym, &keycode, &modifiers))
 | 
			
		||||
  if (!meta_parse_accelerator (accelerator, &combo))
 | 
			
		||||
    {
 | 
			
		||||
      meta_topic (META_DEBUG_KEYBINDINGS,
 | 
			
		||||
                  "Failed to parse accelerator\n");
 | 
			
		||||
@@ -1439,35 +1400,29 @@ meta_display_grab_accelerator (MetaDisplay *display,
 | 
			
		||||
      return META_KEYBINDING_ACTION_NONE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  devirtualize_modifiers (keys, modifiers, &mask);
 | 
			
		||||
  keycode = get_first_keycode_for_keysym (keys, keysym);
 | 
			
		||||
  resolve_key_combo (keys, &combo, &resolved_combo);
 | 
			
		||||
 | 
			
		||||
  if (keycode == 0)
 | 
			
		||||
  if (resolved_combo.keycode == 0)
 | 
			
		||||
    return META_KEYBINDING_ACTION_NONE;
 | 
			
		||||
 | 
			
		||||
  if (get_keybinding (keys, keycode, mask))
 | 
			
		||||
  if (get_keybinding (keys, &resolved_combo))
 | 
			
		||||
    return META_KEYBINDING_ACTION_NONE;
 | 
			
		||||
 | 
			
		||||
  if (META_IS_BACKEND_X11 (backend))
 | 
			
		||||
    meta_change_keygrab (keys, display->screen->xroot, TRUE, keysym, keycode, mask);
 | 
			
		||||
    meta_change_keygrab (keys, display->screen->xroot, TRUE, &resolved_combo);
 | 
			
		||||
 | 
			
		||||
  grab = g_new0 (MetaKeyGrab, 1);
 | 
			
		||||
  grab->action = next_dynamic_keybinding_action ();
 | 
			
		||||
  grab->name = meta_external_binding_name_for_action (grab->action);
 | 
			
		||||
  grab->combo = g_malloc0 (sizeof (MetaKeyCombo));
 | 
			
		||||
  grab->combo->keysym = keysym;
 | 
			
		||||
  grab->combo->keycode = keycode;
 | 
			
		||||
  grab->combo->modifiers = modifiers;
 | 
			
		||||
  grab->combo = combo;
 | 
			
		||||
 | 
			
		||||
  g_hash_table_insert (external_grabs, grab->name, grab);
 | 
			
		||||
 | 
			
		||||
  binding = g_malloc0 (sizeof (MetaKeyBinding));
 | 
			
		||||
  binding = g_slice_new0 (MetaKeyBinding);
 | 
			
		||||
  binding->name = grab->name;
 | 
			
		||||
  binding->handler = HANDLER ("external-grab");
 | 
			
		||||
  binding->keysym = grab->combo->keysym;
 | 
			
		||||
  binding->keycode = grab->combo->keycode;
 | 
			
		||||
  binding->modifiers = grab->combo->modifiers;
 | 
			
		||||
  binding->mask = mask;
 | 
			
		||||
  binding->combo = combo;
 | 
			
		||||
  binding->resolved_combo = resolved_combo;
 | 
			
		||||
 | 
			
		||||
  g_hash_table_add (keys->key_bindings, binding);
 | 
			
		||||
  index_binding (keys, binding);
 | 
			
		||||
@@ -1484,8 +1439,7 @@ meta_display_ungrab_accelerator (MetaDisplay *display,
 | 
			
		||||
  MetaKeyBinding *binding;
 | 
			
		||||
  MetaKeyGrab *grab;
 | 
			
		||||
  char *key;
 | 
			
		||||
  guint mask = 0;
 | 
			
		||||
  guint keycode = 0;
 | 
			
		||||
  MetaResolvedKeyCombo resolved_combo;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (action != META_KEYBINDING_ACTION_NONE, FALSE);
 | 
			
		||||
 | 
			
		||||
@@ -1494,21 +1448,16 @@ meta_display_ungrab_accelerator (MetaDisplay *display,
 | 
			
		||||
  if (!grab)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  devirtualize_modifiers (keys, grab->combo->modifiers, &mask);
 | 
			
		||||
  keycode = get_first_keycode_for_keysym (keys, grab->combo->keysym);
 | 
			
		||||
 | 
			
		||||
  binding = get_keybinding (keys, keycode, mask);
 | 
			
		||||
  resolve_key_combo (keys, &grab->combo, &resolved_combo);
 | 
			
		||||
  binding = get_keybinding (keys, &resolved_combo);
 | 
			
		||||
  if (binding)
 | 
			
		||||
    {
 | 
			
		||||
      guint32 index_key;
 | 
			
		||||
 | 
			
		||||
      if (META_IS_BACKEND_X11 (backend))
 | 
			
		||||
        meta_change_keygrab (keys, display->screen->xroot, FALSE,
 | 
			
		||||
                             binding->keysym,
 | 
			
		||||
                             binding->keycode,
 | 
			
		||||
                             binding->mask);
 | 
			
		||||
        meta_change_keygrab (keys, display->screen->xroot, FALSE, &binding->resolved_combo);
 | 
			
		||||
 | 
			
		||||
      index_key = key_binding_key (binding->keycode, binding->mask);
 | 
			
		||||
      index_key = key_combo_key (&binding->resolved_combo);
 | 
			
		||||
      g_hash_table_remove (keys->key_bindings_index, GINT_TO_POINTER (index_key));
 | 
			
		||||
 | 
			
		||||
      g_hash_table_remove (keys->key_bindings, binding);
 | 
			
		||||
@@ -1627,13 +1576,14 @@ meta_window_ungrab_all_keys (MetaWindow *window, guint32 timestamp)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_display_freeze_keyboard (MetaDisplay *display, Window window, guint32 timestamp)
 | 
			
		||||
meta_display_freeze_keyboard (MetaDisplay *display, guint32 timestamp)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackend *backend = meta_get_backend ();
 | 
			
		||||
 | 
			
		||||
  if (!META_IS_BACKEND_X11 (backend))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  Window window = meta_backend_x11_get_xwindow (META_BACKEND_X11 (backend));
 | 
			
		||||
  grab_keyboard (window, timestamp, XIGrabModeSync);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1723,15 +1673,19 @@ process_event (MetaDisplay          *display,
 | 
			
		||||
               ClutterKeyEvent      *event)
 | 
			
		||||
{
 | 
			
		||||
  MetaKeyBindingManager *keys = &display->key_binding_manager;
 | 
			
		||||
  MetaResolvedKeyCombo resolved_combo;
 | 
			
		||||
  MetaKeyBinding *binding;
 | 
			
		||||
 | 
			
		||||
  /* we used to have release-based bindings but no longer. */
 | 
			
		||||
  if (event->type == CLUTTER_KEY_RELEASE)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  binding = get_keybinding (keys,
 | 
			
		||||
                            event->hardware_keycode,
 | 
			
		||||
                            event->modifier_state);
 | 
			
		||||
  resolved_combo_from_event_params (&resolved_combo, keys,
 | 
			
		||||
                                    event->hardware_keycode,
 | 
			
		||||
                                    event->modifier_state);
 | 
			
		||||
 | 
			
		||||
  binding = get_keybinding (keys, &resolved_combo);
 | 
			
		||||
 | 
			
		||||
  if (!binding ||
 | 
			
		||||
      (!window && binding->flags & META_KEY_BINDING_PER_WINDOW))
 | 
			
		||||
    goto not_found;
 | 
			
		||||
@@ -1782,7 +1736,7 @@ process_overlay_key (MetaDisplay *display,
 | 
			
		||||
 | 
			
		||||
  if (keys->overlay_key_only_pressed)
 | 
			
		||||
    {
 | 
			
		||||
      if (event->hardware_keycode != (int)keys->overlay_key_combo.keycode)
 | 
			
		||||
      if (event->hardware_keycode != (int)keys->overlay_resolved_key_combo.keycode)
 | 
			
		||||
        {
 | 
			
		||||
          keys->overlay_key_only_pressed = FALSE;
 | 
			
		||||
 | 
			
		||||
@@ -1835,7 +1789,7 @@ process_overlay_key (MetaDisplay *display,
 | 
			
		||||
                           clutter_input_device_get_device_id (event->device),
 | 
			
		||||
                           XIAsyncDevice, event->time);
 | 
			
		||||
 | 
			
		||||
          binding = get_keybinding (keys, keys->overlay_key_combo.keycode, 0);
 | 
			
		||||
          binding = get_keybinding (keys, &keys->overlay_resolved_key_combo);
 | 
			
		||||
          if (binding &&
 | 
			
		||||
              meta_compositor_filter_keybinding (display->compositor, binding))
 | 
			
		||||
            return TRUE;
 | 
			
		||||
@@ -1864,7 +1818,7 @@ process_overlay_key (MetaDisplay *display,
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
  else if (event->type == CLUTTER_KEY_PRESS &&
 | 
			
		||||
           event->hardware_keycode == (int)keys->overlay_key_combo.keycode)
 | 
			
		||||
           event->hardware_keycode == (int)keys->overlay_resolved_key_combo.keycode)
 | 
			
		||||
    {
 | 
			
		||||
      keys->overlay_key_only_pressed = TRUE;
 | 
			
		||||
      /* We keep the keyboard frozen - this allows us to use ReplayKeyboard
 | 
			
		||||
@@ -1887,8 +1841,7 @@ process_iso_next_group (MetaDisplay *display,
 | 
			
		||||
{
 | 
			
		||||
  MetaKeyBindingManager *keys = &display->key_binding_manager;
 | 
			
		||||
  gboolean activate;
 | 
			
		||||
  guint32 keycode;
 | 
			
		||||
  guint32 modifiers;
 | 
			
		||||
  MetaResolvedKeyCombo resolved_combo;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  if (event->type == CLUTTER_KEY_RELEASE)
 | 
			
		||||
@@ -1896,13 +1849,14 @@ process_iso_next_group (MetaDisplay *display,
 | 
			
		||||
 | 
			
		||||
  activate = FALSE;
 | 
			
		||||
 | 
			
		||||
  keycode = event->hardware_keycode;
 | 
			
		||||
  modifiers = event->modifier_state & 0xff & ~keys->ignored_modifier_mask;
 | 
			
		||||
  resolved_combo_from_event_params (&resolved_combo, keys,
 | 
			
		||||
                                    event->hardware_keycode,
 | 
			
		||||
                                    event->modifier_state);
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < keys->n_iso_next_group_combos; ++i)
 | 
			
		||||
    {
 | 
			
		||||
      if (keycode == keys->iso_next_group_combos[i].keycode &&
 | 
			
		||||
          modifiers == keys->iso_next_group_combos[i].modifiers)
 | 
			
		||||
      if (resolved_combo.keycode == keys->iso_next_group_combos[i].keycode &&
 | 
			
		||||
          resolved_combo.mask == keys->iso_next_group_combos[i].mask)
 | 
			
		||||
        {
 | 
			
		||||
          /* If the signal handler returns TRUE the keyboard will
 | 
			
		||||
             remain frozen. It's the signal handler's responsibility
 | 
			
		||||
@@ -2922,10 +2876,6 @@ do_choose_window (MetaDisplay     *display,
 | 
			
		||||
  meta_topic (META_DEBUG_KEYBINDINGS,
 | 
			
		||||
              "Tab list = %u\n", type);
 | 
			
		||||
 | 
			
		||||
  /* reverse direction if shift is down */
 | 
			
		||||
  if (event->modifier_state & CLUTTER_SHIFT_MASK)
 | 
			
		||||
    backward = !backward;
 | 
			
		||||
 | 
			
		||||
  window = meta_display_get_tab_next (display,
 | 
			
		||||
                                      type,
 | 
			
		||||
                                      screen->active_workspace,
 | 
			
		||||
@@ -3686,6 +3636,41 @@ init_builtin_key_bindings (MetaDisplay *display)
 | 
			
		||||
                              META_KEY_BINDING_NONE,
 | 
			
		||||
                              META_KEYBINDING_ACTION_NONE,
 | 
			
		||||
                              handle_switch_vt, 7);
 | 
			
		||||
 | 
			
		||||
      add_builtin_keybinding (display,
 | 
			
		||||
                              "switch-to-session-8",
 | 
			
		||||
                              mutter_wayland_keybindings,
 | 
			
		||||
                              META_KEY_BINDING_NONE,
 | 
			
		||||
                              META_KEYBINDING_ACTION_NONE,
 | 
			
		||||
                              handle_switch_vt, 8);
 | 
			
		||||
 | 
			
		||||
      add_builtin_keybinding (display,
 | 
			
		||||
                              "switch-to-session-9",
 | 
			
		||||
                              mutter_wayland_keybindings,
 | 
			
		||||
                              META_KEY_BINDING_NONE,
 | 
			
		||||
                              META_KEYBINDING_ACTION_NONE,
 | 
			
		||||
                              handle_switch_vt, 9);
 | 
			
		||||
 | 
			
		||||
      add_builtin_keybinding (display,
 | 
			
		||||
                              "switch-to-session-10",
 | 
			
		||||
                              mutter_wayland_keybindings,
 | 
			
		||||
                              META_KEY_BINDING_NONE,
 | 
			
		||||
                              META_KEYBINDING_ACTION_NONE,
 | 
			
		||||
                              handle_switch_vt, 10);
 | 
			
		||||
 | 
			
		||||
      add_builtin_keybinding (display,
 | 
			
		||||
                              "switch-to-session-11",
 | 
			
		||||
                              mutter_wayland_keybindings,
 | 
			
		||||
                              META_KEY_BINDING_NONE,
 | 
			
		||||
                              META_KEYBINDING_ACTION_NONE,
 | 
			
		||||
                              handle_switch_vt, 11);
 | 
			
		||||
 | 
			
		||||
      add_builtin_keybinding (display,
 | 
			
		||||
                              "switch-to-session-12",
 | 
			
		||||
                              mutter_wayland_keybindings,
 | 
			
		||||
                              META_KEY_BINDING_NONE,
 | 
			
		||||
                              META_KEYBINDING_ACTION_NONE,
 | 
			
		||||
                              handle_switch_vt, 12);
 | 
			
		||||
    }
 | 
			
		||||
#endif /* HAVE_NATIVE_BACKEND */
 | 
			
		||||
 | 
			
		||||
@@ -4062,7 +4047,7 @@ meta_display_init_keys (MetaDisplay *display)
 | 
			
		||||
  keys->super_mask = 0;
 | 
			
		||||
  keys->meta_mask = 0;
 | 
			
		||||
 | 
			
		||||
  keys->key_bindings = g_hash_table_new_full (NULL, NULL, NULL, g_free);
 | 
			
		||||
  keys->key_bindings = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) meta_key_binding_free);
 | 
			
		||||
  keys->key_bindings_index = g_hash_table_new (NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  reload_modmap (keys);
 | 
			
		||||
@@ -4098,9 +4083,7 @@ meta_display_init_keys (MetaDisplay *display)
 | 
			
		||||
  rebuild_key_binding_table (keys);
 | 
			
		||||
  rebuild_special_bindings (keys);
 | 
			
		||||
 | 
			
		||||
  reload_keycodes (keys);
 | 
			
		||||
  reload_modifiers (keys);
 | 
			
		||||
  rebuild_binding_index (keys);
 | 
			
		||||
  reload_combos (keys);
 | 
			
		||||
 | 
			
		||||
  update_window_grab_modifiers (keys);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -431,42 +431,6 @@ meta_run (void)
 | 
			
		||||
  meta_prefs_init ();
 | 
			
		||||
  meta_prefs_add_listener (prefs_changed_callback, NULL);
 | 
			
		||||
 | 
			
		||||
  meta_ui_set_current_theme (meta_prefs_get_theme ());
 | 
			
		||||
 | 
			
		||||
  /* Try to find some theme that'll work if the theme preference
 | 
			
		||||
   * doesn't exist.  First try Simple (the default theme) then just
 | 
			
		||||
   * try anything in the themes directory.
 | 
			
		||||
   */
 | 
			
		||||
  if (!meta_ui_have_a_theme ())
 | 
			
		||||
    meta_ui_set_current_theme ("Simple");
 | 
			
		||||
 | 
			
		||||
  if (!meta_ui_have_a_theme ())
 | 
			
		||||
    {
 | 
			
		||||
      const char *dir_entry = NULL;
 | 
			
		||||
      GError *err = NULL;
 | 
			
		||||
      GDir   *themes_dir = NULL;
 | 
			
		||||
 | 
			
		||||
      if (!(themes_dir = g_dir_open (MUTTER_DATADIR"/themes", 0, &err)))
 | 
			
		||||
        {
 | 
			
		||||
          meta_fatal (_("Failed to scan themes directory: %s\n"), err->message);
 | 
			
		||||
          g_error_free (err);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          while (((dir_entry = g_dir_read_name (themes_dir)) != NULL) &&
 | 
			
		||||
                 (!meta_ui_have_a_theme ()))
 | 
			
		||||
            {
 | 
			
		||||
              meta_ui_set_current_theme (dir_entry);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          g_dir_close (themes_dir);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!meta_ui_have_a_theme ())
 | 
			
		||||
    meta_fatal (_("Could not find a theme! Be sure %s exists and contains the usual themes.\n"),
 | 
			
		||||
                MUTTER_DATADIR"/themes");
 | 
			
		||||
 | 
			
		||||
  if (!meta_display_open ())
 | 
			
		||||
    meta_exit (META_EXIT_ERROR);
 | 
			
		||||
 | 
			
		||||
@@ -513,9 +477,7 @@ prefs_changed_callback (MetaPreference pref,
 | 
			
		||||
{
 | 
			
		||||
  switch (pref)
 | 
			
		||||
    {
 | 
			
		||||
    case META_PREF_THEME:
 | 
			
		||||
    case META_PREF_DRAGGABLE_BORDER_WIDTH:
 | 
			
		||||
      meta_ui_set_current_theme (meta_prefs_get_theme ());
 | 
			
		||||
      meta_display_retheme_all ();
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,7 @@
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-accel-parse.h"
 | 
			
		||||
#include "keybindings-private.h"
 | 
			
		||||
 | 
			
		||||
#include <xkbcommon/xkbcommon.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
@@ -173,21 +174,16 @@ is_keycode (const gchar *string)
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
accelerator_parse (const gchar         *accelerator,
 | 
			
		||||
                   guint               *accelerator_key,
 | 
			
		||||
                   guint               *accelerator_keycode,
 | 
			
		||||
                   MetaVirtualModifier *accelerator_mods)
 | 
			
		||||
                   MetaKeyCombo        *combo)
 | 
			
		||||
{
 | 
			
		||||
  gboolean error = FALSE;
 | 
			
		||||
  guint keyval, keycode;
 | 
			
		||||
  MetaVirtualModifier mods;
 | 
			
		||||
  gint len;
 | 
			
		||||
 | 
			
		||||
  if (accelerator_key)
 | 
			
		||||
    *accelerator_key = 0;
 | 
			
		||||
  if (accelerator_keycode)
 | 
			
		||||
    *accelerator_keycode = 0;
 | 
			
		||||
  if (accelerator_mods)
 | 
			
		||||
    *accelerator_mods = 0;
 | 
			
		||||
  combo->keysym = 0;
 | 
			
		||||
  combo->keycode = 0;
 | 
			
		||||
  combo->modifiers = 0;
 | 
			
		||||
 | 
			
		||||
  if (accelerator == NULL)
 | 
			
		||||
    {
 | 
			
		||||
@@ -330,34 +326,35 @@ out:
 | 
			
		||||
  if (error)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (accelerator_key)
 | 
			
		||||
    *accelerator_key = keyval;
 | 
			
		||||
  if (accelerator_keycode)
 | 
			
		||||
    *accelerator_keycode = keycode;
 | 
			
		||||
  if (accelerator_mods)
 | 
			
		||||
    *accelerator_mods = mods;
 | 
			
		||||
  combo->keysym = keyval;
 | 
			
		||||
  combo->keycode = keycode;
 | 
			
		||||
  combo->modifiers = mods;
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_parse_accelerator (const char          *accel,
 | 
			
		||||
                        unsigned int        *keysym,
 | 
			
		||||
                        unsigned int        *keycode,
 | 
			
		||||
                        MetaVirtualModifier *mask)
 | 
			
		||||
meta_parse_accelerator (const char   *accel,
 | 
			
		||||
                        MetaKeyCombo *combo)
 | 
			
		||||
{
 | 
			
		||||
  if (!accel[0] || strcmp (accel, "disabled") == 0)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  return accelerator_parse (accel, keysym, keycode, mask);
 | 
			
		||||
  return accelerator_parse (accel, combo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_parse_modifier (const char          *accel,
 | 
			
		||||
                     MetaVirtualModifier *mask)
 | 
			
		||||
{
 | 
			
		||||
  MetaKeyCombo combo;
 | 
			
		||||
 | 
			
		||||
  if (accel == NULL || !accel[0] || strcmp (accel, "disabled") == 0)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  return accelerator_parse (accel, NULL, NULL, mask);
 | 
			
		||||
  if (!accelerator_parse (accel, &combo))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  *mask = combo.modifiers;
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user