Compare commits
	
		
			364 Commits
		
	
	
		
			3.16.3
			...
			wip/garnac
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					9f35b5816a | ||
| 
						 | 
					63c91f9d4f | ||
| 
						 | 
					aaa02440be | ||
| 
						 | 
					9611661154 | ||
| 
						 | 
					a70a2c3744 | ||
| 
						 | 
					bc47b19c3f | ||
| 
						 | 
					bc1dd1cee4 | ||
| 
						 | 
					495c89401a | ||
| 
						 | 
					e2efc85b08 | ||
| 
						 | 
					020ae58fe4 | ||
| 
						 | 
					525644059d | ||
| 
						 | 
					f0f638d2bd | ||
| 
						 | 
					bc8ec2d90d | ||
| 
						 | 
					5b0eabec51 | ||
| 
						 | 
					50099c4c10 | ||
| 
						 | 
					55eef2deb3 | ||
| 
						 | 
					f9db65f47f | ||
| 
						 | 
					a809055470 | ||
| 
						 | 
					247909e161 | ||
| 
						 | 
					e5ce6192f4 | ||
| 
						 | 
					7adbb58736 | ||
| 
						 | 
					0165cb6974 | ||
| 
						 | 
					3cdcd3e9c1 | ||
| 
						 | 
					6fc51e3723 | ||
| 
						 | 
					af45a50cb1 | ||
| 
						 | 
					72d6efc0d5 | ||
| 
						 | 
					e0ffef06dd | ||
| 
						 | 
					d5b69bcd54 | ||
| 
						 | 
					ac8fe2d9b2 | ||
| 
						 | 
					e7a88dc6b2 | ||
| 
						 | 
					bcdda506e1 | ||
| 
						 | 
					9b26694bbc | ||
| 
						 | 
					f053c09083 | ||
| 
						 | 
					ec9abaf1ef | ||
| 
						 | 
					6b88420465 | ||
| 
						 | 
					fc0a834abb | ||
| 
						 | 
					e30010b9f0 | ||
| 
						 | 
					935d76ba04 | ||
| 
						 | 
					cc013e1daa | ||
| 
						 | 
					a7a376ae1f | ||
| 
						 | 
					5e57af6286 | ||
| 
						 | 
					42b3a34f7b | ||
| 
						 | 
					19d814c887 | ||
| 
						 | 
					46eb682c83 | ||
| 
						 | 
					3aea8d8ce6 | ||
| 
						 | 
					40c3c69435 | ||
| 
						 | 
					8071e5b149 | ||
| 
						 | 
					8a481b3e10 | ||
| 
						 | 
					50e3e3b929 | ||
| 
						 | 
					2c7ef2269f | ||
| 
						 | 
					8bded7d497 | ||
| 
						 | 
					9ebe3419c3 | ||
| 
						 | 
					9385c835b8 | ||
| 
						 | 
					efef0c993b | ||
| 
						 | 
					3a2cd3389a | ||
| 
						 | 
					88acfb8e60 | ||
| 
						 | 
					8e22dce5d7 | ||
| 
						 | 
					e0906a77aa | ||
| 
						 | 
					053f5088df | ||
| 
						 | 
					75b992c7d0 | ||
| 
						 | 
					213f0fa160 | ||
| 
						 | 
					5054b2a99c | ||
| 
						 | 
					d455de32a0 | ||
| 
						 | 
					e7390cff83 | ||
| 
						 | 
					49ea6486e2 | ||
| 
						 | 
					996aeaef41 | ||
| 
						 | 
					a27b2597b9 | ||
| 
						 | 
					0e8ca1a042 | ||
| 
						 | 
					f5f26c9cff | ||
| 
						 | 
					91ac69382d | ||
| 
						 | 
					8cc345fcf5 | ||
| 
						 | 
					96b5042dda | ||
| 
						 | 
					428c687b5a | ||
| 
						 | 
					82bdd1e353 | ||
| 
						 | 
					4bebc5e5fa | ||
| 
						 | 
					be5643cee7 | ||
| 
						 | 
					2ee1c5fa61 | ||
| 
						 | 
					c625d2ee9d | ||
| 
						 | 
					3078f70f90 | ||
| 
						 | 
					7309b20c25 | ||
| 
						 | 
					c16a5ec1cf | ||
| 
						 | 
					f3e1964362 | ||
| 
						 | 
					9b9083180f | ||
| 
						 | 
					7606f79a1e | ||
| 
						 | 
					99c0b82b15 | ||
| 
						 | 
					ca7c1d5e02 | ||
| 
						 | 
					4a770907c1 | ||
| 
						 | 
					049f1556dc | ||
| 
						 | 
					7b20d151ed | ||
| 
						 | 
					8ec0c99ff4 | ||
| 
						 | 
					cf3ee327a0 | ||
| 
						 | 
					3ec3cc248d | ||
| 
						 | 
					7fb3ecc12c | ||
| 
						 | 
					4c9af7267d | ||
| 
						 | 
					db4355ba1e | ||
| 
						 | 
					33150569cd | ||
| 
						 | 
					af2a13ded4 | ||
| 
						 | 
					8b200de35a | ||
| 
						 | 
					57ae203aab | ||
| 
						 | 
					bff75b64be | ||
| 
						 | 
					8899b9da01 | ||
| 
						 | 
					76e816a14f | ||
| 
						 | 
					2750db2a89 | ||
| 
						 | 
					86a913d37a | ||
| 
						 | 
					2857fdbdb8 | ||
| 
						 | 
					69a7d5ff02 | ||
| 
						 | 
					a4f763ac3b | ||
| 
						 | 
					f2afa7aa6c | ||
| 
						 | 
					a5d2555196 | ||
| 
						 | 
					dd5a4ecdf9 | ||
| 
						 | 
					43a1d43f2b | ||
| 
						 | 
					d6d377a447 | ||
| 
						 | 
					ffd95c2ad5 | ||
| 
						 | 
					72be89dfb9 | ||
| 
						 | 
					2feeb57dee | ||
| 
						 | 
					9c81b718f9 | ||
| 
						 | 
					3a63d58d9e | ||
| 
						 | 
					a95ae4d178 | ||
| 
						 | 
					a692fd3808 | ||
| 
						 | 
					377ecdb864 | ||
| 
						 | 
					d7f544f42e | ||
| 
						 | 
					1ab8b854df | ||
| 
						 | 
					ae7aabd5de | ||
| 
						 | 
					b975676c5d | ||
| 
						 | 
					86d8c3954f | ||
| 
						 | 
					54557f062e | ||
| 
						 | 
					130807a308 | ||
| 
						 | 
					e84f694668 | ||
| 
						 | 
					b18542f2b6 | ||
| 
						 | 
					da0aac665f | ||
| 
						 | 
					8b0b0cf028 | ||
| 
						 | 
					6f64d6b0aa | ||
| 
						 | 
					ebeca983c7 | ||
| 
						 | 
					cf88675807 | ||
| 
						 | 
					405f1ce3d0 | ||
| 
						 | 
					6190ae3873 | ||
| 
						 | 
					69c267b142 | ||
| 
						 | 
					9abc071283 | ||
| 
						 | 
					a9df4bb81a | ||
| 
						 | 
					bc9e63d3db | ||
| 
						 | 
					5b5ceede2b | ||
| 
						 | 
					4e63c95c02 | ||
| 
						 | 
					67d3a7a2d7 | ||
| 
						 | 
					bc00f118f3 | ||
| 
						 | 
					5801b5518f | ||
| 
						 | 
					25a796afc6 | ||
| 
						 | 
					27b37407d0 | ||
| 
						 | 
					e23e697043 | ||
| 
						 | 
					35729e8659 | ||
| 
						 | 
					dc7e665de9 | ||
| 
						 | 
					2e3bfd1a11 | ||
| 
						 | 
					b7aca07844 | ||
| 
						 | 
					dc780d2c44 | ||
| 
						 | 
					c49b284643 | ||
| 
						 | 
					0373b854c1 | ||
| 
						 | 
					5d837a5c85 | ||
| 
						 | 
					79c86ae890 | ||
| 
						 | 
					7c7cf91c32 | ||
| 
						 | 
					e407f5bbae | ||
| 
						 | 
					8900bd2f5c | ||
| 
						 | 
					83c17134f1 | ||
| 
						 | 
					8e5fb03611 | ||
| 
						 | 
					dece49b53d | ||
| 
						 | 
					443d579d40 | ||
| 
						 | 
					5066eaf691 | ||
| 
						 | 
					6ea7fa9973 | ||
| 
						 | 
					79f755bf0f | ||
| 
						 | 
					1845bfe1b6 | ||
| 
						 | 
					8e22bf5bc9 | ||
| 
						 | 
					c13ddafdb8 | ||
| 
						 | 
					94513726de | ||
| 
						 | 
					0aa4c4d43e | ||
| 
						 | 
					e3db4ab16a | ||
| 
						 | 
					614d6bd0f8 | ||
| 
						 | 
					1d56d50fcd | ||
| 
						 | 
					0ffd4254d9 | ||
| 
						 | 
					36eee04a21 | ||
| 
						 | 
					d3fdaa3232 | ||
| 
						 | 
					165050f8f9 | ||
| 
						 | 
					68279e8a08 | ||
| 
						 | 
					cd1ce2cb0a | ||
| 
						 | 
					b01f95cfdd | ||
| 
						 | 
					4b667d1e09 | ||
| 
						 | 
					fe8454d13f | ||
| 
						 | 
					53a6d16891 | ||
| 
						 | 
					e76c3ecb00 | ||
| 
						 | 
					637be80c86 | ||
| 
						 | 
					975feb9202 | ||
| 
						 | 
					a5417ebee1 | ||
| 
						 | 
					b64b159109 | ||
| 
						 | 
					804ab7894f | ||
| 
						 | 
					299ed424d3 | ||
| 
						 | 
					55692b4019 | ||
| 
						 | 
					2fafa24305 | ||
| 
						 | 
					51a2f28723 | ||
| 
						 | 
					e11feb229b | ||
| 
						 | 
					1ee387bb31 | ||
| 
						 | 
					cba2ab445e | ||
| 
						 | 
					038f828ab1 | ||
| 
						 | 
					4dc5882777 | ||
| 
						 | 
					b0b08d5010 | ||
| 
						 | 
					070cd27786 | ||
| 
						 | 
					9df6cda3e3 | ||
| 
						 | 
					39763d4add | ||
| 
						 | 
					352cac3850 | ||
| 
						 | 
					9c745105f8 | ||
| 
						 | 
					ab9dabe725 | ||
| 
						 | 
					7ce06928e2 | ||
| 
						 | 
					ac79988939 | ||
| 
						 | 
					a43a2af18b | ||
| 
						 | 
					07f533f617 | ||
| 
						 | 
					10504b0fdc | ||
| 
						 | 
					a84f714808 | ||
| 
						 | 
					b41873dced | ||
| 
						 | 
					0a9511b24b | ||
| 
						 | 
					17438ced91 | ||
| 
						 | 
					27c7512e4d | ||
| 
						 | 
					124888764d | ||
| 
						 | 
					7e1c6ff2a2 | ||
| 
						 | 
					2fb8da0d5a | ||
| 
						 | 
					ad51c52b69 | ||
| 
						 | 
					1b22da0039 | ||
| 
						 | 
					8329e97502 | ||
| 
						 | 
					74ca936a00 | ||
| 
						 | 
					141760057b | ||
| 
						 | 
					e648f2c244 | ||
| 
						 | 
					f01247d815 | ||
| 
						 | 
					db6caa2c49 | ||
| 
						 | 
					fbd237bc66 | ||
| 
						 | 
					f6c9261bf6 | ||
| 
						 | 
					14b0a83f64 | ||
| 
						 | 
					441efd17ce | ||
| 
						 | 
					208da2316d | ||
| 
						 | 
					3b993131e8 | ||
| 
						 | 
					117f57f74c | ||
| 
						 | 
					b97ebc4124 | ||
| 
						 | 
					5d10196919 | ||
| 
						 | 
					f295349e26 | ||
| 
						 | 
					eb023ff2c9 | ||
| 
						 | 
					ba7c524a18 | ||
| 
						 | 
					dc99af40f3 | ||
| 
						 | 
					1576b7d5a6 | ||
| 
						 | 
					6ec7fa2cbd | ||
| 
						 | 
					bede9970de | ||
| 
						 | 
					5f1bcc124f | ||
| 
						 | 
					4d3419607a | ||
| 
						 | 
					7dc0b0e602 | ||
| 
						 | 
					1545d4e638 | ||
| 
						 | 
					a191554cf6 | ||
| 
						 | 
					b33a82eb7c | ||
| 
						 | 
					2705c87f74 | ||
| 
						 | 
					9fc1c919e8 | ||
| 
						 | 
					9f04c58ffe | ||
| 
						 | 
					7de1f3a7be | ||
| 
						 | 
					fd443ecf2a | ||
| 
						 | 
					8979e52a6c | ||
| 
						 | 
					e8dd5601e7 | ||
| 
						 | 
					ccca810daf | ||
| 
						 | 
					693456b644 | ||
| 
						 | 
					aacc3d5628 | ||
| 
						 | 
					1ea8efdeda | ||
| 
						 | 
					a3fbbaabe8 | ||
| 
						 | 
					d5d95b2834 | ||
| 
						 | 
					659b8ed471 | ||
| 
						 | 
					94bce5a00f | ||
| 
						 | 
					91b7dedf36 | ||
| 
						 | 
					aa1c819941 | ||
| 
						 | 
					be7e994abd | ||
| 
						 | 
					6c05eb583e | ||
| 
						 | 
					5547c98f97 | ||
| 
						 | 
					ea4979e182 | ||
| 
						 | 
					8da5761ffc | ||
| 
						 | 
					aea71fbd01 | ||
| 
						 | 
					b55f792302 | ||
| 
						 | 
					dd060d78ce | ||
| 
						 | 
					3fe281ada9 | ||
| 
						 | 
					f041b35b9b | ||
| 
						 | 
					afa58746ea | ||
| 
						 | 
					6dbec6f81b | ||
| 
						 | 
					2cbaa6660c | ||
| 
						 | 
					d74b0d5be8 | ||
| 
						 | 
					6b82f61dba | ||
| 
						 | 
					4c6866741d | ||
| 
						 | 
					84baf4e181 | ||
| 
						 | 
					3962f1d982 | ||
| 
						 | 
					414be07a69 | ||
| 
						 | 
					7f3ada7831 | ||
| 
						 | 
					12771a555a | ||
| 
						 | 
					92d6a69153 | ||
| 
						 | 
					734402e14d | ||
| 
						 | 
					5d360a9bce | ||
| 
						 | 
					f8cf5e373c | ||
| 
						 | 
					8df3fa4e67 | ||
| 
						 | 
					bbf2b4e60e | ||
| 
						 | 
					bb4dcd62ec | ||
| 
						 | 
					2345b9c6ad | ||
| 
						 | 
					af7cc87bfa | ||
| 
						 | 
					af3b599cbb | ||
| 
						 | 
					0e73ceb4bd | ||
| 
						 | 
					82a7060cdb | ||
| 
						 | 
					09120132ef | ||
| 
						 | 
					cdac4d0e92 | ||
| 
						 | 
					6aead0c67c | ||
| 
						 | 
					d593a61b39 | ||
| 
						 | 
					9747277b7e | ||
| 
						 | 
					989f9630a4 | ||
| 
						 | 
					daa15d94fd | ||
| 
						 | 
					999b99a077 | ||
| 
						 | 
					fd0b366a96 | ||
| 
						 | 
					320e2d452f | ||
| 
						 | 
					4d5dd01b7d | ||
| 
						 | 
					103c88bd72 | ||
| 
						 | 
					64cf87cfe1 | ||
| 
						 | 
					9f65edd4f5 | ||
| 
						 | 
					ea2496c80a | ||
| 
						 | 
					0c30ceddbe | ||
| 
						 | 
					5c9846c53a | ||
| 
						 | 
					2a8563ab23 | ||
| 
						 | 
					6a77d9722a | ||
| 
						 | 
					ef296031cb | ||
| 
						 | 
					e2d6028924 | ||
| 
						 | 
					4d80a4cc31 | ||
| 
						 | 
					4a968c3b4e | ||
| 
						 | 
					ccb7833e99 | ||
| 
						 | 
					b449ba942a | ||
| 
						 | 
					f53eea2c1c | ||
| 
						 | 
					b62db404ee | ||
| 
						 | 
					90a28e7b1c | ||
| 
						 | 
					8d51a9db5b | ||
| 
						 | 
					b39c00f344 | ||
| 
						 | 
					83ce71c3bf | ||
| 
						 | 
					f9d869a3dd | ||
| 
						 | 
					0b0ce4193f | ||
| 
						 | 
					719d8bd0c7 | ||
| 
						 | 
					4fc1811c15 | ||
| 
						 | 
					4b5f5abb4f | ||
| 
						 | 
					95ad52ba58 | ||
| 
						 | 
					dac30a222e | ||
| 
						 | 
					7d1b593fbd | ||
| 
						 | 
					d6a7559750 | ||
| 
						 | 
					cff5ef0ec2 | ||
| 
						 | 
					d478d8f143 | ||
| 
						 | 
					7eca43cec9 | ||
| 
						 | 
					9060190555 | ||
| 
						 | 
					0de3869656 | ||
| 
						 | 
					9f13033f15 | ||
| 
						 | 
					48bf807430 | ||
| 
						 | 
					c68e43a97f | ||
| 
						 | 
					cc53d48fa8 | ||
| 
						 | 
					ca6e799b97 | ||
| 
						 | 
					0f8e387dc0 | ||
| 
						 | 
					d62c595e51 | ||
| 
						 | 
					dd3cf94744 | ||
| 
						 | 
					eb56e0a3d7 | ||
| 
						 | 
					8937c32cd5 | ||
| 
						 | 
					a8a5da768a | ||
| 
						 | 
					33bfcf56ce | ||
| 
						 | 
					40cccb58a5 | ||
| 
						 | 
					eb6c70137b | ||
| 
						 | 
					df3b412a25 | ||
| 
						 | 
					cfba0a5dfc | ||
| 
						 | 
					3561b46fc6 | ||
| 
						 | 
					8dfb88b669 | ||
| 
						 | 
					2e3086e2aa | 
							
								
								
									
										18
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -57,19 +57,21 @@ testgradient
 | 
			
		||||
m4/*
 | 
			
		||||
INSTALL
 | 
			
		||||
mkinstalldirs
 | 
			
		||||
src/mutter-enum-types.[ch]
 | 
			
		||||
src/stamp-mutter-enum-types.h
 | 
			
		||||
src/mutter-marshal.[ch]
 | 
			
		||||
src/stamp-mutter-marshal.h
 | 
			
		||||
meta-enum-types.[ch]
 | 
			
		||||
src/stamp-meta-enum-types.h
 | 
			
		||||
src/meta-dbus-display-config.[ch]
 | 
			
		||||
src/meta-dbus-idle-monitor.[ch]
 | 
			
		||||
src/meta-dbus-login1.[ch]
 | 
			
		||||
src/gtk-shell-protocol.c
 | 
			
		||||
src/gtk-shell-server-protocol.h
 | 
			
		||||
src/xdg-shell-protocol.c
 | 
			
		||||
src/xdg-shell-server-protocol.h
 | 
			
		||||
src/xserver-protocol.c
 | 
			
		||||
src/xserver-server-protocol.h
 | 
			
		||||
src/xdg-shell-unstable-v*-protocol.c
 | 
			
		||||
src/xdg-shell-unstable-v*-server-protocol.h
 | 
			
		||||
src/pointer-gestures-unstable-v*-protocol.c
 | 
			
		||||
src/pointer-gestures-unstable-v*-server-protocol.h
 | 
			
		||||
src/relative-pointer-unstable-v*-protocol.c
 | 
			
		||||
src/relative-pointer-unstable-v*-server-protocol.h
 | 
			
		||||
src/pointer-constraints-unstable-v*-protocol.c
 | 
			
		||||
src/pointer-constraints-unstable-v*-server-protocol.h
 | 
			
		||||
src/meta/meta-version.h
 | 
			
		||||
doc/reference/*.args
 | 
			
		||||
doc/reference/*.bak
 | 
			
		||||
 
 | 
			
		||||
@@ -9,5 +9,3 @@ DISTCLEANFILES = \
 | 
			
		||||
	intltool-update \
 | 
			
		||||
	po/stamp-it \
 | 
			
		||||
	po/.intltool-merge-cache
 | 
			
		||||
 | 
			
		||||
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										176
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										176
									
								
								NEWS
									
									
									
									
									
								
							@@ -1,3 +1,179 @@
 | 
			
		||||
3.19.4
 | 
			
		||||
======
 | 
			
		||||
* Fix updating stacking order when setting transient_for [Jonas; #755606]
 | 
			
		||||
* Support screen rotation when supported by the driver [Carlos; #745079]
 | 
			
		||||
* Protect against broken WM_CLASS property implementations [Sebastian; #759658]
 | 
			
		||||
* Handle wl_pointer v5 events on wayland [Carlos; #760637]
 | 
			
		||||
* Implement DND actions on wayland [Carlos; #760805]
 | 
			
		||||
* Misc. bug fixes [Jonas, Rui, Ray, Marek; #754711, #756789, #759297, #758613,
 | 
			
		||||
  #760330, #760476, #759222, #760670]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Jonas Ådahl, Marek Chalupa, Carlos Garnacho, Sebastian Keller, Rui Matos,
 | 
			
		||||
  Florian Müllner, Jasper St. Pierre, Ray Strode
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
  Aurimas Černius [lt]
 | 
			
		||||
 | 
			
		||||
3.19.3
 | 
			
		||||
======
 | 
			
		||||
* Correct refresh rate units on KMS/Wayland [Daniel; #758653]
 | 
			
		||||
* Fix crash when initial cursor position is not on a monitor [Marek; #756698]
 | 
			
		||||
* Fix crash when more CRTs are enabled than outputs connected [Rui; #751638]
 | 
			
		||||
* Fix touch pointer emulation on wayland [Carlos; #756754]
 | 
			
		||||
* Allow minimizing windows that don't advertise supporting it [Jasper; #758186]
 | 
			
		||||
* Force 2-finger scroll by default if available [Bastien; #759304]
 | 
			
		||||
* Fix crash during XWayland initialization [Marek; #751845]
 | 
			
		||||
* Ensure to send a ConfigureNotify to just mapped windows [Rui; #759492]
 | 
			
		||||
* Misc. bug fixes and cleanups [Carlos, Jonas, Lionel; #758239, #758633,
 | 
			
		||||
  #755503, #759374]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Jonas Ådahl, Marek Chalupa, Carlos Garnacho, Lionel Landwerlin, Rui Matos,
 | 
			
		||||
  Bastien Nocera, Daniel Stone, Jasper St. Pierre
 | 
			
		||||
 | 
			
		||||
3.19.2
 | 
			
		||||
======
 | 
			
		||||
* Fix crash on monitor unplug [Rui; #756796]
 | 
			
		||||
* Exit cleanly on initialization errors [Owen; #757311]
 | 
			
		||||
* Allow to determine backend setting from session type [Ray; #741666]
 | 
			
		||||
* Fix DRM device detection for non-PCI devices [Alban; #754911]
 | 
			
		||||
* Don't force placement of windows without buffer on wayland [Marek; #751887]
 | 
			
		||||
* Fix initialization of bypass compositor hint [Rui; #758544]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Alban Browaeys, Marek Chalupa, Rui Matos, Florian Müllner, Ray Strode,
 | 
			
		||||
  Owen W. Taylor
 | 
			
		||||
 | 
			
		||||
3.19.1
 | 
			
		||||
======
 | 
			
		||||
* wayland: Allow to trigger popups through keyboard/touch [Carlos; #756296]
 | 
			
		||||
* Fix modifiers-only input source switching on Ubuntu [Alberts; #756543]
 | 
			
		||||
* Misc. bug fixes [Jonas, Rui, Giovanni, Florian; #756675, #756660, #746420,
 | 
			
		||||
  #756548, #756796, #757101, #757148]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Jonas Ådahl, Giovanni Campagna, Carlos Garnacho, Rui Matos,
 | 
			
		||||
  Alberts Muktupāvels, Florian Müllner
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
  Daniel Șerbănescu [ro]
 | 
			
		||||
 | 
			
		||||
3.18.1
 | 
			
		||||
======
 | 
			
		||||
* Misc. crash fixes [Jonas, Rui, Carlos, Owen, Florian; #755096, #754979,
 | 
			
		||||
  #755490, #754357, #745785, #756642]
 | 
			
		||||
* Improve HiDPI support on wayland [Jonas; #755097]
 | 
			
		||||
* Fix doubly-scaled cursor on XWayland HiDPI [Jonas; #755099]
 | 
			
		||||
* Stop hiding titlebar buttons in dialogs [Florian; #641630]
 | 
			
		||||
* Add support for fullscreen/unfullscreen animations [Cosimo; #707248]
 | 
			
		||||
* Misc. bug fixes [Rui, Colin, Florian; #743339, #752047, #756074, #756649]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Jonas Ådahl, Cosimo Cecchi, Carlos Garnacho, Rui Matos, Florian Müllner,
 | 
			
		||||
  Jasper St. Pierre, Colin Walters, Owen W. Taylor
 | 
			
		||||
 | 
			
		||||
3.18.0
 | 
			
		||||
======
 | 
			
		||||
* Misc. fixes [Florian, Jonas; #753434]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Jonas Ådahl, Florian Müllner
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
  Rūdolfs Mazurs [lv]
 | 
			
		||||
 | 
			
		||||
3.17.92
 | 
			
		||||
=======
 | 
			
		||||
* Don't omit the background color for backgrounds that don't fill the screen
 | 
			
		||||
  [Ray; #754476]
 | 
			
		||||
* Fix up key state on FocusIn when running nested [Owen; #753948]
 | 
			
		||||
* Find the right DRM device instead of hardcoding card0 [Marek; #753434]
 | 
			
		||||
* Scale cursor on HiDPI screens [Jonas; #744932]
 | 
			
		||||
* Misc. fixes and cleanups [Lan, Jonas, Javier, Olivier; #754545, #754215,
 | 
			
		||||
  #754621, #754715]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Jonas Ådahl, Marek Chalupa, Olivier Fourdan, Javier Jardón, Ting-Wei Lan,
 | 
			
		||||
  Ray Strode, Owen W. Taylor
 | 
			
		||||
 | 
			
		||||
3.17.91
 | 
			
		||||
=======
 | 
			
		||||
* Send error on pointer-gesture protocol version mismatch [Jonas; #753855]
 | 
			
		||||
* Misc. cleanups [Jonas; #744932]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Jonas Ådahl
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
  Chao-Hsiung Liao [zh_TW], Piotr Drąg [pl]
 | 
			
		||||
 | 
			
		||||
3.17.90
 | 
			
		||||
=======
 | 
			
		||||
* Fix glitch with some fullscreen apps [Rui; #753020]
 | 
			
		||||
* Fix screen update issue with NVidia driver [Aaron, Rui; #728464]
 | 
			
		||||
* Only call frame callbacks for surfaces that get drawn [Adel; #739163]
 | 
			
		||||
* Misc. bug fixes and cleanups [Jonas, Rui, Ting-Wei; #753222, #752753, #753237,
 | 
			
		||||
  #753380, #744104, #744932]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Jonas Ådahl, Adel Gadllah, Carlos Garnacho, Ting-Wei Lan, Rui Matos,
 | 
			
		||||
  Florian Müllner, Aaron Plattner, Jasper St. Pierre
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
  Akom Chotiphantawanon [th]
 | 
			
		||||
 | 
			
		||||
3.17.4
 | 
			
		||||
======
 | 
			
		||||
* nested: Allow basic configuration of dummy outputs [Jonas; #747089]
 | 
			
		||||
* Send wl_surface.enter and wl_surface.leave on output changes [Jonas; #744453]
 | 
			
		||||
* Improve HiDPI handling on wayland [Jonas; #745655, #744934]
 | 
			
		||||
* Implement compositor-side animated cursors [Carlos; #752342]
 | 
			
		||||
* Misc. bug fixes [Peter, Marek, Carlos, Matthias, Rui; #750816, #751884,
 | 
			
		||||
  #752248, #752551, #752552, #752673, #752674]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Jonas Ådahl, Marek Chalupa, Matthias Clasen, Carlos Garnacho, Peter Hutterer,
 | 
			
		||||
  Rui Matos, Florian Müllner, Jasper St. Pierre
 | 
			
		||||
 | 
			
		||||
3.17.3
 | 
			
		||||
======
 | 
			
		||||
* Add X11/wayland clipboard interaction [Carlos; #738312]
 | 
			
		||||
* Support VM monitor layout hints on wayland [Thomas; #750363]
 | 
			
		||||
* Misc. bug fixes [Rui, Jonas, Olivier, Carlos, Ting-Wei, Peter, Florian;
 | 
			
		||||
  #749994, #750256, #749716, #748705, #750552, #751036, #750007, #751136,
 | 
			
		||||
  #750552, #751471, #751715, #750680]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Jonas Ådahl, Dave Airlie, Cosimo Cecchi, Olivier Fourdan, Carlos Garnacho,
 | 
			
		||||
  Thomas Hellstrom, Peter Hutterer, Ting-Wei Lan, Jasper Lievisse Adriaanse,
 | 
			
		||||
  Rui Matos, Florian Müllner, Jasper St. Pierre
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
  Marek Černocký [cs], Christian Kirbach [de], Pedro Albuquerque [pt]
 | 
			
		||||
 | 
			
		||||
3.17.2
 | 
			
		||||
======
 | 
			
		||||
* Honor default value for click method setting [Rui; #746290]
 | 
			
		||||
* Add X11/wayland clipboard interoperation [Carlos; #738312]
 | 
			
		||||
* Misc. bug fixes [Rui; #749076, #749711]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Carlos Garnacho, Rui Matos, Jasper St. Pierre
 | 
			
		||||
 | 
			
		||||
3.17.1
 | 
			
		||||
======
 | 
			
		||||
* Add public method to get neighboring monitor [Florian; #633994]
 | 
			
		||||
* Apply the right settings to the right input devices [Carlos; #747886]
 | 
			
		||||
* Fix scroll button setting [Ondrej; #747967]
 | 
			
		||||
* Add support for modal hint on wayland [Jonas; #745720]
 | 
			
		||||
* Don't reset idle time for non-hardware events [Rui; #748541]
 | 
			
		||||
* Misc. bug fixes [Ray, Rui; #748380, #748478]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Jonas Ådahl, Carlos Garnacho, Ondrej Holy, Rui Matos, Florian Müllner,
 | 
			
		||||
  Jasper St. Pierre, Ray Strode, Tomeu Vizoso
 | 
			
		||||
 | 
			
		||||
3.16.1
 | 
			
		||||
======
 | 
			
		||||
* Add function to refresh all background instances [Rui; #739178]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										37
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								configure.ac
									
									
									
									
									
								
							@@ -1,8 +1,8 @@
 | 
			
		||||
AC_PREREQ(2.62)
 | 
			
		||||
 | 
			
		||||
m4_define([mutter_major_version], [3])
 | 
			
		||||
m4_define([mutter_minor_version], [16])
 | 
			
		||||
m4_define([mutter_micro_version], [1])
 | 
			
		||||
m4_define([mutter_minor_version], [19])
 | 
			
		||||
m4_define([mutter_micro_version], [4])
 | 
			
		||||
 | 
			
		||||
m4_define([mutter_version],
 | 
			
		||||
          [mutter_major_version.mutter_minor_version.mutter_micro_version])
 | 
			
		||||
@@ -46,37 +46,25 @@ IT_PROG_INTLTOOL([0.41])
 | 
			
		||||
AC_PROG_CC
 | 
			
		||||
AC_PROG_CC_C_O
 | 
			
		||||
AC_PROG_INSTALL
 | 
			
		||||
AC_PROG_SED
 | 
			
		||||
AC_HEADER_STDC
 | 
			
		||||
PKG_PROG_PKG_CONFIG([0.21])
 | 
			
		||||
 | 
			
		||||
# Sets GLIB_GENMARSHAL and GLIB_MKENUMS
 | 
			
		||||
AM_PATH_GLIB_2_0()
 | 
			
		||||
 | 
			
		||||
#### Integer sizes
 | 
			
		||||
 | 
			
		||||
AC_CHECK_SIZEOF(char)
 | 
			
		||||
AC_CHECK_SIZEOF(short)
 | 
			
		||||
AC_CHECK_SIZEOF(long)
 | 
			
		||||
AC_CHECK_SIZEOF(int)
 | 
			
		||||
AC_CHECK_SIZEOF(void *)
 | 
			
		||||
AC_CHECK_SIZEOF(long long)
 | 
			
		||||
AC_CHECK_SIZEOF(__int64)
 | 
			
		||||
 | 
			
		||||
## byte order
 | 
			
		||||
AC_C_BIGENDIAN
 | 
			
		||||
 | 
			
		||||
CANBERRA_GTK=libcanberra-gtk3
 | 
			
		||||
CANBERRA_GTK_VERSION=0.26
 | 
			
		||||
 | 
			
		||||
CLUTTER_PACKAGE=clutter-1.0
 | 
			
		||||
 | 
			
		||||
MUTTER_PC_MODULES="
 | 
			
		||||
   gtk+-3.0 >= 3.9.11
 | 
			
		||||
   gtk+-3.0 >= 3.19.8
 | 
			
		||||
   gio-unix-2.0 >= 2.35.1
 | 
			
		||||
   pango >= 1.2.0
 | 
			
		||||
   cairo >= 1.10.0
 | 
			
		||||
   gsettings-desktop-schemas >= 3.15.92
 | 
			
		||||
   $CLUTTER_PACKAGE >= 1.21.3
 | 
			
		||||
   gsettings-desktop-schemas >= 3.19.3
 | 
			
		||||
   $CLUTTER_PACKAGE >= 1.25.1
 | 
			
		||||
   cogl-1.0 >= 1.17.1
 | 
			
		||||
   upower-glib >= 0.99.0
 | 
			
		||||
   gnome-desktop-3.0
 | 
			
		||||
@@ -232,6 +220,10 @@ AS_IF([test "$have_wayland" = "yes"], [
 | 
			
		||||
    [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])
 | 
			
		||||
 | 
			
		||||
  PKG_CHECK_MODULES(WAYLAND_PROTOCOLS, [wayland-protocols >= 1.1],
 | 
			
		||||
		    [ac_wayland_protocols_pkgdatadir=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols`])
 | 
			
		||||
  AC_SUBST(WAYLAND_PROTOCOLS_DATADIR, $ac_wayland_protocols_pkgdatadir)
 | 
			
		||||
])
 | 
			
		||||
AM_CONDITIONAL([HAVE_WAYLAND],[test "$have_wayland" = "yes"])
 | 
			
		||||
 | 
			
		||||
@@ -284,6 +276,8 @@ AC_CHECK_LIB(Xrandr, XRRUpdateConfiguration,
 | 
			
		||||
 | 
			
		||||
if test "x$found_randr" = "xyes"; then
 | 
			
		||||
   AC_DEFINE(HAVE_RANDR, , [Have the Xrandr extension library])
 | 
			
		||||
   PKG_CHECK_EXISTS([xrandr >= 1.5.0],
 | 
			
		||||
                 AC_DEFINE([HAVE_XRANDR15],[1],[Define if you have support for XRandR 1.5 or greater]))
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
MUTTER_LIBS="$MUTTER_LIBS $RANDR_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
 | 
			
		||||
@@ -330,7 +324,10 @@ if test "x$enable_debug" = "xyes"; then
 | 
			
		||||
	CFLAGS="$CFLAGS -g -O"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
GTK_DOC_CHECK([1.15], [--flavour no-tmpl])
 | 
			
		||||
AC_CHECK_DECL([GL_EXT_x11_sync_object],
 | 
			
		||||
              [],
 | 
			
		||||
              [AC_MSG_ERROR([GL_EXT_x11_sync_object definition not found, please update your GL headers])],
 | 
			
		||||
              [#include <GL/glx.h>])
 | 
			
		||||
 | 
			
		||||
#### Warnings (last since -Werror can disturb other tests)
 | 
			
		||||
 | 
			
		||||
@@ -403,8 +400,6 @@ Makefile
 | 
			
		||||
data/Makefile
 | 
			
		||||
doc/Makefile
 | 
			
		||||
doc/man/Makefile
 | 
			
		||||
doc/reference/Makefile
 | 
			
		||||
doc/reference/meta-docs.sgml
 | 
			
		||||
src/Makefile
 | 
			
		||||
src/libmutter.pc
 | 
			
		||||
src/compositor/plugins/Makefile
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
desktopfiles_in_files = \
 | 
			
		||||
	mutter.desktop.in \
 | 
			
		||||
	mutter-wayland.desktop.in
 | 
			
		||||
	mutter.desktop.in
 | 
			
		||||
desktopfilesdir = $(datadir)/applications
 | 
			
		||||
desktopfiles_DATA = $(desktopfiles_in_files:.desktop.in=.desktop)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +0,0 @@
 | 
			
		||||
[Desktop Entry]
 | 
			
		||||
Type=Application
 | 
			
		||||
_Name=Mutter (wayland compositor)
 | 
			
		||||
Exec=mutter --wayland --display-server
 | 
			
		||||
NoDisplay=true
 | 
			
		||||
# name of loadable control center module
 | 
			
		||||
X-GNOME-WMSettingsModule=metacity
 | 
			
		||||
# name we put on the WM spec check window
 | 
			
		||||
X-GNOME-WMName=Mutter
 | 
			
		||||
# back compat only 
 | 
			
		||||
X-GnomeWMSettingsLibrary=metacity
 | 
			
		||||
X-GNOME-Bugzilla-Bugzilla=GNOME
 | 
			
		||||
X-GNOME-Bugzilla-Product=mutter
 | 
			
		||||
X-GNOME-Bugzilla-Component=general
 | 
			
		||||
X-GNOME-Autostart-Phase=WindowManager
 | 
			
		||||
X-GNOME-Provides=windowmanager
 | 
			
		||||
X-GNOME-Autostart-Notify=true
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
SUBDIRS = man reference
 | 
			
		||||
SUBDIRS = man
 | 
			
		||||
 | 
			
		||||
EXTRA_DIST = dialogs.txt code-overview.txt \
 | 
			
		||||
	how-to-get-focus-right.txt rationales.txt
 | 
			
		||||
 
 | 
			
		||||
@@ -1,183 +0,0 @@
 | 
			
		||||
## Process this file with automake to produce Makefile.in
 | 
			
		||||
 | 
			
		||||
# We require automake 1.6 at least.
 | 
			
		||||
AUTOMAKE_OPTIONS = 1.6
 | 
			
		||||
 | 
			
		||||
# This is a blank Makefile.am for using gtk-doc.
 | 
			
		||||
# Copy this to your project's API docs directory and modify the variables to
 | 
			
		||||
# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
 | 
			
		||||
# of using the various options.
 | 
			
		||||
 | 
			
		||||
# The name of the module, e.g. 'glib'.
 | 
			
		||||
DOC_MODULE=meta
 | 
			
		||||
 | 
			
		||||
# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
 | 
			
		||||
#DOC_MODULE_VERSION=2
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# The top-level SGML file. You can change this if you want to.
 | 
			
		||||
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
 | 
			
		||||
 | 
			
		||||
# Directories containing the source code, relative to $(srcdir).
 | 
			
		||||
# gtk-doc will search all .c and .h files beneath these paths
 | 
			
		||||
# for inline comments documenting functions and macros.
 | 
			
		||||
# e.g. DOC_SOURCE_DIR=../../../gtk ../../../gdk
 | 
			
		||||
DOC_SOURCE_DIR=../../src/
 | 
			
		||||
 | 
			
		||||
# Extra options to pass to gtkdoc-scangobj. Not normally needed.
 | 
			
		||||
SCANGOBJ_OPTIONS=
 | 
			
		||||
 | 
			
		||||
# Extra options to supply to gtkdoc-scan.
 | 
			
		||||
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
 | 
			
		||||
SCAN_OPTIONS=--rebuild-types
 | 
			
		||||
 | 
			
		||||
# Extra options to supply to gtkdoc-mkdb.
 | 
			
		||||
# e.g. MKDB_OPTIONS=--xml-mode --output-format=xml
 | 
			
		||||
MKDB_OPTIONS=--xml-mode --output-format=xml
 | 
			
		||||
 | 
			
		||||
# Extra options to supply to gtkdoc-mktmpl
 | 
			
		||||
# e.g. MKTMPL_OPTIONS=--only-section-tmpl
 | 
			
		||||
MKTMPL_OPTIONS=
 | 
			
		||||
 | 
			
		||||
# Extra options to supply to gtkdoc-mkhtml
 | 
			
		||||
MKHTML_OPTIONS=
 | 
			
		||||
 | 
			
		||||
# Extra options to supply to gtkdoc-fixref. Not normally needed.
 | 
			
		||||
# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
 | 
			
		||||
FIXXREF_OPTIONS=
 | 
			
		||||
 | 
			
		||||
# Used for dependencies. The docs will be rebuilt if any of these change.
 | 
			
		||||
# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
 | 
			
		||||
# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
 | 
			
		||||
HFILE_GLOB=$(top_srcdir)/src/*/*.h
 | 
			
		||||
CFILE_GLOB=$(top_srcdir)/src/*/*.c
 | 
			
		||||
 | 
			
		||||
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
 | 
			
		||||
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
 | 
			
		||||
EXTRA_HFILES=
 | 
			
		||||
 | 
			
		||||
# Header files or dirs to ignore when scanning. Use base file/dir names
 | 
			
		||||
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
 | 
			
		||||
IGNORE_HFILES= \
 | 
			
		||||
	async-getprop.h \
 | 
			
		||||
	atoms.h \
 | 
			
		||||
	bell.h \
 | 
			
		||||
	boxes-private.h \
 | 
			
		||||
	clutter-utils.h \
 | 
			
		||||
	cogl-utils.h \
 | 
			
		||||
	compositor-private.h \
 | 
			
		||||
	constraints.h \
 | 
			
		||||
	core.h \
 | 
			
		||||
	display-private.h \
 | 
			
		||||
	draw-workspace.h \
 | 
			
		||||
	edge-resistance.h \
 | 
			
		||||
	eventqueue.h \
 | 
			
		||||
	frame.h \
 | 
			
		||||
	frames.h \
 | 
			
		||||
	group-private.h \
 | 
			
		||||
	group-props.h \
 | 
			
		||||
	iconcache.h \
 | 
			
		||||
	inlinepixbufs.h \
 | 
			
		||||
	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 \
 | 
			
		||||
	meta-texture-rectangle.h \
 | 
			
		||||
	meta-texture-tower.h \
 | 
			
		||||
	meta-window-actor-private.h \
 | 
			
		||||
	meta-window-group.h \
 | 
			
		||||
	meta-window-shape.h \
 | 
			
		||||
	mutter-enum-types.h \
 | 
			
		||||
	mutter-Xatomtype.h \
 | 
			
		||||
	place.h \
 | 
			
		||||
	preview-widget.h \
 | 
			
		||||
	region-utils.h \
 | 
			
		||||
	resizepopup.h \
 | 
			
		||||
	screen-private.h \
 | 
			
		||||
	session.h \
 | 
			
		||||
	stack.h \
 | 
			
		||||
	stack-tracker.h \
 | 
			
		||||
	stamp-mutter-enum-types.h \
 | 
			
		||||
	tabpopup.h \
 | 
			
		||||
	theme.h \
 | 
			
		||||
	theme-private.h \
 | 
			
		||||
	tile-preview.h \
 | 
			
		||||
	ui.h \
 | 
			
		||||
	window-private.h \
 | 
			
		||||
	window-props.h \
 | 
			
		||||
	workspace-private.h \
 | 
			
		||||
	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	\
 | 
			
		||||
	wayland				\
 | 
			
		||||
	$(NULL)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
MKDB_OPTIONS+=--ignore-files="$(IGNORE_HFILES)"
 | 
			
		||||
 | 
			
		||||
# Images to copy into HTML directory.
 | 
			
		||||
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
 | 
			
		||||
HTML_IMAGES=
 | 
			
		||||
 | 
			
		||||
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
 | 
			
		||||
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
 | 
			
		||||
content_files= \
 | 
			
		||||
	mutter-overview.xml \
 | 
			
		||||
	running-mutter.xml \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
 | 
			
		||||
# These files must be listed here *and* in content_files
 | 
			
		||||
# e.g. expand_content_files=running.sgml
 | 
			
		||||
expand_content_files= \
 | 
			
		||||
	mutter-overview.xml \
 | 
			
		||||
	running-mutter.xml \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
 | 
			
		||||
# Only needed if you are using gtkdoc-scangobj to dynamically query widget
 | 
			
		||||
# signals and properties.
 | 
			
		||||
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
 | 
			
		||||
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
 | 
			
		||||
GTKDOC_CFLAGS=$(MUTTER_CFLAGS)
 | 
			
		||||
GTKDOC_LIBS=$(MUTTER_LIBS) $(top_builddir)/src/libmutter.la
 | 
			
		||||
 | 
			
		||||
# This includes the standard gtk-doc make rules, copied by gtkdocize.
 | 
			
		||||
include $(top_srcdir)/gtk-doc.make
 | 
			
		||||
 | 
			
		||||
# Other files to distribute
 | 
			
		||||
# e.g. EXTRA_DIST += version.xml.in
 | 
			
		||||
EXTRA_DIST +=
 | 
			
		||||
 | 
			
		||||
# Files not to distribute
 | 
			
		||||
# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
 | 
			
		||||
# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
 | 
			
		||||
DISTCLEANFILES = $(DOC_MODULES).types
 | 
			
		||||
 | 
			
		||||
# Comment this out if you want 'make check' to test you doc status
 | 
			
		||||
# and run some sanity checks
 | 
			
		||||
if ENABLE_GTK_DOC
 | 
			
		||||
TESTS_ENVIRONMENT = cd $(srcdir) && \
 | 
			
		||||
  DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \
 | 
			
		||||
  SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir)
 | 
			
		||||
#TESTS = $(GTKDOC_CHECK)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
-include $(top_srcdir)/git.mk
 | 
			
		||||
@@ -1,58 +0,0 @@
 | 
			
		||||
<?xml version="1.0"?>
 | 
			
		||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
 | 
			
		||||
               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
 | 
			
		||||
[
 | 
			
		||||
  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
 | 
			
		||||
  <!ENTITY version "@VERSION@">
 | 
			
		||||
]>
 | 
			
		||||
<book id="index">
 | 
			
		||||
  <bookinfo>
 | 
			
		||||
    <title>Mutter Reference Manual</title>
 | 
			
		||||
    <releaseinfo>
 | 
			
		||||
      This document is for Mutter &version;.
 | 
			
		||||
      The latest version of this documentation can be found on-line at
 | 
			
		||||
      <ulink role="online-location" url="http://developer.gnome.org/meta/">http://developer.gnome.org/meta/</ulink>.
 | 
			
		||||
    </releaseinfo>
 | 
			
		||||
  </bookinfo>
 | 
			
		||||
 | 
			
		||||
  <xi:include href="xml/mutter-overview.xml"/>
 | 
			
		||||
  <xi:include href="xml/running-mutter.xml"/>
 | 
			
		||||
 | 
			
		||||
  <part id="core-reference">
 | 
			
		||||
    <title>Mutter Core Reference</title>
 | 
			
		||||
    <xi:include href="xml/main.xml"/>
 | 
			
		||||
    <xi:include href="xml/common.xml"/>
 | 
			
		||||
    <xi:include href="xml/prefs.xml"/>
 | 
			
		||||
    <xi:include href="xml/util.xml"/>
 | 
			
		||||
    <xi:include href="xml/errors.xml"/>
 | 
			
		||||
    <xi:include href="xml/meta-plugin.xml"/>
 | 
			
		||||
    <xi:include href="xml/barrier.xml"/>
 | 
			
		||||
    <xi:include href="xml/boxes.xml"/>
 | 
			
		||||
    <xi:include href="xml/compositor.xml"/>
 | 
			
		||||
    <xi:include href="xml/display.xml"/>
 | 
			
		||||
    <xi:include href="xml/group.xml"/>
 | 
			
		||||
    <xi:include href="xml/keybindings.xml"/>
 | 
			
		||||
    <xi:include href="xml/meta-background-actor.xml"/>
 | 
			
		||||
    <xi:include href="xml/meta-shadow-factory.xml"/>
 | 
			
		||||
    <xi:include href="xml/meta-shaped-texture.xml"/>
 | 
			
		||||
    <xi:include href="xml/meta-window-actor.xml"/>
 | 
			
		||||
    <xi:include href="xml/screen.xml"/>
 | 
			
		||||
    <xi:include href="xml/window.xml"/>
 | 
			
		||||
    <xi:include href="xml/workspace.xml"/>
 | 
			
		||||
  </part>
 | 
			
		||||
 | 
			
		||||
  <chapter id="object-tree">
 | 
			
		||||
    <title>Object Hierarchy</title>
 | 
			
		||||
     <xi:include href="xml/tree_index.sgml"/>
 | 
			
		||||
  </chapter>
 | 
			
		||||
  <index id="api-index-full">
 | 
			
		||||
    <title>API Index</title>
 | 
			
		||||
    <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
 | 
			
		||||
  </index>
 | 
			
		||||
  <index id="deprecated-api-index" role="deprecated">
 | 
			
		||||
    <title>Index of deprecated API</title>
 | 
			
		||||
    <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
 | 
			
		||||
  </index>
 | 
			
		||||
 | 
			
		||||
  <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
 | 
			
		||||
</book>
 | 
			
		||||
@@ -1,674 +0,0 @@
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>barrier</FILE>
 | 
			
		||||
<TITLE>MetaBarrier</TITLE>
 | 
			
		||||
MetaBarrier
 | 
			
		||||
MetaBarrierClass
 | 
			
		||||
meta_barrier_is_active
 | 
			
		||||
meta_barrier_destroy
 | 
			
		||||
meta_barrier_release
 | 
			
		||||
MetaBarrierDirection
 | 
			
		||||
MetaBarrierEvent
 | 
			
		||||
<SUBSECTION Standard>
 | 
			
		||||
META_BARRIER
 | 
			
		||||
META_BARRIER_CLASS
 | 
			
		||||
META_BARRIER_GET_CLASS
 | 
			
		||||
META_IS_BARRIER
 | 
			
		||||
META_IS_BARRIER_CLASS
 | 
			
		||||
META_TYPE_BARRIER
 | 
			
		||||
META_TYPE_BARRIER_EVENT
 | 
			
		||||
MetaBarrierPrivate
 | 
			
		||||
meta_barrier_event_get_type
 | 
			
		||||
meta_barrier_get_type
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>boxes</FILE>
 | 
			
		||||
MetaRectangle
 | 
			
		||||
MetaStrut
 | 
			
		||||
MetaEdgeType
 | 
			
		||||
MetaEdge
 | 
			
		||||
meta_rectangle_copy
 | 
			
		||||
meta_rectangle_free
 | 
			
		||||
meta_rect
 | 
			
		||||
meta_rectangle_area
 | 
			
		||||
meta_rectangle_intersect
 | 
			
		||||
meta_rectangle_equal
 | 
			
		||||
meta_rectangle_union
 | 
			
		||||
meta_rectangle_overlap
 | 
			
		||||
meta_rectangle_vert_overlap
 | 
			
		||||
meta_rectangle_horiz_overlap
 | 
			
		||||
meta_rectangle_could_fit_rect
 | 
			
		||||
meta_rectangle_contains_rect
 | 
			
		||||
<SUBSECTION Standard>
 | 
			
		||||
META_TYPE_RECTANGLE
 | 
			
		||||
meta_rectangle_get_type
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>common</FILE>
 | 
			
		||||
META_VIRTUAL_CORE_POINTER_ID
 | 
			
		||||
META_VIRTUAL_CORE_KEYBOARD_ID
 | 
			
		||||
MetaFrameFlags
 | 
			
		||||
MetaMenuOp
 | 
			
		||||
MetaWindowMenuFunc
 | 
			
		||||
MetaGrabOp
 | 
			
		||||
MetaCursor
 | 
			
		||||
MetaFrameType
 | 
			
		||||
MetaVirtualModifier
 | 
			
		||||
MetaDirection
 | 
			
		||||
MetaMotionDirection
 | 
			
		||||
MetaSide
 | 
			
		||||
MetaButtonFunction
 | 
			
		||||
MAX_BUTTONS_PER_CORNER
 | 
			
		||||
MetaButtonLayout
 | 
			
		||||
MetaFrameBorders
 | 
			
		||||
meta_frame_borders_clear
 | 
			
		||||
META_ICON_WIDTH
 | 
			
		||||
META_ICON_HEIGHT
 | 
			
		||||
META_MINI_ICON_WIDTH
 | 
			
		||||
META_MINI_ICON_HEIGHT
 | 
			
		||||
META_DEFAULT_ICON_NAME
 | 
			
		||||
META_PRIORITY_RESIZE
 | 
			
		||||
META_PRIORITY_BEFORE_REDRAW
 | 
			
		||||
META_PRIORITY_REDRAW
 | 
			
		||||
META_PRIORITY_PREFS_NOTIFY
 | 
			
		||||
POINT_IN_RECT
 | 
			
		||||
MetaStackLayer
 | 
			
		||||
MetaWindowMenu
 | 
			
		||||
MetaResizePopup
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>compositor</FILE>
 | 
			
		||||
MetaCompEffect
 | 
			
		||||
MetaCompositor
 | 
			
		||||
meta_compositor_new
 | 
			
		||||
meta_compositor_destroy
 | 
			
		||||
meta_compositor_manage_screen
 | 
			
		||||
meta_compositor_unmanage_screen
 | 
			
		||||
meta_compositor_window_shape_changed
 | 
			
		||||
meta_compositor_process_event
 | 
			
		||||
meta_compositor_filter_keybinding
 | 
			
		||||
meta_compositor_add_window
 | 
			
		||||
meta_compositor_remove_window
 | 
			
		||||
meta_compositor_show_window
 | 
			
		||||
meta_compositor_hide_window
 | 
			
		||||
meta_compositor_switch_workspace
 | 
			
		||||
meta_compositor_maximize_window
 | 
			
		||||
meta_compositor_unmaximize_window
 | 
			
		||||
meta_compositor_sync_window_geometry
 | 
			
		||||
meta_compositor_set_updates_frozen
 | 
			
		||||
meta_compositor_queue_frame_drawn
 | 
			
		||||
meta_compositor_sync_stack
 | 
			
		||||
meta_compositor_sync_screen_size
 | 
			
		||||
meta_compositor_flash_screen
 | 
			
		||||
meta_get_stage_for_screen
 | 
			
		||||
meta_get_overlay_group_for_screen
 | 
			
		||||
meta_get_overlay_window
 | 
			
		||||
meta_get_window_actors
 | 
			
		||||
meta_get_window_group_for_screen
 | 
			
		||||
meta_get_top_window_group_for_screen
 | 
			
		||||
meta_disable_unredirect_for_screen
 | 
			
		||||
meta_enable_unredirect_for_screen
 | 
			
		||||
meta_set_stage_input_region
 | 
			
		||||
meta_empty_stage_input_region
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>display</FILE>
 | 
			
		||||
MetaTabList
 | 
			
		||||
MetaTabShowType
 | 
			
		||||
meta_XFree
 | 
			
		||||
meta_display_get_compositor_version
 | 
			
		||||
meta_display_get_xinput_opcode
 | 
			
		||||
meta_display_supports_extended_barriers
 | 
			
		||||
meta_display_get_xdisplay
 | 
			
		||||
meta_display_get_compositor
 | 
			
		||||
meta_display_get_screens
 | 
			
		||||
meta_display_has_shape
 | 
			
		||||
meta_display_screen_for_root
 | 
			
		||||
meta_display_get_focus_window
 | 
			
		||||
meta_display_xwindow_is_a_no_focus_window
 | 
			
		||||
meta_display_get_damage_event_base
 | 
			
		||||
meta_display_get_shape_event_base
 | 
			
		||||
meta_display_xserver_time_is_before
 | 
			
		||||
meta_display_get_last_user_time
 | 
			
		||||
meta_display_get_current_time
 | 
			
		||||
meta_display_get_current_time_roundtrip
 | 
			
		||||
meta_display_get_ignored_modifier_mask
 | 
			
		||||
meta_display_get_tab_list
 | 
			
		||||
meta_display_get_tab_next
 | 
			
		||||
meta_display_get_tab_current
 | 
			
		||||
meta_display_begin_grab_op
 | 
			
		||||
meta_display_end_grab_op
 | 
			
		||||
meta_display_get_grab_op
 | 
			
		||||
meta_display_add_keybinding
 | 
			
		||||
meta_display_remove_keybinding
 | 
			
		||||
meta_display_get_keybinding_action
 | 
			
		||||
meta_display_set_input_focus_window
 | 
			
		||||
meta_display_focus_the_no_focus_window
 | 
			
		||||
meta_display_sort_windows_by_stacking
 | 
			
		||||
meta_display_get_leader_window
 | 
			
		||||
meta_display_add_ignored_crossing_serial
 | 
			
		||||
meta_display_unmanage_screen
 | 
			
		||||
meta_display_clear_mouse_mode
 | 
			
		||||
MetaDisplay
 | 
			
		||||
MetaDisplayClass
 | 
			
		||||
<SUBSECTION Standard>
 | 
			
		||||
META_DISPLAY
 | 
			
		||||
META_DISPLAY_CLASS
 | 
			
		||||
META_DISPLAY_GET_CLASS
 | 
			
		||||
META_IS_DISPLAY
 | 
			
		||||
META_IS_DISPLAY_CLASS
 | 
			
		||||
META_TYPE_DISPLAY
 | 
			
		||||
meta_display_get_type
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>errors</FILE>
 | 
			
		||||
meta_error_trap_push
 | 
			
		||||
meta_error_trap_pop
 | 
			
		||||
meta_error_trap_push_with_return
 | 
			
		||||
meta_error_trap_pop_with_return
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>group</FILE>
 | 
			
		||||
MetaGroup
 | 
			
		||||
meta_window_get_group
 | 
			
		||||
meta_window_compute_group
 | 
			
		||||
meta_window_shutdown_group
 | 
			
		||||
meta_window_group_leader_changed
 | 
			
		||||
meta_display_lookup_group
 | 
			
		||||
meta_group_list_windows
 | 
			
		||||
meta_group_update_layers
 | 
			
		||||
meta_group_get_startup_id
 | 
			
		||||
meta_group_get_size
 | 
			
		||||
meta_group_property_notify
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>keybindings</FILE>
 | 
			
		||||
MetaKeyBinding
 | 
			
		||||
META_TYPE_KEY_BINDING
 | 
			
		||||
meta_key_binding_get_name
 | 
			
		||||
meta_key_binding_get_modifiers
 | 
			
		||||
meta_key_binding_get_mask
 | 
			
		||||
meta_key_binding_is_builtin
 | 
			
		||||
meta_keybindings_set_custom_handler
 | 
			
		||||
meta_screen_ungrab_all_keys
 | 
			
		||||
meta_screen_grab_all_keys
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>main</FILE>
 | 
			
		||||
meta_get_option_context
 | 
			
		||||
meta_init
 | 
			
		||||
meta_run
 | 
			
		||||
meta_get_replace_current_wm
 | 
			
		||||
meta_set_wm_name
 | 
			
		||||
meta_set_gnome_wm_keybindings
 | 
			
		||||
MetaExitCode
 | 
			
		||||
meta_exit
 | 
			
		||||
meta_quit
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>meta-background</FILE>
 | 
			
		||||
<TITLE>MetaBackground</TITLE>
 | 
			
		||||
MetaBackgroundEffects
 | 
			
		||||
MetaBackground
 | 
			
		||||
MetaBackgroundClass
 | 
			
		||||
meta_background_new
 | 
			
		||||
meta_background_copy
 | 
			
		||||
meta_background_load_gradient
 | 
			
		||||
meta_background_load_color
 | 
			
		||||
meta_background_load_still_frame
 | 
			
		||||
meta_background_load_file_async
 | 
			
		||||
meta_background_load_file_finish
 | 
			
		||||
meta_background_get_filename
 | 
			
		||||
meta_background_get_style
 | 
			
		||||
meta_background_get_shading
 | 
			
		||||
meta_background_get_color
 | 
			
		||||
meta_background_get_second_color
 | 
			
		||||
<SUBSECTION Standard>
 | 
			
		||||
META_BACKGROUND
 | 
			
		||||
META_BACKGROUND_CLASS
 | 
			
		||||
META_BACKGROUND_GET_CLASS
 | 
			
		||||
META_IS_BACKGROUND
 | 
			
		||||
META_IS_BACKGROUND_CLASS
 | 
			
		||||
META_TYPE_BACKGROUND
 | 
			
		||||
MetaBackgroundPrivate
 | 
			
		||||
meta_background_get_type
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>meta-background-actor</FILE>
 | 
			
		||||
<TITLE>MetaBackgroundActor</TITLE>
 | 
			
		||||
MetaBackgroundActor
 | 
			
		||||
MetaBackgroundActorClass
 | 
			
		||||
meta_background_actor_new_for_screen
 | 
			
		||||
MetaSnippetHook
 | 
			
		||||
meta_background_actor_add_glsl_snippet
 | 
			
		||||
meta_background_actor_set_uniform_float
 | 
			
		||||
<SUBSECTION Standard>
 | 
			
		||||
META_BACKGROUND_ACTOR
 | 
			
		||||
META_BACKGROUND_ACTOR_CLASS
 | 
			
		||||
META_BACKGROUND_ACTOR_GET_CLASS
 | 
			
		||||
META_IS_BACKGROUND_ACTOR
 | 
			
		||||
META_IS_BACKGROUND_ACTOR_CLASS
 | 
			
		||||
META_TYPE_BACKGROUND_ACTOR
 | 
			
		||||
MetaBackgroundActorPrivate
 | 
			
		||||
meta_background_actor_get_type
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>meta-background-group</FILE>
 | 
			
		||||
<TITLE>MetaBackgroundGroup</TITLE>
 | 
			
		||||
MetaBackgroundGroupClass
 | 
			
		||||
meta_background_group_new
 | 
			
		||||
<SUBSECTION Standard>
 | 
			
		||||
META_BACKGROUND_GROUP
 | 
			
		||||
META_BACKGROUND_GROUP_CLASS
 | 
			
		||||
META_BACKGROUND_GROUP_GET_CLASS
 | 
			
		||||
META_IS_BACKGROUND_GROUP
 | 
			
		||||
META_IS_BACKGROUND_GROUP_CLASS
 | 
			
		||||
META_TYPE_BACKGROUND_GROUP
 | 
			
		||||
MetaBackgroundGroupPrivate
 | 
			
		||||
meta_background_group_get_type
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>meta-plugin</FILE>
 | 
			
		||||
<TITLE>MetaPlugin</TITLE>
 | 
			
		||||
MetaPlugin
 | 
			
		||||
MetaPluginClass
 | 
			
		||||
MetaPluginInfo
 | 
			
		||||
meta_plugin_running
 | 
			
		||||
meta_plugin_debug_mode
 | 
			
		||||
meta_plugin_get_info
 | 
			
		||||
MetaPluginVersion
 | 
			
		||||
META_PLUGIN_DECLARE
 | 
			
		||||
meta_plugin_switch_workspace_completed
 | 
			
		||||
meta_plugin_minimize_completed
 | 
			
		||||
meta_plugin_unminimize_completed
 | 
			
		||||
meta_plugin_maximize_completed
 | 
			
		||||
meta_plugin_unmaximize_completed
 | 
			
		||||
meta_plugin_map_completed
 | 
			
		||||
meta_plugin_destroy_completed
 | 
			
		||||
MetaModalOptions
 | 
			
		||||
meta_plugin_begin_modal
 | 
			
		||||
meta_plugin_end_modal
 | 
			
		||||
meta_plugin_get_screen
 | 
			
		||||
meta_plugin_manager_set_plugin_type
 | 
			
		||||
<SUBSECTION Standard>
 | 
			
		||||
META_IS_PLUGIN
 | 
			
		||||
META_IS_PLUGIN_CLASS
 | 
			
		||||
META_PLUGIN
 | 
			
		||||
META_PLUGIN_CLASS
 | 
			
		||||
META_PLUGIN_GET_CLASS
 | 
			
		||||
META_TYPE_PLUGIN
 | 
			
		||||
MetaPluginPrivate
 | 
			
		||||
meta_plugin_get_type
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>meta-shadow-factory</FILE>
 | 
			
		||||
MetaShadowParams
 | 
			
		||||
meta_shadow_factory_get_default
 | 
			
		||||
meta_shadow_factory_set_params
 | 
			
		||||
meta_shadow_factory_get_params
 | 
			
		||||
MetaShadowFactory
 | 
			
		||||
MetaShadowFactoryClass
 | 
			
		||||
<SUBSECTION Standard>
 | 
			
		||||
META_IS_SHADOW_FACTORY
 | 
			
		||||
META_IS_SHADOW_FACTORY_CLASS
 | 
			
		||||
META_SHADOW_FACTORY
 | 
			
		||||
META_SHADOW_FACTORY_CLASS
 | 
			
		||||
META_SHADOW_FACTORY_GET_CLASS
 | 
			
		||||
META_TYPE_SHADOW_FACTORY
 | 
			
		||||
meta_shadow_factory_get_type
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>meta-shaped-texture</FILE>
 | 
			
		||||
<TITLE>MetaShapedTexture</TITLE>
 | 
			
		||||
MetaShapedTexture
 | 
			
		||||
MetaShapedTextureClass
 | 
			
		||||
meta_shaped_texture_new
 | 
			
		||||
meta_shaped_texture_set_create_mipmaps
 | 
			
		||||
meta_shaped_texture_update_area
 | 
			
		||||
meta_shaped_texture_set_pixmap
 | 
			
		||||
meta_shaped_texture_get_texture
 | 
			
		||||
meta_shaped_texture_set_mask_texture
 | 
			
		||||
meta_shaped_texture_set_clip_region
 | 
			
		||||
meta_shaped_texture_get_image
 | 
			
		||||
<SUBSECTION Standard>
 | 
			
		||||
META_IS_SHAPED_TEXTURE
 | 
			
		||||
META_IS_SHAPED_TEXTURE_CLASS
 | 
			
		||||
META_SHAPED_TEXTURE
 | 
			
		||||
META_SHAPED_TEXTURE_CLASS
 | 
			
		||||
META_SHAPED_TEXTURE_GET_CLASS
 | 
			
		||||
META_TYPE_SHAPED_TEXTURE
 | 
			
		||||
MetaShapedTexturePrivate
 | 
			
		||||
meta_shaped_texture_get_type
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>meta-window-actor</FILE>
 | 
			
		||||
<TITLE>MetaWindowActor</TITLE>
 | 
			
		||||
MetaWindowActor
 | 
			
		||||
MetaWindowActorClass
 | 
			
		||||
meta_window_actor_get_x_window
 | 
			
		||||
meta_window_actor_get_workspace
 | 
			
		||||
meta_window_actor_get_meta_window
 | 
			
		||||
meta_window_actor_get_texture
 | 
			
		||||
meta_window_actor_is_override_redirect
 | 
			
		||||
meta_window_actor_get_description
 | 
			
		||||
meta_window_actor_showing_on_its_workspace
 | 
			
		||||
meta_window_actor_is_destroyed
 | 
			
		||||
<SUBSECTION Standard>
 | 
			
		||||
META_IS_WINDOW_ACTOR
 | 
			
		||||
META_IS_WINDOW_ACTOR_CLASS
 | 
			
		||||
META_TYPE_WINDOW_ACTOR
 | 
			
		||||
META_WINDOW_ACTOR
 | 
			
		||||
META_WINDOW_ACTOR_CLASS
 | 
			
		||||
META_WINDOW_ACTOR_GET_CLASS
 | 
			
		||||
MetaWindowActorPrivate
 | 
			
		||||
meta_window_actor_get_type
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>meta-cullable</FILE>
 | 
			
		||||
<TITLE>MetaCullable</TITLE>
 | 
			
		||||
MetaCullable
 | 
			
		||||
MetaCullableInterface
 | 
			
		||||
meta_cullable_cull_out
 | 
			
		||||
meta_cullable_reset_culling
 | 
			
		||||
meta_cullable_cull_out_children
 | 
			
		||||
meta_cullable_reset_culling_children
 | 
			
		||||
<SUBSECTION Standard>
 | 
			
		||||
META_TYPE_CULLABLE
 | 
			
		||||
META_CULLABLE
 | 
			
		||||
META_IS_CULLABLE
 | 
			
		||||
META_CULLABLE_GET_IFACE
 | 
			
		||||
meta_cullable_get_type
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>prefs</FILE>
 | 
			
		||||
MetaPreference
 | 
			
		||||
MetaPrefsChangedFunc
 | 
			
		||||
meta_prefs_add_listener
 | 
			
		||||
meta_prefs_remove_listener
 | 
			
		||||
meta_prefs_init
 | 
			
		||||
meta_prefs_override_preference_schema
 | 
			
		||||
meta_preference_to_string
 | 
			
		||||
meta_prefs_get_mouse_button_mods
 | 
			
		||||
meta_prefs_get_mouse_button_resize
 | 
			
		||||
meta_prefs_get_mouse_button_menu
 | 
			
		||||
meta_prefs_get_focus_mode
 | 
			
		||||
meta_prefs_get_focus_new_windows
 | 
			
		||||
meta_prefs_get_attach_modal_dialogs
 | 
			
		||||
meta_prefs_get_raise_on_click
 | 
			
		||||
meta_prefs_get_theme
 | 
			
		||||
meta_prefs_get_titlebar_font
 | 
			
		||||
meta_prefs_get_num_workspaces
 | 
			
		||||
meta_prefs_get_dynamic_workspaces
 | 
			
		||||
meta_prefs_get_disable_workarounds
 | 
			
		||||
meta_prefs_get_auto_raise
 | 
			
		||||
meta_prefs_get_auto_raise_delay
 | 
			
		||||
meta_prefs_get_focus_change_on_pointer_rest
 | 
			
		||||
meta_prefs_get_gnome_accessibility
 | 
			
		||||
meta_prefs_get_gnome_animations
 | 
			
		||||
meta_prefs_get_edge_tiling
 | 
			
		||||
meta_prefs_get_auto_maximize
 | 
			
		||||
meta_prefs_get_button_layout
 | 
			
		||||
meta_prefs_get_action_double_click_titlebar
 | 
			
		||||
meta_prefs_get_action_middle_click_titlebar
 | 
			
		||||
meta_prefs_get_action_right_click_titlebar
 | 
			
		||||
meta_prefs_set_num_workspaces
 | 
			
		||||
meta_prefs_get_workspace_name
 | 
			
		||||
meta_prefs_change_workspace_name
 | 
			
		||||
meta_prefs_get_cursor_theme
 | 
			
		||||
meta_prefs_get_cursor_size
 | 
			
		||||
meta_prefs_get_compositing_manager
 | 
			
		||||
meta_prefs_get_force_fullscreen
 | 
			
		||||
meta_prefs_set_force_fullscreen
 | 
			
		||||
meta_prefs_get_workspaces_only_on_primary
 | 
			
		||||
meta_prefs_get_no_tab_popup
 | 
			
		||||
meta_prefs_set_no_tab_popup
 | 
			
		||||
meta_prefs_get_draggable_border_width
 | 
			
		||||
meta_prefs_get_ignore_request_hide_titlebar
 | 
			
		||||
meta_prefs_set_ignore_request_hide_titlebar
 | 
			
		||||
MetaKeyBindingAction
 | 
			
		||||
MetaKeyBindingFlags
 | 
			
		||||
MetaKeyCombo
 | 
			
		||||
MetaKeyHandlerFunc
 | 
			
		||||
meta_prefs_get_keybindings
 | 
			
		||||
meta_prefs_get_keybinding_action
 | 
			
		||||
meta_prefs_get_window_binding
 | 
			
		||||
meta_prefs_get_overlay_binding
 | 
			
		||||
meta_prefs_get_visual_bell
 | 
			
		||||
meta_prefs_bell_is_audible
 | 
			
		||||
meta_prefs_get_visual_bell_type
 | 
			
		||||
MetaKeyHandler
 | 
			
		||||
<SUBSECTION Standard>
 | 
			
		||||
meta_key_binding_get_type
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>screen</FILE>
 | 
			
		||||
MetaScreen
 | 
			
		||||
MetaScreenClass
 | 
			
		||||
meta_screen_get_screen_number
 | 
			
		||||
meta_screen_get_display
 | 
			
		||||
meta_screen_get_xroot
 | 
			
		||||
meta_screen_get_size
 | 
			
		||||
meta_screen_get_compositor_data
 | 
			
		||||
meta_screen_set_compositor_data
 | 
			
		||||
meta_screen_for_x_screen
 | 
			
		||||
meta_screen_set_cm_selection
 | 
			
		||||
meta_screen_unset_cm_selection
 | 
			
		||||
meta_screen_get_startup_sequences
 | 
			
		||||
meta_screen_get_workspaces
 | 
			
		||||
meta_screen_get_n_workspaces
 | 
			
		||||
meta_screen_get_workspace_by_index
 | 
			
		||||
meta_screen_remove_workspace
 | 
			
		||||
meta_screen_append_new_workspace
 | 
			
		||||
meta_screen_get_active_workspace_index
 | 
			
		||||
meta_screen_get_active_workspace
 | 
			
		||||
meta_screen_get_n_monitors
 | 
			
		||||
meta_screen_get_primary_monitor
 | 
			
		||||
meta_screen_get_current_monitor
 | 
			
		||||
meta_screen_get_monitor_geometry
 | 
			
		||||
meta_screen_get_monitor_index_for_rect
 | 
			
		||||
meta_screen_focus_default_window
 | 
			
		||||
MetaScreenCorner
 | 
			
		||||
meta_screen_override_workspace_layout
 | 
			
		||||
<SUBSECTION Standard>
 | 
			
		||||
META_IS_SCREEN
 | 
			
		||||
META_IS_SCREEN_CLASS
 | 
			
		||||
META_SCREEN
 | 
			
		||||
META_SCREEN_CLASS
 | 
			
		||||
META_SCREEN_GET_CLASS
 | 
			
		||||
META_TYPE_SCREEN
 | 
			
		||||
meta_screen_get_type
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>util</FILE>
 | 
			
		||||
meta_is_verbose
 | 
			
		||||
meta_set_verbose
 | 
			
		||||
meta_is_debugging
 | 
			
		||||
meta_set_debugging
 | 
			
		||||
meta_is_syncing
 | 
			
		||||
meta_set_syncing
 | 
			
		||||
meta_set_replace_current_wm
 | 
			
		||||
meta_debug_spew_real
 | 
			
		||||
meta_verbose_real
 | 
			
		||||
meta_bug
 | 
			
		||||
meta_warning
 | 
			
		||||
meta_fatal
 | 
			
		||||
MetaDebugTopic
 | 
			
		||||
meta_topic_real
 | 
			
		||||
meta_add_verbose_topic
 | 
			
		||||
meta_remove_verbose_topic
 | 
			
		||||
meta_push_no_msg_prefix
 | 
			
		||||
meta_pop_no_msg_prefix
 | 
			
		||||
meta_unsigned_long_equal
 | 
			
		||||
meta_unsigned_long_hash
 | 
			
		||||
meta_frame_type_to_string
 | 
			
		||||
meta_gravity_to_string
 | 
			
		||||
_
 | 
			
		||||
N_
 | 
			
		||||
meta_g_utf8_strndup
 | 
			
		||||
meta_free_gslist_and_elements
 | 
			
		||||
meta_show_dialog
 | 
			
		||||
meta_debug_spew
 | 
			
		||||
meta_verbose
 | 
			
		||||
meta_topic
 | 
			
		||||
MetaLaterType
 | 
			
		||||
meta_later_add
 | 
			
		||||
meta_later_remove
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>window</FILE>
 | 
			
		||||
MetaWindow
 | 
			
		||||
MetaWindowClass
 | 
			
		||||
MetaWindowType
 | 
			
		||||
MetaMaximizeFlags
 | 
			
		||||
meta_window_get_frame
 | 
			
		||||
meta_window_has_focus
 | 
			
		||||
meta_window_appears_focused
 | 
			
		||||
meta_window_is_shaded
 | 
			
		||||
meta_window_is_monitor_sized
 | 
			
		||||
meta_window_is_override_redirect
 | 
			
		||||
meta_window_is_skip_taskbar
 | 
			
		||||
meta_window_get_rect
 | 
			
		||||
meta_window_get_buffer_rect
 | 
			
		||||
meta_window_get_frame_rect
 | 
			
		||||
meta_window_client_rect_to_frame_rect
 | 
			
		||||
meta_window_frame_rect_to_client_rect
 | 
			
		||||
meta_window_get_screen
 | 
			
		||||
meta_window_get_display
 | 
			
		||||
meta_window_get_xwindow
 | 
			
		||||
meta_window_get_window_type
 | 
			
		||||
meta_window_get_window_type_atom
 | 
			
		||||
meta_window_get_workspace
 | 
			
		||||
meta_window_get_monitor
 | 
			
		||||
meta_window_is_on_all_workspaces
 | 
			
		||||
meta_window_located_on_workspace
 | 
			
		||||
meta_window_is_hidden
 | 
			
		||||
meta_window_activate
 | 
			
		||||
meta_window_activate_with_workspace
 | 
			
		||||
meta_window_get_description
 | 
			
		||||
meta_window_get_wm_class
 | 
			
		||||
meta_window_get_wm_class_instance
 | 
			
		||||
meta_window_showing_on_its_workspace
 | 
			
		||||
meta_window_get_gtk_application_id
 | 
			
		||||
meta_window_get_gtk_unique_bus_name
 | 
			
		||||
meta_window_get_gtk_application_object_path
 | 
			
		||||
meta_window_get_gtk_window_object_path
 | 
			
		||||
meta_window_get_gtk_app_menu_object_path
 | 
			
		||||
meta_window_get_gtk_menubar_object_path
 | 
			
		||||
meta_window_move
 | 
			
		||||
meta_window_move_frame
 | 
			
		||||
meta_window_move_resize_frame
 | 
			
		||||
meta_window_move_to_monitor
 | 
			
		||||
meta_window_resize
 | 
			
		||||
meta_window_set_demands_attention
 | 
			
		||||
meta_window_unset_demands_attention
 | 
			
		||||
meta_window_get_startup_id
 | 
			
		||||
meta_window_change_workspace_by_index
 | 
			
		||||
meta_window_change_workspace
 | 
			
		||||
meta_window_get_compositor_private
 | 
			
		||||
meta_window_set_compositor_private
 | 
			
		||||
meta_window_configure_notify
 | 
			
		||||
meta_window_get_role
 | 
			
		||||
meta_window_get_layer
 | 
			
		||||
meta_window_find_root_ancestor
 | 
			
		||||
meta_window_is_ancestor_of_transient
 | 
			
		||||
MetaWindowForeachFunc
 | 
			
		||||
meta_window_foreach_transient
 | 
			
		||||
meta_window_foreach_ancestor
 | 
			
		||||
meta_window_get_maximized
 | 
			
		||||
meta_window_is_fullscreen
 | 
			
		||||
meta_window_is_on_primary_monitor
 | 
			
		||||
meta_window_requested_bypass_compositor
 | 
			
		||||
meta_window_requested_dont_bypass_compositor
 | 
			
		||||
meta_window_is_mapped
 | 
			
		||||
meta_window_toplevel_is_mapped
 | 
			
		||||
meta_window_get_icon_geometry
 | 
			
		||||
meta_window_set_icon_geometry
 | 
			
		||||
meta_window_maximize
 | 
			
		||||
meta_window_unmaximize
 | 
			
		||||
meta_window_minimize
 | 
			
		||||
meta_window_unminimize
 | 
			
		||||
meta_window_raise
 | 
			
		||||
meta_window_lower
 | 
			
		||||
meta_window_get_title
 | 
			
		||||
meta_window_get_transient_for
 | 
			
		||||
meta_window_get_transient_for_as_xid
 | 
			
		||||
meta_window_delete
 | 
			
		||||
meta_window_get_stable_sequence
 | 
			
		||||
meta_window_get_user_time
 | 
			
		||||
meta_window_get_pid
 | 
			
		||||
meta_window_get_client_machine
 | 
			
		||||
meta_window_is_remote
 | 
			
		||||
meta_window_is_modal
 | 
			
		||||
meta_window_is_attached_dialog
 | 
			
		||||
meta_window_get_mutter_hints
 | 
			
		||||
meta_window_get_frame_type
 | 
			
		||||
meta_window_get_frame_bounds
 | 
			
		||||
meta_window_get_tile_match
 | 
			
		||||
meta_window_make_fullscreen
 | 
			
		||||
meta_window_unmake_fullscreen
 | 
			
		||||
meta_window_make_above
 | 
			
		||||
meta_window_unmake_above
 | 
			
		||||
meta_window_shade
 | 
			
		||||
meta_window_unshade
 | 
			
		||||
meta_window_stick
 | 
			
		||||
meta_window_unstick
 | 
			
		||||
meta_window_kill
 | 
			
		||||
meta_window_focus
 | 
			
		||||
meta_window_check_alive
 | 
			
		||||
meta_window_get_work_area_current_monitor
 | 
			
		||||
meta_window_get_work_area_for_monitor
 | 
			
		||||
meta_window_get_work_area_all_monitors
 | 
			
		||||
meta_window_begin_grab_op
 | 
			
		||||
<SUBSECTION Standard>
 | 
			
		||||
META_IS_WINDOW
 | 
			
		||||
META_IS_WINDOW_CLASS
 | 
			
		||||
META_TYPE_WINDOW
 | 
			
		||||
META_WINDOW
 | 
			
		||||
META_WINDOW_CLASS
 | 
			
		||||
META_WINDOW_GET_CLASS
 | 
			
		||||
meta_window_get_type
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
<SECTION>
 | 
			
		||||
<FILE>workspace</FILE>
 | 
			
		||||
MetaWorkspace
 | 
			
		||||
MetaWorkspaceClass
 | 
			
		||||
meta_workspace_index
 | 
			
		||||
meta_workspace_get_screen
 | 
			
		||||
meta_workspace_list_windows
 | 
			
		||||
meta_workspace_get_work_area_for_monitor
 | 
			
		||||
meta_workspace_get_work_area_all_monitors
 | 
			
		||||
meta_workspace_activate
 | 
			
		||||
meta_workspace_activate_with_focus
 | 
			
		||||
meta_workspace_update_window_hints
 | 
			
		||||
meta_workspace_set_builtin_struts
 | 
			
		||||
meta_workspace_get_neighbor
 | 
			
		||||
<SUBSECTION Standard>
 | 
			
		||||
META_IS_WORKSPACE
 | 
			
		||||
META_IS_WORKSPACE_CLASS
 | 
			
		||||
META_TYPE_WORKSPACE
 | 
			
		||||
META_WORKSPACE
 | 
			
		||||
META_WORKSPACE_CLASS
 | 
			
		||||
META_WORKSPACE_GET_CLASS
 | 
			
		||||
meta_workspace_get_type
 | 
			
		||||
</SECTION>
 | 
			
		||||
 | 
			
		||||
@@ -1,15 +0,0 @@
 | 
			
		||||
<part id="mutter-overview">
 | 
			
		||||
 | 
			
		||||
  <title>Overview</title>
 | 
			
		||||
 | 
			
		||||
  <partintro>
 | 
			
		||||
 | 
			
		||||
    <para>Mutter is a GObject-based library for creating compositing window managers.</para>
 | 
			
		||||
 | 
			
		||||
    <para>Compositors that wish to use Mutter must implement a subclass of #MetaPlugin and register it with meta_plugin_manager_set_plugin_type() before calling meta_init() but after g_type_init().</para>
 | 
			
		||||
 | 
			
		||||
    <para>#MetaPlugin provides virtual functions that allow to override default behavior in the window management code, such as the effect to perform when a window is created or when switching workspaces.</para>
 | 
			
		||||
 | 
			
		||||
  </partintro>
 | 
			
		||||
 | 
			
		||||
</part>
 | 
			
		||||
@@ -1,100 +0,0 @@
 | 
			
		||||
<part id="running-mutter">
 | 
			
		||||
 | 
			
		||||
  <title>Running Mutter</title>
 | 
			
		||||
 | 
			
		||||
  <partintro>
 | 
			
		||||
 | 
			
		||||
    <section id="environment-variables">
 | 
			
		||||
      <title>Environment Variables</title>
 | 
			
		||||
 | 
			
		||||
      <para>
 | 
			
		||||
        Mutter automatically checks environment variables during
 | 
			
		||||
        its initialization. These environment variables are meant
 | 
			
		||||
        as debug tools or overrides for default behaviours:
 | 
			
		||||
      </para>
 | 
			
		||||
 | 
			
		||||
      <variablelist>
 | 
			
		||||
        <varlistentry>
 | 
			
		||||
          <term>MUTTER_VERBOSE</term>
 | 
			
		||||
          <listitem>
 | 
			
		||||
            <para>Enable verbose mode, in which more information is printed to the console. Mutter needs to be built with the --enable-verbose-mode option (enabled by default). For more fine-grained control of the output, see meta_add_verbose_topic().</para>
 | 
			
		||||
          </listitem>
 | 
			
		||||
        </varlistentry>
 | 
			
		||||
        <varlistentry>
 | 
			
		||||
          <term>MUTTER_DEBUG</term>
 | 
			
		||||
          <listitem>
 | 
			
		||||
            <para>Traps and prints X errors to the console.</para>
 | 
			
		||||
          </listitem>
 | 
			
		||||
        </varlistentry>
 | 
			
		||||
        <varlistentry>
 | 
			
		||||
          <term>MUTTER_G_FATAL_WARNINGS</term>
 | 
			
		||||
          <listitem>
 | 
			
		||||
            <para>Causes any logging from the domains Mutter, Gtk, Gdk, Pango or GLib to terminate the process (only when using the log functions in GLib).</para>
 | 
			
		||||
          </listitem>
 | 
			
		||||
        </varlistentry>
 | 
			
		||||
        <varlistentry>
 | 
			
		||||
          <term>MUTTER_USE_LOGFILE</term>
 | 
			
		||||
          <listitem>
 | 
			
		||||
            <para>Log all messages to a temporary file.</para>
 | 
			
		||||
          </listitem>
 | 
			
		||||
        </varlistentry>
 | 
			
		||||
        <varlistentry>
 | 
			
		||||
          <term>MUTTER_DEBUG_XINERAMA</term>
 | 
			
		||||
          <listitem>
 | 
			
		||||
            <para>Log extra information about support of the XINERAMA extension.</para>
 | 
			
		||||
          </listitem>
 | 
			
		||||
        </varlistentry>
 | 
			
		||||
        <varlistentry>
 | 
			
		||||
          <term>MUTTER_DEBUG_SM</term>
 | 
			
		||||
          <listitem>
 | 
			
		||||
            <para>Log extra information about session management.</para>
 | 
			
		||||
          </listitem>
 | 
			
		||||
        </varlistentry>
 | 
			
		||||
        <varlistentry>
 | 
			
		||||
          <term>MUTTER_DEBUG_BUTTON_GRABS</term>
 | 
			
		||||
          <listitem>
 | 
			
		||||
            <para>Log extra information about button grabs.</para>
 | 
			
		||||
          </listitem>
 | 
			
		||||
        </varlistentry>
 | 
			
		||||
        <varlistentry>
 | 
			
		||||
          <term>MUTTER_SYNC</term>
 | 
			
		||||
          <listitem>
 | 
			
		||||
            <para>Call XSync after each X call.</para>
 | 
			
		||||
          </listitem>
 | 
			
		||||
        </varlistentry>
 | 
			
		||||
        <varlistentry>
 | 
			
		||||
          <term>MUTTER_DISPLAY</term>
 | 
			
		||||
          <listitem>
 | 
			
		||||
            <para>Name of the X11 display to use.</para>
 | 
			
		||||
          </listitem>
 | 
			
		||||
        </varlistentry>
 | 
			
		||||
        <varlistentry>
 | 
			
		||||
          <term>META_DISABLE_MIPMAPS</term>
 | 
			
		||||
          <listitem>
 | 
			
		||||
            <para>Disable use of mipmaps for the textures that back window pixmaps.</para>
 | 
			
		||||
          </listitem>
 | 
			
		||||
        </varlistentry>
 | 
			
		||||
        <varlistentry>
 | 
			
		||||
          <term>MUTTER_USE_STATIC_GRAVITY</term>
 | 
			
		||||
          <listitem>
 | 
			
		||||
            <para>Enable support for clients with static bit-gravity.</para>
 | 
			
		||||
          </listitem>
 | 
			
		||||
        </varlistentry>
 | 
			
		||||
        <varlistentry>
 | 
			
		||||
          <term>MUTTER_WM_CLASS_FILTER</term>
 | 
			
		||||
          <listitem>
 | 
			
		||||
            <para>Comma-separated list of WM_CLASS names to which to restrict Mutter to.</para>
 | 
			
		||||
          </listitem>
 | 
			
		||||
        </varlistentry>
 | 
			
		||||
        <varlistentry>
 | 
			
		||||
          <term>MUTTER_DISABLE_FALLBACK_COLOR</term>
 | 
			
		||||
          <listitem>
 | 
			
		||||
            <para>Disable fallback for themed colors, for easier detection of typographical errors.</para>
 | 
			
		||||
          </listitem>
 | 
			
		||||
        </varlistentry>
 | 
			
		||||
      </variablelist>
 | 
			
		||||
 | 
			
		||||
    </section>
 | 
			
		||||
 | 
			
		||||
  </partintro>
 | 
			
		||||
</part>
 | 
			
		||||
@@ -1 +1,2 @@
 | 
			
		||||
data/mutter-wayland.desktop.in
 | 
			
		||||
# List of source files that should NOT be translated.
 | 
			
		||||
# Please keep this file sorted alphabetically.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										66
									
								
								po/cs.po
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								po/cs.po
									
									
									
									
									
								
							@@ -30,91 +30,91 @@ msgstr "Navigace"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:2
 | 
			
		||||
msgid "Move window to workspace 1"
 | 
			
		||||
msgstr "Přesunout okno na plochu 1"
 | 
			
		||||
msgstr "Přesunout okno na pracovní plochu 1"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:3
 | 
			
		||||
msgid "Move window to workspace 2"
 | 
			
		||||
msgstr "Přesunout okno na plochu 2"
 | 
			
		||||
msgstr "Přesunout okno na pracovní plochu 2"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:4
 | 
			
		||||
msgid "Move window to workspace 3"
 | 
			
		||||
msgstr "Přesunout okno na plochu 3"
 | 
			
		||||
msgstr "Přesunout okno na pracovní plochu 3"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:5
 | 
			
		||||
msgid "Move window to workspace 4"
 | 
			
		||||
msgstr "Přesunout okno na plochu 4"
 | 
			
		||||
msgstr "Přesunout okno na pracovní plochu 4"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:6
 | 
			
		||||
msgid "Move window to last workspace"
 | 
			
		||||
msgstr "Přesunout okno na poslední plochu"
 | 
			
		||||
msgstr "Přesunout okno na poslední pracovní plochu"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:7
 | 
			
		||||
msgid "Move window one workspace to the left"
 | 
			
		||||
msgstr "Přesunout okno o plochu doleva"
 | 
			
		||||
msgstr "Přesunout okno o jednu pracovní plochu doleva"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:8
 | 
			
		||||
msgid "Move window one workspace to the right"
 | 
			
		||||
msgstr "Přesunout okno o plochu doprava"
 | 
			
		||||
msgstr "Přesunout okno o jednu pracovní plochu doprava"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:9
 | 
			
		||||
msgid "Move window one workspace up"
 | 
			
		||||
msgstr "Přesunout okno o plochu nahoru"
 | 
			
		||||
msgstr "Přesunout okno o jednu pracovní plochu nahoru"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:10
 | 
			
		||||
msgid "Move window one workspace down"
 | 
			
		||||
msgstr "Přesunout okno o plochu dolů"
 | 
			
		||||
msgstr "Přesunout okno o jednu pracovní plochu dolů"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:11
 | 
			
		||||
msgid "Move window one monitor to the left"
 | 
			
		||||
msgstr "Přesunout okno o monitor doleva"
 | 
			
		||||
msgstr "Přesunout okno o jeden monitor doleva"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:12
 | 
			
		||||
msgid "Move window one monitor to the right"
 | 
			
		||||
msgstr "Přesunout okno o monitor doprava"
 | 
			
		||||
msgstr "Přesunout okno o jeden monitor doprava"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:13
 | 
			
		||||
msgid "Move window one monitor up"
 | 
			
		||||
msgstr "Přesunout okno o monitor nahoru"
 | 
			
		||||
msgstr "Přesunout okno o jeden monitor nahoru"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:14
 | 
			
		||||
msgid "Move window one monitor down"
 | 
			
		||||
msgstr "Přesunout okno o monitor dolů"
 | 
			
		||||
msgstr "Přesunout okno o jeden monitor dolů"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:15
 | 
			
		||||
msgid "Switch applications"
 | 
			
		||||
msgstr "Přepnout mezi aplikacemi"
 | 
			
		||||
msgstr "Přepnout do jiné aplikace"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:16
 | 
			
		||||
msgid "Switch to previous application"
 | 
			
		||||
msgstr "Přepnout na předchozí aplikaci"
 | 
			
		||||
msgstr "Přepnout do předchozí aplikaci"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:17
 | 
			
		||||
msgid "Switch windows"
 | 
			
		||||
msgstr "Přepnout mezi okny"
 | 
			
		||||
msgstr "Přepnout do jiného okna"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:18
 | 
			
		||||
msgid "Switch to previous window"
 | 
			
		||||
msgstr "Přepnout na předchozí okno"
 | 
			
		||||
msgstr "Přepnout do minulého okna"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:19
 | 
			
		||||
msgid "Switch windows of an application"
 | 
			
		||||
msgstr "Přepnout mezi okny aplikace"
 | 
			
		||||
msgstr "Přepnout do jiného okna aplikace"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:20
 | 
			
		||||
msgid "Switch to previous window of an application"
 | 
			
		||||
msgstr "Přepnout na předchozí okno aplikace"
 | 
			
		||||
msgstr "Přepnout do předchozího okna aplikace"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:21
 | 
			
		||||
msgid "Switch system controls"
 | 
			
		||||
msgstr "Přepnout mezi systémovými ovládacími prvky"
 | 
			
		||||
msgstr "Přepnout na systémový ovládací prvek"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:22
 | 
			
		||||
msgid "Switch to previous system control"
 | 
			
		||||
msgstr "Přepnout na předchozí systémové ovládací prvky"
 | 
			
		||||
msgstr "Přepnout na minulý systémový ovládací prvek"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:23
 | 
			
		||||
msgid "Switch windows directly"
 | 
			
		||||
msgstr "Přepnout přímo mezi okny"
 | 
			
		||||
msgstr "Přepnout do minulého okna"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:24
 | 
			
		||||
msgid "Switch directly to previous window"
 | 
			
		||||
@@ -122,15 +122,15 @@ msgstr "Přepnout přímo na předchozí okno"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:25
 | 
			
		||||
msgid "Switch windows of an app directly"
 | 
			
		||||
msgstr "Přepnout přímo mezi okny aplikace"
 | 
			
		||||
msgstr "Přepnout do jiného okna aplikace"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:26
 | 
			
		||||
msgid "Switch directly to previous window of an app"
 | 
			
		||||
msgstr "Přepnout přímo na předchozí okno aplikace"
 | 
			
		||||
msgstr "Přepnout do předchozího okna aplikace"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:27
 | 
			
		||||
msgid "Switch system controls directly"
 | 
			
		||||
msgstr "Přepnout přímo mezi systémovými ovládacími prvky"
 | 
			
		||||
msgstr "Přepnout na minulý systémový ovládací prvek"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:28
 | 
			
		||||
msgid "Switch directly to previous system control"
 | 
			
		||||
@@ -198,7 +198,7 @@ msgstr "Aktivovat nabídku okna"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-windows.xml.in.h:3
 | 
			
		||||
msgid "Toggle fullscreen mode"
 | 
			
		||||
msgstr "Přepnout režim na celou obrazovku"
 | 
			
		||||
msgstr "Přepnout režim celé obrazovky"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-windows.xml.in.h:4
 | 
			
		||||
msgid "Toggle maximization state"
 | 
			
		||||
@@ -210,7 +210,7 @@ msgstr "Maximalizovat okno"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-windows.xml.in.h:6
 | 
			
		||||
msgid "Restore window"
 | 
			
		||||
msgstr "Obnovit okno"
 | 
			
		||||
msgstr "Obnovit velikost okna"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-windows.xml.in.h:7
 | 
			
		||||
msgid "Toggle shaded state"
 | 
			
		||||
@@ -234,20 +234,20 @@ msgstr "Změnit velikost okna"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-windows.xml.in.h:12
 | 
			
		||||
msgid "Toggle window on all workspaces or one"
 | 
			
		||||
msgstr "Přepnout výskyt okna na všech plochách nebo jen na jedné"
 | 
			
		||||
msgstr "Přepnout okno na všechny/jednu pracovní plochu"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-windows.xml.in.h:13
 | 
			
		||||
msgid "Raise window if covered, otherwise lower it"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Přenést okno do popředí, pokud je zakryté, jinak jej odsunout do pozadí"
 | 
			
		||||
"Když je okno zakryté vynést jej do popředí, jinak odsunout do pozadí"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-windows.xml.in.h:14
 | 
			
		||||
msgid "Raise window above other windows"
 | 
			
		||||
msgstr "Přenést okno do popředí nad ostatní okna"
 | 
			
		||||
msgstr "Vynést okno do popředí nad ostatní okna"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-windows.xml.in.h:15
 | 
			
		||||
msgid "Lower window below other windows"
 | 
			
		||||
msgstr "Odsunout okno do pozadí pod ostatní okna"
 | 
			
		||||
msgstr "Odsunout okno do pozadí za ostatní okna"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-windows.xml.in.h:16
 | 
			
		||||
msgid "Maximize window vertically"
 | 
			
		||||
@@ -259,11 +259,11 @@ msgstr "Maximalizovat okno vodorovně"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-windows.xml.in.h:18
 | 
			
		||||
msgid "View split on left"
 | 
			
		||||
msgstr "Zobrazit rozdělení nalevo"
 | 
			
		||||
msgstr "Rozdělit okno přes levou půlku obrazovky"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-windows.xml.in.h:19
 | 
			
		||||
msgid "View split on right"
 | 
			
		||||
msgstr "Zobrazit rozdělení napravo"
 | 
			
		||||
msgstr "Rozdělit okno přes pravou půlku obrazovky"
 | 
			
		||||
 | 
			
		||||
#: ../data/mutter.desktop.in.h:1
 | 
			
		||||
msgid "Mutter"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										114
									
								
								po/lt.po
									
									
									
									
									
								
							
							
						
						
									
										114
									
								
								po/lt.po
									
									
									
									
									
								
							@@ -13,8 +13,8 @@ msgstr ""
 | 
			
		||||
"Project-Id-Version: lt\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
 | 
			
		||||
"product=mutter&keywords=I18N+L10N&component=general\n"
 | 
			
		||||
"POT-Creation-Date: 2015-02-28 11:14+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2015-02-28 21:34+0200\n"
 | 
			
		||||
"POT-Creation-Date: 2016-01-05 13:43+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2016-01-05 18:04+0200\n"
 | 
			
		||||
"Last-Translator: Aurimas Černius <aurisc4@gmail.com>\n"
 | 
			
		||||
"Language-Team: Lietuvių <gnome-lt@lists.akl.lt>\n"
 | 
			
		||||
"Language: lt\n"
 | 
			
		||||
@@ -23,7 +23,7 @@ msgstr ""
 | 
			
		||||
"Content-Transfer-Encoding: 8bit\n"
 | 
			
		||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n"
 | 
			
		||||
"%100<10 || n%100>=20) ? 1 : 2);\n"
 | 
			
		||||
"X-Generator: Gtranslator 2.91.6\n"
 | 
			
		||||
"X-Generator: Poedit 1.8.6\n"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:1
 | 
			
		||||
msgid "Navigation"
 | 
			
		||||
@@ -31,39 +31,39 @@ msgstr "Navigacija"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:2
 | 
			
		||||
msgid "Move window to workspace 1"
 | 
			
		||||
msgstr "Perkelti langą į darbalaukį Nr.1"
 | 
			
		||||
msgstr "Perkelti langą į darbo sritį Nr.1"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:3
 | 
			
		||||
msgid "Move window to workspace 2"
 | 
			
		||||
msgstr "Perkelti langą į darbalaukį Nr.2"
 | 
			
		||||
msgstr "Perkelti langą į darbo sritį Nr.2"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:4
 | 
			
		||||
msgid "Move window to workspace 3"
 | 
			
		||||
msgstr "Perkelti langą į darbalaukį Nr.3"
 | 
			
		||||
msgstr "Perkelti langą į darbo sritį Nr.3"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:5
 | 
			
		||||
msgid "Move window to workspace 4"
 | 
			
		||||
msgstr "Perkelti langą į darbalaukį Nr.4"
 | 
			
		||||
msgstr "Perkelti langą į darbo sritį Nr.4"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:6
 | 
			
		||||
msgid "Move window to last workspace"
 | 
			
		||||
msgstr "Perkelti langą į pastarąjį darbalaukį"
 | 
			
		||||
msgstr "Perkelti langą į pastarąją darbo sritį"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:7
 | 
			
		||||
msgid "Move window one workspace to the left"
 | 
			
		||||
msgstr "Perkelti langą į kairiau esantį darbalaukį"
 | 
			
		||||
msgstr "Perkelti langą į kairiau esančią darbo sritį"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:8
 | 
			
		||||
msgid "Move window one workspace to the right"
 | 
			
		||||
msgstr "Perkelti langą į dešiniau esantį darbalaukį"
 | 
			
		||||
msgstr "Perkelti langą į dešiniau esančią darbo sritį"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:9
 | 
			
		||||
msgid "Move window one workspace up"
 | 
			
		||||
msgstr "Perkelti langą į aukščiau esantį darbalaukį"
 | 
			
		||||
msgstr "Perkelti langą į aukščiau esančią darbo sritį"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:10
 | 
			
		||||
msgid "Move window one workspace down"
 | 
			
		||||
msgstr "Perkelti langą į žemiau esantį darbalaukį"
 | 
			
		||||
msgstr "Perkelti langą į žemiau esančią darbo sritį"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:11
 | 
			
		||||
msgid "Move window one monitor to the left"
 | 
			
		||||
@@ -143,39 +143,39 @@ msgstr "Paslėpti visus įprastinius langus"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:30
 | 
			
		||||
msgid "Switch to workspace 1"
 | 
			
		||||
msgstr "Persijungti į darbalaukį Nr.1"
 | 
			
		||||
msgstr "Persijungti į darbo sritį Nr.1"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:31
 | 
			
		||||
msgid "Switch to workspace 2"
 | 
			
		||||
msgstr "Persijungti į darbalaukį Nr.2"
 | 
			
		||||
msgstr "Persijungti į darbo sritį Nr.2"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:32
 | 
			
		||||
msgid "Switch to workspace 3"
 | 
			
		||||
msgstr "Persijungti į darbalaukį Nr.3"
 | 
			
		||||
msgstr "Persijungti į darbo sritį Nr.3"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:33
 | 
			
		||||
msgid "Switch to workspace 4"
 | 
			
		||||
msgstr "Persijungti į darbalaukį Nr.4"
 | 
			
		||||
msgstr "Persijungti į darbo sritį Nr.4"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:34
 | 
			
		||||
msgid "Switch to last workspace"
 | 
			
		||||
msgstr "Persijungti į pastarąjį darbalaukį"
 | 
			
		||||
msgstr "Persijungti į pastarąją darbo sritį"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:35
 | 
			
		||||
msgid "Move to workspace left"
 | 
			
		||||
msgstr "Perkelti į darbalaukį kairėje"
 | 
			
		||||
msgstr "Perkelti į darbo sritį kairėje"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:36
 | 
			
		||||
msgid "Move to workspace right"
 | 
			
		||||
msgstr "Perkelti į darbalaukį dešinėje"
 | 
			
		||||
msgstr "Perkelti į darbo sritį dešinėje"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:37
 | 
			
		||||
msgid "Move to workspace above"
 | 
			
		||||
msgstr "Perkelti į darbalaukį viršuje"
 | 
			
		||||
msgstr "Perkelti į darbo sritį viršuje"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-navigation.xml.in.h:38
 | 
			
		||||
msgid "Move to workspace below"
 | 
			
		||||
msgstr "Perkelti į darbalaukį apačioje"
 | 
			
		||||
msgstr "Perkelti į darbo sritį apačioje"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-system.xml.in.h:1
 | 
			
		||||
msgid "System"
 | 
			
		||||
@@ -235,7 +235,7 @@ msgstr "Keisti lango dydį"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-windows.xml.in.h:12
 | 
			
		||||
msgid "Toggle window on all workspaces or one"
 | 
			
		||||
msgstr "Perjungti lango buvimo visuose darbalaukiuose būseną"
 | 
			
		||||
msgstr "Perjungti lango buvimo visose darbo srityse būseną"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-mutter-windows.xml.in.h:13
 | 
			
		||||
msgid "Raise window if covered, otherwise lower it"
 | 
			
		||||
@@ -272,7 +272,7 @@ msgstr "Mutter"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:1
 | 
			
		||||
msgid "Modifier to use for extended window management operations"
 | 
			
		||||
msgstr "Klavišas, naudojamas kartu su specialiais lango valdymo veiksmais"
 | 
			
		||||
msgstr "Klavišas, naudojamas kartu su specialiomis lango tvarkymo operacijomis"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:2
 | 
			
		||||
msgid ""
 | 
			
		||||
@@ -315,7 +315,7 @@ msgstr ""
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:7
 | 
			
		||||
msgid "Workspaces are managed dynamically"
 | 
			
		||||
msgstr "Darbalaukiai valdomi dinamiškai"
 | 
			
		||||
msgstr "Darbo sritys tvarkomos dinamiškai"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:8
 | 
			
		||||
msgid ""
 | 
			
		||||
@@ -323,21 +323,21 @@ msgid ""
 | 
			
		||||
"static number of workspaces (determined by the num-workspaces key in org."
 | 
			
		||||
"gnome.desktop.wm.preferences)."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Nusako, ar darbastaliai yra valdomi dinamiškai, ar yra pastovus darbalaukių "
 | 
			
		||||
"skaičius (nusakomas raktu num-workspaces schemoje org.gnome.desktop.wm."
 | 
			
		||||
"preferences)."
 | 
			
		||||
"Nusako, ar darbo sritys yra tvarkomos dinamiškai, ar yra pastovus darbo "
 | 
			
		||||
"sričių skaičius (nusakomas raktu num-workspaces schemoje org.gnome.desktop."
 | 
			
		||||
"wm.preferences)."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:9
 | 
			
		||||
msgid "Workspaces only on primary"
 | 
			
		||||
msgstr "Darbalaukiai tik pagrindiniame"
 | 
			
		||||
msgstr "Darbo sritys tik pagrindiniame"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:10
 | 
			
		||||
msgid ""
 | 
			
		||||
"Determines whether workspace switching should happen for windows on all "
 | 
			
		||||
"monitors or only for windows on the primary monitor."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Nusako, ar darbalaukių perjungimas turi įvykti langams viusose monitoriuose, "
 | 
			
		||||
"ar tik langams pagrindiniame monitoriuje."
 | 
			
		||||
"Nusako, ar darbo sričių perjungimas turi įvykti langams visuose "
 | 
			
		||||
"monitoriuose, ar tik langams pagrindiniame monitoriuje."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:11
 | 
			
		||||
msgid "No tab popup"
 | 
			
		||||
@@ -438,46 +438,41 @@ msgid "Switch to VT 7"
 | 
			
		||||
msgstr "Persijungti į VT 7"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:8
 | 
			
		||||
#| msgid "Switch to VT 1"
 | 
			
		||||
msgid "Switch to VT 8"
 | 
			
		||||
msgstr "Persijungti į VT 8"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:9
 | 
			
		||||
#| msgid "Switch to VT 1"
 | 
			
		||||
msgid "Switch to VT 9"
 | 
			
		||||
msgstr "Persijungti į VT 9"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:10
 | 
			
		||||
#| msgid "Switch to VT 1"
 | 
			
		||||
msgid "Switch to VT 10"
 | 
			
		||||
msgstr "Persijungti į VT 10"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:11
 | 
			
		||||
#| msgid "Switch to VT 1"
 | 
			
		||||
msgid "Switch to VT 11"
 | 
			
		||||
msgstr "Persijungti į VT 11"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:12
 | 
			
		||||
#| msgid "Switch to VT 1"
 | 
			
		||||
msgid "Switch to VT 12"
 | 
			
		||||
msgstr "Persijungti į VT 12"
 | 
			
		||||
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:364
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:518
 | 
			
		||||
msgid "Built-in display"
 | 
			
		||||
msgstr "Integruotas vaizduoklis"
 | 
			
		||||
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:391
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:544
 | 
			
		||||
msgid "Unknown"
 | 
			
		||||
msgstr "Nežinomas"
 | 
			
		||||
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:393
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:546
 | 
			
		||||
msgid "Unknown Display"
 | 
			
		||||
msgstr "Nežinomas vaizduoklis"
 | 
			
		||||
 | 
			
		||||
#. TRANSLATORS: this is a monitor vendor name, followed by a
 | 
			
		||||
#. * size in inches, like 'Dell 15"'
 | 
			
		||||
#.
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:401
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:554
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%s %s"
 | 
			
		||||
msgstr "%s %s"
 | 
			
		||||
@@ -489,7 +484,7 @@ msgstr "%s %s"
 | 
			
		||||
msgid ""
 | 
			
		||||
"Another compositing manager is already running on screen %i on display \"%s"
 | 
			
		||||
"\"."
 | 
			
		||||
msgstr "Kita kompozicijos valdyklė jau veikia ekrane %i vaizduoklyje „%s“."
 | 
			
		||||
msgstr "Kita kompozicijos tvarkytuvė jau veikia ekrane %i vaizduoklyje „%s“."
 | 
			
		||||
 | 
			
		||||
#: ../src/core/bell.c:185
 | 
			
		||||
msgid "Bell event"
 | 
			
		||||
@@ -518,40 +513,40 @@ msgstr "_Laukti"
 | 
			
		||||
msgid "_Force Quit"
 | 
			
		||||
msgstr "_Priverstinai išeiti"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/display.c:562
 | 
			
		||||
#: ../src/core/display.c:563
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Failed to open X Window System display '%s'\n"
 | 
			
		||||
msgstr "Nepavyko atverti X Window sistemos ekrano „%s“\n"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/main.c:176
 | 
			
		||||
#: ../src/core/main.c:180
 | 
			
		||||
msgid "Disable connection to session manager"
 | 
			
		||||
msgstr "Išjungti susijungimą su sesijos valdykle"
 | 
			
		||||
msgstr "Išjungti susijungimą su sesijos tvarkytuve"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/main.c:182
 | 
			
		||||
#: ../src/core/main.c:186
 | 
			
		||||
msgid "Replace the running window manager"
 | 
			
		||||
msgstr "Pakeisti veikiančią langų valdyklę"
 | 
			
		||||
msgstr "Pakeisti veikiančią langų tvarkytuvę"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/main.c:188
 | 
			
		||||
#: ../src/core/main.c:192
 | 
			
		||||
msgid "Specify session management ID"
 | 
			
		||||
msgstr "Nurodyti sesijos valdymo ID"
 | 
			
		||||
msgstr "Nurodyti sesijos tvarkymo ID"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/main.c:193
 | 
			
		||||
#: ../src/core/main.c:197
 | 
			
		||||
msgid "X Display to use"
 | 
			
		||||
msgstr "Naudotinas X ekranas"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/main.c:199
 | 
			
		||||
#: ../src/core/main.c:203
 | 
			
		||||
msgid "Initialize session from savefile"
 | 
			
		||||
msgstr "Inicializuoti sesiją iš išsaugojimo failo"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/main.c:205
 | 
			
		||||
#: ../src/core/main.c:209
 | 
			
		||||
msgid "Make X calls synchronous"
 | 
			
		||||
msgstr "Sinchronizuoti X iškvietimus"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/main.c:212
 | 
			
		||||
#: ../src/core/main.c:216
 | 
			
		||||
msgid "Run as a wayland compositor"
 | 
			
		||||
msgstr "Vykdyti kaip wayland kompozitorių"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/main.c:220
 | 
			
		||||
#: ../src/core/main.c:224
 | 
			
		||||
msgid "Run as a full display server, rather than nested"
 | 
			
		||||
msgstr "Vykdyti kaip visą vaizduoklio serverį, o ne vidinį"
 | 
			
		||||
 | 
			
		||||
@@ -580,24 +575,21 @@ msgstr "Parodyti versiją"
 | 
			
		||||
msgid "Mutter plugin to use"
 | 
			
		||||
msgstr "Naudojamas Mutter įskiepis"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/prefs.c:2004
 | 
			
		||||
#: ../src/core/prefs.c:1997
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Workspace %d"
 | 
			
		||||
msgstr "Darbalaukis %d"
 | 
			
		||||
msgstr "Darbo sritis %d"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/screen.c:525
 | 
			
		||||
#: ../src/core/screen.c:526
 | 
			
		||||
#, 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 ""
 | 
			
		||||
"Vaizduoklis „%s“ jau turi langų valdyklę; pabandykite pakeisti esamą langų "
 | 
			
		||||
"valdyklę naudodami parametrą --replace."
 | 
			
		||||
"Vaizduoklis „%s“ jau turi langų tvarkytuvę; pabandykite pakeisti esamą langų "
 | 
			
		||||
"tvarkytuvę, naudodami parametrą --replace."
 | 
			
		||||
 | 
			
		||||
#: ../src/core/screen.c:607
 | 
			
		||||
#: ../src/core/screen.c:608
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Screen %d on display '%s' is invalid\n"
 | 
			
		||||
msgstr "Ekranas %d vaizduoklyje „%s“ netinkamas\n"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										51
									
								
								po/pl.po
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								po/pl.po
									
									
									
									
									
								
							@@ -15,8 +15,8 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: mutter\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: \n"
 | 
			
		||||
"POT-Creation-Date: 2015-03-05 00:23+0100\n"
 | 
			
		||||
"PO-Revision-Date: 2015-03-05 00:24+0100\n"
 | 
			
		||||
"POT-Creation-Date: 2015-08-26 18:49+0200\n"
 | 
			
		||||
"PO-Revision-Date: 2015-08-26 18:50+0200\n"
 | 
			
		||||
"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
 | 
			
		||||
"Language-Team: Polish <gnomepl@aviary.pl>\n"
 | 
			
		||||
"Language: pl\n"
 | 
			
		||||
@@ -285,9 +285,9 @@ msgid ""
 | 
			
		||||
"\"Windows key\" on PC hardware. It's expected that this binding either the "
 | 
			
		||||
"default or set to the empty string."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Ten klawisz inicjuje tryb \"overlay\", który jest połączeniem podglądu okien "
 | 
			
		||||
"i systemu uruchamiania programów. Domyślnie jest przeznaczony do powiązania "
 | 
			
		||||
"z klawiszem \"Windows\" na komputerach typu PC. Ustawienie tego powiązania "
 | 
			
		||||
"Ten klawisz inicjuje tryb „overlay”, który jest połączeniem podglądu okien i "
 | 
			
		||||
"systemu uruchamiania programów. Domyślnie jest przeznaczony do powiązania z "
 | 
			
		||||
"klawiszem „Windows” na komputerach typu PC. Ustawienie tego powiązania "
 | 
			
		||||
"powinno być domyślne lub puste."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:3
 | 
			
		||||
@@ -300,9 +300,9 @@ msgid ""
 | 
			
		||||
"attached to the titlebar of the parent window and are moved together with "
 | 
			
		||||
"the parent window."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Jeśli wynosi \"true\", to modalne okna dialogowe pojawiają się dołączone do "
 | 
			
		||||
"paska tytułowego okna nadrzędnego zamiast posiadać oddzielne paski tytułowe "
 | 
			
		||||
"i są przenoszone razem z nim."
 | 
			
		||||
"Jeśli wynosi wartość „true”, to modalne okna dialogowe pojawiają się "
 | 
			
		||||
"dołączone do paska tytułowego okna nadrzędnego zamiast posiadać oddzielne "
 | 
			
		||||
"paski tytułowe i są przenoszone razem z nim."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:5
 | 
			
		||||
msgid "Enable edge tiling when dropping windows on screen edges"
 | 
			
		||||
@@ -332,7 +332,7 @@ msgid ""
 | 
			
		||||
"gnome.desktop.wm.preferences)."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Określa, czy obszary robocze są zarządzane dynamicznie, czy istnieje "
 | 
			
		||||
"statyczna liczba obszarów (określona przez klucz \"num-workspaces\" w org."
 | 
			
		||||
"statyczna liczba obszarów (określona przez klucz „num-workspaces” w org."
 | 
			
		||||
"gnome.desktop.wm.preferences)."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:9
 | 
			
		||||
@@ -369,9 +369,9 @@ msgid ""
 | 
			
		||||
"the focus will not be changed immediately when entering a window, but only "
 | 
			
		||||
"after the pointer stops moving."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Jeśli jest ustawione na wartość \"true\", a tryb aktywności to \"sloppy\" "
 | 
			
		||||
"lub \"mouse\", to aktywność nie będzie zmieniana od razu po przejściu do "
 | 
			
		||||
"okna, ale dopiero po zatrzymaniu ruchu kursora."
 | 
			
		||||
"Jeśli jest ustawione na wartość „true”, a tryb aktywności to „sloppy” lub "
 | 
			
		||||
"„mouse”, to aktywność nie będzie zmieniana od razu po przejściu do okna, ale "
 | 
			
		||||
"dopiero po zatrzymaniu ruchu kursora."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:15
 | 
			
		||||
msgid "Draggable border width"
 | 
			
		||||
@@ -409,7 +409,7 @@ msgid ""
 | 
			
		||||
"When true, the new windows will always be put in the center of the active "
 | 
			
		||||
"screen of the monitor."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Jeśli wynosi \"true\", to nowe okna będą zawsze umieszczane na środku "
 | 
			
		||||
"Jeśli wynosi wartość „true”, to nowe okna będą zawsze umieszczane na środku "
 | 
			
		||||
"aktywnego ekranu monitora."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:21
 | 
			
		||||
@@ -468,22 +468,22 @@ msgstr "Przełączenie na 11. konsolę wirtualną"
 | 
			
		||||
msgid "Switch to VT 12"
 | 
			
		||||
msgstr "Przełączenie na 12. konsolę wirtualną"
 | 
			
		||||
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:364
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:500
 | 
			
		||||
msgid "Built-in display"
 | 
			
		||||
msgstr "Wbudowany ekran"
 | 
			
		||||
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:391
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:526
 | 
			
		||||
msgid "Unknown"
 | 
			
		||||
msgstr "Nieznany"
 | 
			
		||||
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:393
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:528
 | 
			
		||||
msgid "Unknown Display"
 | 
			
		||||
msgstr "Nieznany ekran"
 | 
			
		||||
 | 
			
		||||
#. TRANSLATORS: this is a monitor vendor name, followed by a
 | 
			
		||||
#. * size in inches, like 'Dell 15"'
 | 
			
		||||
#.
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:401
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:536
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%s %s"
 | 
			
		||||
msgstr "%s %s"
 | 
			
		||||
@@ -496,7 +496,7 @@ msgid ""
 | 
			
		||||
"Another compositing manager is already running on screen %i on display \"%s"
 | 
			
		||||
"\"."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Inny menedżer składania jest już uruchomiony na podekranie %i ekranu \"%s\"."
 | 
			
		||||
"Inny menedżer składania jest już uruchomiony na podekranie %i ekranu „%s”."
 | 
			
		||||
 | 
			
		||||
#: ../src/core/bell.c:185
 | 
			
		||||
msgid "Bell event"
 | 
			
		||||
@@ -505,7 +505,7 @@ msgstr "Zdarzenie sygnału dźwiękowego"
 | 
			
		||||
#: ../src/core/delete.c:127
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "“%s” is not responding."
 | 
			
		||||
msgstr "Okno \"%s\" nie odpowiada."
 | 
			
		||||
msgstr "Okno „%s” nie odpowiada."
 | 
			
		||||
 | 
			
		||||
#: ../src/core/delete.c:129
 | 
			
		||||
msgid "Application is not responding."
 | 
			
		||||
@@ -525,11 +525,10 @@ msgstr "_Czekaj"
 | 
			
		||||
msgid "_Force Quit"
 | 
			
		||||
msgstr "_Zakończ"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/display.c:562
 | 
			
		||||
#: ../src/core/display.c:563
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Failed to open X Window System display '%s'\n"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Otwarcie połączenia z ekranem \"%s\" systemu X Window się nie powiodło\n"
 | 
			
		||||
msgstr "Otwarcie połączenia z ekranem „%s” systemu X Window się nie powiodło\n"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/main.c:176
 | 
			
		||||
msgid "Disable connection to session manager"
 | 
			
		||||
@@ -573,7 +572,7 @@ msgid ""
 | 
			
		||||
"PARTICULAR PURPOSE.\n"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"mutter %s\n"
 | 
			
		||||
"Copyright (C) 2001-%d Havoc Pennington, Red Hat, Inc., oraz inni\n"
 | 
			
		||||
"Copyright (C) 2001—%d Havoc Pennington, Red Hat, Inc., oraz inni\n"
 | 
			
		||||
"Niniejszy program jest wolnym oprogramowaniem, aby poznać warunki, pod\n"
 | 
			
		||||
"jakimi dopuszczalne jest kopiowanie programu, zajrzyj do jego źródeł.\n"
 | 
			
		||||
"Na program nie udziela się ŻADNYCH GWARANCJI, nawet domyślnej gwarancji\n"
 | 
			
		||||
@@ -598,13 +597,13 @@ msgid ""
 | 
			
		||||
"Display \"%s\" already has a window manager; try using the --replace option "
 | 
			
		||||
"to replace the current window manager."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Na ekranie \"%s\" działa już menedżer okien. Aby zastąpić działającego "
 | 
			
		||||
"Na ekranie „%s” działa już menedżer okien. Aby zastąpić działającego "
 | 
			
		||||
"menedżera okien, proszę spróbować użyć opcji --replace."
 | 
			
		||||
 | 
			
		||||
#: ../src/core/screen.c:607
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Screen %d on display '%s' is invalid\n"
 | 
			
		||||
msgstr "Podekran %d ekranu \"%s\" jest nieprawidłowy\n"
 | 
			
		||||
msgstr "Podekran %d ekranu „%s” jest nieprawidłowy\n"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/util.c:118
 | 
			
		||||
msgid "Mutter was compiled without support for verbose mode\n"
 | 
			
		||||
@@ -616,7 +615,7 @@ msgid ""
 | 
			
		||||
"These windows do not support "save current setup" and will have to "
 | 
			
		||||
"be restarted manually next time you log in."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Te okna nie obsługują opcji zapisu obecnego stanu (\"save current setup\"), "
 | 
			
		||||
"Te okna nie obsługują opcji zapisu obecnego stanu („save current setup”), "
 | 
			
		||||
"więc przy następnym zalogowaniu będą musiały zostać uruchomione ręcznie."
 | 
			
		||||
 | 
			
		||||
#: ../src/x11/window-props.c:549
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								po/zh_TW.po
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								po/zh_TW.po
									
									
									
									
									
								
							@@ -10,7 +10,7 @@ msgstr ""
 | 
			
		||||
"Project-Id-Version: metacity 3.3.4\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
 | 
			
		||||
"product=mutter&keywords=I18N+L10N&component=general\n"
 | 
			
		||||
"POT-Creation-Date: 2015-02-20 23:22+0000\n"
 | 
			
		||||
"POT-Creation-Date: 2015-07-21 10:52+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2015-02-21 16:33+0800\n"
 | 
			
		||||
"Last-Translator: Chao-Hsiung Liao <j_h_liau@yahoo.com.tw>\n"
 | 
			
		||||
"Language-Team: Chinese (Taiwan) <zh-l10n@lists.linux.org.tw>\n"
 | 
			
		||||
@@ -439,22 +439,22 @@ msgstr "切換至 VT 11"
 | 
			
		||||
msgid "Switch to VT 12"
 | 
			
		||||
msgstr "切換至 VT 12"
 | 
			
		||||
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:364
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:500
 | 
			
		||||
msgid "Built-in display"
 | 
			
		||||
msgstr "內建顯示"
 | 
			
		||||
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:391
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:526
 | 
			
		||||
msgid "Unknown"
 | 
			
		||||
msgstr "不明"
 | 
			
		||||
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:393
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:528
 | 
			
		||||
msgid "Unknown Display"
 | 
			
		||||
msgstr "不明的顯示器"
 | 
			
		||||
 | 
			
		||||
#. TRANSLATORS: this is a monitor vendor name, followed by a
 | 
			
		||||
#. * size in inches, like 'Dell 15"'
 | 
			
		||||
#.
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:401
 | 
			
		||||
#: ../src/backends/meta-monitor-manager.c:536
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%s %s"
 | 
			
		||||
msgstr "%s %s"
 | 
			
		||||
@@ -462,7 +462,7 @@ msgstr "%s %s"
 | 
			
		||||
# FIXME: I'm still unclear about the meaning of XGetSelectionOwner -- Abel
 | 
			
		||||
#. 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:456
 | 
			
		||||
#: ../src/compositor/compositor.c:451
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Another compositing manager is already running on screen %i on display \"%s"
 | 
			
		||||
@@ -496,14 +496,14 @@ msgstr "等待(_W)"
 | 
			
		||||
msgid "_Force Quit"
 | 
			
		||||
msgstr "強制結束(_F)"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/display.c:562
 | 
			
		||||
#: ../src/core/display.c:563
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Failed to open X Window System display '%s'\n"
 | 
			
		||||
msgstr "無法開啟 X Window 畫面‘%s’\n"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/main.c:176
 | 
			
		||||
msgid "Disable connection to session manager"
 | 
			
		||||
msgstr "停用到作業階段管理程式的連線"
 | 
			
		||||
msgstr "停用到作業階段管理員的連線"
 | 
			
		||||
 | 
			
		||||
#: ../src/core/main.c:182
 | 
			
		||||
msgid "Replace the running window manager"
 | 
			
		||||
@@ -1053,9 +1053,9 @@ msgstr "%s(在 %s)"
 | 
			
		||||
#~ msgid ""
 | 
			
		||||
#~ "\"%s\" found in configuration database is not a valid value for mouse "
 | 
			
		||||
#~ "button modifier\n"
 | 
			
		||||
#~ msgstr "組態資料庫中的“%s”設定值不是有效的滑鼠按鈕修改功能鍵\n"
 | 
			
		||||
#~ msgstr "設定資料庫中的“%s”設定值不是有效的滑鼠按鈕修改功能鍵\n"
 | 
			
		||||
 | 
			
		||||
#~ msgid ""
 | 
			
		||||
#~ "\"%s\" found in configuration database is not a valid value for "
 | 
			
		||||
#~ "keybinding \"%s\"\n"
 | 
			
		||||
#~ msgstr "組態資料庫中的“%s”不是按鍵組合“%s”的有效設定值\n"
 | 
			
		||||
#~ msgstr "設定資料庫中的“%s”不是按鍵組合“%s”的有效設定值\n"
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@ dist_stacking_DATA =				\
 | 
			
		||||
	tests/stacking/basic-wayland.metatest	\
 | 
			
		||||
	tests/stacking/minimized.metatest   	\
 | 
			
		||||
	tests/stacking/mixed-windows.metatest   \
 | 
			
		||||
	tests/stacking/set-parent.metatest	\
 | 
			
		||||
	tests/stacking/override-redirect.metatest
 | 
			
		||||
 | 
			
		||||
mutter-all.test: tests/mutter-all.test.in
 | 
			
		||||
@@ -41,9 +42,6 @@ endif
 | 
			
		||||
# Some random test programs for bits of the code
 | 
			
		||||
 | 
			
		||||
testboxes_SOURCES = core/testboxes.c
 | 
			
		||||
testasyncgetprop_SOURCES = x11/testasyncgetprop.c
 | 
			
		||||
 | 
			
		||||
noinst_PROGRAMS+=testboxes testasyncgetprop
 | 
			
		||||
 | 
			
		||||
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
 | 
			
		||||
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
 | 
			
		||||
 | 
			
		||||
noinst_PROGRAMS += testboxes
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										103
									
								
								src/Makefile.am
									
									
									
									
									
								
							
							
						
						
									
										103
									
								
								src/Makefile.am
									
									
									
									
									
								
							@@ -39,22 +39,27 @@ mutter_built_sources = \
 | 
			
		||||
	$(dbus_idle_built_sources)		\
 | 
			
		||||
	$(dbus_display_config_built_sources)	\
 | 
			
		||||
	$(dbus_login1_built_sources)		\
 | 
			
		||||
	mutter-enum-types.h 			\
 | 
			
		||||
	mutter-enum-types.c			\
 | 
			
		||||
	meta/meta-enum-types.h			\
 | 
			
		||||
	meta-enum-types.c			\
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
if HAVE_WAYLAND
 | 
			
		||||
mutter_built_sources += \
 | 
			
		||||
	pointer-gestures-unstable-v1-protocol.c				\
 | 
			
		||||
	pointer-gestures-unstable-v1-server-protocol.h			\
 | 
			
		||||
	gtk-shell-protocol.c			\
 | 
			
		||||
	gtk-shell-server-protocol.h		\
 | 
			
		||||
	xdg-shell-protocol.c			\
 | 
			
		||||
	xdg-shell-server-protocol.h		\
 | 
			
		||||
	xdg-shell-unstable-v5-protocol.c				\
 | 
			
		||||
	xdg-shell-unstable-v5-server-protocol.h				\
 | 
			
		||||
	relative-pointer-unstable-v1-protocol.c				\
 | 
			
		||||
	relative-pointer-unstable-v1-server-protocol.h			\
 | 
			
		||||
	pointer-constraints-unstable-v1-protocol.c			\
 | 
			
		||||
	pointer-constraints-unstable-v1-server-protocol.h		\
 | 
			
		||||
	$(NULL)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
wayland_protocols =				\
 | 
			
		||||
	wayland/protocol/gtk-shell.xml		\
 | 
			
		||||
	wayland/protocol/xdg-shell.xml		\
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
libmutter_la_SOURCES =				\
 | 
			
		||||
@@ -65,7 +70,6 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	backends/meta-barrier-private.h		\
 | 
			
		||||
	backends/meta-cursor.c			\
 | 
			
		||||
	backends/meta-cursor.h			\
 | 
			
		||||
	backends/meta-cursor-private.h		\
 | 
			
		||||
	backends/meta-cursor-tracker.c		\
 | 
			
		||||
	backends/meta-cursor-tracker-private.h	\
 | 
			
		||||
	backends/meta-cursor-renderer.c		\
 | 
			
		||||
@@ -84,6 +88,8 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	backends/meta-monitor-manager-private.h	\
 | 
			
		||||
	backends/meta-monitor-manager-dummy.c	\
 | 
			
		||||
	backends/meta-monitor-manager-dummy.h	\
 | 
			
		||||
	backends/meta-pointer-constraint.c	\
 | 
			
		||||
	backends/meta-pointer-constraint.h	\
 | 
			
		||||
	backends/meta-stage.h			\
 | 
			
		||||
	backends/meta-stage.c			\
 | 
			
		||||
	backends/edid-parse.c			\
 | 
			
		||||
@@ -94,6 +100,8 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	backends/x11/meta-barrier-x11.h			\
 | 
			
		||||
	backends/x11/meta-cursor-renderer-x11.c		\
 | 
			
		||||
	backends/x11/meta-cursor-renderer-x11.h		\
 | 
			
		||||
	backends/x11/nested/meta-cursor-renderer-x11-nested.c		\
 | 
			
		||||
	backends/x11/nested/meta-cursor-renderer-x11-nested.h		\
 | 
			
		||||
	backends/x11/meta-idle-monitor-xsync.c		\
 | 
			
		||||
	backends/x11/meta-idle-monitor-xsync.h		\
 | 
			
		||||
	backends/x11/meta-input-settings-x11.c		\
 | 
			
		||||
@@ -108,6 +116,8 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	core/boxes.c				\
 | 
			
		||||
	core/boxes-private.h			\
 | 
			
		||||
	meta/boxes.h				\
 | 
			
		||||
	core/meta-border.c			\
 | 
			
		||||
	core/meta-border.h			\
 | 
			
		||||
	compositor/clutter-utils.c		\
 | 
			
		||||
	compositor/clutter-utils.h		\
 | 
			
		||||
	compositor/cogl-utils.c			\
 | 
			
		||||
@@ -132,13 +142,14 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	compositor/meta-plugin-manager.c	\
 | 
			
		||||
	compositor/meta-plugin-manager.h	\
 | 
			
		||||
	compositor/meta-shadow-factory.c	\
 | 
			
		||||
	compositor/meta-shadow-factory-private.h	\
 | 
			
		||||
	compositor/meta-shaped-texture.c	\
 | 
			
		||||
	compositor/meta-shaped-texture-private.h 	\
 | 
			
		||||
	compositor/meta-surface-actor.c		\
 | 
			
		||||
	compositor/meta-surface-actor.h		\
 | 
			
		||||
	compositor/meta-surface-actor-x11.c	\
 | 
			
		||||
	compositor/meta-surface-actor-x11.h	\
 | 
			
		||||
	compositor/meta-sync-ring.c		\
 | 
			
		||||
	compositor/meta-sync-ring.h		\
 | 
			
		||||
	compositor/meta-texture-rectangle.c	\
 | 
			
		||||
	compositor/meta-texture-rectangle.h	\
 | 
			
		||||
	compositor/meta-texture-tower.c		\
 | 
			
		||||
@@ -148,7 +159,6 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	compositor/meta-window-group.c		\
 | 
			
		||||
	compositor/meta-window-group.h		\
 | 
			
		||||
	compositor/meta-window-shape.c		\
 | 
			
		||||
	compositor/meta-window-shape.h		\
 | 
			
		||||
	compositor/region-utils.c		\
 | 
			
		||||
	compositor/region-utils.h		\
 | 
			
		||||
	meta/compositor.h			\
 | 
			
		||||
@@ -159,6 +169,7 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	meta/meta-plugin.h			\
 | 
			
		||||
	meta/meta-shadow-factory.h		\
 | 
			
		||||
	meta/meta-window-actor.h		\
 | 
			
		||||
	meta/meta-window-shape.h		\
 | 
			
		||||
	meta/compositor-mutter.h 		\
 | 
			
		||||
	core/constraints.c			\
 | 
			
		||||
	core/constraints.h			\
 | 
			
		||||
@@ -187,6 +198,8 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	core/screen.c				\
 | 
			
		||||
	core/screen-private.h			\
 | 
			
		||||
	meta/screen.h				\
 | 
			
		||||
	core/startup-notification.c		\
 | 
			
		||||
	core/startup-notification-private.h	\
 | 
			
		||||
	meta/types.h				\
 | 
			
		||||
	core/restart.c				\
 | 
			
		||||
	core/stack.c				\
 | 
			
		||||
@@ -210,10 +223,7 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	meta/theme.h				\
 | 
			
		||||
	ui/theme-private.h			\
 | 
			
		||||
	ui/ui.c					\
 | 
			
		||||
	x11/iconcache.c				\
 | 
			
		||||
	x11/iconcache.h				\
 | 
			
		||||
	x11/async-getprop.c			\
 | 
			
		||||
	x11/async-getprop.h			\
 | 
			
		||||
	x11/atomnames.h				\
 | 
			
		||||
	x11/events.c				\
 | 
			
		||||
	x11/events.h				\
 | 
			
		||||
	x11/group-private.h			\
 | 
			
		||||
@@ -221,6 +231,8 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	x11/group-props.h			\
 | 
			
		||||
	x11/group.c				\
 | 
			
		||||
	meta/group.h				\
 | 
			
		||||
	x11/iconcache.c				\
 | 
			
		||||
	x11/iconcache.h				\
 | 
			
		||||
	x11/session.c				\
 | 
			
		||||
	x11/session.h				\
 | 
			
		||||
	x11/window-props.c			\
 | 
			
		||||
@@ -242,6 +254,8 @@ libmutter_la_SOURCES +=				\
 | 
			
		||||
	wayland/meta-wayland-private.h		\
 | 
			
		||||
	wayland/meta-xwayland.c			\
 | 
			
		||||
	wayland/meta-xwayland.h			\
 | 
			
		||||
	wayland/meta-xwayland-selection.c	\
 | 
			
		||||
	wayland/meta-xwayland-selection-private.h	\
 | 
			
		||||
	wayland/meta-xwayland-private.h		\
 | 
			
		||||
	wayland/meta-wayland-buffer.c      	\
 | 
			
		||||
	wayland/meta-wayland-buffer.h      	\
 | 
			
		||||
@@ -249,10 +263,23 @@ libmutter_la_SOURCES +=				\
 | 
			
		||||
	wayland/meta-wayland-region.h      	\
 | 
			
		||||
	wayland/meta-wayland-data-device.c      \
 | 
			
		||||
	wayland/meta-wayland-data-device.h      \
 | 
			
		||||
	wayland/meta-wayland-data-device-private.h	\
 | 
			
		||||
	wayland/meta-wayland-pointer-gestures.c	\
 | 
			
		||||
	wayland/meta-wayland-pointer-gestures.h	\
 | 
			
		||||
	wayland/meta-wayland-pointer-gesture-swipe.c	\
 | 
			
		||||
	wayland/meta-wayland-pointer-gesture-swipe.h	\
 | 
			
		||||
	wayland/meta-wayland-pointer-gesture-pinch.c	\
 | 
			
		||||
	wayland/meta-wayland-pointer-gesture-pinch.h	\
 | 
			
		||||
	wayland/meta-wayland-keyboard.c		\
 | 
			
		||||
	wayland/meta-wayland-keyboard.h		\
 | 
			
		||||
	wayland/meta-wayland-pointer.c		\
 | 
			
		||||
	wayland/meta-wayland-pointer.h		\
 | 
			
		||||
	wayland/meta-wayland-pointer-constraints.c	\
 | 
			
		||||
	wayland/meta-wayland-pointer-constraints.h	\
 | 
			
		||||
	wayland/meta-pointer-lock-wayland.c		\
 | 
			
		||||
	wayland/meta-pointer-lock-wayland.h		\
 | 
			
		||||
	wayland/meta-pointer-confinement-wayland.c	\
 | 
			
		||||
	wayland/meta-pointer-confinement-wayland.h	\
 | 
			
		||||
	wayland/meta-wayland-popup.c		\
 | 
			
		||||
	wayland/meta-wayland-popup.h		\
 | 
			
		||||
	wayland/meta-wayland-seat.c		\
 | 
			
		||||
@@ -265,8 +292,8 @@ libmutter_la_SOURCES +=				\
 | 
			
		||||
	wayland/meta-wayland-versions.h		\
 | 
			
		||||
	wayland/meta-wayland-outputs.c		\
 | 
			
		||||
	wayland/meta-wayland-outputs.h		\
 | 
			
		||||
	wayland/window-wayland.c		\
 | 
			
		||||
	wayland/window-wayland.h		\
 | 
			
		||||
	wayland/meta-window-wayland.c		\
 | 
			
		||||
	wayland/meta-window-wayland.h		\
 | 
			
		||||
	$(NULL)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
@@ -322,6 +349,7 @@ libmutterinclude_headers =			\
 | 
			
		||||
	meta/meta-shaped-texture.h		\
 | 
			
		||||
	meta/meta-shadow-factory.h		\
 | 
			
		||||
	meta/meta-window-actor.h		\
 | 
			
		||||
	meta/meta-window-shape.h		\
 | 
			
		||||
	meta/prefs.h				\
 | 
			
		||||
	meta/screen.h				\
 | 
			
		||||
	meta/theme.h				\
 | 
			
		||||
@@ -332,22 +360,18 @@ libmutterinclude_headers =			\
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
libmutterinclude_built_headers =		\
 | 
			
		||||
	meta/meta-version.h
 | 
			
		||||
	meta/meta-version.h			\
 | 
			
		||||
	meta/meta-enum-types.h			\
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
libmutterinclude_base_headers =			\
 | 
			
		||||
	$(libmutterinclude_headers)		\
 | 
			
		||||
	$(libmutterinclude_built_headers)
 | 
			
		||||
 | 
			
		||||
# Excluded from scanning for introspection but installed
 | 
			
		||||
# atomnames.h: macros cause problems for scanning process
 | 
			
		||||
libmutterinclude_extra_headers =		\
 | 
			
		||||
	meta/atomnames.h
 | 
			
		||||
 | 
			
		||||
libmutterincludedir = $(includedir)/mutter/meta
 | 
			
		||||
 | 
			
		||||
libmutterinclude_HEADERS =			\
 | 
			
		||||
	$(libmutterinclude_headers)		\
 | 
			
		||||
	$(libmutterinclude_extra_headers)
 | 
			
		||||
	$(libmutterinclude_headers)
 | 
			
		||||
 | 
			
		||||
nodist_libmutterinclude_HEADERS =		\
 | 
			
		||||
	$(libmutterinclude_built_headers)
 | 
			
		||||
@@ -390,7 +414,6 @@ Meta-$(api_version).gir: libmutter.la
 | 
			
		||||
@META_GIR@_CFLAGS = $(AM_CPPFLAGS)
 | 
			
		||||
@META_GIR@_LIBS = libmutter.la
 | 
			
		||||
@META_GIR@_FILES =				\
 | 
			
		||||
	mutter-enum-types.h			\
 | 
			
		||||
	$(libmutterinclude_base_headers)	\
 | 
			
		||||
	$(filter %.c,$(libmutter_la_SOURCES) $(nodist_libmutter_la_SOURCES))
 | 
			
		||||
@META_GIR@_SCANNERFLAGS = --warn-all --warn-error
 | 
			
		||||
@@ -413,8 +436,8 @@ pkgconfig_DATA = libmutter.pc
 | 
			
		||||
EXTRA_DIST +=					\
 | 
			
		||||
	$(wayland_protocols)			\
 | 
			
		||||
	libmutter.pc.in				\
 | 
			
		||||
	mutter-enum-types.h.in			\
 | 
			
		||||
	mutter-enum-types.c.in			\
 | 
			
		||||
	meta-enum-types.h.in			\
 | 
			
		||||
	meta-enum-types.c.in			\
 | 
			
		||||
	org.freedesktop.login1.xml		\
 | 
			
		||||
	org.gnome.Mutter.DisplayConfig.xml	\
 | 
			
		||||
	org.gnome.Mutter.IdleMonitor.xml	\
 | 
			
		||||
@@ -424,26 +447,26 @@ BUILT_SOURCES =					\
 | 
			
		||||
	$(mutter_built_sources)			\
 | 
			
		||||
	$(libmutterinclude_built_headers)
 | 
			
		||||
 | 
			
		||||
MUTTER_STAMP_FILES = stamp-mutter-enum-types.h
 | 
			
		||||
MUTTER_STAMP_FILES = stamp-meta-enum-types.h
 | 
			
		||||
CLEANFILES += $(MUTTER_STAMP_FILES)
 | 
			
		||||
 | 
			
		||||
mutter-enum-types.h: stamp-mutter-enum-types.h Makefile
 | 
			
		||||
meta/meta-enum-types.h: stamp-meta-enum-types.h Makefile
 | 
			
		||||
	@true
 | 
			
		||||
stamp-mutter-enum-types.h: $(libmutterinclude_base_headers) mutter-enum-types.h.in
 | 
			
		||||
stamp-meta-enum-types.h: $(libmutterinclude_headers) meta-enum-types.h.in
 | 
			
		||||
	$(AM_V_GEN) ( cd $(srcdir) && \
 | 
			
		||||
	  $(GLIB_MKENUMS) \
 | 
			
		||||
	    --template mutter-enum-types.h.in \
 | 
			
		||||
	    --template meta-enum-types.h.in \
 | 
			
		||||
	  $(libmutterinclude_base_headers) ) >> xgen-teth && \
 | 
			
		||||
	(cmp -s xgen-teth mutter-enum-types.h || cp xgen-teth mutter-enum-types.h) && \
 | 
			
		||||
	(cmp -s xgen-teth meta/meta-enum-types.h || cp xgen-teth meta/meta-enum-types.h) && \
 | 
			
		||||
	rm -f xgen-teth && \
 | 
			
		||||
	echo timestamp > $(@F)
 | 
			
		||||
 | 
			
		||||
mutter-enum-types.c: stamp-mutter-enum-types.h mutter-enum-types.c.in
 | 
			
		||||
meta-enum-types.c: stamp-meta-enum-types.h meta-enum-types.c.in
 | 
			
		||||
	  $(AM_V_GEN) ( cd $(srcdir) && \
 | 
			
		||||
	  $(GLIB_MKENUMS) \
 | 
			
		||||
	    --template mutter-enum-types.c.in \
 | 
			
		||||
	    --template meta-enum-types.c.in \
 | 
			
		||||
	  $(libmutterinclude_base_headers) ) >> xgen-tetc && \
 | 
			
		||||
	cp xgen-tetc mutter-enum-types.c && \
 | 
			
		||||
	cp xgen-tetc meta-enum-types.c && \
 | 
			
		||||
	rm -f xgen-tetc
 | 
			
		||||
 | 
			
		||||
dbus_display_config_built_sources = meta-dbus-display-config.c meta-dbus-display-config.h
 | 
			
		||||
@@ -472,6 +495,20 @@ $(dbus_login1_built_sources) : Makefile.am org.freedesktop.login1.xml
 | 
			
		||||
		--generate-c-code meta-dbus-login1					\
 | 
			
		||||
		$(srcdir)/org.freedesktop.login1.xml
 | 
			
		||||
 | 
			
		||||
.SECONDEXPANSION:
 | 
			
		||||
 | 
			
		||||
define protostability
 | 
			
		||||
$(shell echo $1 | sed 's/.*\(\<unstable\>\|\<stable\>\).*/\1/')
 | 
			
		||||
endef
 | 
			
		||||
 | 
			
		||||
define protoname
 | 
			
		||||
$(shell echo $1 | sed 's/\([a-z\-]\+\)-[a-z]\+-v[0-9]\+/\1/')
 | 
			
		||||
endef
 | 
			
		||||
 | 
			
		||||
%-protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)/$$(call protostability,$$*)/$$(call protoname,$$*)/$$*.xml
 | 
			
		||||
	$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
 | 
			
		||||
%-server-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/$$(call protostability,$$*)/$$(call protoname,$$*)/$$*.xml
 | 
			
		||||
	$(AM_V_GEN)$(WAYLAND_SCANNER) server-header < $< > $@
 | 
			
		||||
%-protocol.c : $(srcdir)/wayland/protocol/%.xml
 | 
			
		||||
	$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
 | 
			
		||||
%-server-protocol.h : $(srcdir)/wayland/protocol/%.xml
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,7 @@
 | 
			
		||||
#include <meta/meta-idle-monitor.h>
 | 
			
		||||
#include "meta-cursor-renderer.h"
 | 
			
		||||
#include "meta-monitor-manager-private.h"
 | 
			
		||||
#include "backends/meta-pointer-constraint.h"
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_XKB_RULES_FILE "evdev"
 | 
			
		||||
#define DEFAULT_XKB_MODEL "pc105+inet"
 | 
			
		||||
@@ -51,6 +52,8 @@ struct _MetaBackend
 | 
			
		||||
 | 
			
		||||
  GHashTable *device_monitors;
 | 
			
		||||
  gint current_device_id;
 | 
			
		||||
 | 
			
		||||
  MetaPointerConstraint *client_pointer_constraint;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaBackendClass
 | 
			
		||||
@@ -87,6 +90,13 @@ struct _MetaBackendClass
 | 
			
		||||
 | 
			
		||||
  void (* update_screen_size) (MetaBackend *backend, int width, int height);
 | 
			
		||||
  void (* select_stage_events) (MetaBackend *backend);
 | 
			
		||||
 | 
			
		||||
  gboolean (* get_relative_motion_deltas) (MetaBackend *backend,
 | 
			
		||||
                                           const        ClutterEvent *event,
 | 
			
		||||
                                           double       *dx,
 | 
			
		||||
                                           double       *dy,
 | 
			
		||||
                                           double       *dx_unaccel,
 | 
			
		||||
                                           double       *dy_unaccel);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend,
 | 
			
		||||
@@ -110,4 +120,14 @@ struct xkb_keymap * meta_backend_get_keymap (MetaBackend *backend);
 | 
			
		||||
void meta_backend_update_last_device (MetaBackend *backend,
 | 
			
		||||
                                      int          device_id);
 | 
			
		||||
 | 
			
		||||
gboolean meta_backend_get_relative_motion_deltas (MetaBackend *backend,
 | 
			
		||||
                                                  const        ClutterEvent *event,
 | 
			
		||||
                                                  double       *dx,
 | 
			
		||||
                                                  double       *dy,
 | 
			
		||||
                                                  double       *dx_unaccel,
 | 
			
		||||
                                                  double       *dy_unaccel);
 | 
			
		||||
 | 
			
		||||
void meta_backend_set_client_pointer_constraint (MetaBackend *backend,
 | 
			
		||||
                                                 MetaPointerConstraint *constraint);
 | 
			
		||||
 | 
			
		||||
#endif /* META_BACKEND_PRIVATE_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,8 @@
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include <meta/meta-backend.h>
 | 
			
		||||
#include "meta-backend-private.h"
 | 
			
		||||
#include "meta-input-settings-private.h"
 | 
			
		||||
@@ -351,6 +353,17 @@ meta_backend_real_select_stage_events (MetaBackend *backend)
 | 
			
		||||
  /* Do nothing */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_backend_real_get_relative_motion_deltas (MetaBackend *backend,
 | 
			
		||||
                                             const         ClutterEvent *event,
 | 
			
		||||
                                             double        *dx,
 | 
			
		||||
                                             double        *dy,
 | 
			
		||||
                                             double        *dx_unaccel,
 | 
			
		||||
                                             double        *dy_unaccel)
 | 
			
		||||
{
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_backend_class_init (MetaBackendClass *klass)
 | 
			
		||||
{
 | 
			
		||||
@@ -364,6 +377,7 @@ meta_backend_class_init (MetaBackendClass *klass)
 | 
			
		||||
  klass->ungrab_device = meta_backend_real_ungrab_device;
 | 
			
		||||
  klass->update_screen_size = meta_backend_real_update_screen_size;
 | 
			
		||||
  klass->select_stage_events = meta_backend_real_select_stage_events;
 | 
			
		||||
  klass->get_relative_motion_deltas = meta_backend_real_get_relative_motion_deltas;
 | 
			
		||||
 | 
			
		||||
  g_signal_new ("keymap-changed",
 | 
			
		||||
                G_TYPE_FROM_CLASS (object_class),
 | 
			
		||||
@@ -542,6 +556,32 @@ meta_backend_update_last_device (MetaBackend *backend,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_backend_get_relative_motion_deltas (MetaBackend *backend,
 | 
			
		||||
                                         const        ClutterEvent *event,
 | 
			
		||||
                                         double       *dx,
 | 
			
		||||
                                         double       *dy,
 | 
			
		||||
                                         double       *dx_unaccel,
 | 
			
		||||
                                         double       *dy_unaccel)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackendClass *klass = META_BACKEND_GET_CLASS (backend);
 | 
			
		||||
  return klass->get_relative_motion_deltas (backend,
 | 
			
		||||
                                            event,
 | 
			
		||||
                                            dx, dy,
 | 
			
		||||
                                            dx_unaccel, dy_unaccel);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_backend_set_client_pointer_constraint (MetaBackend           *backend,
 | 
			
		||||
                                            MetaPointerConstraint *constraint)
 | 
			
		||||
{
 | 
			
		||||
  g_assert (!constraint || (constraint && !backend->client_pointer_constraint));
 | 
			
		||||
 | 
			
		||||
  g_clear_object (&backend->client_pointer_constraint);
 | 
			
		||||
  if (constraint)
 | 
			
		||||
    backend->client_pointer_constraint = g_object_ref (constraint);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GType
 | 
			
		||||
get_backend_type (void)
 | 
			
		||||
{
 | 
			
		||||
@@ -626,7 +666,10 @@ meta_clutter_init (void)
 | 
			
		||||
  meta_create_backend ();
 | 
			
		||||
 | 
			
		||||
  if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
 | 
			
		||||
    g_error ("Unable to initialize Clutter.\n");
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("Unable to initialize Clutter.\n");
 | 
			
		||||
      exit (1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * XXX: We cannot handle high dpi scaling yet, so fix the scale to 1
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,8 @@
 | 
			
		||||
#ifndef META_BARRIER_PRIVATE_H
 | 
			
		||||
#define META_BARRIER_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include "core/meta-border.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_BARRIER_IMPL            (meta_barrier_impl_get_type ())
 | 
			
		||||
@@ -67,14 +69,7 @@ G_END_DECLS
 | 
			
		||||
struct _MetaBarrierPrivate
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display;
 | 
			
		||||
 | 
			
		||||
  int x1;
 | 
			
		||||
  int y1;
 | 
			
		||||
  int x2;
 | 
			
		||||
  int y2;
 | 
			
		||||
 | 
			
		||||
  MetaBarrierDirection directions;
 | 
			
		||||
 | 
			
		||||
  MetaBorder border;
 | 
			
		||||
  MetaBarrierImpl *impl;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@
 | 
			
		||||
#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 <meta/meta-enum-types.h>
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaBarrier, meta_barrier, G_TYPE_OBJECT)
 | 
			
		||||
G_DEFINE_TYPE (MetaBarrierImpl, meta_barrier_impl, G_TYPE_OBJECT)
 | 
			
		||||
@@ -61,19 +61,20 @@ meta_barrier_get_property (GObject    *object,
 | 
			
		||||
      g_value_set_object (value, priv->display);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_X1:
 | 
			
		||||
      g_value_set_int (value, priv->x1);
 | 
			
		||||
      g_value_set_int (value, priv->border.line.a.x);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_Y1:
 | 
			
		||||
      g_value_set_int (value, priv->y1);
 | 
			
		||||
      g_value_set_int (value, priv->border.line.a.y);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_X2:
 | 
			
		||||
      g_value_set_int (value, priv->x2);
 | 
			
		||||
      g_value_set_int (value, priv->border.line.b.x);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_Y2:
 | 
			
		||||
      g_value_set_int (value, priv->y2);
 | 
			
		||||
      g_value_set_int (value, priv->border.line.b.y);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_DIRECTIONS:
 | 
			
		||||
      g_value_set_flags (value, priv->directions);
 | 
			
		||||
      g_value_set_flags (value,
 | 
			
		||||
                         meta_border_get_allows_directions (&priv->border));
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
@@ -95,19 +96,20 @@ meta_barrier_set_property (GObject      *object,
 | 
			
		||||
      priv->display = g_value_get_object (value);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_X1:
 | 
			
		||||
      priv->x1 = g_value_get_int (value);
 | 
			
		||||
      priv->border.line.a.x = g_value_get_int (value);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_Y1:
 | 
			
		||||
      priv->y1 = g_value_get_int (value);
 | 
			
		||||
      priv->border.line.a.y = g_value_get_int (value);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_X2:
 | 
			
		||||
      priv->x2 = g_value_get_int (value);
 | 
			
		||||
      priv->border.line.b.x = g_value_get_int (value);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_Y2:
 | 
			
		||||
      priv->y2 = g_value_get_int (value);
 | 
			
		||||
      priv->border.line.b.y = g_value_get_int (value);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_DIRECTIONS:
 | 
			
		||||
      priv->directions = g_value_get_flags (value);
 | 
			
		||||
      meta_border_set_allows_directions (&priv->border,
 | 
			
		||||
                                         g_value_get_flags (value));
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
@@ -166,7 +168,8 @@ meta_barrier_constructed (GObject *object)
 | 
			
		||||
  MetaBarrier *barrier = META_BARRIER (object);
 | 
			
		||||
  MetaBarrierPrivate *priv = barrier->priv;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (priv->x1 == priv->x2 || priv->y1 == priv->y2);
 | 
			
		||||
  g_return_if_fail (priv->border.line.a.x == priv->border.line.b.x ||
 | 
			
		||||
                    priv->border.line.a.y == priv->border.line.b.y);
 | 
			
		||||
 | 
			
		||||
#if defined(HAVE_NATIVE_BACKEND)
 | 
			
		||||
  if (META_IS_BACKEND_NATIVE (meta_get_backend ()))
 | 
			
		||||
 
 | 
			
		||||
@@ -1,59 +0,0 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2013 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: Giovanni Campagna <gcampagn@redhat.com>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef META_CURSOR_PRIVATE_H
 | 
			
		||||
#define META_CURSOR_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include "meta-cursor.h"
 | 
			
		||||
 | 
			
		||||
#include <cogl/cogl.h>
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
#include <gbm.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  CoglTexture2D *texture;
 | 
			
		||||
  int hot_x, hot_y;
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
  struct gbm_bo *bo;
 | 
			
		||||
#endif
 | 
			
		||||
} MetaCursorImage;
 | 
			
		||||
 | 
			
		||||
struct _MetaCursorReference {
 | 
			
		||||
  int ref_count;
 | 
			
		||||
 | 
			
		||||
  MetaCursor cursor;
 | 
			
		||||
  MetaCursorImage image;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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 */
 | 
			
		||||
@@ -25,9 +25,10 @@
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-cursor-renderer.h"
 | 
			
		||||
#include "meta-cursor-private.h"
 | 
			
		||||
 | 
			
		||||
#include <meta/meta-backend.h>
 | 
			
		||||
#include <backends/meta-backend-private.h>
 | 
			
		||||
#include <backends/meta-monitor-manager-private.h>
 | 
			
		||||
#include <meta/util.h>
 | 
			
		||||
 | 
			
		||||
#include <cogl/cogl.h>
 | 
			
		||||
@@ -38,9 +39,8 @@
 | 
			
		||||
struct _MetaCursorRendererPrivate
 | 
			
		||||
{
 | 
			
		||||
  int current_x, current_y;
 | 
			
		||||
  MetaRectangle current_rect;
 | 
			
		||||
 | 
			
		||||
  MetaCursorReference *displayed_cursor;
 | 
			
		||||
  MetaCursorSprite *displayed_cursor;
 | 
			
		||||
  gboolean handled_by_backend;
 | 
			
		||||
};
 | 
			
		||||
typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate;
 | 
			
		||||
@@ -48,27 +48,33 @@ typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate;
 | 
			
		||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRenderer, meta_cursor_renderer, G_TYPE_OBJECT);
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
queue_redraw (MetaCursorRenderer *renderer)
 | 
			
		||||
queue_redraw (MetaCursorRenderer *renderer,
 | 
			
		||||
              MetaCursorSprite   *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
 | 
			
		||||
  MetaBackend *backend = meta_get_backend ();
 | 
			
		||||
  ClutterActor *stage = meta_backend_get_stage (backend);
 | 
			
		||||
  CoglTexture *texture;
 | 
			
		||||
  MetaRectangle rect = { 0 };
 | 
			
		||||
 | 
			
		||||
  if (cursor_sprite)
 | 
			
		||||
    rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
 | 
			
		||||
 | 
			
		||||
  /* During early initialization, we can have no stage */
 | 
			
		||||
  if (!stage)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (priv->displayed_cursor && !priv->handled_by_backend)
 | 
			
		||||
    texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, NULL, NULL);
 | 
			
		||||
  if (cursor_sprite && !priv->handled_by_backend)
 | 
			
		||||
    texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
 | 
			
		||||
  else
 | 
			
		||||
    texture = NULL;
 | 
			
		||||
 | 
			
		||||
  meta_stage_set_cursor (META_STAGE (stage), texture, &priv->current_rect);
 | 
			
		||||
  meta_stage_set_cursor (META_STAGE (stage), texture, &rect);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_cursor_renderer_real_update_cursor (MetaCursorRenderer *renderer)
 | 
			
		||||
meta_cursor_renderer_real_update_cursor (MetaCursorRenderer *renderer,
 | 
			
		||||
                                         MetaCursorSprite   *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
@@ -84,34 +90,63 @@ meta_cursor_renderer_init (MetaCursorRenderer *renderer)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaRectangle
 | 
			
		||||
meta_cursor_renderer_calculate_rect (MetaCursorRenderer *renderer,
 | 
			
		||||
                                     MetaCursorSprite   *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererPrivate *priv =
 | 
			
		||||
    meta_cursor_renderer_get_instance_private (renderer);
 | 
			
		||||
  CoglTexture *texture;
 | 
			
		||||
  int hot_x, hot_y;
 | 
			
		||||
  int width, height;
 | 
			
		||||
  float texture_scale;
 | 
			
		||||
 | 
			
		||||
  texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
 | 
			
		||||
  if (!texture)
 | 
			
		||||
    return (MetaRectangle) { 0 };
 | 
			
		||||
 | 
			
		||||
  meta_cursor_sprite_get_hotspot (cursor_sprite, &hot_x, &hot_y);
 | 
			
		||||
  texture_scale = meta_cursor_sprite_get_texture_scale (cursor_sprite);
 | 
			
		||||
  width = cogl_texture_get_width (texture);
 | 
			
		||||
  height = cogl_texture_get_height (texture);
 | 
			
		||||
 | 
			
		||||
  return (MetaRectangle) {
 | 
			
		||||
    .x = (int)roundf (priv->current_x - (hot_x * texture_scale)),
 | 
			
		||||
    .y = (int)roundf (priv->current_y - (hot_y * texture_scale)),
 | 
			
		||||
    .width = (int)roundf (width * texture_scale),
 | 
			
		||||
    .height = (int)roundf (height * texture_scale),
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
is_cursor_in_monitors_area (int x, int y)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (meta_get_backend ());
 | 
			
		||||
  return meta_monitor_manager_get_monitor_at_point (monitor_manager,
 | 
			
		||||
                                                    (gfloat) x, (gfloat) y) >= 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_cursor (MetaCursorRenderer *renderer)
 | 
			
		||||
update_cursor (MetaCursorRenderer *renderer,
 | 
			
		||||
               MetaCursorSprite   *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
 | 
			
		||||
  gboolean handled_by_backend;
 | 
			
		||||
  gboolean should_redraw = FALSE;
 | 
			
		||||
 | 
			
		||||
  if (priv->displayed_cursor)
 | 
			
		||||
    {
 | 
			
		||||
      CoglTexture *texture;
 | 
			
		||||
      int hot_x, hot_y;
 | 
			
		||||
  /* do not render cursor if it is not on any monitor. Such situation
 | 
			
		||||
   * can occur e. g. after monitor hot-plug */
 | 
			
		||||
  if (!is_cursor_in_monitors_area (priv->current_x, priv->current_y))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
      texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, &hot_x, &hot_y);
 | 
			
		||||
  if (cursor_sprite)
 | 
			
		||||
    meta_cursor_sprite_prepare_at (cursor_sprite,
 | 
			
		||||
                                   priv->current_x,
 | 
			
		||||
                                   priv->current_y);
 | 
			
		||||
 | 
			
		||||
      priv->current_rect.x = priv->current_x - hot_x;
 | 
			
		||||
      priv->current_rect.y = priv->current_y - hot_y;
 | 
			
		||||
      priv->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (texture));
 | 
			
		||||
      priv->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (texture));
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      priv->current_rect.x = 0;
 | 
			
		||||
      priv->current_rect.y = 0;
 | 
			
		||||
      priv->current_rect.width = 0;
 | 
			
		||||
      priv->current_rect.height = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  handled_by_backend = META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer);
 | 
			
		||||
  handled_by_backend =
 | 
			
		||||
    META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer,
 | 
			
		||||
                                                              cursor_sprite);
 | 
			
		||||
  if (handled_by_backend != priv->handled_by_backend)
 | 
			
		||||
    {
 | 
			
		||||
      priv->handled_by_backend = handled_by_backend;
 | 
			
		||||
@@ -122,7 +157,7 @@ update_cursor (MetaCursorRenderer *renderer)
 | 
			
		||||
    should_redraw = TRUE;
 | 
			
		||||
 | 
			
		||||
  if (should_redraw)
 | 
			
		||||
    queue_redraw (renderer);
 | 
			
		||||
    queue_redraw (renderer, cursor_sprite);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaCursorRenderer *
 | 
			
		||||
@@ -132,16 +167,25 @@ meta_cursor_renderer_new (void)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_cursor_renderer_set_cursor (MetaCursorRenderer  *renderer,
 | 
			
		||||
                                 MetaCursorReference *cursor)
 | 
			
		||||
meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
 | 
			
		||||
                                 MetaCursorSprite   *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
 | 
			
		||||
 | 
			
		||||
  if (priv->displayed_cursor == cursor)
 | 
			
		||||
  if (priv->displayed_cursor == cursor_sprite)
 | 
			
		||||
    return;
 | 
			
		||||
  priv->displayed_cursor = cursor_sprite;
 | 
			
		||||
 | 
			
		||||
  priv->displayed_cursor = cursor;
 | 
			
		||||
  update_cursor (renderer);
 | 
			
		||||
  update_cursor (renderer, cursor_sprite);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_cursor_renderer_force_update (MetaCursorRenderer *renderer)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererPrivate *priv =
 | 
			
		||||
    meta_cursor_renderer_get_instance_private (renderer);
 | 
			
		||||
 | 
			
		||||
  update_cursor (renderer, priv->displayed_cursor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -155,10 +199,10 @@ meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
 | 
			
		||||
  priv->current_x = x;
 | 
			
		||||
  priv->current_y = y;
 | 
			
		||||
 | 
			
		||||
  update_cursor (renderer);
 | 
			
		||||
  update_cursor (renderer, priv->displayed_cursor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaCursorReference *
 | 
			
		||||
MetaCursorSprite *
 | 
			
		||||
meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
 | 
			
		||||
@@ -166,10 +210,27 @@ meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer)
 | 
			
		||||
  return priv->displayed_cursor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const MetaRectangle *
 | 
			
		||||
meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer)
 | 
			
		||||
#ifdef HAVE_WAYLAND
 | 
			
		||||
void
 | 
			
		||||
meta_cursor_renderer_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer,
 | 
			
		||||
                                                    MetaCursorSprite   *cursor_sprite,
 | 
			
		||||
                                                    struct wl_resource *buffer)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
 | 
			
		||||
 | 
			
		||||
  return &priv->current_rect;
 | 
			
		||||
  MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_GET_CLASS (renderer);
 | 
			
		||||
 | 
			
		||||
  if (renderer_class->realize_cursor_from_wl_buffer)
 | 
			
		||||
    renderer_class->realize_cursor_from_wl_buffer (renderer, cursor_sprite, buffer);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_cursor_renderer_realize_cursor_from_xcursor (MetaCursorRenderer *renderer,
 | 
			
		||||
                                                  MetaCursorSprite   *cursor_sprite,
 | 
			
		||||
                                                  XcursorImage       *xc_image)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_GET_CLASS (renderer);
 | 
			
		||||
 | 
			
		||||
  if (renderer_class->realize_cursor_from_xcursor)
 | 
			
		||||
    renderer_class->realize_cursor_from_xcursor (renderer, cursor_sprite, xc_image);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -26,43 +26,56 @@
 | 
			
		||||
#define META_CURSOR_RENDERER_H
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
#include <X11/Xcursor/Xcursor.h>
 | 
			
		||||
#ifdef HAVE_WAYLAND
 | 
			
		||||
#include <wayland-server.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <meta/screen.h>
 | 
			
		||||
#include "meta-cursor.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))
 | 
			
		||||
#define META_IS_CURSOR_RENDERER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_RENDERER))
 | 
			
		||||
#define META_IS_CURSOR_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_CURSOR_RENDERER))
 | 
			
		||||
#define META_CURSOR_RENDERER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_CURSOR_RENDERER, MetaCursorRendererClass))
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaCursorRenderer        MetaCursorRenderer;
 | 
			
		||||
typedef struct _MetaCursorRendererClass   MetaCursorRendererClass;
 | 
			
		||||
 | 
			
		||||
struct _MetaCursorRenderer
 | 
			
		||||
{
 | 
			
		||||
  GObject parent;
 | 
			
		||||
};
 | 
			
		||||
#define META_TYPE_CURSOR_RENDERER (meta_cursor_renderer_get_type ())
 | 
			
		||||
G_DECLARE_DERIVABLE_TYPE (MetaCursorRenderer, meta_cursor_renderer,
 | 
			
		||||
                          META, CURSOR_RENDERER, GObject);
 | 
			
		||||
 | 
			
		||||
struct _MetaCursorRendererClass
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass parent_class;
 | 
			
		||||
 | 
			
		||||
  gboolean (* update_cursor) (MetaCursorRenderer *renderer);
 | 
			
		||||
  gboolean (* update_cursor) (MetaCursorRenderer *renderer,
 | 
			
		||||
                              MetaCursorSprite   *cursor_sprite);
 | 
			
		||||
#ifdef HAVE_WAYLAND
 | 
			
		||||
  void (* realize_cursor_from_wl_buffer) (MetaCursorRenderer *renderer,
 | 
			
		||||
                                          MetaCursorSprite *cursor_sprite,
 | 
			
		||||
                                          struct wl_resource *buffer);
 | 
			
		||||
#endif
 | 
			
		||||
  void (* realize_cursor_from_xcursor) (MetaCursorRenderer *renderer,
 | 
			
		||||
                                        MetaCursorSprite *cursor_sprite,
 | 
			
		||||
                                        XcursorImage *xc_image);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType meta_cursor_renderer_get_type (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
MetaCursorRenderer * meta_cursor_renderer_new (void);
 | 
			
		||||
 | 
			
		||||
void meta_cursor_renderer_set_cursor (MetaCursorRenderer  *renderer,
 | 
			
		||||
                                      MetaCursorReference *cursor);
 | 
			
		||||
void meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
 | 
			
		||||
                                      MetaCursorSprite   *cursor_sprite);
 | 
			
		||||
 | 
			
		||||
void meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
 | 
			
		||||
                                        int x, int y);
 | 
			
		||||
void meta_cursor_renderer_force_update (MetaCursorRenderer *renderer);
 | 
			
		||||
 | 
			
		||||
MetaCursorReference * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer);
 | 
			
		||||
const MetaRectangle * meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer);
 | 
			
		||||
MetaCursorSprite * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer);
 | 
			
		||||
 | 
			
		||||
MetaRectangle meta_cursor_renderer_calculate_rect (MetaCursorRenderer *renderer,
 | 
			
		||||
                                                   MetaCursorSprite   *cursor_sprite);
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_WAYLAND
 | 
			
		||||
void meta_cursor_renderer_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer,
 | 
			
		||||
                                                         MetaCursorSprite   *cursor_sprite,
 | 
			
		||||
                                                         struct wl_resource *buffer);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void meta_cursor_renderer_realize_cursor_from_xcursor (MetaCursorRenderer *renderer,
 | 
			
		||||
                                                       MetaCursorSprite   *cursor_sprite,
 | 
			
		||||
                                                       XcursorImage       *xc_image);
 | 
			
		||||
 | 
			
		||||
#endif /* META_CURSOR_RENDERER_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,7 @@ struct _MetaCursorTracker {
 | 
			
		||||
 | 
			
		||||
  gboolean is_showing;
 | 
			
		||||
 | 
			
		||||
  MetaCursorReference *displayed_cursor;
 | 
			
		||||
  MetaCursorSprite *displayed_cursor;
 | 
			
		||||
 | 
			
		||||
  /* Wayland clients can set a NULL buffer as their cursor
 | 
			
		||||
   * explicitly, which means that we shouldn't display anything.
 | 
			
		||||
@@ -42,12 +42,12 @@ struct _MetaCursorTracker {
 | 
			
		||||
   * determine an unset window cursor; we need an extra boolean.
 | 
			
		||||
   */
 | 
			
		||||
  gboolean has_window_cursor;
 | 
			
		||||
  MetaCursorReference *window_cursor;
 | 
			
		||||
  MetaCursorSprite *window_cursor;
 | 
			
		||||
 | 
			
		||||
  MetaCursorReference *root_cursor;
 | 
			
		||||
  MetaCursorSprite *root_cursor;
 | 
			
		||||
 | 
			
		||||
  /* The cursor from the X11 server. */
 | 
			
		||||
  MetaCursorReference *xfixes_cursor;
 | 
			
		||||
  MetaCursorSprite *xfixes_cursor;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaCursorTrackerClass {
 | 
			
		||||
@@ -57,16 +57,16 @@ struct _MetaCursorTrackerClass {
 | 
			
		||||
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
 | 
			
		||||
					    XEvent            *xevent);
 | 
			
		||||
 | 
			
		||||
void     meta_cursor_tracker_set_window_cursor   (MetaCursorTracker   *tracker,
 | 
			
		||||
                                                  MetaCursorReference *cursor);
 | 
			
		||||
void     meta_cursor_tracker_unset_window_cursor (MetaCursorTracker   *tracker);
 | 
			
		||||
void     meta_cursor_tracker_set_root_cursor     (MetaCursorTracker   *tracker,
 | 
			
		||||
                                                  MetaCursorReference *cursor);
 | 
			
		||||
void     meta_cursor_tracker_set_window_cursor   (MetaCursorTracker *tracker,
 | 
			
		||||
                                                  MetaCursorSprite  *cursor_sprite);
 | 
			
		||||
void     meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
 | 
			
		||||
void     meta_cursor_tracker_set_root_cursor     (MetaCursorTracker *tracker,
 | 
			
		||||
                                                  MetaCursorSprite  *cursor_sprite);
 | 
			
		||||
 | 
			
		||||
void     meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
 | 
			
		||||
					      int                new_x,
 | 
			
		||||
					      int                new_y);
 | 
			
		||||
 | 
			
		||||
MetaCursorReference * meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker);
 | 
			
		||||
MetaCursorSprite * meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,6 @@
 | 
			
		||||
#include <X11/extensions/Xfixes.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-backend-private.h"
 | 
			
		||||
#include "meta-cursor-private.h"
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
 | 
			
		||||
 | 
			
		||||
@@ -54,7 +53,7 @@ enum {
 | 
			
		||||
 | 
			
		||||
static guint signals[LAST_SIGNAL];
 | 
			
		||||
 | 
			
		||||
static MetaCursorReference *
 | 
			
		||||
static MetaCursorSprite *
 | 
			
		||||
get_displayed_cursor (MetaCursorTracker *tracker)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display = meta_get_display ();
 | 
			
		||||
@@ -80,14 +79,14 @@ update_displayed_cursor (MetaCursorTracker *tracker)
 | 
			
		||||
static void
 | 
			
		||||
sync_cursor (MetaCursorTracker *tracker)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorReference *displayed_cursor = get_displayed_cursor (tracker);
 | 
			
		||||
  MetaCursorSprite *displayed_cursor = get_displayed_cursor (tracker);
 | 
			
		||||
 | 
			
		||||
  if (tracker->displayed_cursor == displayed_cursor)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  g_clear_pointer (&tracker->displayed_cursor, meta_cursor_reference_unref);
 | 
			
		||||
  g_clear_object (&tracker->displayed_cursor);
 | 
			
		||||
  if (displayed_cursor)
 | 
			
		||||
    tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor);
 | 
			
		||||
    tracker->displayed_cursor = g_object_ref (displayed_cursor);
 | 
			
		||||
 | 
			
		||||
  update_displayed_cursor (tracker);
 | 
			
		||||
  g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
 | 
			
		||||
@@ -108,9 +107,9 @@ meta_cursor_tracker_finalize (GObject *object)
 | 
			
		||||
  MetaCursorTracker *self = META_CURSOR_TRACKER (object);
 | 
			
		||||
 | 
			
		||||
  if (self->displayed_cursor)
 | 
			
		||||
    meta_cursor_reference_unref (self->displayed_cursor);
 | 
			
		||||
    g_object_unref (self->displayed_cursor);
 | 
			
		||||
  if (self->root_cursor)
 | 
			
		||||
    meta_cursor_reference_unref (self->root_cursor);
 | 
			
		||||
    g_object_unref (self->root_cursor);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_cursor_tracker_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
@@ -156,13 +155,13 @@ meta_cursor_tracker_get_for_screen (MetaScreen *screen)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
set_window_cursor (MetaCursorTracker   *tracker,
 | 
			
		||||
                   gboolean             has_cursor,
 | 
			
		||||
                   MetaCursorReference *cursor)
 | 
			
		||||
set_window_cursor (MetaCursorTracker *tracker,
 | 
			
		||||
                   gboolean           has_cursor,
 | 
			
		||||
                   MetaCursorSprite  *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  g_clear_pointer (&tracker->window_cursor, meta_cursor_reference_unref);
 | 
			
		||||
  if (cursor)
 | 
			
		||||
    tracker->window_cursor = meta_cursor_reference_ref (cursor);
 | 
			
		||||
  g_clear_object (&tracker->window_cursor);
 | 
			
		||||
  if (cursor_sprite)
 | 
			
		||||
    tracker->window_cursor = g_object_ref (cursor_sprite);
 | 
			
		||||
  tracker->has_window_cursor = has_cursor;
 | 
			
		||||
  sync_cursor (tracker);
 | 
			
		||||
}
 | 
			
		||||
@@ -184,28 +183,12 @@ meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
 | 
			
		||||
  if (notify_event->subtype != XFixesDisplayCursorNotify)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  g_clear_pointer (&tracker->xfixes_cursor, meta_cursor_reference_unref);
 | 
			
		||||
  g_clear_object (&tracker->xfixes_cursor);
 | 
			
		||||
  g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaCursorReference *
 | 
			
		||||
meta_cursor_reference_take_texture (CoglTexture2D *texture,
 | 
			
		||||
                                    int            hot_x,
 | 
			
		||||
                                    int            hot_y)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorReference *self;
 | 
			
		||||
 | 
			
		||||
  self = g_slice_new0 (MetaCursorReference);
 | 
			
		||||
  self->ref_count = 1;
 | 
			
		||||
  self->image.texture = texture;
 | 
			
		||||
  self->image.hot_x = hot_x;
 | 
			
		||||
  self->image.hot_y = hot_y;
 | 
			
		||||
 | 
			
		||||
  return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
ensure_xfixes_cursor (MetaCursorTracker *tracker)
 | 
			
		||||
{
 | 
			
		||||
@@ -263,10 +246,13 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
 | 
			
		||||
 | 
			
		||||
  if (sprite != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      MetaCursorReference *cursor = meta_cursor_reference_take_texture (sprite,
 | 
			
		||||
                                                                        cursor_image->xhot,
 | 
			
		||||
                                                                        cursor_image->yhot);
 | 
			
		||||
      tracker->xfixes_cursor = cursor;
 | 
			
		||||
      MetaCursorSprite *cursor_sprite = meta_cursor_sprite_new ();
 | 
			
		||||
      meta_cursor_sprite_set_texture (cursor_sprite,
 | 
			
		||||
                                      sprite,
 | 
			
		||||
                                      cursor_image->xhot,
 | 
			
		||||
                                      cursor_image->yhot);
 | 
			
		||||
      cogl_object_unref (sprite);
 | 
			
		||||
      tracker->xfixes_cursor = cursor_sprite;
 | 
			
		||||
    }
 | 
			
		||||
  XFree (cursor_image);
 | 
			
		||||
}
 | 
			
		||||
@@ -279,22 +265,22 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
 | 
			
		||||
CoglTexture *
 | 
			
		||||
meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorReference *cursor;
 | 
			
		||||
  MetaCursorSprite *cursor_sprite;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL);
 | 
			
		||||
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
    {
 | 
			
		||||
      cursor = tracker->displayed_cursor;
 | 
			
		||||
      cursor_sprite = tracker->displayed_cursor;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      ensure_xfixes_cursor (tracker);
 | 
			
		||||
      cursor = tracker->xfixes_cursor;
 | 
			
		||||
      cursor_sprite = tracker->xfixes_cursor;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (cursor)
 | 
			
		||||
    return meta_cursor_reference_get_cogl_texture (cursor, NULL, NULL);
 | 
			
		||||
  if (cursor_sprite)
 | 
			
		||||
    return meta_cursor_sprite_get_cogl_texture (cursor_sprite);
 | 
			
		||||
  else
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
@@ -311,22 +297,22 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
 | 
			
		||||
                             int               *x,
 | 
			
		||||
                             int               *y)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorReference *cursor;
 | 
			
		||||
  MetaCursorSprite *cursor_sprite;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (META_IS_CURSOR_TRACKER (tracker));
 | 
			
		||||
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
    {
 | 
			
		||||
      cursor = tracker->displayed_cursor;
 | 
			
		||||
      cursor_sprite = tracker->displayed_cursor;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      ensure_xfixes_cursor (tracker);
 | 
			
		||||
      cursor = tracker->xfixes_cursor;
 | 
			
		||||
      cursor_sprite = tracker->xfixes_cursor;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (cursor)
 | 
			
		||||
    meta_cursor_reference_get_cogl_texture (cursor, x, y);
 | 
			
		||||
  if (cursor_sprite)
 | 
			
		||||
    meta_cursor_sprite_get_hotspot (cursor_sprite, x, y);
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      if (x)
 | 
			
		||||
@@ -337,10 +323,10 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_cursor_tracker_set_window_cursor (MetaCursorTracker   *tracker,
 | 
			
		||||
                                       MetaCursorReference *cursor)
 | 
			
		||||
meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
 | 
			
		||||
                                       MetaCursorSprite  *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  set_window_cursor (tracker, TRUE, cursor);
 | 
			
		||||
  set_window_cursor (tracker, TRUE, cursor_sprite);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -350,12 +336,12 @@ meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_cursor_tracker_set_root_cursor (MetaCursorTracker   *tracker,
 | 
			
		||||
                                     MetaCursorReference *cursor)
 | 
			
		||||
meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
 | 
			
		||||
                                     MetaCursorSprite  *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  g_clear_pointer (&tracker->root_cursor, meta_cursor_reference_unref);
 | 
			
		||||
  if (cursor)
 | 
			
		||||
    tracker->root_cursor = meta_cursor_reference_ref (cursor);
 | 
			
		||||
  g_clear_object (&tracker->root_cursor);
 | 
			
		||||
  if (cursor_sprite)
 | 
			
		||||
    tracker->root_cursor = g_object_ref (cursor_sprite);
 | 
			
		||||
 | 
			
		||||
  sync_cursor (tracker);
 | 
			
		||||
}
 | 
			
		||||
@@ -375,12 +361,12 @@ get_pointer_position_gdk (int         *x,
 | 
			
		||||
                          int         *y,
 | 
			
		||||
                          int         *mods)
 | 
			
		||||
{
 | 
			
		||||
  GdkDeviceManager *gmanager;
 | 
			
		||||
  GdkSeat *gseat;
 | 
			
		||||
  GdkDevice *gdevice;
 | 
			
		||||
  GdkScreen *gscreen;
 | 
			
		||||
 | 
			
		||||
  gmanager = gdk_display_get_device_manager (gdk_display_get_default ());
 | 
			
		||||
  gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
 | 
			
		||||
  gseat = gdk_display_get_default_seat (gdk_display_get_default ());
 | 
			
		||||
  gdevice = gdk_seat_get_pointer (gseat);
 | 
			
		||||
 | 
			
		||||
  gdk_device_get_position (gdevice, &gscreen, x, y);
 | 
			
		||||
  if (mods)
 | 
			
		||||
@@ -438,7 +424,7 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
 | 
			
		||||
  sync_cursor (tracker);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaCursorReference *
 | 
			
		||||
MetaCursorSprite *
 | 
			
		||||
meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker)
 | 
			
		||||
{
 | 
			
		||||
  return tracker->displayed_cursor;
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-cursor-private.h"
 | 
			
		||||
#include "meta-cursor.h"
 | 
			
		||||
 | 
			
		||||
#include <meta/errors.h>
 | 
			
		||||
 | 
			
		||||
@@ -29,56 +29,38 @@
 | 
			
		||||
#include "screen-private.h"
 | 
			
		||||
#include "meta-backend-private.h"
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
#include "backends/native/meta-cursor-renderer-native.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <X11/cursorfont.h>
 | 
			
		||||
#include <X11/extensions/Xfixes.h>
 | 
			
		||||
#include <X11/Xcursor/Xcursor.h>
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_WAYLAND
 | 
			
		||||
#include <cogl/cogl-wayland-server.h>
 | 
			
		||||
#endif
 | 
			
		||||
enum {
 | 
			
		||||
  PREPARE_AT,
 | 
			
		||||
 | 
			
		||||
MetaCursorReference *
 | 
			
		||||
meta_cursor_reference_ref (MetaCursorReference *self)
 | 
			
		||||
  LAST_SIGNAL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static guint signals[LAST_SIGNAL];
 | 
			
		||||
 | 
			
		||||
struct _MetaCursorSprite
 | 
			
		||||
{
 | 
			
		||||
  g_assert (self->ref_count > 0);
 | 
			
		||||
  self->ref_count++;
 | 
			
		||||
  GObject parent;
 | 
			
		||||
 | 
			
		||||
  return self;
 | 
			
		||||
}
 | 
			
		||||
  MetaCursor cursor;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_cursor_image_free (MetaCursorImage *image)
 | 
			
		||||
{
 | 
			
		||||
  if (image->texture)
 | 
			
		||||
    cogl_object_unref (image->texture);
 | 
			
		||||
  CoglTexture2D *texture;
 | 
			
		||||
  float texture_scale;
 | 
			
		||||
  int hot_x, hot_y;
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
  if (image->bo)
 | 
			
		||||
    gbm_bo_destroy (image->bo);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
  int current_frame;
 | 
			
		||||
  XcursorImages *xcursor_images;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_cursor_reference_free (MetaCursorReference *self)
 | 
			
		||||
{
 | 
			
		||||
  meta_cursor_image_free (&self->image);
 | 
			
		||||
  g_slice_free (MetaCursorReference, self);
 | 
			
		||||
}
 | 
			
		||||
  int theme_scale;
 | 
			
		||||
  gboolean theme_dirty;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_cursor_reference_unref (MetaCursorReference *self)
 | 
			
		||||
{
 | 
			
		||||
  self->ref_count--;
 | 
			
		||||
 | 
			
		||||
  if (self->ref_count == 0)
 | 
			
		||||
    meta_cursor_reference_free (self);
 | 
			
		||||
}
 | 
			
		||||
G_DEFINE_TYPE (MetaCursorSprite, meta_cursor_sprite, G_TYPE_OBJECT)
 | 
			
		||||
 | 
			
		||||
static const char *
 | 
			
		||||
translate_meta_cursor (MetaCursor cursor)
 | 
			
		||||
@@ -135,93 +117,27 @@ meta_cursor_create_x_cursor (Display    *xdisplay,
 | 
			
		||||
  return XcursorLibraryLoadCursor (xdisplay, translate_meta_cursor (cursor));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static XcursorImage *
 | 
			
		||||
load_cursor_on_client (MetaCursor cursor)
 | 
			
		||||
static XcursorImages *
 | 
			
		||||
load_cursor_on_client (MetaCursor cursor, int scale)
 | 
			
		||||
{
 | 
			
		||||
  return XcursorLibraryLoadImage (translate_meta_cursor (cursor),
 | 
			
		||||
                                  meta_prefs_get_cursor_theme (),
 | 
			
		||||
                                  meta_prefs_get_cursor_size ());
 | 
			
		||||
  return XcursorLibraryLoadImages (translate_meta_cursor (cursor),
 | 
			
		||||
                                   meta_prefs_get_cursor_theme (),
 | 
			
		||||
                                   meta_prefs_get_cursor_size () * scale);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
static void
 | 
			
		||||
get_hardware_cursor_size (uint64_t *cursor_width, uint64_t *cursor_height)
 | 
			
		||||
meta_cursor_sprite_load_from_xcursor_image (MetaCursorSprite *self,
 | 
			
		||||
                                            XcursorImage     *xc_image)
 | 
			
		||||
{
 | 
			
		||||
  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,
 | 
			
		||||
                                   uint               width,
 | 
			
		||||
                                   uint               height,
 | 
			
		||||
                                   int                rowstride,
 | 
			
		||||
                                   uint32_t           gbm_format)
 | 
			
		||||
{
 | 
			
		||||
  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 %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 | GBM_BO_USE_WRITE))
 | 
			
		||||
    {
 | 
			
		||||
      uint8_t buf[4 * cursor_width * cursor_height];
 | 
			
		||||
      uint i;
 | 
			
		||||
 | 
			
		||||
      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 * cursor_width, pixels + i * rowstride, width * 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)
 | 
			
		||||
{
 | 
			
		||||
  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));
 | 
			
		||||
  else
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_cursor_image_load_from_xcursor_image (MetaCursorImage   *image,
 | 
			
		||||
                                           XcursorImage      *xc_image)
 | 
			
		||||
{
 | 
			
		||||
  uint width, height, rowstride;
 | 
			
		||||
  CoglPixelFormat cogl_format;
 | 
			
		||||
  ClutterBackend *clutter_backend;
 | 
			
		||||
  CoglContext *cogl_context;
 | 
			
		||||
  CoglTexture *texture;
 | 
			
		||||
 | 
			
		||||
  g_assert (self->texture == NULL);
 | 
			
		||||
 | 
			
		||||
  width           = xc_image->width;
 | 
			
		||||
  height          = xc_image->height;
 | 
			
		||||
@@ -233,196 +149,210 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage   *image,
 | 
			
		||||
  cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  image->hot_x = xc_image->xhot;
 | 
			
		||||
  image->hot_y = xc_image->yhot;
 | 
			
		||||
 | 
			
		||||
  clutter_backend = clutter_get_default_backend ();
 | 
			
		||||
  cogl_context = clutter_backend_get_cogl_context (clutter_backend);
 | 
			
		||||
  image->texture = cogl_texture_2d_new_from_data (cogl_context,
 | 
			
		||||
                                                  width, height,
 | 
			
		||||
                                                  cogl_format,
 | 
			
		||||
                                                  rowstride,
 | 
			
		||||
                                                  (uint8_t *) xc_image->pixels,
 | 
			
		||||
                                                  NULL);
 | 
			
		||||
  texture = cogl_texture_2d_new_from_data (cogl_context,
 | 
			
		||||
                                           width, height,
 | 
			
		||||
                                           cogl_format,
 | 
			
		||||
                                           rowstride,
 | 
			
		||||
                                           (uint8_t *) xc_image->pixels,
 | 
			
		||||
                                           NULL);
 | 
			
		||||
  meta_cursor_sprite_set_texture (self, texture,
 | 
			
		||||
                                  xc_image->xhot, xc_image->yhot);
 | 
			
		||||
  cogl_object_unref (texture);
 | 
			
		||||
 | 
			
		||||
#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_ARGB8888);
 | 
			
		||||
#endif
 | 
			
		||||
  meta_cursor_renderer_realize_cursor_from_xcursor (renderer, self, xc_image);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
load_cursor_image (MetaCursorReference *cursor)
 | 
			
		||||
static XcursorImage *
 | 
			
		||||
meta_cursor_sprite_get_current_frame_image (MetaCursorSprite *self)
 | 
			
		||||
{
 | 
			
		||||
  return self->xcursor_images->images[self->current_frame];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_cursor_sprite_tick_frame (MetaCursorSprite *self)
 | 
			
		||||
{
 | 
			
		||||
  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)
 | 
			
		||||
  if (!meta_cursor_sprite_is_animated (self))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  meta_cursor_image_load_from_xcursor_image (&cursor->image, image);
 | 
			
		||||
  XcursorImageDestroy (image);
 | 
			
		||||
  self->current_frame++;
 | 
			
		||||
 | 
			
		||||
  if (self->current_frame >= self->xcursor_images->nimage)
 | 
			
		||||
    self->current_frame = 0;
 | 
			
		||||
 | 
			
		||||
  image = meta_cursor_sprite_get_current_frame_image (self);
 | 
			
		||||
 | 
			
		||||
  g_clear_pointer (&self->texture, cogl_object_unref);
 | 
			
		||||
  meta_cursor_sprite_load_from_xcursor_image (self, image);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaCursorReference *
 | 
			
		||||
meta_cursor_reference_from_theme (MetaCursor cursor)
 | 
			
		||||
guint
 | 
			
		||||
meta_cursor_sprite_get_current_frame_time (MetaCursorSprite *self)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorReference *self = g_slice_new0 (MetaCursorReference);
 | 
			
		||||
  self->ref_count = 1;
 | 
			
		||||
  self->cursor = cursor;
 | 
			
		||||
  return self;
 | 
			
		||||
  if (!meta_cursor_sprite_is_animated (self))
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
  return self->xcursor_images->images[self->current_frame]->delay;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_cursor_sprite_is_animated (MetaCursorSprite *self)
 | 
			
		||||
{
 | 
			
		||||
  return (self->xcursor_images &&
 | 
			
		||||
          self->xcursor_images->nimage > 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaCursorSprite *
 | 
			
		||||
meta_cursor_sprite_new (void)
 | 
			
		||||
{
 | 
			
		||||
  return g_object_new (META_TYPE_CURSOR_SPRITE, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_WAYLAND
 | 
			
		||||
static void
 | 
			
		||||
meta_cursor_image_load_from_buffer (MetaCursorImage    *image,
 | 
			
		||||
                                    struct wl_resource *buffer,
 | 
			
		||||
                                    int                 hot_x,
 | 
			
		||||
                                    int                 hot_y)
 | 
			
		||||
meta_cursor_sprite_load_from_theme (MetaCursorSprite *self)
 | 
			
		||||
{
 | 
			
		||||
  ClutterBackend *backend;
 | 
			
		||||
  CoglContext *cogl_context;
 | 
			
		||||
  XcursorImage *image;
 | 
			
		||||
 | 
			
		||||
  image->hot_x = hot_x;
 | 
			
		||||
  image->hot_y = hot_y;
 | 
			
		||||
  g_assert (self->cursor != META_CURSOR_NONE);
 | 
			
		||||
 | 
			
		||||
  backend = clutter_get_default_backend ();
 | 
			
		||||
  cogl_context = clutter_backend_get_cogl_context (backend);
 | 
			
		||||
 | 
			
		||||
  image->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
  struct gbm_device *gbm = get_gbm_device ();
 | 
			
		||||
  if (gbm)
 | 
			
		||||
  /* We might be reloading with a different scale. If so clear the old data. */
 | 
			
		||||
  if (self->xcursor_images)
 | 
			
		||||
    {
 | 
			
		||||
      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
 | 
			
		||||
            case WL_SHM_FORMAT_ARGB8888:
 | 
			
		||||
              gbm_format = GBM_FORMAT_ARGB8888;
 | 
			
		||||
              break;
 | 
			
		||||
            case WL_SHM_FORMAT_XRGB8888:
 | 
			
		||||
              gbm_format = GBM_FORMAT_XRGB8888;
 | 
			
		||||
              break;
 | 
			
		||||
#else
 | 
			
		||||
            case WL_SHM_FORMAT_ARGB8888:
 | 
			
		||||
              gbm_format = GBM_FORMAT_ARGB8888;
 | 
			
		||||
              break;
 | 
			
		||||
            case WL_SHM_FORMAT_XRGB8888:
 | 
			
		||||
              gbm_format = GBM_FORMAT_XRGB8888;
 | 
			
		||||
              break;
 | 
			
		||||
#endif
 | 
			
		||||
            default:
 | 
			
		||||
              g_warn_if_reached ();
 | 
			
		||||
              gbm_format = GBM_FORMAT_ARGB8888;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          meta_cursor_image_load_gbm_buffer (gbm,
 | 
			
		||||
                                             image,
 | 
			
		||||
                                             (uint8_t *) wl_shm_buffer_get_data (shm_buffer),
 | 
			
		||||
                                             width, height, rowstride,
 | 
			
		||||
                                             gbm_format);
 | 
			
		||||
 | 
			
		||||
          wl_shm_buffer_end_access (shm_buffer);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          /* 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");
 | 
			
		||||
        }
 | 
			
		||||
      g_clear_pointer (&self->texture, cogl_object_unref);
 | 
			
		||||
      XcursorImagesDestroy (self->xcursor_images);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  self->current_frame = 0;
 | 
			
		||||
  self->xcursor_images = load_cursor_on_client (self->cursor,
 | 
			
		||||
                                                self->theme_scale);
 | 
			
		||||
  if (!self->xcursor_images)
 | 
			
		||||
    meta_fatal ("Could not find cursor. Perhaps set XCURSOR_PATH?");
 | 
			
		||||
 | 
			
		||||
  image = meta_cursor_sprite_get_current_frame_image (self);
 | 
			
		||||
  meta_cursor_sprite_load_from_xcursor_image (self, image);
 | 
			
		||||
 | 
			
		||||
  self->theme_dirty = FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaCursorReference *
 | 
			
		||||
meta_cursor_reference_from_buffer (struct wl_resource *buffer,
 | 
			
		||||
                                   int                 hot_x,
 | 
			
		||||
                                   int                 hot_y)
 | 
			
		||||
MetaCursorSprite *
 | 
			
		||||
meta_cursor_sprite_from_theme (MetaCursor cursor)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorReference *self;
 | 
			
		||||
  MetaCursorSprite *self;
 | 
			
		||||
 | 
			
		||||
  self = g_slice_new0 (MetaCursorReference);
 | 
			
		||||
  self->ref_count = 1;
 | 
			
		||||
  meta_cursor_image_load_from_buffer (&self->image, buffer, hot_x, hot_y);
 | 
			
		||||
  self = meta_cursor_sprite_new ();
 | 
			
		||||
 | 
			
		||||
  self->cursor = cursor;
 | 
			
		||||
  self->theme_dirty = TRUE;
 | 
			
		||||
 | 
			
		||||
  return self;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_cursor_sprite_set_texture (MetaCursorSprite *self,
 | 
			
		||||
                                CoglTexture      *texture,
 | 
			
		||||
                                int               hot_x,
 | 
			
		||||
                                int               hot_y)
 | 
			
		||||
{
 | 
			
		||||
  g_clear_pointer (&self->texture, cogl_object_unref);
 | 
			
		||||
  if (texture)
 | 
			
		||||
    self->texture = cogl_object_ref (texture);
 | 
			
		||||
  self->hot_x = hot_x;
 | 
			
		||||
  self->hot_y = hot_y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_cursor_sprite_set_texture_scale (MetaCursorSprite *self,
 | 
			
		||||
                                      float             scale)
 | 
			
		||||
{
 | 
			
		||||
  self->texture_scale = scale;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_cursor_sprite_set_theme_scale (MetaCursorSprite *self,
 | 
			
		||||
                                    int               theme_scale)
 | 
			
		||||
{
 | 
			
		||||
  if (self->theme_scale != theme_scale)
 | 
			
		||||
    self->theme_dirty = TRUE;
 | 
			
		||||
  self->theme_scale = theme_scale;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CoglTexture *
 | 
			
		||||
meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor,
 | 
			
		||||
                                        int                 *hot_x,
 | 
			
		||||
                                        int                 *hot_y)
 | 
			
		||||
meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *self)
 | 
			
		||||
{
 | 
			
		||||
  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);
 | 
			
		||||
  return COGL_TEXTURE (self->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)
 | 
			
		||||
meta_cursor_sprite_get_meta_cursor (MetaCursorSprite *self)
 | 
			
		||||
{
 | 
			
		||||
  return cursor->cursor;
 | 
			
		||||
  return self->cursor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_cursor_sprite_get_hotspot (MetaCursorSprite *self,
 | 
			
		||||
                                int              *hot_x,
 | 
			
		||||
                                int              *hot_y)
 | 
			
		||||
{
 | 
			
		||||
  *hot_x = self->hot_x;
 | 
			
		||||
  *hot_y = self->hot_y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float
 | 
			
		||||
meta_cursor_sprite_get_texture_scale (MetaCursorSprite *self)
 | 
			
		||||
{
 | 
			
		||||
  return self->texture_scale;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_cursor_sprite_prepare_at (MetaCursorSprite *self,
 | 
			
		||||
                               int               x,
 | 
			
		||||
                               int               y)
 | 
			
		||||
{
 | 
			
		||||
  g_signal_emit (self, signals[PREPARE_AT], 0, x, y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_cursor_sprite_realize_texture (MetaCursorSprite *self)
 | 
			
		||||
{
 | 
			
		||||
  if (self->theme_dirty)
 | 
			
		||||
    meta_cursor_sprite_load_from_theme (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_cursor_sprite_init (MetaCursorSprite *self)
 | 
			
		||||
{
 | 
			
		||||
  self->texture_scale = 1.0f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_cursor_sprite_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorSprite *self = META_CURSOR_SPRITE (object);
 | 
			
		||||
 | 
			
		||||
  if (self->xcursor_images)
 | 
			
		||||
    XcursorImagesDestroy (self->xcursor_images);
 | 
			
		||||
 | 
			
		||||
  g_clear_pointer (&self->texture, cogl_object_unref);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_cursor_sprite_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_cursor_sprite_class_init (MetaCursorSpriteClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->finalize = meta_cursor_sprite_finalize;
 | 
			
		||||
 | 
			
		||||
  signals[PREPARE_AT] = g_signal_new ("prepare-at",
 | 
			
		||||
                                      G_TYPE_FROM_CLASS (object_class),
 | 
			
		||||
                                      G_SIGNAL_RUN_LAST,
 | 
			
		||||
                                      0,
 | 
			
		||||
                                      NULL, NULL, NULL,
 | 
			
		||||
                                      G_TYPE_NONE, 2,
 | 
			
		||||
                                      G_TYPE_INT,
 | 
			
		||||
                                      G_TYPE_INT);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,25 +22,54 @@
 | 
			
		||||
#ifndef META_CURSOR_H
 | 
			
		||||
#define META_CURSOR_H
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaCursorReference MetaCursorReference;
 | 
			
		||||
 | 
			
		||||
MetaCursorReference * meta_cursor_reference_ref (MetaCursorReference *cursor);
 | 
			
		||||
void meta_cursor_reference_unref (MetaCursorReference *cursor);
 | 
			
		||||
 | 
			
		||||
#include <meta/common.h>
 | 
			
		||||
#include <meta/boxes.h>
 | 
			
		||||
 | 
			
		||||
MetaCursorReference * meta_cursor_reference_from_theme  (MetaCursor          cursor);
 | 
			
		||||
typedef struct _MetaCursorSprite MetaCursorSprite;
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_WAYLAND
 | 
			
		||||
#include <wayland-server.h>
 | 
			
		||||
MetaCursorReference * meta_cursor_reference_from_buffer (struct wl_resource *buffer,
 | 
			
		||||
                                                         int                 hot_x,
 | 
			
		||||
                                                         int                 hot_y);
 | 
			
		||||
#endif
 | 
			
		||||
#define META_TYPE_CURSOR_SPRITE (meta_cursor_sprite_get_type ())
 | 
			
		||||
G_DECLARE_FINAL_TYPE (MetaCursorSprite,
 | 
			
		||||
                      meta_cursor_sprite,
 | 
			
		||||
                      META, CURSOR_SPRITE,
 | 
			
		||||
                      GObject);
 | 
			
		||||
 | 
			
		||||
MetaCursor meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor);
 | 
			
		||||
MetaCursorSprite * meta_cursor_sprite_new (void);
 | 
			
		||||
 | 
			
		||||
MetaCursorSprite * meta_cursor_sprite_from_theme  (MetaCursor cursor);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void meta_cursor_sprite_set_theme_scale (MetaCursorSprite *self,
 | 
			
		||||
                                         int               scale);
 | 
			
		||||
 | 
			
		||||
MetaCursor meta_cursor_sprite_get_meta_cursor (MetaCursorSprite *self);
 | 
			
		||||
 | 
			
		||||
Cursor meta_cursor_create_x_cursor (Display    *xdisplay,
 | 
			
		||||
                                    MetaCursor  cursor);
 | 
			
		||||
 | 
			
		||||
void meta_cursor_sprite_prepare_at (MetaCursorSprite *self,
 | 
			
		||||
                                    int               x,
 | 
			
		||||
                                    int               y);
 | 
			
		||||
 | 
			
		||||
void meta_cursor_sprite_realize_texture (MetaCursorSprite *self);
 | 
			
		||||
 | 
			
		||||
void meta_cursor_sprite_set_texture (MetaCursorSprite *self,
 | 
			
		||||
                                     CoglTexture      *texture,
 | 
			
		||||
                                     int               hot_x,
 | 
			
		||||
                                     int               hot_y);
 | 
			
		||||
 | 
			
		||||
void meta_cursor_sprite_set_texture_scale (MetaCursorSprite *self,
 | 
			
		||||
                                           float             scale);
 | 
			
		||||
 | 
			
		||||
CoglTexture *meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *self);
 | 
			
		||||
 | 
			
		||||
void meta_cursor_sprite_get_hotspot (MetaCursorSprite *self,
 | 
			
		||||
                                     int              *hot_x,
 | 
			
		||||
                                     int              *hot_y);
 | 
			
		||||
 | 
			
		||||
float meta_cursor_sprite_get_texture_scale (MetaCursorSprite *self);
 | 
			
		||||
 | 
			
		||||
gboolean meta_cursor_sprite_is_animated            (MetaCursorSprite *self);
 | 
			
		||||
void     meta_cursor_sprite_tick_frame             (MetaCursorSprite *self);
 | 
			
		||||
guint    meta_cursor_sprite_get_current_frame_time (MetaCursorSprite *self);
 | 
			
		||||
 | 
			
		||||
#endif /* META_CURSOR_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -63,9 +63,9 @@ struct _MetaInputSettingsClass
 | 
			
		||||
  void (* set_invert_scroll) (MetaInputSettings  *settings,
 | 
			
		||||
                              ClutterInputDevice *device,
 | 
			
		||||
                              gboolean            inverted);
 | 
			
		||||
  void (* set_scroll_method) (MetaInputSettings            *settings,
 | 
			
		||||
                              ClutterInputDevice           *device,
 | 
			
		||||
                              GDesktopTouchpadScrollMethod  mode);
 | 
			
		||||
  void (* set_edge_scroll)   (MetaInputSettings  *settings,
 | 
			
		||||
                              ClutterInputDevice *device,
 | 
			
		||||
                              gboolean            enabled);
 | 
			
		||||
  void (* set_scroll_button) (MetaInputSettings  *settings,
 | 
			
		||||
                              ClutterInputDevice *device,
 | 
			
		||||
                              guint               button);
 | 
			
		||||
 
 | 
			
		||||
@@ -209,6 +209,10 @@ update_touchpad_left_handed (MetaInputSettings  *input_settings,
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  gboolean enabled = FALSE;
 | 
			
		||||
 | 
			
		||||
  if (device &&
 | 
			
		||||
      clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  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");
 | 
			
		||||
@@ -230,7 +234,6 @@ update_touchpad_left_handed (MetaInputSettings  *input_settings,
 | 
			
		||||
 | 
			
		||||
  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);
 | 
			
		||||
@@ -251,13 +254,16 @@ update_mouse_left_handed (MetaInputSettings  *input_settings,
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  gboolean enabled;
 | 
			
		||||
 | 
			
		||||
  if (device &&
 | 
			
		||||
      clutter_input_device_get_device_type (device) != CLUTTER_POINTER_DEVICE)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  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);
 | 
			
		||||
@@ -366,6 +372,10 @@ update_touchpad_tap_enabled (MetaInputSettings  *input_settings,
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  gboolean enabled;
 | 
			
		||||
 | 
			
		||||
  if (device &&
 | 
			
		||||
      clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  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");
 | 
			
		||||
@@ -385,28 +395,32 @@ update_touchpad_tap_enabled (MetaInputSettings  *input_settings,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_touchpad_scroll_method (MetaInputSettings *input_settings,
 | 
			
		||||
                               ClutterInputDevice *device)
 | 
			
		||||
update_touchpad_edge_scroll (MetaInputSettings *input_settings,
 | 
			
		||||
                             ClutterInputDevice *device)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsClass *input_settings_class;
 | 
			
		||||
  GDesktopTouchpadScrollMethod method;
 | 
			
		||||
  gboolean edge_scroll_enabled;
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
 | 
			
		||||
  if (device &&
 | 
			
		||||
      clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  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");
 | 
			
		||||
  edge_scroll_enabled = g_settings_get_boolean (priv->touchpad_settings, "edge-scrolling-enabled");
 | 
			
		||||
 | 
			
		||||
  if (device)
 | 
			
		||||
    {
 | 
			
		||||
      settings_device_set_uint_setting (input_settings, device,
 | 
			
		||||
                                        input_settings_class->set_scroll_method,
 | 
			
		||||
                                        method);
 | 
			
		||||
      settings_device_set_bool_setting (input_settings, device,
 | 
			
		||||
                                        input_settings_class->set_edge_scroll,
 | 
			
		||||
                                        edge_scroll_enabled);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      settings_set_uint_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
 | 
			
		||||
                                 (ConfigUintFunc) input_settings_class->set_scroll_method,
 | 
			
		||||
                                 method);
 | 
			
		||||
      settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
 | 
			
		||||
                                 (ConfigBoolFunc) input_settings_class->set_edge_scroll,
 | 
			
		||||
                                 edge_scroll_enabled);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -415,9 +429,13 @@ update_touchpad_click_method (MetaInputSettings *input_settings,
 | 
			
		||||
                              ClutterInputDevice *device)
 | 
			
		||||
{
 | 
			
		||||
  MetaInputSettingsClass *input_settings_class;
 | 
			
		||||
  GDesktopTouchpadScrollMethod method;
 | 
			
		||||
  GDesktopTouchpadClickMethod method;
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
 | 
			
		||||
  if (device &&
 | 
			
		||||
      clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  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, "click-method");
 | 
			
		||||
@@ -444,6 +462,10 @@ update_touchpad_send_events (MetaInputSettings  *input_settings,
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  GDesktopDeviceSendEvents mode;
 | 
			
		||||
 | 
			
		||||
  if (device &&
 | 
			
		||||
      clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  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");
 | 
			
		||||
@@ -486,27 +508,28 @@ update_trackball_scroll_button (MetaInputSettings  *input_settings,
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  guint button;
 | 
			
		||||
 | 
			
		||||
  if (device && !device_is_trackball (device))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
 | 
			
		||||
  /* This key is 'i' in the schema but it also specifies a minimum
 | 
			
		||||
   * range of 0 so the cast here is safe. */
 | 
			
		||||
  button = (guint) g_settings_get_int (priv->trackball_settings, "scroll-wheel-emulation-button");
 | 
			
		||||
 | 
			
		||||
  if (device && device_is_trackball (device))
 | 
			
		||||
  if (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;
 | 
			
		||||
          device = devices->data;
 | 
			
		||||
 | 
			
		||||
          if (device_is_trackball (device))
 | 
			
		||||
            input_settings_class->set_scroll_button (input_settings, device, button);
 | 
			
		||||
@@ -622,8 +645,8 @@ meta_input_settings_changed_cb (GSettings  *settings,
 | 
			
		||||
        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 (strcmp (key, "edge-scrolling-enabled") == 0)
 | 
			
		||||
        update_touchpad_edge_scroll (input_settings, NULL);
 | 
			
		||||
      else if (strcmp (key, "click-method") == 0)
 | 
			
		||||
        update_touchpad_click_method (input_settings, NULL);
 | 
			
		||||
    }
 | 
			
		||||
@@ -748,7 +771,7 @@ apply_device_settings (MetaInputSettings  *input_settings,
 | 
			
		||||
  update_device_natural_scroll (input_settings, device);
 | 
			
		||||
  update_touchpad_tap_enabled (input_settings, device);
 | 
			
		||||
  update_touchpad_send_events (input_settings, device);
 | 
			
		||||
  update_touchpad_scroll_method (input_settings, device);
 | 
			
		||||
  update_touchpad_edge_scroll (input_settings, device);
 | 
			
		||||
  update_touchpad_click_method (input_settings, device);
 | 
			
		||||
 | 
			
		||||
  update_trackball_scroll_button (input_settings, device);
 | 
			
		||||
 
 | 
			
		||||
@@ -65,6 +65,7 @@ typedef struct {
 | 
			
		||||
 | 
			
		||||
  gboolean is_primary;
 | 
			
		||||
  gboolean is_presentation;
 | 
			
		||||
  gboolean is_underscanning;
 | 
			
		||||
} MetaOutputConfig;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
@@ -82,7 +83,8 @@ struct _MetaMonitorConfig {
 | 
			
		||||
  gboolean current_is_for_laptop_lid;
 | 
			
		||||
  MetaConfiguration *previous;
 | 
			
		||||
 | 
			
		||||
  GFile *file;
 | 
			
		||||
  GFile *user_file;
 | 
			
		||||
  GFile *system_file;
 | 
			
		||||
  GCancellable *save_cancellable;
 | 
			
		||||
 | 
			
		||||
  UpClient *up_client;
 | 
			
		||||
@@ -238,6 +240,7 @@ meta_monitor_config_init (MetaMonitorConfig *self)
 | 
			
		||||
{
 | 
			
		||||
  const char *filename;
 | 
			
		||||
  char *path;
 | 
			
		||||
  const char * const *system_dirs;
 | 
			
		||||
 | 
			
		||||
  self->configs = g_hash_table_new_full (config_hash, config_equal, NULL, (GDestroyNotify) config_unref);
 | 
			
		||||
 | 
			
		||||
@@ -246,9 +249,17 @@ meta_monitor_config_init (MetaMonitorConfig *self)
 | 
			
		||||
    filename = "monitors.xml";
 | 
			
		||||
 | 
			
		||||
  path = g_build_filename (g_get_user_config_dir (), filename, NULL);
 | 
			
		||||
  self->file = g_file_new_for_path (path);
 | 
			
		||||
  self->user_file = g_file_new_for_path (path);
 | 
			
		||||
  g_free (path);
 | 
			
		||||
 | 
			
		||||
  for (system_dirs = g_get_system_config_dirs (); !self->system_file && *system_dirs; system_dirs++)
 | 
			
		||||
    {
 | 
			
		||||
      path = g_build_filename (*system_dirs, filename, NULL);
 | 
			
		||||
      if (g_file_test (path, G_FILE_TEST_EXISTS))
 | 
			
		||||
        self->system_file = g_file_new_for_path (path);
 | 
			
		||||
      g_free (path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  self->up_client = up_client_new ();
 | 
			
		||||
  self->lid_is_closed = up_client_get_lid_is_closed (self->up_client);
 | 
			
		||||
 | 
			
		||||
@@ -393,7 +404,8 @@ handle_start_element (GMarkupParseContext  *context,
 | 
			
		||||
             strcmp (element_name, "reflect_x") == 0 ||
 | 
			
		||||
             strcmp (element_name, "reflect_y") == 0 ||
 | 
			
		||||
             strcmp (element_name, "primary") == 0 ||
 | 
			
		||||
             strcmp (element_name, "presentation") == 0) && parser->unknown_count == 0)
 | 
			
		||||
             strcmp (element_name, "presentation") == 0 ||
 | 
			
		||||
             strcmp (element_name, "underscanning") == 0) && parser->unknown_count == 0)
 | 
			
		||||
          {
 | 
			
		||||
            parser->state = STATE_OUTPUT_FIELD;
 | 
			
		||||
 | 
			
		||||
@@ -477,8 +489,8 @@ handle_end_element (GMarkupParseContext  *context,
 | 
			
		||||
              }
 | 
			
		||||
            else
 | 
			
		||||
              {
 | 
			
		||||
                if (parser->output.rect.width == 0 &&
 | 
			
		||||
                    parser->output.rect.width == 0)
 | 
			
		||||
                if (parser->output.rect.width == 0 ||
 | 
			
		||||
                    parser->output.rect.height == 0)
 | 
			
		||||
                  parser->output.enabled = FALSE;
 | 
			
		||||
                else
 | 
			
		||||
                  parser->output.enabled = TRUE;
 | 
			
		||||
@@ -700,6 +712,8 @@ handle_text (GMarkupParseContext *context,
 | 
			
		||||
          parser->output.is_primary = read_bool (text, text_len, error);
 | 
			
		||||
        else if (strcmp (parser->output_field, "presentation") == 0)
 | 
			
		||||
          parser->output.is_presentation = read_bool (text, text_len, error);
 | 
			
		||||
        else if (strcmp (parser->output_field, "underscanning") == 0)
 | 
			
		||||
          parser->output.is_underscanning = read_bool (text, text_len, error);
 | 
			
		||||
        else
 | 
			
		||||
          g_assert_not_reached ();
 | 
			
		||||
        return;
 | 
			
		||||
@@ -717,8 +731,8 @@ static const GMarkupParser config_parser = {
 | 
			
		||||
  .text = handle_text,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_config_load (MetaMonitorConfig  *self)
 | 
			
		||||
static gboolean
 | 
			
		||||
load_config_file (MetaMonitorConfig *self, GFile *file)
 | 
			
		||||
{
 | 
			
		||||
  char *contents;
 | 
			
		||||
  gsize size;
 | 
			
		||||
@@ -736,14 +750,12 @@ meta_monitor_config_load (MetaMonitorConfig  *self)
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  error = NULL;
 | 
			
		||||
  ok = g_file_load_contents (self->file, NULL, &contents, &size, NULL, &error);
 | 
			
		||||
  ok = g_file_load_contents (file, NULL, &contents, &size, NULL, &error);
 | 
			
		||||
  if (!ok)
 | 
			
		||||
    {
 | 
			
		||||
      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
 | 
			
		||||
        meta_warning ("Failed to load stored monitor configuration: %s\n", error->message);
 | 
			
		||||
 | 
			
		||||
      g_error_free (error);
 | 
			
		||||
      return;
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  memset (&parser, 0, sizeof (ConfigParser));
 | 
			
		||||
@@ -772,6 +784,17 @@ meta_monitor_config_load (MetaMonitorConfig  *self)
 | 
			
		||||
 | 
			
		||||
  g_markup_parse_context_free (context);
 | 
			
		||||
  g_free (contents);
 | 
			
		||||
 | 
			
		||||
  return ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_config_load (MetaMonitorConfig *self)
 | 
			
		||||
{
 | 
			
		||||
  if (self->user_file && load_config_file (self, self->user_file))
 | 
			
		||||
    return;
 | 
			
		||||
  if (self->system_file && load_config_file (self, self->system_file))
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaMonitorConfig *
 | 
			
		||||
@@ -863,14 +886,14 @@ apply_configuration (MetaMonitorConfig  *self,
 | 
			
		||||
                     MetaConfiguration  *config,
 | 
			
		||||
		     MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
  GPtrArray *crtcs, *outputs;
 | 
			
		||||
  gboolean ret = FALSE;
 | 
			
		||||
  g_autoptr(GPtrArray) crtcs = NULL;
 | 
			
		||||
  g_autoptr(GPtrArray) outputs = NULL;
 | 
			
		||||
 | 
			
		||||
  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))
 | 
			
		||||
    goto out;
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  meta_monitor_manager_apply_configuration (manager,
 | 
			
		||||
                                            (MetaCRTCInfo**)crtcs->pdata, crtcs->len,
 | 
			
		||||
@@ -882,12 +905,7 @@ apply_configuration (MetaMonitorConfig  *self,
 | 
			
		||||
   * inside turn_off_laptop_display / apply_configuration_with_lid */
 | 
			
		||||
  self->current_is_for_laptop_lid = FALSE;
 | 
			
		||||
 | 
			
		||||
  ret = TRUE;
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  g_ptr_array_unref (crtcs);
 | 
			
		||||
  g_ptr_array_unref (outputs);
 | 
			
		||||
  return ret;
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
@@ -1056,12 +1074,12 @@ meta_monitor_config_apply_stored (MetaMonitorConfig  *self,
 | 
			
		||||
 * which are internal monitors), or failing that, the one with the
 | 
			
		||||
 * best resolution
 | 
			
		||||
 */
 | 
			
		||||
static MetaOutput *
 | 
			
		||||
static int
 | 
			
		||||
find_primary_output (MetaOutput *outputs,
 | 
			
		||||
                     unsigned    n_outputs)
 | 
			
		||||
{
 | 
			
		||||
  unsigned i;
 | 
			
		||||
  MetaOutput *best;
 | 
			
		||||
  int best;
 | 
			
		||||
  int best_width, best_height;
 | 
			
		||||
 | 
			
		||||
  g_assert (n_outputs >= 1);
 | 
			
		||||
@@ -1069,23 +1087,23 @@ find_primary_output (MetaOutput *outputs,
 | 
			
		||||
  for (i = 0; i < n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      if (outputs[i].is_primary)
 | 
			
		||||
        return &outputs[i];
 | 
			
		||||
        return i;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      if (output_is_laptop (&outputs[i]))
 | 
			
		||||
        return &outputs[i];
 | 
			
		||||
        return i;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  best = NULL;
 | 
			
		||||
  best = -1;
 | 
			
		||||
  best_width = 0; best_height = 0;
 | 
			
		||||
  for (i = 0; i < n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      if (outputs[i].preferred_mode->width * outputs[i].preferred_mode->height >
 | 
			
		||||
          best_width * best_height)
 | 
			
		||||
        {
 | 
			
		||||
          best = &outputs[i];
 | 
			
		||||
          best = i;
 | 
			
		||||
          best_width = outputs[i].preferred_mode->width;
 | 
			
		||||
          best_height = outputs[i].preferred_mode->height;
 | 
			
		||||
        }
 | 
			
		||||
@@ -1123,7 +1141,7 @@ make_suggested_config (MetaMonitorConfig *self,
 | 
			
		||||
                       MetaConfiguration *config)
 | 
			
		||||
{
 | 
			
		||||
  unsigned int i;
 | 
			
		||||
  MetaOutput *primary;
 | 
			
		||||
  int primary;
 | 
			
		||||
  GList *region = NULL;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (config != NULL, FALSE);
 | 
			
		||||
@@ -1131,7 +1149,7 @@ make_suggested_config (MetaMonitorConfig *self,
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      gboolean is_primary = (&outputs[i] == primary);
 | 
			
		||||
      gboolean is_primary = ((int)i == primary);
 | 
			
		||||
 | 
			
		||||
      if (outputs[i].suggested_x < 0 || outputs[i].suggested_y < 0)
 | 
			
		||||
          return FALSE;
 | 
			
		||||
@@ -1158,6 +1176,81 @@ make_suggested_config (MetaMonitorConfig *self,
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
config_one_untiled_output (MetaOutput *outputs,
 | 
			
		||||
                           MetaConfiguration *config,
 | 
			
		||||
                           int idx, gboolean is_primary,
 | 
			
		||||
                           int *x, unsigned long *output_configured_bitmap)
 | 
			
		||||
{
 | 
			
		||||
  MetaOutput *output = &outputs[idx];
 | 
			
		||||
 | 
			
		||||
  if (*output_configured_bitmap & (1 << idx))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  init_config_from_preferred_mode (&config->outputs[idx], output);
 | 
			
		||||
  config->outputs[idx].is_primary = is_primary;
 | 
			
		||||
  config->outputs[idx].rect.x = *x;
 | 
			
		||||
  *x += config->outputs[idx].rect.width;
 | 
			
		||||
  *output_configured_bitmap |= (1 << idx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
config_one_tiled_group (MetaOutput *outputs,
 | 
			
		||||
                        MetaConfiguration *config,
 | 
			
		||||
                        int base_idx, gboolean is_primary,
 | 
			
		||||
                        int n_outputs,
 | 
			
		||||
                        int *x, unsigned long *output_configured_bitmap)
 | 
			
		||||
{
 | 
			
		||||
  guint32 num_h_tile, num_v_tile, ht, vt;
 | 
			
		||||
  int j;
 | 
			
		||||
  int cur_x, cur_y, addx = 0;
 | 
			
		||||
 | 
			
		||||
  if (*output_configured_bitmap & (1 << base_idx))
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
  if (outputs[base_idx].tile_info.group_id == 0)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  cur_x = cur_y = 0;
 | 
			
		||||
  num_h_tile = outputs[base_idx].tile_info.max_h_tiles;
 | 
			
		||||
  num_v_tile = outputs[base_idx].tile_info.max_v_tiles;
 | 
			
		||||
 | 
			
		||||
  /* iterate over horizontal tiles */
 | 
			
		||||
  cur_x = *x;
 | 
			
		||||
  for (ht = 0; ht < num_h_tile; ht++)
 | 
			
		||||
    {
 | 
			
		||||
      cur_y = 0;
 | 
			
		||||
      addx = 0;
 | 
			
		||||
      for (vt = 0; vt < num_v_tile; vt++)
 | 
			
		||||
        {
 | 
			
		||||
          for (j = 0; j < n_outputs; j++)
 | 
			
		||||
            {
 | 
			
		||||
              if (outputs[j].tile_info.group_id != outputs[base_idx].tile_info.group_id)
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
              if (outputs[j].tile_info.loc_h_tile != ht ||
 | 
			
		||||
                  outputs[j].tile_info.loc_v_tile != vt)
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
              if (ht == 0 && vt == 0 && is_primary)
 | 
			
		||||
                config->outputs[j].is_primary = TRUE;
 | 
			
		||||
 | 
			
		||||
              init_config_from_preferred_mode (&config->outputs[j], &outputs[j]);
 | 
			
		||||
              config->outputs[j].rect.x = cur_x;
 | 
			
		||||
              config->outputs[j].rect.y = cur_y;
 | 
			
		||||
 | 
			
		||||
              *output_configured_bitmap |= (1 << j);
 | 
			
		||||
              cur_y += outputs[j].tile_info.tile_h;
 | 
			
		||||
              if (vt == 0)
 | 
			
		||||
                addx += outputs[j].tile_info.tile_w;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
      cur_x += addx;
 | 
			
		||||
    }
 | 
			
		||||
  *x = cur_x;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
make_linear_config (MetaMonitorConfig *self,
 | 
			
		||||
                    MetaOutput        *outputs,
 | 
			
		||||
@@ -1166,31 +1259,41 @@ make_linear_config (MetaMonitorConfig *self,
 | 
			
		||||
                    int                max_height,
 | 
			
		||||
                    MetaConfiguration *config)
 | 
			
		||||
{
 | 
			
		||||
  MetaOutput *primary;
 | 
			
		||||
  unsigned long output_configured_bitmap = 0;
 | 
			
		||||
  unsigned i;
 | 
			
		||||
  int x;
 | 
			
		||||
  int primary;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (config != NULL);
 | 
			
		||||
 | 
			
		||||
  primary = find_primary_output (outputs, n_outputs);
 | 
			
		||||
 | 
			
		||||
  x = primary->preferred_mode->width;
 | 
			
		||||
  x = 0;
 | 
			
		||||
  /* set the primary up first at 0 */
 | 
			
		||||
  if (outputs[primary].tile_info.group_id)
 | 
			
		||||
    {
 | 
			
		||||
      config_one_tiled_group (outputs, config, primary, TRUE, n_outputs,
 | 
			
		||||
                              &x, &output_configured_bitmap);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      config_one_untiled_output (outputs, config, primary, TRUE,
 | 
			
		||||
                                 &x, &output_configured_bitmap);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* then add other tiled monitors */
 | 
			
		||||
  for (i = 0; i < n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      gboolean is_primary = (&outputs[i] == primary);
 | 
			
		||||
      config_one_tiled_group (outputs, config, i, FALSE, n_outputs,
 | 
			
		||||
                              &x, &output_configured_bitmap);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
      init_config_from_preferred_mode (&config->outputs[i], &outputs[i]);
 | 
			
		||||
      config->outputs[i].is_primary = is_primary;
 | 
			
		||||
  /* then add remaining monitors */
 | 
			
		||||
  for (i = 0; i < n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      config_one_untiled_output (outputs, config, i, FALSE,
 | 
			
		||||
                                 &x, &output_configured_bitmap);
 | 
			
		||||
 | 
			
		||||
      if (is_primary)
 | 
			
		||||
        {
 | 
			
		||||
          config->outputs[i].rect.x = 0;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          config->outputs[i].rect.x = x;
 | 
			
		||||
          x += config->outputs[i].rect.width;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1314,7 +1417,7 @@ ensure_at_least_one_output (MetaMonitorConfig  *self,
 | 
			
		||||
                            unsigned            n_outputs)
 | 
			
		||||
{
 | 
			
		||||
  MetaConfiguration *config;
 | 
			
		||||
  MetaOutput *primary;
 | 
			
		||||
  int primary;
 | 
			
		||||
  unsigned i;
 | 
			
		||||
 | 
			
		||||
  /* Check that we have at least one active output */
 | 
			
		||||
@@ -1332,7 +1435,7 @@ ensure_at_least_one_output (MetaMonitorConfig  *self,
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      gboolean is_primary = (&outputs[i] == primary);
 | 
			
		||||
      gboolean is_primary = ((int)i == primary);
 | 
			
		||||
 | 
			
		||||
      if (is_primary)
 | 
			
		||||
        {
 | 
			
		||||
@@ -1408,6 +1511,7 @@ init_config_from_output (MetaOutputConfig *config,
 | 
			
		||||
  config->transform = output->crtc->transform;
 | 
			
		||||
  config->is_primary = output->is_primary;
 | 
			
		||||
  config->is_presentation = output->is_presentation;
 | 
			
		||||
  config->is_underscanning = output->is_underscanning;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -1598,7 +1702,8 @@ meta_monitor_config_save (MetaMonitorConfig *self)
 | 
			
		||||
                                      "      <reflect_x>%s</reflect_x>\n"
 | 
			
		||||
                                      "      <reflect_y>no</reflect_y>\n"
 | 
			
		||||
                                      "      <primary>%s</primary>\n"
 | 
			
		||||
                                      "      <presentation>%s</presentation>\n",
 | 
			
		||||
                                      "      <presentation>%s</presentation>\n"
 | 
			
		||||
                                      "      <underscanning>%s</underscanning>\n",
 | 
			
		||||
                                      output->rect.width,
 | 
			
		||||
                                      output->rect.height,
 | 
			
		||||
                                      refresh_rate,
 | 
			
		||||
@@ -1607,7 +1712,8 @@ meta_monitor_config_save (MetaMonitorConfig *self)
 | 
			
		||||
                                      rotation_map[output->transform & 0x3],
 | 
			
		||||
                                      output->transform >= META_MONITOR_TRANSFORM_FLIPPED ? "yes" : "no",
 | 
			
		||||
                                      output->is_primary ? "yes" : "no",
 | 
			
		||||
                                      output->is_presentation ? "yes" : "no");
 | 
			
		||||
                                      output->is_presentation ? "yes" : "no",
 | 
			
		||||
                                      output->is_underscanning ? "yes" : "no");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          g_string_append (buffer, "    </output>\n");
 | 
			
		||||
@@ -1622,7 +1728,7 @@ meta_monitor_config_save (MetaMonitorConfig *self)
 | 
			
		||||
  closure->config = g_object_ref (self);
 | 
			
		||||
  closure->buffer = buffer;
 | 
			
		||||
 | 
			
		||||
  g_file_replace_contents_async (self->file,
 | 
			
		||||
  g_file_replace_contents_async (self->user_file,
 | 
			
		||||
                                 buffer->str, buffer->len,
 | 
			
		||||
                                 NULL, /* etag */
 | 
			
		||||
                                 TRUE,
 | 
			
		||||
@@ -1740,7 +1846,7 @@ crtc_assignment_assign (CrtcAssignment       *assign,
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      MetaCRTCInfo *info = g_slice_new0 (MetaCRTCInfo);
 | 
			
		||||
      info = g_slice_new0 (MetaCRTCInfo);
 | 
			
		||||
 | 
			
		||||
      info->crtc = crtc;
 | 
			
		||||
      info->mode = mode;
 | 
			
		||||
@@ -1814,7 +1920,6 @@ real_assign_crtcs (CrtcAssignment     *assignment,
 | 
			
		||||
  MetaOutputKey *output_key;
 | 
			
		||||
  MetaOutputConfig *output_config;
 | 
			
		||||
  unsigned int i;
 | 
			
		||||
  gboolean success;
 | 
			
		||||
 | 
			
		||||
  if (output_num == assignment->config->n_outputs)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
@@ -1831,8 +1936,6 @@ real_assign_crtcs (CrtcAssignment     *assignment,
 | 
			
		||||
                                      &crtcs, &n_crtcs,
 | 
			
		||||
                                      &outputs, &n_outputs);
 | 
			
		||||
 | 
			
		||||
  success = FALSE;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_crtcs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaCRTC *crtc = &crtcs[i];
 | 
			
		||||
@@ -1879,10 +1982,7 @@ real_assign_crtcs (CrtcAssignment     *assignment,
 | 
			
		||||
                                              output))
 | 
			
		||||
                    {
 | 
			
		||||
                      if (real_assign_crtcs (assignment, output_num + 1))
 | 
			
		||||
                        {
 | 
			
		||||
                          success = TRUE;
 | 
			
		||||
                          goto out;
 | 
			
		||||
                        }
 | 
			
		||||
                        return TRUE;
 | 
			
		||||
 | 
			
		||||
                      crtc_assignment_unassign (assignment, crtc, output);
 | 
			
		||||
                    }
 | 
			
		||||
@@ -1891,8 +1991,7 @@ real_assign_crtcs (CrtcAssignment     *assignment,
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
  return success;
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
@@ -1941,6 +2040,7 @@ meta_monitor_config_assign_crtcs (MetaConfiguration  *config,
 | 
			
		||||
                                                &config->keys[i]);
 | 
			
		||||
      output_info->is_primary = output_config->is_primary;
 | 
			
		||||
      output_info->is_presentation = output_config->is_presentation;
 | 
			
		||||
      output_info->is_underscanning = output_config->is_underscanning;
 | 
			
		||||
 | 
			
		||||
      g_ptr_array_add (outputs, output_info);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,10 @@
 | 
			
		||||
 | 
			
		||||
#include "meta-monitor-manager-dummy.h"
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include <meta/util.h>
 | 
			
		||||
 | 
			
		||||
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
 | 
			
		||||
 | 
			
		||||
struct _MetaMonitorManagerDummy
 | 
			
		||||
@@ -44,9 +48,69 @@ G_DEFINE_TYPE (MetaMonitorManagerDummy, meta_monitor_manager_dummy, META_TYPE_MO
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
  unsigned int num_monitors = 1;
 | 
			
		||||
  int *monitor_scales = NULL;
 | 
			
		||||
  const char *num_monitors_str;
 | 
			
		||||
  const char *monitor_scales_str;
 | 
			
		||||
  unsigned int i;
 | 
			
		||||
  int current_x = 0;
 | 
			
		||||
 | 
			
		||||
  /* To control what monitor configuration is generated, there are two available
 | 
			
		||||
   * environmental variables that can be used:
 | 
			
		||||
   *
 | 
			
		||||
   * MUTTER_DEBUG_NUM_DUMMY_MONITORS
 | 
			
		||||
   *
 | 
			
		||||
   * Specifies the number of dummy monitors to include in the stage. Every
 | 
			
		||||
   * monitor is 1024x786 pixels and they are placed on a horizontal row.
 | 
			
		||||
   *
 | 
			
		||||
   * MUTTER_DEBUG_DUMMY_MONITOR_SCALES
 | 
			
		||||
   *
 | 
			
		||||
   * A comma separated list that specifies the scales of the dummy monitors.
 | 
			
		||||
   *
 | 
			
		||||
   * For example the following configuration results in two monitors, where the
 | 
			
		||||
   * first one has the monitor scale 1, and the other the monitor scale 2.
 | 
			
		||||
   *
 | 
			
		||||
   * MUTTER_DEBUG_NUM_DUMMY_MONITORS=2
 | 
			
		||||
   * MUTTER_DEBUG_DUMMY_MONITOR_SCALES=1,2
 | 
			
		||||
   */
 | 
			
		||||
  num_monitors_str = getenv ("MUTTER_DEBUG_NUM_DUMMY_MONITORS");
 | 
			
		||||
  if (num_monitors_str)
 | 
			
		||||
    {
 | 
			
		||||
      num_monitors = g_ascii_strtoll (num_monitors_str, NULL, 10);
 | 
			
		||||
      if (num_monitors <= 0)
 | 
			
		||||
        {
 | 
			
		||||
          meta_warning ("Invalid number of dummy monitors");
 | 
			
		||||
          num_monitors = 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  monitor_scales = g_newa (int, num_monitors);
 | 
			
		||||
  for (i = 0; i < num_monitors; i++)
 | 
			
		||||
    monitor_scales[i] = 1;
 | 
			
		||||
 | 
			
		||||
  monitor_scales_str = getenv ("MUTTER_DEBUG_DUMMY_MONITOR_SCALES");
 | 
			
		||||
  if (monitor_scales_str)
 | 
			
		||||
    {
 | 
			
		||||
      gchar **scales_str_list;
 | 
			
		||||
 | 
			
		||||
      scales_str_list = g_strsplit (monitor_scales_str, ",", -1);
 | 
			
		||||
      if (g_strv_length (scales_str_list) != num_monitors)
 | 
			
		||||
        meta_warning ("Number of specified monitor scales differ from number "
 | 
			
		||||
                      "of monitors (defaults to 1).\n");
 | 
			
		||||
      for (i = 0; i < num_monitors && scales_str_list[i]; i++)
 | 
			
		||||
        {
 | 
			
		||||
          int scale = g_ascii_strtoll (scales_str_list[i], NULL, 10);
 | 
			
		||||
          if (scale == 1 || scale == 2)
 | 
			
		||||
            monitor_scales[i] = scale;
 | 
			
		||||
          else
 | 
			
		||||
            meta_warning ("Invalid dummy monitor scale");
 | 
			
		||||
        }
 | 
			
		||||
      g_strfreev (scales_str_list);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  manager->max_screen_width = 65535;
 | 
			
		||||
  manager->max_screen_height = 65535;
 | 
			
		||||
  manager->screen_width = 1024;
 | 
			
		||||
  manager->screen_width = 1024 * num_monitors;
 | 
			
		||||
  manager->screen_height = 768;
 | 
			
		||||
 | 
			
		||||
  manager->modes = g_new0 (MetaMonitorMode, 1);
 | 
			
		||||
@@ -57,46 +121,52 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
 | 
			
		||||
  manager->modes[0].height = 768;
 | 
			
		||||
  manager->modes[0].refresh_rate = 60.0;
 | 
			
		||||
 | 
			
		||||
  manager->crtcs = g_new0 (MetaCRTC, 1);
 | 
			
		||||
  manager->n_crtcs = 1;
 | 
			
		||||
  manager->crtcs = g_new0 (MetaCRTC, num_monitors);
 | 
			
		||||
  manager->n_crtcs = num_monitors;
 | 
			
		||||
  manager->outputs = g_new0 (MetaOutput, num_monitors);
 | 
			
		||||
  manager->n_outputs = num_monitors;
 | 
			
		||||
 | 
			
		||||
  manager->crtcs[0].crtc_id = 1;
 | 
			
		||||
  manager->crtcs[0].rect.x = 0;
 | 
			
		||||
  manager->crtcs[0].rect.y = 0;
 | 
			
		||||
  manager->crtcs[0].rect.width = manager->modes[0].width;
 | 
			
		||||
  manager->crtcs[0].rect.height = manager->modes[0].height;
 | 
			
		||||
  manager->crtcs[0].current_mode = &manager->modes[0];
 | 
			
		||||
  manager->crtcs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
 | 
			
		||||
  manager->crtcs[0].all_transforms = ALL_TRANSFORMS;
 | 
			
		||||
  manager->crtcs[0].is_dirty = FALSE;
 | 
			
		||||
  manager->crtcs[0].logical_monitor = NULL;
 | 
			
		||||
  for (i = 0; i < num_monitors; i++)
 | 
			
		||||
    {
 | 
			
		||||
      manager->crtcs[i].crtc_id = i + 1;
 | 
			
		||||
      manager->crtcs[i].rect.x = current_x;
 | 
			
		||||
      manager->crtcs[i].rect.y = 0;
 | 
			
		||||
      manager->crtcs[i].rect.width = manager->modes[0].width;
 | 
			
		||||
      manager->crtcs[i].rect.height = manager->modes[0].height;
 | 
			
		||||
      manager->crtcs[i].current_mode = &manager->modes[0];
 | 
			
		||||
      manager->crtcs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
 | 
			
		||||
      manager->crtcs[i].all_transforms = ALL_TRANSFORMS;
 | 
			
		||||
      manager->crtcs[i].is_dirty = FALSE;
 | 
			
		||||
      manager->crtcs[i].logical_monitor = NULL;
 | 
			
		||||
 | 
			
		||||
  manager->outputs = g_new0 (MetaOutput, 1);
 | 
			
		||||
  manager->n_outputs = 1;
 | 
			
		||||
      current_x += manager->crtcs[i].rect.width;
 | 
			
		||||
 | 
			
		||||
  manager->outputs[0].crtc = &manager->crtcs[0];
 | 
			
		||||
  manager->outputs[0].winsys_id = 1;
 | 
			
		||||
  manager->outputs[0].name = g_strdup ("LVDS");
 | 
			
		||||
  manager->outputs[0].vendor = g_strdup ("MetaProducts Inc.");
 | 
			
		||||
  manager->outputs[0].product = g_strdup ("unknown");
 | 
			
		||||
  manager->outputs[0].serial = g_strdup ("0xC0FFEE");
 | 
			
		||||
  manager->outputs[0].width_mm = 222;
 | 
			
		||||
  manager->outputs[0].height_mm = 125;
 | 
			
		||||
  manager->outputs[0].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
 | 
			
		||||
  manager->outputs[0].preferred_mode = &manager->modes[0];
 | 
			
		||||
  manager->outputs[0].n_modes = 1;
 | 
			
		||||
  manager->outputs[0].modes = g_new0 (MetaMonitorMode *, 1);
 | 
			
		||||
  manager->outputs[0].modes[0] = &manager->modes[0];
 | 
			
		||||
  manager->outputs[0].n_possible_crtcs = 1;
 | 
			
		||||
  manager->outputs[0].possible_crtcs = g_new0 (MetaCRTC *, 1);
 | 
			
		||||
  manager->outputs[0].possible_crtcs[0] = &manager->crtcs[0];
 | 
			
		||||
  manager->outputs[0].n_possible_clones = 0;
 | 
			
		||||
  manager->outputs[0].possible_clones = g_new0 (MetaOutput *, 0);
 | 
			
		||||
  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;
 | 
			
		||||
  manager->outputs[0].scale = 1;
 | 
			
		||||
      manager->outputs[i].crtc = &manager->crtcs[i];
 | 
			
		||||
      manager->outputs[i].winsys_id = i + 1;
 | 
			
		||||
      manager->outputs[i].name = g_strdup_printf ("LVDS%d", i + 1);
 | 
			
		||||
      manager->outputs[i].vendor = g_strdup ("MetaProducts Inc.");
 | 
			
		||||
      manager->outputs[i].product = g_strdup ("unknown");
 | 
			
		||||
      manager->outputs[i].serial = g_strdup ("0xC0FFEE");
 | 
			
		||||
      manager->outputs[i].suggested_x = -1;
 | 
			
		||||
      manager->outputs[i].suggested_y = -1;
 | 
			
		||||
      manager->outputs[i].width_mm = 222;
 | 
			
		||||
      manager->outputs[i].height_mm = 125;
 | 
			
		||||
      manager->outputs[i].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
 | 
			
		||||
      manager->outputs[i].preferred_mode = &manager->modes[0];
 | 
			
		||||
      manager->outputs[i].n_modes = 1;
 | 
			
		||||
      manager->outputs[i].modes = g_new0 (MetaMonitorMode *, 1);
 | 
			
		||||
      manager->outputs[i].modes[0] = &manager->modes[0];
 | 
			
		||||
      manager->outputs[i].n_possible_crtcs = 1;
 | 
			
		||||
      manager->outputs[i].possible_crtcs = g_new0 (MetaCRTC *, 1);
 | 
			
		||||
      manager->outputs[i].possible_crtcs[0] = &manager->crtcs[i];
 | 
			
		||||
      manager->outputs[i].n_possible_clones = 0;
 | 
			
		||||
      manager->outputs[i].possible_clones = g_new0 (MetaOutput *, 0);
 | 
			
		||||
      manager->outputs[i].backlight = -1;
 | 
			
		||||
      manager->outputs[i].backlight_min = 0;
 | 
			
		||||
      manager->outputs[i].backlight_max = 0;
 | 
			
		||||
      manager->outputs[i].connector_type = META_CONNECTOR_TYPE_LVDS;
 | 
			
		||||
      manager->outputs[i].scale = monitor_scales[i];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -127,7 +197,7 @@ meta_monitor_manager_dummy_apply_config (MetaMonitorManager *manager,
 | 
			
		||||
        {
 | 
			
		||||
          MetaMonitorMode *mode;
 | 
			
		||||
          MetaOutput *output;
 | 
			
		||||
          int i, n_outputs;
 | 
			
		||||
          unsigned int j;
 | 
			
		||||
          int width, height;
 | 
			
		||||
 | 
			
		||||
          mode = crtc_info->mode;
 | 
			
		||||
@@ -153,10 +223,9 @@ meta_monitor_manager_dummy_apply_config (MetaMonitorManager *manager,
 | 
			
		||||
          screen_width = MAX (screen_width, crtc_info->x + width);
 | 
			
		||||
          screen_height = MAX (screen_height, crtc_info->y + height);
 | 
			
		||||
 | 
			
		||||
          n_outputs = crtc_info->outputs->len;
 | 
			
		||||
          for (i = 0; i < n_outputs; i++)
 | 
			
		||||
          for (j = 0; j < crtc_info->outputs->len; j++)
 | 
			
		||||
            {
 | 
			
		||||
              output = ((MetaOutput**)crtc_info->outputs->pdata)[i];
 | 
			
		||||
              output = ((MetaOutput**)crtc_info->outputs->pdata)[j];
 | 
			
		||||
 | 
			
		||||
              output->is_dirty = TRUE;
 | 
			
		||||
              output->crtc = crtc;
 | 
			
		||||
 
 | 
			
		||||
@@ -56,6 +56,7 @@ typedef struct _MetaMonitorMode MetaMonitorMode;
 | 
			
		||||
typedef struct _MetaMonitorInfo MetaMonitorInfo;
 | 
			
		||||
typedef struct _MetaCRTCInfo MetaCRTCInfo;
 | 
			
		||||
typedef struct _MetaOutputInfo MetaOutputInfo;
 | 
			
		||||
typedef struct _MetaTileInfo MetaTileInfo;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  META_MONITOR_TRANSFORM_NORMAL,
 | 
			
		||||
@@ -89,6 +90,17 @@ typedef enum {
 | 
			
		||||
  META_CONNECTOR_TYPE_DSI = 16,
 | 
			
		||||
} MetaConnectorType;
 | 
			
		||||
 | 
			
		||||
struct _MetaTileInfo {
 | 
			
		||||
  guint32 group_id;
 | 
			
		||||
  guint32 flags;
 | 
			
		||||
  guint32 max_h_tiles;
 | 
			
		||||
  guint32 max_v_tiles;
 | 
			
		||||
  guint32 loc_h_tile;
 | 
			
		||||
  guint32 loc_v_tile;
 | 
			
		||||
  guint32 tile_w;
 | 
			
		||||
  guint32 tile_h;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaOutput
 | 
			
		||||
{
 | 
			
		||||
  /* The CRTC driving this output, NULL if the output is not enabled */
 | 
			
		||||
@@ -132,6 +144,8 @@ struct _MetaOutput
 | 
			
		||||
  */
 | 
			
		||||
  gboolean is_primary;
 | 
			
		||||
  gboolean is_presentation;
 | 
			
		||||
  gboolean is_underscanning;
 | 
			
		||||
  gboolean supports_underscanning;
 | 
			
		||||
 | 
			
		||||
  gpointer driver_private;
 | 
			
		||||
  GDestroyNotify driver_notify;
 | 
			
		||||
@@ -140,6 +154,8 @@ struct _MetaOutput
 | 
			
		||||
  gboolean hotplug_mode_update;
 | 
			
		||||
  gint suggested_x;
 | 
			
		||||
  gint suggested_y;
 | 
			
		||||
 | 
			
		||||
  MetaTileInfo tile_info;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaCRTC
 | 
			
		||||
@@ -158,7 +174,11 @@ struct _MetaCRTC
 | 
			
		||||
  /* Used when changing configuration */
 | 
			
		||||
  gboolean is_dirty;
 | 
			
		||||
 | 
			
		||||
  MetaCursorReference *cursor;
 | 
			
		||||
  /* Used by cursor renderer backend */
 | 
			
		||||
  void *cursor_renderer_private;
 | 
			
		||||
 | 
			
		||||
  gpointer driver_private;
 | 
			
		||||
  GDestroyNotify driver_notify;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaMonitorMode
 | 
			
		||||
@@ -175,6 +195,7 @@ struct _MetaMonitorMode
 | 
			
		||||
  GDestroyNotify driver_notify;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define META_MAX_OUTPUTS_PER_MONITOR 4
 | 
			
		||||
/**
 | 
			
		||||
 * MetaMonitorInfo:
 | 
			
		||||
 *
 | 
			
		||||
@@ -190,9 +211,14 @@ struct _MetaMonitorInfo
 | 
			
		||||
  int number;
 | 
			
		||||
  int xinerama_index;
 | 
			
		||||
  MetaRectangle rect;
 | 
			
		||||
  /* for tiled monitors these are calculated, from untiled just copied */
 | 
			
		||||
  float refresh_rate;
 | 
			
		||||
  int width_mm;
 | 
			
		||||
  int height_mm;
 | 
			
		||||
  gboolean is_primary;
 | 
			
		||||
  gboolean is_presentation; /* XXX: not yet used */
 | 
			
		||||
  gboolean in_fullscreen;
 | 
			
		||||
  int scale;
 | 
			
		||||
 | 
			
		||||
  /* The primary or first output for this monitor, 0 if we can't figure out.
 | 
			
		||||
     It can be matched to a winsys_id of a MetaOutput.
 | 
			
		||||
@@ -203,6 +229,12 @@ struct _MetaMonitorInfo
 | 
			
		||||
     the primary one).
 | 
			
		||||
  */
 | 
			
		||||
  glong winsys_id;
 | 
			
		||||
 | 
			
		||||
  guint32 tile_group_id;
 | 
			
		||||
 | 
			
		||||
  int monitor_winsys_xid;
 | 
			
		||||
  int n_outputs;
 | 
			
		||||
  MetaOutput *outputs[META_MAX_OUTPUTS_PER_MONITOR];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -230,6 +262,7 @@ struct _MetaOutputInfo {
 | 
			
		||||
  MetaOutput  *output;
 | 
			
		||||
  gboolean     is_primary;
 | 
			
		||||
  gboolean     is_presentation;
 | 
			
		||||
  gboolean     is_underscanning;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_MONITOR_MANAGER            (meta_monitor_manager_get_type ())
 | 
			
		||||
@@ -319,6 +352,13 @@ struct _MetaMonitorManagerClass
 | 
			
		||||
                          unsigned short     *,
 | 
			
		||||
                          unsigned short     *,
 | 
			
		||||
                          unsigned short     *);
 | 
			
		||||
 | 
			
		||||
  void (*add_monitor) (MetaMonitorManager *,
 | 
			
		||||
                       MetaMonitorInfo *);
 | 
			
		||||
 | 
			
		||||
  void (*delete_monitor) (MetaMonitorManager *,
 | 
			
		||||
                          int monitor_winsys_xid);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void                meta_monitor_manager_rebuild_derived   (MetaMonitorManager *manager);
 | 
			
		||||
@@ -374,6 +414,10 @@ gint               meta_monitor_manager_get_monitor_at_point (MetaMonitorManager
 | 
			
		||||
                                                              gfloat              x,
 | 
			
		||||
                                                              gfloat              y);
 | 
			
		||||
 | 
			
		||||
void meta_monitor_manager_clear_output (MetaOutput *output);
 | 
			
		||||
void meta_monitor_manager_clear_mode (MetaMonitorMode *mode);
 | 
			
		||||
void meta_monitor_manager_clear_crtc (MetaCRTC *crtc);
 | 
			
		||||
 | 
			
		||||
/* Returns true if transform causes width and height to be inverted
 | 
			
		||||
   This is true for the odd transforms in the enum */
 | 
			
		||||
static inline gboolean
 | 
			
		||||
 
 | 
			
		||||
@@ -71,6 +71,98 @@ meta_monitor_manager_init (MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * rules for constructing a tiled monitor
 | 
			
		||||
 * 1. find a tile_group_id
 | 
			
		||||
 * 2. iterate over all outputs for that tile group id
 | 
			
		||||
 * 3. see if output has a crtc and if it is configured for the tile size
 | 
			
		||||
 * 4. calculate the total tile size
 | 
			
		||||
 * 5. set tile finished size
 | 
			
		||||
 * 6. check for more tile_group_id
 | 
			
		||||
*/
 | 
			
		||||
static void
 | 
			
		||||
construct_tile_monitor (MetaMonitorManager *manager,
 | 
			
		||||
                        GArray *monitor_infos,
 | 
			
		||||
                        guint32 tile_group_id)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorInfo info;
 | 
			
		||||
  unsigned i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < monitor_infos->len; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaMonitorInfo *pinfo = &g_array_index (monitor_infos, MetaMonitorInfo, i);
 | 
			
		||||
 | 
			
		||||
      if (pinfo->tile_group_id == tile_group_id)
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* didn't find it */
 | 
			
		||||
  info.number = monitor_infos->len;
 | 
			
		||||
  info.tile_group_id = tile_group_id;
 | 
			
		||||
  info.is_presentation = FALSE;
 | 
			
		||||
  info.refresh_rate = 0.0;
 | 
			
		||||
  info.width_mm = 0;
 | 
			
		||||
  info.height_mm = 0;
 | 
			
		||||
  info.is_primary = FALSE;
 | 
			
		||||
  info.rect.x = INT_MAX;
 | 
			
		||||
  info.rect.y = INT_MAX;
 | 
			
		||||
  info.rect.width = 0;
 | 
			
		||||
  info.rect.height = 0;
 | 
			
		||||
  info.winsys_id = 0;
 | 
			
		||||
  info.n_outputs = 0;
 | 
			
		||||
  info.monitor_winsys_xid = 0;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < manager->n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaOutput *output = &manager->outputs[i];
 | 
			
		||||
 | 
			
		||||
      if (!output->tile_info.group_id)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (output->tile_info.group_id != tile_group_id)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (!output->crtc)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (output->crtc->rect.width != (int)output->tile_info.tile_w ||
 | 
			
		||||
          output->crtc->rect.height != (int)output->tile_info.tile_h)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (output->tile_info.loc_h_tile == 0 && output->tile_info.loc_v_tile == 0)
 | 
			
		||||
        {
 | 
			
		||||
          info.refresh_rate = output->crtc->current_mode->refresh_rate;
 | 
			
		||||
          info.width_mm = output->width_mm;
 | 
			
		||||
          info.height_mm = output->height_mm;
 | 
			
		||||
          info.winsys_id = output->winsys_id;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      /* hack */
 | 
			
		||||
      if (output->crtc->rect.x < info.rect.x)
 | 
			
		||||
        info.rect.x = output->crtc->rect.x;
 | 
			
		||||
      if (output->crtc->rect.y < info.rect.y)
 | 
			
		||||
        info.rect.y = output->crtc->rect.y;
 | 
			
		||||
 | 
			
		||||
      if (output->tile_info.loc_h_tile == 0)
 | 
			
		||||
        info.rect.height += output->tile_info.tile_h;
 | 
			
		||||
 | 
			
		||||
      if (output->tile_info.loc_v_tile == 0)
 | 
			
		||||
        info.rect.width += output->tile_info.tile_w;
 | 
			
		||||
 | 
			
		||||
      if (info.n_outputs > META_MAX_OUTPUTS_PER_MONITOR)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      info.outputs[info.n_outputs++] = output;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* if we don't have a winsys id, i.e. we haven't found tile 0,0
 | 
			
		||||
     don't try and add this to the monitor infos */
 | 
			
		||||
  if (!info.winsys_id)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  g_array_append_val (monitor_infos, info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * make_logical_config:
 | 
			
		||||
 *
 | 
			
		||||
@@ -81,16 +173,26 @@ meta_monitor_manager_init (MetaMonitorManager *manager)
 | 
			
		||||
static void
 | 
			
		||||
make_logical_config (MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (manager);
 | 
			
		||||
  GArray *monitor_infos;
 | 
			
		||||
  unsigned int i, j;
 | 
			
		||||
 | 
			
		||||
  monitor_infos = g_array_sized_new (FALSE, TRUE, sizeof (MetaMonitorInfo),
 | 
			
		||||
                                     manager->n_outputs);
 | 
			
		||||
                                     manager->n_crtcs);
 | 
			
		||||
 | 
			
		||||
  /* Walk the list of MetaCRTCs, and build a MetaMonitorInfo
 | 
			
		||||
     for each of them, unless they reference a rectangle that
 | 
			
		||||
     is already there.
 | 
			
		||||
  */
 | 
			
		||||
  /* for tiling we need to work out how many tiled outputs there are */
 | 
			
		||||
  for (i = 0; i < manager->n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaOutput *output = &manager->outputs[i];
 | 
			
		||||
 | 
			
		||||
      if (output->tile_info.group_id)
 | 
			
		||||
        construct_tile_monitor (manager, monitor_infos, output->tile_info.group_id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < manager->n_crtcs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaCRTC *crtc = &manager->crtcs[i];
 | 
			
		||||
@@ -102,8 +204,8 @@ make_logical_config (MetaMonitorManager *manager)
 | 
			
		||||
      for (j = 0; j < monitor_infos->len; j++)
 | 
			
		||||
        {
 | 
			
		||||
          MetaMonitorInfo *info = &g_array_index (monitor_infos, MetaMonitorInfo, j);
 | 
			
		||||
          if (meta_rectangle_equal (&crtc->rect,
 | 
			
		||||
                                    &info->rect))
 | 
			
		||||
          if (meta_rectangle_contains_rect (&info->rect,
 | 
			
		||||
                                            &crtc->rect))
 | 
			
		||||
            {
 | 
			
		||||
              crtc->logical_monitor = info;
 | 
			
		||||
              break;
 | 
			
		||||
@@ -115,7 +217,10 @@ make_logical_config (MetaMonitorManager *manager)
 | 
			
		||||
          MetaMonitorInfo info;
 | 
			
		||||
 | 
			
		||||
          info.number = monitor_infos->len;
 | 
			
		||||
          info.tile_group_id = 0;
 | 
			
		||||
          info.rect = crtc->rect;
 | 
			
		||||
          info.refresh_rate = crtc->current_mode->refresh_rate;
 | 
			
		||||
          info.scale = 1;
 | 
			
		||||
          info.is_primary = FALSE;
 | 
			
		||||
          /* This starts true because we want
 | 
			
		||||
             is_presentation only if all outputs are
 | 
			
		||||
@@ -125,7 +230,8 @@ make_logical_config (MetaMonitorManager *manager)
 | 
			
		||||
          info.is_presentation = TRUE;
 | 
			
		||||
          info.in_fullscreen = -1;
 | 
			
		||||
          info.winsys_id = 0;
 | 
			
		||||
 | 
			
		||||
          info.n_outputs = 0;
 | 
			
		||||
          info.monitor_winsys_xid = 0;
 | 
			
		||||
          g_array_append_val (monitor_infos, info);
 | 
			
		||||
 | 
			
		||||
          crtc->logical_monitor = &g_array_index (monitor_infos, MetaMonitorInfo,
 | 
			
		||||
@@ -147,6 +253,9 @@ make_logical_config (MetaMonitorManager *manager)
 | 
			
		||||
      if (output->crtc == NULL)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (output->tile_info.group_id)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      /* We must have a logical monitor on every CRTC at this point */
 | 
			
		||||
      g_assert (output->crtc->logical_monitor != NULL);
 | 
			
		||||
 | 
			
		||||
@@ -155,8 +264,17 @@ make_logical_config (MetaMonitorManager *manager)
 | 
			
		||||
      info->is_primary = info->is_primary || output->is_primary;
 | 
			
		||||
      info->is_presentation = info->is_presentation && output->is_presentation;
 | 
			
		||||
 | 
			
		||||
      info->width_mm = output->width_mm;
 | 
			
		||||
      info->height_mm = output->height_mm;
 | 
			
		||||
 | 
			
		||||
      info->outputs[0] = output;
 | 
			
		||||
      info->n_outputs = 1;
 | 
			
		||||
 | 
			
		||||
      if (output->is_primary || info->winsys_id == 0)
 | 
			
		||||
        info->winsys_id = output->winsys_id;
 | 
			
		||||
        {
 | 
			
		||||
          info->scale = output->scale;
 | 
			
		||||
          info->winsys_id = output->winsys_id;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (info->is_primary)
 | 
			
		||||
        manager->primary_monitor_index = info->number;
 | 
			
		||||
@@ -164,6 +282,10 @@ make_logical_config (MetaMonitorManager *manager)
 | 
			
		||||
 | 
			
		||||
  manager->n_monitor_infos = monitor_infos->len;
 | 
			
		||||
  manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
 | 
			
		||||
 | 
			
		||||
  if (manager_class->add_monitor)
 | 
			
		||||
    for (i = 0; i < manager->n_monitor_infos; i++)
 | 
			
		||||
      manager_class->add_monitor (manager, &manager->monitor_infos[i]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -224,6 +346,23 @@ meta_monitor_manager_constructed (GObject *object)
 | 
			
		||||
  manager->in_init = FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_monitor_manager_clear_output (MetaOutput *output)
 | 
			
		||||
{
 | 
			
		||||
  g_free (output->name);
 | 
			
		||||
  g_free (output->vendor);
 | 
			
		||||
  g_free (output->product);
 | 
			
		||||
  g_free (output->serial);
 | 
			
		||||
  g_free (output->modes);
 | 
			
		||||
  g_free (output->possible_crtcs);
 | 
			
		||||
  g_free (output->possible_clones);
 | 
			
		||||
 | 
			
		||||
  if (output->driver_notify)
 | 
			
		||||
    output->driver_notify (output);
 | 
			
		||||
 | 
			
		||||
  memset (output, 0, sizeof (*output));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
 | 
			
		||||
                                        int         n_old_outputs)
 | 
			
		||||
@@ -231,22 +370,22 @@ meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_old_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      g_free (old_outputs[i].name);
 | 
			
		||||
      g_free (old_outputs[i].vendor);
 | 
			
		||||
      g_free (old_outputs[i].product);
 | 
			
		||||
      g_free (old_outputs[i].serial);
 | 
			
		||||
      g_free (old_outputs[i].modes);
 | 
			
		||||
      g_free (old_outputs[i].possible_crtcs);
 | 
			
		||||
      g_free (old_outputs[i].possible_clones);
 | 
			
		||||
 | 
			
		||||
      if (old_outputs[i].driver_notify)
 | 
			
		||||
        old_outputs[i].driver_notify (&old_outputs[i]);
 | 
			
		||||
    }
 | 
			
		||||
    meta_monitor_manager_clear_output (&old_outputs[i]);
 | 
			
		||||
 | 
			
		||||
  g_free (old_outputs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_monitor_manager_clear_mode (MetaMonitorMode *mode)
 | 
			
		||||
{
 | 
			
		||||
  g_free (mode->name);
 | 
			
		||||
 | 
			
		||||
  if (mode->driver_notify)
 | 
			
		||||
    mode->driver_notify (mode);
 | 
			
		||||
 | 
			
		||||
  memset (mode, 0, sizeof (*mode));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
 | 
			
		||||
                                      int              n_old_modes)
 | 
			
		||||
@@ -254,16 +393,32 @@ meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_old_modes; i++)
 | 
			
		||||
    {
 | 
			
		||||
      g_free (old_modes[i].name);
 | 
			
		||||
 | 
			
		||||
      if (old_modes[i].driver_notify)
 | 
			
		||||
        old_modes[i].driver_notify (&old_modes[i]);
 | 
			
		||||
    }
 | 
			
		||||
    meta_monitor_manager_clear_mode (&old_modes[i]);
 | 
			
		||||
 | 
			
		||||
  g_free (old_modes);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_monitor_manager_clear_crtc (MetaCRTC *crtc)
 | 
			
		||||
{
 | 
			
		||||
  if (crtc->driver_notify)
 | 
			
		||||
    crtc->driver_notify (crtc);
 | 
			
		||||
 | 
			
		||||
  memset (crtc, 0, sizeof (*crtc));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_free_crtc_array (MetaCRTC *old_crtcs,
 | 
			
		||||
                                      int       n_old_crtcs)
 | 
			
		||||
{
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_old_crtcs; i++)
 | 
			
		||||
    meta_monitor_manager_clear_crtc (&old_crtcs[i]);
 | 
			
		||||
 | 
			
		||||
  g_free (old_crtcs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
@@ -271,8 +426,8 @@ meta_monitor_manager_finalize (GObject *object)
 | 
			
		||||
 | 
			
		||||
  meta_monitor_manager_free_output_array (manager->outputs, manager->n_outputs);
 | 
			
		||||
  meta_monitor_manager_free_mode_array (manager->modes, manager->n_modes);
 | 
			
		||||
  meta_monitor_manager_free_crtc_array (manager->crtcs, manager->n_crtcs);
 | 
			
		||||
  g_free (manager->monitor_infos);
 | 
			
		||||
  g_free (manager->crtcs);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_monitor_manager_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
@@ -353,16 +508,14 @@ static char *
 | 
			
		||||
make_display_name (MetaMonitorManager *manager,
 | 
			
		||||
                   MetaOutput         *output)
 | 
			
		||||
{
 | 
			
		||||
  char *inches = NULL;
 | 
			
		||||
  char *vendor_name = NULL;
 | 
			
		||||
  char *ret;
 | 
			
		||||
  g_autofree char *inches = NULL;
 | 
			
		||||
  g_autofree char *vendor_name = NULL;
 | 
			
		||||
 | 
			
		||||
  switch (output->connector_type)
 | 
			
		||||
    {
 | 
			
		||||
    case META_CONNECTOR_TYPE_LVDS:
 | 
			
		||||
    case META_CONNECTOR_TYPE_eDP:
 | 
			
		||||
      ret = g_strdup (_("Built-in display"));
 | 
			
		||||
      goto out;
 | 
			
		||||
      return g_strdup (_("Built-in display"));
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
@@ -398,18 +551,12 @@ make_display_name (MetaMonitorManager *manager,
 | 
			
		||||
      /* TRANSLATORS: this is a monitor vendor name, followed by a
 | 
			
		||||
       * size in inches, like 'Dell 15"'
 | 
			
		||||
       */
 | 
			
		||||
      ret = g_strdup_printf (_("%s %s"), vendor_name, inches);
 | 
			
		||||
      return g_strdup_printf (_("%s %s"), vendor_name, inches);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      ret = g_strdup (vendor_name);
 | 
			
		||||
      return g_strdup (vendor_name);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  g_free (inches);
 | 
			
		||||
  g_free (vendor_name);
 | 
			
		||||
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *
 | 
			
		||||
@@ -520,6 +667,10 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
 | 
			
		||||
                             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)));
 | 
			
		||||
      g_variant_builder_add (&properties, "{sv}", "underscanning",
 | 
			
		||||
                             g_variant_new_boolean (output->is_underscanning));
 | 
			
		||||
      g_variant_builder_add (&properties, "{sv}", "supports-underscanning",
 | 
			
		||||
                             g_variant_new_boolean (output->supports_underscanning));
 | 
			
		||||
 | 
			
		||||
      edid_file = manager_class->get_edid_file (manager, output);
 | 
			
		||||
      if (edid_file)
 | 
			
		||||
@@ -540,6 +691,20 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (output->tile_info.group_id)
 | 
			
		||||
        {
 | 
			
		||||
          g_variant_builder_add (&properties, "{sv}", "tile",
 | 
			
		||||
                                 g_variant_new ("(uuuuuuuu)",
 | 
			
		||||
                                                output->tile_info.group_id,
 | 
			
		||||
                                                output->tile_info.flags,
 | 
			
		||||
                                                output->tile_info.max_h_tiles,
 | 
			
		||||
                                                output->tile_info.max_v_tiles,
 | 
			
		||||
                                                output->tile_info.loc_h_tile,
 | 
			
		||||
                                                output->tile_info.loc_v_tile,
 | 
			
		||||
                                                output->tile_info.tile_w,
 | 
			
		||||
                                                output->tile_info.tile_h));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
 | 
			
		||||
                             i, /* ID */
 | 
			
		||||
                             (gint64)output->winsys_id,
 | 
			
		||||
@@ -737,8 +902,7 @@ meta_monitor_manager_handle_apply_configuration  (MetaDBusDisplayConfig *skeleto
 | 
			
		||||
          crtc_info->y = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (transform < META_MONITOR_TRANSFORM_NORMAL ||
 | 
			
		||||
          transform > META_MONITOR_TRANSFORM_FLIPPED_270 ||
 | 
			
		||||
      if (transform > META_MONITOR_TRANSFORM_FLIPPED_270 ||
 | 
			
		||||
          ((crtc->all_transforms & (1 << transform)) == 0))
 | 
			
		||||
        {
 | 
			
		||||
          g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
 | 
			
		||||
@@ -808,7 +972,7 @@ meta_monitor_manager_handle_apply_configuration  (MetaDBusDisplayConfig *skeleto
 | 
			
		||||
  while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_index, &properties))
 | 
			
		||||
    {
 | 
			
		||||
      MetaOutputInfo *output_info;
 | 
			
		||||
      gboolean primary, presentation;
 | 
			
		||||
      gboolean primary, presentation, underscanning;
 | 
			
		||||
 | 
			
		||||
      if (output_index >= manager->n_outputs)
 | 
			
		||||
        {
 | 
			
		||||
@@ -827,6 +991,9 @@ meta_monitor_manager_handle_apply_configuration  (MetaDBusDisplayConfig *skeleto
 | 
			
		||||
      if (g_variant_lookup (properties, "presentation", "b", &presentation))
 | 
			
		||||
        output_info->is_presentation = presentation;
 | 
			
		||||
 | 
			
		||||
      if (g_variant_lookup (properties, "underscanning", "b", &underscanning))
 | 
			
		||||
        output_info->is_underscanning = underscanning;
 | 
			
		||||
 | 
			
		||||
      g_ptr_array_add (output_infos, output_info);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1194,37 +1361,58 @@ 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;
 | 
			
		||||
  unsigned int n_old_outputs, n_old_crtcs, 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_crtcs = manager->crtcs;
 | 
			
		||||
  n_old_crtcs = manager->n_crtcs;
 | 
			
		||||
  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);
 | 
			
		||||
  meta_monitor_manager_free_crtc_array (old_crtcs, n_old_crtcs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (manager);
 | 
			
		||||
  MetaMonitorInfo *old_monitor_infos;
 | 
			
		||||
 | 
			
		||||
  unsigned old_n_monitor_infos;
 | 
			
		||||
  unsigned i, j;
 | 
			
		||||
  old_monitor_infos = manager->monitor_infos;
 | 
			
		||||
  old_n_monitor_infos = manager->n_monitor_infos;
 | 
			
		||||
 | 
			
		||||
  if (manager->in_init)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  make_logical_config (manager);
 | 
			
		||||
 | 
			
		||||
  if (manager_class->delete_monitor)
 | 
			
		||||
    {
 | 
			
		||||
      for (i = 0; i < old_n_monitor_infos; i++)
 | 
			
		||||
        {
 | 
			
		||||
          gboolean delete_mon = TRUE;
 | 
			
		||||
          for (j = 0; j < manager->n_monitor_infos; j++)
 | 
			
		||||
            {
 | 
			
		||||
              if (manager->monitor_infos[j].monitor_winsys_xid == old_monitor_infos[i].monitor_winsys_xid)
 | 
			
		||||
                {
 | 
			
		||||
                  delete_mon = FALSE;
 | 
			
		||||
                  break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
          if (delete_mon)
 | 
			
		||||
            manager_class->delete_monitor (manager, old_monitor_infos[i].monitor_winsys_xid);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  g_signal_emit_by_name (manager, "monitors-changed");
 | 
			
		||||
 | 
			
		||||
  g_free (old_monitor_infos);
 | 
			
		||||
@@ -1245,25 +1433,35 @@ meta_output_parse_edid (MetaOutput *meta_output,
 | 
			
		||||
  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);
 | 
			
		||||
      if (!g_utf8_validate (meta_output->vendor, -1, NULL))
 | 
			
		||||
        g_clear_pointer (&meta_output->vendor, g_free);
 | 
			
		||||
 | 
			
		||||
      meta_output->product = g_strndup (parsed_edid->dsc_product_name, 14);
 | 
			
		||||
      if (!g_utf8_validate (meta_output->product, -1, NULL) ||
 | 
			
		||||
          meta_output->product[0] == '\0')
 | 
			
		||||
        {
 | 
			
		||||
          g_clear_pointer (&meta_output->product, g_free);
 | 
			
		||||
          meta_output->product = g_strdup_printf ("0x%04x", (unsigned) parsed_edid->product_code);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      meta_output->serial = g_strndup (parsed_edid->dsc_serial_number, 14);
 | 
			
		||||
      if (!g_utf8_validate (meta_output->serial, -1, NULL) ||
 | 
			
		||||
          meta_output->serial[0] == '\0')
 | 
			
		||||
        {
 | 
			
		||||
          g_clear_pointer (&meta_output->serial, g_free);
 | 
			
		||||
          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");
 | 
			
		||||
    }
 | 
			
		||||
    meta_output->vendor = g_strdup ("unknown");
 | 
			
		||||
  if (!meta_output->product)
 | 
			
		||||
    meta_output->product = g_strdup ("unknown");
 | 
			
		||||
  if (!meta_output->serial)
 | 
			
		||||
    meta_output->serial = g_strdup ("unknown");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										57
									
								
								src/backends/meta-pointer-constraint.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/backends/meta-pointer-constraint.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
/* -*- 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>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "backends/meta-pointer-constraint.h"
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaPointerConstraint, meta_pointer_constraint, G_TYPE_OBJECT);
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_pointer_constraint_init (MetaPointerConstraint *constraint)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_pointer_constraint_class_init (MetaPointerConstraintClass *klass)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_pointer_constraint_constrain (MetaPointerConstraint *constraint,
 | 
			
		||||
                                   ClutterInputDevice    *device,
 | 
			
		||||
                                   guint32                time,
 | 
			
		||||
                                   float                  prev_x,
 | 
			
		||||
                                   float                  prev_y,
 | 
			
		||||
                                   float                  *x,
 | 
			
		||||
                                   float                  *y)
 | 
			
		||||
{
 | 
			
		||||
  META_POINTER_CONSTRAINT_GET_CLASS (constraint)->constrain (constraint,
 | 
			
		||||
                                                             device,
 | 
			
		||||
                                                             time,
 | 
			
		||||
                                                             prev_x, prev_y,
 | 
			
		||||
                                                             x, y);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										60
									
								
								src/backends/meta-pointer-constraint.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/backends/meta-pointer-constraint.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
			
		||||
/* -*- 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_POINTER_CONSTRAINT_H
 | 
			
		||||
#define META_POINTER_CONSTRAINT_H
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_POINTER_CONSTRAINT (meta_pointer_constraint_get_type ())
 | 
			
		||||
G_DECLARE_DERIVABLE_TYPE (MetaPointerConstraint, meta_pointer_constraint,
 | 
			
		||||
                          META, POINTER_CONSTRAINT, GObject);
 | 
			
		||||
 | 
			
		||||
struct _MetaPointerConstraintClass
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass parent_class;
 | 
			
		||||
 | 
			
		||||
  void (*constrain) (MetaPointerConstraint *constraint,
 | 
			
		||||
                     ClutterInputDevice *device,
 | 
			
		||||
                     guint32 time,
 | 
			
		||||
                     float prev_x,
 | 
			
		||||
                     float prev_y,
 | 
			
		||||
                     float *x,
 | 
			
		||||
                     float *y);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void meta_pointer_constraint_constrain (MetaPointerConstraint *constraint,
 | 
			
		||||
                                        ClutterInputDevice    *device,
 | 
			
		||||
                                        guint32                time,
 | 
			
		||||
                                        float                  prev_x,
 | 
			
		||||
                                        float                  prev_y,
 | 
			
		||||
                                        float                 *x,
 | 
			
		||||
                                        float                 *y);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* META_POINTER_CONSTRAINT_H */
 | 
			
		||||
@@ -24,7 +24,6 @@
 | 
			
		||||
 | 
			
		||||
#include "meta-stage.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-cursor-private.h"
 | 
			
		||||
#include <meta/meta-backend.h>
 | 
			
		||||
#include <meta/util.h>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,20 +29,26 @@
 | 
			
		||||
 | 
			
		||||
#include <meta/main.h>
 | 
			
		||||
#include <clutter/evdev/clutter-evdev.h>
 | 
			
		||||
#include <libupower-glib/upower.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-barrier-native.h"
 | 
			
		||||
#include "meta-idle-monitor-native.h"
 | 
			
		||||
#include "meta-monitor-manager-kms.h"
 | 
			
		||||
#include "meta-cursor-renderer-native.h"
 | 
			
		||||
#include "meta-launcher.h"
 | 
			
		||||
#include "backends/meta-cursor-tracker-private.h"
 | 
			
		||||
#include "backends/meta-pointer-constraint.h"
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
struct _MetaBackendNativePrivate
 | 
			
		||||
{
 | 
			
		||||
  MetaLauncher *launcher;
 | 
			
		||||
 | 
			
		||||
  MetaBarrierManagerNative *barrier_manager;
 | 
			
		||||
 | 
			
		||||
  GSettings *keyboard_settings;
 | 
			
		||||
  UpClient *up_client;
 | 
			
		||||
  guint sleep_signal_id;
 | 
			
		||||
  GCancellable *cancellable;
 | 
			
		||||
  GDBusConnection *system_bus;
 | 
			
		||||
};
 | 
			
		||||
typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate;
 | 
			
		||||
 | 
			
		||||
@@ -56,9 +62,69 @@ meta_backend_native_finalize (GObject *object)
 | 
			
		||||
 | 
			
		||||
  meta_launcher_free (priv->launcher);
 | 
			
		||||
 | 
			
		||||
  g_object_unref (priv->up_client);
 | 
			
		||||
  if (priv->sleep_signal_id)
 | 
			
		||||
    g_dbus_connection_signal_unsubscribe (priv->system_bus, priv->sleep_signal_id);
 | 
			
		||||
  g_cancellable_cancel (priv->cancellable);
 | 
			
		||||
  g_clear_object (&priv->cancellable);
 | 
			
		||||
  g_clear_object (&priv->system_bus);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_backend_native_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
prepare_for_sleep_cb (GDBusConnection *connection,
 | 
			
		||||
                      const gchar     *sender_name,
 | 
			
		||||
                      const gchar     *object_path,
 | 
			
		||||
                      const gchar     *interface_name,
 | 
			
		||||
                      const gchar     *signal_name,
 | 
			
		||||
                      GVariant        *parameters,
 | 
			
		||||
                      gpointer         user_data)
 | 
			
		||||
{
 | 
			
		||||
  gboolean suspending;
 | 
			
		||||
  g_variant_get (parameters, "(b)", &suspending);
 | 
			
		||||
  if (suspending)
 | 
			
		||||
    return;
 | 
			
		||||
  meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
system_bus_gotten_cb (GObject      *object,
 | 
			
		||||
                      GAsyncResult *res,
 | 
			
		||||
                      gpointer      user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackendNativePrivate *priv;
 | 
			
		||||
  GDBusConnection *bus;
 | 
			
		||||
 | 
			
		||||
  bus = g_bus_get_finish (res, NULL);
 | 
			
		||||
  if (!bus)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  priv = meta_backend_native_get_instance_private (META_BACKEND_NATIVE (user_data));
 | 
			
		||||
  priv->system_bus = bus;
 | 
			
		||||
  priv->sleep_signal_id = g_dbus_connection_signal_subscribe (priv->system_bus,
 | 
			
		||||
                                                              "org.freedesktop.login1",
 | 
			
		||||
                                                              "org.freedesktop.login1.Manager",
 | 
			
		||||
                                                              "PrepareForSleep",
 | 
			
		||||
                                                              "/org/freedesktop/login1",
 | 
			
		||||
                                                              NULL,
 | 
			
		||||
                                                              G_DBUS_SIGNAL_FLAGS_NONE,
 | 
			
		||||
                                                              prepare_for_sleep_cb,
 | 
			
		||||
                                                              NULL,
 | 
			
		||||
                                                              NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
lid_is_closed_changed_cb (UpClient   *client,
 | 
			
		||||
                          GParamSpec *pspec,
 | 
			
		||||
                          gpointer    user_data)
 | 
			
		||||
{
 | 
			
		||||
  if (up_client_get_lid_is_closed (client))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
constrain_to_barriers (ClutterInputDevice *device,
 | 
			
		||||
                       guint32             time,
 | 
			
		||||
@@ -75,6 +141,24 @@ constrain_to_barriers (ClutterInputDevice *device,
 | 
			
		||||
                                       new_x, new_y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
constrain_to_client_constraint (ClutterInputDevice *device,
 | 
			
		||||
                                guint32             time,
 | 
			
		||||
                                float               prev_x,
 | 
			
		||||
                                float               prev_y,
 | 
			
		||||
                                float              *x,
 | 
			
		||||
                                float              *y)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackend *backend = meta_get_backend ();
 | 
			
		||||
  MetaPointerConstraint *constraint = backend->client_pointer_constraint;
 | 
			
		||||
 | 
			
		||||
  if (!constraint)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  meta_pointer_constraint_constrain (constraint, device,
 | 
			
		||||
                                     time, prev_x, prev_y, x, y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The pointer constrain code is mostly a rip-off of the XRandR code from Xorg.
 | 
			
		||||
 * (from xserver/randr/rrcrtc.c, RRConstrainCursorHarder)
 | 
			
		||||
@@ -129,10 +213,12 @@ constrain_all_screen_monitors (ClutterInputDevice *device,
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
pointer_constrain_callback (ClutterInputDevice *device,
 | 
			
		||||
			    guint32             time,
 | 
			
		||||
			    float              *new_x,
 | 
			
		||||
			    float              *new_y,
 | 
			
		||||
			    gpointer            user_data)
 | 
			
		||||
                            guint32             time,
 | 
			
		||||
                            float               prev_x,
 | 
			
		||||
                            float               prev_y,
 | 
			
		||||
                            float              *new_x,
 | 
			
		||||
                            float              *new_y,
 | 
			
		||||
                            gpointer            user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManager *monitor_manager;
 | 
			
		||||
  MetaMonitorInfo *monitors;
 | 
			
		||||
@@ -141,6 +227,9 @@ pointer_constrain_callback (ClutterInputDevice *device,
 | 
			
		||||
  /* Constrain to barriers */
 | 
			
		||||
  constrain_to_barriers (device, time, new_x, new_y);
 | 
			
		||||
 | 
			
		||||
  /* Constrain to pointer lock */
 | 
			
		||||
  constrain_to_client_constraint (device, time, prev_x, prev_y, new_x, new_y);
 | 
			
		||||
 | 
			
		||||
  monitor_manager = meta_monitor_manager_get ();
 | 
			
		||||
  monitors = meta_monitor_manager_get_monitor_infos (monitor_manager, &n_monitors);
 | 
			
		||||
 | 
			
		||||
@@ -191,11 +280,16 @@ meta_backend_native_warp_pointer (MetaBackend *backend,
 | 
			
		||||
{
 | 
			
		||||
  ClutterDeviceManager *manager = clutter_device_manager_get_default ();
 | 
			
		||||
  ClutterInputDevice *device = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE);
 | 
			
		||||
  MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (NULL);
 | 
			
		||||
 | 
			
		||||
  /* XXX */
 | 
			
		||||
  guint32 time_ = 0;
 | 
			
		||||
 | 
			
		||||
  /* Warp the input device pointer state. */
 | 
			
		||||
  clutter_evdev_warp_pointer (device, time_, x, y);
 | 
			
		||||
 | 
			
		||||
  /* Warp displayed pointer cursor. */
 | 
			
		||||
  meta_cursor_tracker_update_position (tracker, x, y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -242,6 +336,19 @@ meta_backend_native_lock_layout_group (MetaBackend *backend,
 | 
			
		||||
  g_signal_emit_by_name (backend, "keymap-layout-group-changed", idx, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_backend_native_get_relative_motion_deltas (MetaBackend *backend,
 | 
			
		||||
                                                const        ClutterEvent *event,
 | 
			
		||||
                                                double       *dx,
 | 
			
		||||
                                                double       *dy,
 | 
			
		||||
                                                double       *dx_unaccel,
 | 
			
		||||
                                                double       *dy_unaccel)
 | 
			
		||||
{
 | 
			
		||||
  return clutter_evdev_event_get_relative_motion (event,
 | 
			
		||||
                                                  dx, dy,
 | 
			
		||||
                                                  dx_unaccel, dy_unaccel);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_backend_native_class_init (MetaBackendNativeClass *klass)
 | 
			
		||||
{
 | 
			
		||||
@@ -259,17 +366,33 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass)
 | 
			
		||||
  backend_class->set_keymap = meta_backend_native_set_keymap;
 | 
			
		||||
  backend_class->get_keymap = meta_backend_native_get_keymap;
 | 
			
		||||
  backend_class->lock_layout_group = meta_backend_native_lock_layout_group;
 | 
			
		||||
  backend_class->get_relative_motion_deltas = meta_backend_native_get_relative_motion_deltas;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_backend_native_init (MetaBackendNative *native)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
 | 
			
		||||
  GError *error = NULL;
 | 
			
		||||
 | 
			
		||||
  /* We're a display server, so start talking to weston-launch. */
 | 
			
		||||
  priv->launcher = meta_launcher_new ();
 | 
			
		||||
  priv->launcher = meta_launcher_new (&error);
 | 
			
		||||
  if (priv->launcher == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("Can't initialize KMS backend: %s\n", error->message);
 | 
			
		||||
      exit (1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  priv->barrier_manager = meta_barrier_manager_native_new ();
 | 
			
		||||
 | 
			
		||||
  priv->up_client = up_client_new ();
 | 
			
		||||
  g_signal_connect (priv->up_client, "notify::lid-is-closed",
 | 
			
		||||
                    G_CALLBACK (lid_is_closed_changed_cb), NULL);
 | 
			
		||||
 | 
			
		||||
  priv->cancellable = g_cancellable_new ();
 | 
			
		||||
  g_bus_get (G_BUS_TYPE_SYSTEM,
 | 
			
		||||
             priv->cancellable,
 | 
			
		||||
             system_bus_gotten_cb,
 | 
			
		||||
             native);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
 
 | 
			
		||||
@@ -93,126 +93,18 @@ next_serial (void)
 | 
			
		||||
  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;
 | 
			
		||||
  return meta_border_is_horizontal (&barrier->priv->border);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
  return meta_border_is_blocking_directions (&barrier->priv->border,
 | 
			
		||||
                                             directions);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -224,31 +116,16 @@ dismiss_pointer (MetaBarrierImplNative *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
 | 
			
		||||
static MetaLine2
 | 
			
		||||
calculate_barrier_hit_box (MetaBarrier *barrier)
 | 
			
		||||
{
 | 
			
		||||
  Line2 hit_box = barrier_to_line (barrier);
 | 
			
		||||
  MetaLine2 hit_box = barrier->priv->border.line;
 | 
			
		||||
 | 
			
		||||
  if (is_barrier_horizontal (barrier))
 | 
			
		||||
    {
 | 
			
		||||
@@ -273,7 +150,8 @@ calculate_barrier_hit_box (MetaBarrier *barrier)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
is_within_box (Line2 box, Vector2 point)
 | 
			
		||||
is_within_box (MetaLine2   box,
 | 
			
		||||
               MetaVector2 point)
 | 
			
		||||
{
 | 
			
		||||
  return (point.x >= box.a.x && point.x < box.b.x &&
 | 
			
		||||
          point.y >= box.a.y && point.y < box.b.y);
 | 
			
		||||
@@ -288,8 +166,8 @@ maybe_release_barrier (gpointer key,
 | 
			
		||||
  MetaBarrierImplNativePrivate *priv =
 | 
			
		||||
    meta_barrier_impl_native_get_instance_private (self);
 | 
			
		||||
  MetaBarrier *barrier = priv->barrier;
 | 
			
		||||
  Line2 *motion = user_data;
 | 
			
		||||
  Line2 hit_box;
 | 
			
		||||
  MetaLine2 *motion = user_data;
 | 
			
		||||
  MetaLine2 hit_box;
 | 
			
		||||
 | 
			
		||||
  if (priv->state != META_BARRIER_STATE_HELD)
 | 
			
		||||
    return;
 | 
			
		||||
@@ -297,8 +175,10 @@ maybe_release_barrier (gpointer key,
 | 
			
		||||
  /* 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))
 | 
			
		||||
      if (motion->b.x > MAX (barrier->priv->border.line.a.x,
 | 
			
		||||
                             barrier->priv->border.line.b.x) ||
 | 
			
		||||
          motion->b.x < MIN (barrier->priv->border.line.a.x,
 | 
			
		||||
                             barrier->priv->border.line.b.x))
 | 
			
		||||
        {
 | 
			
		||||
          dismiss_pointer (self);
 | 
			
		||||
          return;
 | 
			
		||||
@@ -306,8 +186,10 @@ maybe_release_barrier (gpointer key,
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      if (motion->b.y > MAX (barrier->priv->y1, barrier->priv->y2) ||
 | 
			
		||||
          motion->b.y < MIN (barrier->priv->y1, barrier->priv->y2))
 | 
			
		||||
      if (motion->b.y > MAX (barrier->priv->border.line.a.y,
 | 
			
		||||
                             barrier->priv->border.line.b.y) ||
 | 
			
		||||
          motion->b.y < MIN (barrier->priv->border.line.a.y,
 | 
			
		||||
                             barrier->priv->border.line.b.y))
 | 
			
		||||
        {
 | 
			
		||||
          dismiss_pointer (self);
 | 
			
		||||
          return;
 | 
			
		||||
@@ -330,7 +212,7 @@ maybe_release_barriers (MetaBarrierManagerNative *manager,
 | 
			
		||||
                        float                     x,
 | 
			
		||||
                        float                     y)
 | 
			
		||||
{
 | 
			
		||||
  Line2 motion = {
 | 
			
		||||
  MetaLine2 motion = {
 | 
			
		||||
    .a = {
 | 
			
		||||
      .x = prev_x,
 | 
			
		||||
      .y = prev_y,
 | 
			
		||||
@@ -350,7 +232,7 @@ typedef struct _MetaClosestBarrierData
 | 
			
		||||
{
 | 
			
		||||
  struct
 | 
			
		||||
  {
 | 
			
		||||
    Line2                       motion;
 | 
			
		||||
    MetaLine2                   motion;
 | 
			
		||||
    MetaBarrierDirection        directions;
 | 
			
		||||
  } in;
 | 
			
		||||
 | 
			
		||||
@@ -371,8 +253,7 @@ update_closest_barrier (gpointer key,
 | 
			
		||||
    meta_barrier_impl_native_get_instance_private (self);
 | 
			
		||||
  MetaBarrier *barrier = priv->barrier;
 | 
			
		||||
  MetaClosestBarrierData *data = user_data;
 | 
			
		||||
  Line2 barrier_line;
 | 
			
		||||
  Vector2 intersection;
 | 
			
		||||
  MetaVector2 intersection;
 | 
			
		||||
  float dx, dy;
 | 
			
		||||
  float distance_2;
 | 
			
		||||
 | 
			
		||||
@@ -391,17 +272,9 @@ update_closest_barrier (gpointer key,
 | 
			
		||||
 | 
			
		||||
  /* 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))
 | 
			
		||||
  if (!meta_line2_intersects_with (&barrier->priv->border.line,
 | 
			
		||||
                                   &data->in.motion,
 | 
			
		||||
                                   &intersection))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  /* Calculate the distance to the barrier and keep track of the closest
 | 
			
		||||
@@ -570,9 +443,9 @@ clamp_to_barrier (MetaBarrierImplNative *self,
 | 
			
		||||
  if (is_barrier_horizontal (barrier))
 | 
			
		||||
    {
 | 
			
		||||
      if (*motion_dir & META_BARRIER_DIRECTION_POSITIVE_Y)
 | 
			
		||||
        *y = barrier->priv->y1;
 | 
			
		||||
        *y = barrier->priv->border.line.a.y;
 | 
			
		||||
      else if (*motion_dir & META_BARRIER_DIRECTION_NEGATIVE_Y)
 | 
			
		||||
        *y = barrier->priv->y1;
 | 
			
		||||
        *y = barrier->priv->border.line.a.y;
 | 
			
		||||
 | 
			
		||||
      priv->blocked_dir = *motion_dir & (META_BARRIER_DIRECTION_POSITIVE_Y |
 | 
			
		||||
                                         META_BARRIER_DIRECTION_NEGATIVE_Y);
 | 
			
		||||
@@ -582,9 +455,9 @@ clamp_to_barrier (MetaBarrierImplNative *self,
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      if (*motion_dir & META_BARRIER_DIRECTION_POSITIVE_X)
 | 
			
		||||
        *x = barrier->priv->x1;
 | 
			
		||||
        *x = barrier->priv->border.line.a.x;
 | 
			
		||||
      else if (*motion_dir & META_BARRIER_DIRECTION_NEGATIVE_X)
 | 
			
		||||
        *x = barrier->priv->x1;
 | 
			
		||||
        *x = barrier->priv->border.line.a.x;
 | 
			
		||||
 | 
			
		||||
      priv->blocked_dir = *motion_dir & (META_BARRIER_DIRECTION_POSITIVE_X |
 | 
			
		||||
                                         META_BARRIER_DIRECTION_NEGATIVE_X);
 | 
			
		||||
 
 | 
			
		||||
@@ -26,11 +26,16 @@
 | 
			
		||||
 | 
			
		||||
#include "meta-cursor-renderer-native.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <gbm.h>
 | 
			
		||||
#include <xf86drm.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
#include <meta/util.h>
 | 
			
		||||
#include <meta/meta-backend.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-cursor-private.h"
 | 
			
		||||
#include "meta-monitor-manager-private.h"
 | 
			
		||||
#include "meta/boxes.h"
 | 
			
		||||
 | 
			
		||||
#ifndef DRM_CAP_CURSOR_WIDTH
 | 
			
		||||
#define DRM_CAP_CURSOR_WIDTH 0x8
 | 
			
		||||
@@ -39,10 +44,28 @@
 | 
			
		||||
#define DRM_CAP_CURSOR_HEIGHT 0x9
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* When animating a cursor, we usually call drmModeSetCursor2 once per frame.
 | 
			
		||||
 * Though, testing shows that we need to triple buffer the cursor buffer in
 | 
			
		||||
 * order to avoid glitches when animating the cursor, at least when running on
 | 
			
		||||
 * Intel. The reason for this might be (but is not confirmed to be) due to
 | 
			
		||||
 * the user space gbm_bo cache, making us reuse and overwrite the kernel side
 | 
			
		||||
 * buffer content before it was scanned out. To avoid this, we keep a user space
 | 
			
		||||
 * reference to each buffer we set until at least one frame after it was drawn.
 | 
			
		||||
 * In effect, this means we three active cursor gbm_bo's: one that that just has
 | 
			
		||||
 * been set, one that was previously set and may or may not have been scanned
 | 
			
		||||
 * out, and one pending that will be replaced if the cursor sprite changes.
 | 
			
		||||
 */
 | 
			
		||||
#define HW_CURSOR_BUFFER_COUNT 3
 | 
			
		||||
 | 
			
		||||
static GQuark quark_cursor_sprite = 0;
 | 
			
		||||
 | 
			
		||||
struct _MetaCursorRendererNativePrivate
 | 
			
		||||
{
 | 
			
		||||
  gboolean has_hw_cursor;
 | 
			
		||||
 | 
			
		||||
  MetaCursorSprite *last_cursor;
 | 
			
		||||
  guint animation_timeout_id;
 | 
			
		||||
 | 
			
		||||
  int drm_fd;
 | 
			
		||||
  struct gbm_device *gbm;
 | 
			
		||||
 | 
			
		||||
@@ -51,77 +74,167 @@ struct _MetaCursorRendererNativePrivate
 | 
			
		||||
};
 | 
			
		||||
typedef struct _MetaCursorRendererNativePrivate MetaCursorRendererNativePrivate;
 | 
			
		||||
 | 
			
		||||
typedef enum _MetaCursorGbmBoState
 | 
			
		||||
{
 | 
			
		||||
  META_CURSOR_GBM_BO_STATE_NONE,
 | 
			
		||||
  META_CURSOR_GBM_BO_STATE_SET,
 | 
			
		||||
  META_CURSOR_GBM_BO_STATE_INVALIDATED,
 | 
			
		||||
} MetaCursorGbmBoState;
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaCursorNativePrivate
 | 
			
		||||
{
 | 
			
		||||
  guint active_bo;
 | 
			
		||||
  MetaCursorGbmBoState pending_bo_state;
 | 
			
		||||
  struct gbm_bo *bos[HW_CURSOR_BUFFER_COUNT];
 | 
			
		||||
} MetaCursorNativePrivate;
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_native, META_TYPE_CURSOR_RENDERER);
 | 
			
		||||
 | 
			
		||||
static MetaCursorNativePrivate *
 | 
			
		||||
ensure_cursor_priv (MetaCursorSprite *cursor_sprite);
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_cursor_renderer_native_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererNative *renderer = META_CURSOR_RENDERER_NATIVE (object);
 | 
			
		||||
  MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (renderer);
 | 
			
		||||
 | 
			
		||||
  if (priv->gbm)
 | 
			
		||||
    gbm_device_destroy (priv->gbm);
 | 
			
		||||
  if (priv->animation_timeout_id)
 | 
			
		||||
    g_source_remove (priv->animation_timeout_id);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_cursor_renderer_native_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static guint
 | 
			
		||||
get_pending_cursor_sprite_gbm_bo_index (MetaCursorSprite *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorNativePrivate *cursor_priv =
 | 
			
		||||
    g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite);
 | 
			
		||||
 | 
			
		||||
  return (cursor_priv->active_bo + 1) % HW_CURSOR_BUFFER_COUNT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct gbm_bo *
 | 
			
		||||
get_pending_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorNativePrivate *cursor_priv =
 | 
			
		||||
    g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite);
 | 
			
		||||
  guint pending_bo;
 | 
			
		||||
 | 
			
		||||
  if (!cursor_priv)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  pending_bo = get_pending_cursor_sprite_gbm_bo_index (cursor_sprite);
 | 
			
		||||
  return cursor_priv->bos[pending_bo];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct gbm_bo *
 | 
			
		||||
get_active_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorNativePrivate *cursor_priv =
 | 
			
		||||
    g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite);
 | 
			
		||||
 | 
			
		||||
  if (!cursor_priv)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  return cursor_priv->bos[cursor_priv->active_bo];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
set_pending_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite,
 | 
			
		||||
                                  struct gbm_bo    *bo)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorNativePrivate *cursor_priv;
 | 
			
		||||
  guint pending_bo;
 | 
			
		||||
 | 
			
		||||
  cursor_priv = ensure_cursor_priv (cursor_sprite);
 | 
			
		||||
 | 
			
		||||
  pending_bo = get_pending_cursor_sprite_gbm_bo_index (cursor_sprite);
 | 
			
		||||
  cursor_priv->bos[pending_bo] = bo;
 | 
			
		||||
  cursor_priv->pending_bo_state = META_CURSOR_GBM_BO_STATE_SET;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
set_crtc_cursor (MetaCursorRendererNative *native,
 | 
			
		||||
                 MetaCRTC                 *crtc,
 | 
			
		||||
                 MetaCursorReference      *cursor,
 | 
			
		||||
                 MetaCursorSprite         *cursor_sprite,
 | 
			
		||||
                 gboolean                  force)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
 | 
			
		||||
 | 
			
		||||
  if (crtc->cursor == cursor && !force)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  crtc->cursor = cursor;
 | 
			
		||||
 | 
			
		||||
  if (cursor)
 | 
			
		||||
  if (cursor_sprite)
 | 
			
		||||
    {
 | 
			
		||||
      MetaCursorNativePrivate *cursor_priv =
 | 
			
		||||
        g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite);
 | 
			
		||||
      struct gbm_bo *bo;
 | 
			
		||||
      union gbm_bo_handle handle;
 | 
			
		||||
      int hot_x, hot_y;
 | 
			
		||||
 | 
			
		||||
      bo = meta_cursor_reference_get_gbm_bo (cursor, &hot_x, &hot_y);
 | 
			
		||||
      if (cursor_priv->pending_bo_state == META_CURSOR_GBM_BO_STATE_SET)
 | 
			
		||||
        bo = get_pending_cursor_sprite_gbm_bo (cursor_sprite);
 | 
			
		||||
      else
 | 
			
		||||
        bo = get_active_cursor_sprite_gbm_bo (cursor_sprite);
 | 
			
		||||
 | 
			
		||||
      if (!force && bo == crtc->cursor_renderer_private)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
      crtc->cursor_renderer_private = bo;
 | 
			
		||||
 | 
			
		||||
      handle = gbm_bo_get_handle (bo);
 | 
			
		||||
      meta_cursor_sprite_get_hotspot (cursor_sprite, &hot_x, &hot_y);
 | 
			
		||||
 | 
			
		||||
      drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, handle.u32,
 | 
			
		||||
                         priv->cursor_width, priv->cursor_height, hot_x, hot_y);
 | 
			
		||||
 | 
			
		||||
      if (cursor_priv->pending_bo_state == META_CURSOR_GBM_BO_STATE_SET)
 | 
			
		||||
        {
 | 
			
		||||
          cursor_priv->active_bo =
 | 
			
		||||
            (cursor_priv->active_bo + 1) % HW_CURSOR_BUFFER_COUNT;
 | 
			
		||||
          cursor_priv->pending_bo_state = META_CURSOR_GBM_BO_STATE_NONE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, 0, 0, 0, 0, 0);
 | 
			
		||||
      if (force || crtc->cursor_renderer_private != NULL)
 | 
			
		||||
        {
 | 
			
		||||
          drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, 0, 0, 0, 0, 0);
 | 
			
		||||
          crtc->cursor_renderer_private = NULL;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_hw_cursor (MetaCursorRendererNative *native,
 | 
			
		||||
                  MetaCursorSprite         *cursor_sprite,
 | 
			
		||||
                  gboolean                  force)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
 | 
			
		||||
  MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
 | 
			
		||||
  const MetaRectangle *cursor_rect = meta_cursor_renderer_get_rect (renderer);
 | 
			
		||||
  MetaCursorReference *cursor = meta_cursor_renderer_get_cursor (renderer);
 | 
			
		||||
  MetaMonitorManager *monitors;
 | 
			
		||||
  MetaCRTC *crtcs;
 | 
			
		||||
  unsigned int i, n_crtcs;
 | 
			
		||||
  MetaRectangle rect;
 | 
			
		||||
 | 
			
		||||
  monitors = meta_monitor_manager_get ();
 | 
			
		||||
  meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  if (cursor_sprite)
 | 
			
		||||
    rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
 | 
			
		||||
  else
 | 
			
		||||
    rect = (MetaRectangle) { 0 };
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_crtcs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      gboolean crtc_should_have_cursor;
 | 
			
		||||
      MetaCursorReference *crtc_cursor;
 | 
			
		||||
      gboolean crtc_should_use_cursor;
 | 
			
		||||
      MetaCursorSprite *crtc_cursor;
 | 
			
		||||
      MetaRectangle *crtc_rect;
 | 
			
		||||
 | 
			
		||||
      crtc_rect = &crtcs[i].rect;
 | 
			
		||||
 | 
			
		||||
      crtc_should_have_cursor = (priv->has_hw_cursor && meta_rectangle_overlap (cursor_rect, crtc_rect));
 | 
			
		||||
      if (crtc_should_have_cursor)
 | 
			
		||||
        crtc_cursor = cursor;
 | 
			
		||||
      crtc_should_use_cursor = (priv->has_hw_cursor &&
 | 
			
		||||
                                meta_rectangle_overlap (&rect, crtc_rect));
 | 
			
		||||
      if (crtc_should_use_cursor)
 | 
			
		||||
        crtc_cursor = cursor_sprite;
 | 
			
		||||
      else
 | 
			
		||||
        crtc_cursor = NULL;
 | 
			
		||||
 | 
			
		||||
@@ -130,34 +243,382 @@ update_hw_cursor (MetaCursorRendererNative *native,
 | 
			
		||||
      if (crtc_cursor)
 | 
			
		||||
        {
 | 
			
		||||
          drmModeMoveCursor (priv->drm_fd, crtcs[i].crtc_id,
 | 
			
		||||
                             cursor_rect->x - crtc_rect->x,
 | 
			
		||||
                             cursor_rect->y - crtc_rect->y);
 | 
			
		||||
                             rect.x - crtc_rect->x,
 | 
			
		||||
                             rect.y - crtc_rect->y);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
should_have_hw_cursor (MetaCursorRenderer *renderer)
 | 
			
		||||
has_valid_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorReference *cursor = meta_cursor_renderer_get_cursor (renderer);
 | 
			
		||||
  MetaCursorNativePrivate *cursor_priv =
 | 
			
		||||
    g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite);
 | 
			
		||||
 | 
			
		||||
  if (cursor)
 | 
			
		||||
    return (meta_cursor_reference_get_gbm_bo (cursor, NULL, NULL) != NULL);
 | 
			
		||||
  else
 | 
			
		||||
  if (!cursor_priv)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  switch (cursor_priv->pending_bo_state)
 | 
			
		||||
    {
 | 
			
		||||
    case META_CURSOR_GBM_BO_STATE_NONE:
 | 
			
		||||
      return get_active_cursor_sprite_gbm_bo (cursor_sprite) != NULL;
 | 
			
		||||
    case META_CURSOR_GBM_BO_STATE_SET:
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    case META_CURSOR_GBM_BO_STATE_INVALIDATED:
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_assert_not_reached ();
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer)
 | 
			
		||||
cursor_over_transformed_crtc (MetaCursorRenderer *renderer,
 | 
			
		||||
                              MetaCursorSprite   *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManager *monitors;
 | 
			
		||||
  MetaCRTC *crtcs;
 | 
			
		||||
  unsigned int i, n_crtcs;
 | 
			
		||||
  MetaRectangle rect;
 | 
			
		||||
 | 
			
		||||
  monitors = meta_monitor_manager_get ();
 | 
			
		||||
  meta_monitor_manager_get_resources (monitors, NULL, NULL,
 | 
			
		||||
                                      &crtcs, &n_crtcs, NULL, NULL);
 | 
			
		||||
  rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_crtcs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      if (!meta_rectangle_overlap (&rect, &crtcs[i].rect))
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (crtcs[i].transform != META_MONITOR_TRANSFORM_NORMAL)
 | 
			
		||||
        return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
should_have_hw_cursor (MetaCursorRenderer *renderer,
 | 
			
		||||
                       MetaCursorSprite   *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  CoglTexture *texture;
 | 
			
		||||
 | 
			
		||||
  if (!cursor_sprite)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (cursor_over_transformed_crtc (renderer, cursor_sprite))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
 | 
			
		||||
  if (!texture)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (meta_cursor_sprite_get_texture_scale (cursor_sprite) != 1)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (!has_valid_cursor_sprite_gbm_bo (cursor_sprite))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_cursor_renderer_native_update_animation (MetaCursorRendererNative *native)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
 | 
			
		||||
  MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
 | 
			
		||||
  MetaCursorSprite *cursor_sprite = meta_cursor_renderer_get_cursor (renderer);
 | 
			
		||||
 | 
			
		||||
  priv->animation_timeout_id = 0;
 | 
			
		||||
  meta_cursor_sprite_tick_frame (cursor_sprite);
 | 
			
		||||
  meta_cursor_renderer_force_update (renderer);
 | 
			
		||||
 | 
			
		||||
  return G_SOURCE_REMOVE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_cursor_renderer_native_trigger_frame (MetaCursorRendererNative *native,
 | 
			
		||||
                                           MetaCursorSprite         *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
 | 
			
		||||
  gboolean cursor_change;
 | 
			
		||||
  guint delay;
 | 
			
		||||
 | 
			
		||||
  cursor_change = cursor_sprite != priv->last_cursor;
 | 
			
		||||
  priv->last_cursor = cursor_sprite;
 | 
			
		||||
 | 
			
		||||
  if (!cursor_change && priv->animation_timeout_id)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (priv->animation_timeout_id)
 | 
			
		||||
    {
 | 
			
		||||
      g_source_remove (priv->animation_timeout_id);
 | 
			
		||||
      priv->animation_timeout_id = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (cursor_sprite && meta_cursor_sprite_is_animated (cursor_sprite))
 | 
			
		||||
    {
 | 
			
		||||
      delay = meta_cursor_sprite_get_current_frame_time (cursor_sprite);
 | 
			
		||||
 | 
			
		||||
      if (delay == 0)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
      priv->animation_timeout_id =
 | 
			
		||||
        g_timeout_add (delay,
 | 
			
		||||
                       (GSourceFunc) meta_cursor_renderer_native_update_animation,
 | 
			
		||||
                       native);
 | 
			
		||||
      g_source_set_name_by_id (priv->animation_timeout_id,
 | 
			
		||||
                               "[mutter] meta_cursor_renderer_native_update_animation");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer,
 | 
			
		||||
                                           MetaCursorSprite   *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
 | 
			
		||||
  MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
 | 
			
		||||
 | 
			
		||||
  priv->has_hw_cursor = should_have_hw_cursor (renderer);
 | 
			
		||||
  update_hw_cursor (native, FALSE);
 | 
			
		||||
  if (cursor_sprite)
 | 
			
		||||
    meta_cursor_sprite_realize_texture (cursor_sprite);
 | 
			
		||||
 | 
			
		||||
  meta_cursor_renderer_native_trigger_frame (native, cursor_sprite);
 | 
			
		||||
 | 
			
		||||
  priv->has_hw_cursor = should_have_hw_cursor (renderer, cursor_sprite);
 | 
			
		||||
  update_hw_cursor (native, cursor_sprite, FALSE);
 | 
			
		||||
  return priv->has_hw_cursor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
get_hardware_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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
cursor_priv_free (gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorNativePrivate *cursor_priv = data;
 | 
			
		||||
  guint i;
 | 
			
		||||
 | 
			
		||||
  if (!data)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < HW_CURSOR_BUFFER_COUNT; i++)
 | 
			
		||||
    g_clear_pointer (&cursor_priv->bos[0], (GDestroyNotify) gbm_bo_destroy);
 | 
			
		||||
  g_slice_free (MetaCursorNativePrivate, cursor_priv);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaCursorNativePrivate *
 | 
			
		||||
ensure_cursor_priv (MetaCursorSprite *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorNativePrivate *cursor_priv =
 | 
			
		||||
    g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite);
 | 
			
		||||
 | 
			
		||||
  if (!cursor_priv)
 | 
			
		||||
    {
 | 
			
		||||
      cursor_priv = g_slice_new0 (MetaCursorNativePrivate);
 | 
			
		||||
      g_object_set_qdata_full (G_OBJECT (cursor_sprite),
 | 
			
		||||
                               quark_cursor_sprite,
 | 
			
		||||
                               cursor_priv,
 | 
			
		||||
                               cursor_priv_free);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return cursor_priv;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
load_cursor_sprite_gbm_buffer (MetaCursorRendererNative *native,
 | 
			
		||||
                               MetaCursorSprite         *cursor_sprite,
 | 
			
		||||
                               uint8_t                  *pixels,
 | 
			
		||||
                               uint                      width,
 | 
			
		||||
                               uint                      height,
 | 
			
		||||
                               int                       rowstride,
 | 
			
		||||
                               uint32_t                  gbm_format)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererNativePrivate *priv =
 | 
			
		||||
    meta_cursor_renderer_native_get_instance_private (native);
 | 
			
		||||
  uint64_t cursor_width, cursor_height;
 | 
			
		||||
 | 
			
		||||
  get_hardware_cursor_size (native, &cursor_width, &cursor_height);
 | 
			
		||||
 | 
			
		||||
  if (width > cursor_width || height > cursor_height)
 | 
			
		||||
    {
 | 
			
		||||
      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 (priv->gbm, gbm_format,
 | 
			
		||||
                                      GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE))
 | 
			
		||||
    {
 | 
			
		||||
      struct gbm_bo *bo;
 | 
			
		||||
      uint8_t buf[4 * cursor_width * cursor_height];
 | 
			
		||||
      uint i;
 | 
			
		||||
 | 
			
		||||
      bo = gbm_bo_create (priv->gbm, cursor_width, cursor_height,
 | 
			
		||||
                          gbm_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
 | 
			
		||||
      if (!bo)
 | 
			
		||||
        {
 | 
			
		||||
          meta_warning ("Failed to allocate HW cursor buffer\n");
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      memset (buf, 0, sizeof(buf));
 | 
			
		||||
      for (i = 0; i < height; i++)
 | 
			
		||||
        memcpy (buf + i * 4 * cursor_width, pixels + i * rowstride, width * 4);
 | 
			
		||||
      if (gbm_bo_write (bo, buf, cursor_width * cursor_height * 4) != 0)
 | 
			
		||||
        {
 | 
			
		||||
          meta_warning ("Failed to write cursors buffer data: %s",
 | 
			
		||||
                        g_strerror (errno));
 | 
			
		||||
          gbm_bo_destroy (bo);
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      set_pending_cursor_sprite_gbm_bo (cursor_sprite, bo);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      meta_warning ("HW cursor for format %d not supported\n", gbm_format);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
invalidate_pending_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorNativePrivate *cursor_priv =
 | 
			
		||||
    g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite);
 | 
			
		||||
  guint pending_bo;
 | 
			
		||||
 | 
			
		||||
  if (!cursor_priv)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  pending_bo = get_pending_cursor_sprite_gbm_bo_index (cursor_sprite);
 | 
			
		||||
  g_clear_pointer (&cursor_priv->bos[pending_bo],
 | 
			
		||||
                   (GDestroyNotify) gbm_bo_destroy);
 | 
			
		||||
  cursor_priv->pending_bo_state = META_CURSOR_GBM_BO_STATE_INVALIDATED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_WAYLAND
 | 
			
		||||
static void
 | 
			
		||||
meta_cursor_renderer_native_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer,
 | 
			
		||||
                                                           MetaCursorSprite *cursor_sprite,
 | 
			
		||||
                                                           struct wl_resource *buffer)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
 | 
			
		||||
  MetaCursorRendererNativePrivate *priv =
 | 
			
		||||
    meta_cursor_renderer_native_get_instance_private (native);
 | 
			
		||||
  uint32_t gbm_format;
 | 
			
		||||
  uint64_t cursor_width, cursor_height;
 | 
			
		||||
  CoglTexture *texture;
 | 
			
		||||
  uint width, height;
 | 
			
		||||
 | 
			
		||||
  /* Destroy any previous pending cursor buffer; we'll always either fail (which
 | 
			
		||||
   * should unset, or succeed, which will set new buffer.
 | 
			
		||||
   */
 | 
			
		||||
  invalidate_pending_cursor_sprite_gbm_bo (cursor_sprite);
 | 
			
		||||
 | 
			
		||||
  texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
 | 
			
		||||
  width = cogl_texture_get_width (texture);
 | 
			
		||||
  height = cogl_texture_get_height (texture);
 | 
			
		||||
 | 
			
		||||
  struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (buffer);
 | 
			
		||||
  if (shm_buffer)
 | 
			
		||||
    {
 | 
			
		||||
      int rowstride = wl_shm_buffer_get_stride (shm_buffer);
 | 
			
		||||
      uint8_t *buffer_data;
 | 
			
		||||
 | 
			
		||||
      wl_shm_buffer_begin_access (shm_buffer);
 | 
			
		||||
 | 
			
		||||
      switch (wl_shm_buffer_get_format (shm_buffer))
 | 
			
		||||
        {
 | 
			
		||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
 | 
			
		||||
        case WL_SHM_FORMAT_ARGB8888:
 | 
			
		||||
          gbm_format = GBM_FORMAT_ARGB8888;
 | 
			
		||||
          break;
 | 
			
		||||
        case WL_SHM_FORMAT_XRGB8888:
 | 
			
		||||
          gbm_format = GBM_FORMAT_XRGB8888;
 | 
			
		||||
          break;
 | 
			
		||||
#else
 | 
			
		||||
        case WL_SHM_FORMAT_ARGB8888:
 | 
			
		||||
          gbm_format = GBM_FORMAT_ARGB8888;
 | 
			
		||||
          break;
 | 
			
		||||
        case WL_SHM_FORMAT_XRGB8888:
 | 
			
		||||
          gbm_format = GBM_FORMAT_XRGB8888;
 | 
			
		||||
          break;
 | 
			
		||||
#endif
 | 
			
		||||
        default:
 | 
			
		||||
          g_warn_if_reached ();
 | 
			
		||||
          gbm_format = GBM_FORMAT_ARGB8888;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      buffer_data = wl_shm_buffer_get_data (shm_buffer);
 | 
			
		||||
      load_cursor_sprite_gbm_buffer (native,
 | 
			
		||||
                                     cursor_sprite,
 | 
			
		||||
                                     buffer_data,
 | 
			
		||||
                                     width, height, rowstride,
 | 
			
		||||
                                     gbm_format);
 | 
			
		||||
 | 
			
		||||
      wl_shm_buffer_end_access (shm_buffer);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      struct gbm_bo *bo;
 | 
			
		||||
 | 
			
		||||
      /* 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 (native, &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;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      bo = gbm_bo_import (priv->gbm,
 | 
			
		||||
                          GBM_BO_IMPORT_WL_BUFFER,
 | 
			
		||||
                          buffer,
 | 
			
		||||
                          GBM_BO_USE_CURSOR);
 | 
			
		||||
      if (!bo)
 | 
			
		||||
        {
 | 
			
		||||
          meta_warning ("Importing HW cursor from wl_buffer failed\n");
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      set_pending_cursor_sprite_gbm_bo (cursor_sprite, bo);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_cursor_renderer_native_realize_cursor_from_xcursor (MetaCursorRenderer *renderer,
 | 
			
		||||
                                                         MetaCursorSprite *cursor_sprite,
 | 
			
		||||
                                                         XcursorImage *xc_image)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
 | 
			
		||||
 | 
			
		||||
  invalidate_pending_cursor_sprite_gbm_bo (cursor_sprite);
 | 
			
		||||
 | 
			
		||||
  load_cursor_sprite_gbm_buffer (native,
 | 
			
		||||
                                 cursor_sprite,
 | 
			
		||||
                                 (uint8_t *) xc_image->pixels,
 | 
			
		||||
                                 xc_image->width,
 | 
			
		||||
                                 xc_image->height,
 | 
			
		||||
                                 xc_image->width * 4,
 | 
			
		||||
                                 GBM_FORMAT_ARGB8888);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass)
 | 
			
		||||
{
 | 
			
		||||
@@ -166,6 +627,22 @@ meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass)
 | 
			
		||||
 | 
			
		||||
  object_class->finalize = meta_cursor_renderer_native_finalize;
 | 
			
		||||
  renderer_class->update_cursor = meta_cursor_renderer_native_update_cursor;
 | 
			
		||||
#ifdef HAVE_WAYLAND
 | 
			
		||||
  renderer_class->realize_cursor_from_wl_buffer =
 | 
			
		||||
    meta_cursor_renderer_native_realize_cursor_from_wl_buffer;
 | 
			
		||||
#endif
 | 
			
		||||
  renderer_class->realize_cursor_from_xcursor =
 | 
			
		||||
    meta_cursor_renderer_native_realize_cursor_from_xcursor;
 | 
			
		||||
 | 
			
		||||
  quark_cursor_sprite = g_quark_from_static_string ("-meta-cursor-native");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
force_update_hw_cursor (MetaCursorRendererNative *native)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
 | 
			
		||||
 | 
			
		||||
  update_hw_cursor (native, meta_cursor_renderer_get_cursor (renderer), TRUE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -173,7 +650,7 @@ on_monitors_changed (MetaMonitorManager       *monitors,
 | 
			
		||||
                     MetaCursorRendererNative *native)
 | 
			
		||||
{
 | 
			
		||||
  /* Our tracking is all messed up, so force an update. */
 | 
			
		||||
  update_hw_cursor (native, TRUE);
 | 
			
		||||
  force_update_hw_cursor (native);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -192,7 +669,7 @@ 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);
 | 
			
		||||
      priv->gbm = cogl_kms_renderer_get_gbm (cogl_renderer);
 | 
			
		||||
 | 
			
		||||
      uint64_t width, height;
 | 
			
		||||
      if (drmGetCap (priv->drm_fd, DRM_CAP_CURSOR_WIDTH, &width) == 0 &&
 | 
			
		||||
@@ -218,18 +695,8 @@ 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)
 | 
			
		||||
{
 | 
			
		||||
  update_hw_cursor (native, TRUE);
 | 
			
		||||
  force_update_hw_cursor (native);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -164,56 +164,36 @@ meta_idle_monitor_native_init (MetaIdleMonitorNative *monitor_native)
 | 
			
		||||
  monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  MetaIdleMonitorNative *monitor_native;
 | 
			
		||||
  GList *fired_watches;
 | 
			
		||||
} CheckNativeClosure;
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
check_native_watch (gpointer key,
 | 
			
		||||
                    gpointer value,
 | 
			
		||||
                    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorWatchNative *watch_native = value;
 | 
			
		||||
  MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native;
 | 
			
		||||
  CheckNativeClosure *closure = user_data;
 | 
			
		||||
  gboolean steal;
 | 
			
		||||
 | 
			
		||||
  if (watch->timeout_msec == 0)
 | 
			
		||||
    {
 | 
			
		||||
      closure->fired_watches = g_list_prepend (closure->fired_watches, watch);
 | 
			
		||||
      steal = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      g_source_set_ready_time (watch_native->timeout_source,
 | 
			
		||||
                               closure->monitor_native->last_event_time +
 | 
			
		||||
                               watch->timeout_msec * 1000);
 | 
			
		||||
      steal = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return steal;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
fire_native_watch (gpointer watch,
 | 
			
		||||
                   gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  _meta_idle_monitor_watch_fire (watch);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_idle_monitor_native_reset_idletime (MetaIdleMonitor *monitor)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor);
 | 
			
		||||
  CheckNativeClosure closure;
 | 
			
		||||
  GList *node, *watch_ids;
 | 
			
		||||
 | 
			
		||||
  monitor_native->last_event_time = g_get_monotonic_time ();
 | 
			
		||||
 | 
			
		||||
  closure.monitor_native = monitor_native;
 | 
			
		||||
  closure.fired_watches = NULL;
 | 
			
		||||
  g_hash_table_foreach_steal (monitor->watches, check_native_watch, &closure);
 | 
			
		||||
  watch_ids = g_hash_table_get_keys (monitor->watches);
 | 
			
		||||
 | 
			
		||||
  g_list_foreach (closure.fired_watches, fire_native_watch, NULL);
 | 
			
		||||
  g_list_free (closure.fired_watches);
 | 
			
		||||
  for (node = watch_ids; node != NULL; node = node->next)
 | 
			
		||||
    {
 | 
			
		||||
      guint watch_id = GPOINTER_TO_UINT (node->data);
 | 
			
		||||
      MetaIdleMonitorWatchNative *watch;
 | 
			
		||||
 | 
			
		||||
      watch = g_hash_table_lookup (monitor->watches, GUINT_TO_POINTER (watch_id));
 | 
			
		||||
      if (!watch)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (watch->base.timeout_msec == 0)
 | 
			
		||||
        {
 | 
			
		||||
          _meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          g_source_set_ready_time (watch->timeout_source,
 | 
			
		||||
                                   monitor_native->last_event_time +
 | 
			
		||||
                                   watch->base.timeout_msec * 1000);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_list_free (watch_ids);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -154,30 +154,30 @@ device_set_click_method (struct libinput_device            *libinput_device,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_native_set_scroll_method (MetaInputSettings            *settings,
 | 
			
		||||
                                              ClutterInputDevice           *device,
 | 
			
		||||
                                              GDesktopTouchpadScrollMethod  mode)
 | 
			
		||||
meta_input_settings_native_set_edge_scroll (MetaInputSettings            *settings,
 | 
			
		||||
                                            ClutterInputDevice           *device,
 | 
			
		||||
                                            gboolean                      edge_scrolling_enabled)
 | 
			
		||||
{
 | 
			
		||||
  enum libinput_config_scroll_method scroll_method = 0;
 | 
			
		||||
  struct libinput_device *libinput_device;
 | 
			
		||||
  enum libinput_config_scroll_method supported;
 | 
			
		||||
 | 
			
		||||
  libinput_device = clutter_evdev_input_device_get_libinput_device (device);
 | 
			
		||||
  supported = libinput_device_config_scroll_get_methods (libinput_device);
 | 
			
		||||
 | 
			
		||||
  switch (mode)
 | 
			
		||||
  if (supported & LIBINPUT_CONFIG_SCROLL_2FG)
 | 
			
		||||
    {
 | 
			
		||||
    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_EDGE;
 | 
			
		||||
      break;
 | 
			
		||||
    case G_DESKTOP_TOUCHPAD_SCROLL_METHOD_TWO_FINGER_SCROLLING:
 | 
			
		||||
      scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
      return;
 | 
			
		||||
  }
 | 
			
		||||
    }
 | 
			
		||||
  else if (supported & LIBINPUT_CONFIG_SCROLL_EDGE &&
 | 
			
		||||
           edge_scrolling_enabled)
 | 
			
		||||
    {
 | 
			
		||||
      scroll_method = LIBINPUT_CONFIG_SCROLL_EDGE;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      scroll_method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  device_set_scroll_method (libinput_device, scroll_method);
 | 
			
		||||
}
 | 
			
		||||
@@ -252,7 +252,7 @@ meta_input_settings_native_class_init (MetaInputSettingsNativeClass *klass)
 | 
			
		||||
  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_edge_scroll = meta_input_settings_native_set_edge_scroll;
 | 
			
		||||
  input_settings_class->set_scroll_button = meta_input_settings_native_set_scroll_button;
 | 
			
		||||
  input_settings_class->set_click_method = meta_input_settings_native_set_click_method;
 | 
			
		||||
  input_settings_class->set_keyboard_repeat = meta_input_settings_native_set_keyboard_repeat;
 | 
			
		||||
 
 | 
			
		||||
@@ -37,12 +37,20 @@
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include <systemd/sd-login.h>
 | 
			
		||||
#include <gudev/gudev.h>
 | 
			
		||||
 | 
			
		||||
#include "dbus-utils.h"
 | 
			
		||||
#include "meta-dbus-login1.h"
 | 
			
		||||
 | 
			
		||||
#include "backends/meta-backend-private.h"
 | 
			
		||||
#include "meta-cursor-renderer-native.h"
 | 
			
		||||
#include "meta-idle-monitor-native.h"
 | 
			
		||||
 | 
			
		||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUdevDevice, g_object_unref)
 | 
			
		||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUdevClient, g_object_unref)
 | 
			
		||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUdevEnumerator, g_object_unref)
 | 
			
		||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(Login1Session, g_object_unref)
 | 
			
		||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(Login1Seat, g_object_unref)
 | 
			
		||||
 | 
			
		||||
struct _MetaLauncher
 | 
			
		||||
{
 | 
			
		||||
@@ -53,14 +61,21 @@ struct _MetaLauncher
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static Login1Session *
 | 
			
		||||
get_session_proxy (GCancellable *cancellable)
 | 
			
		||||
get_session_proxy (GCancellable *cancellable,
 | 
			
		||||
                   GError      **error)
 | 
			
		||||
{
 | 
			
		||||
  char *proxy_path;
 | 
			
		||||
  char *session_id;
 | 
			
		||||
  g_autofree char *proxy_path = NULL;
 | 
			
		||||
  g_autofree char *session_id = NULL;
 | 
			
		||||
  Login1Session *session_proxy;
 | 
			
		||||
 | 
			
		||||
  if (sd_pid_get_session (getpid (), &session_id) < 0)
 | 
			
		||||
    return NULL;
 | 
			
		||||
    {
 | 
			
		||||
      g_set_error (error,
 | 
			
		||||
                   G_IO_ERROR,
 | 
			
		||||
                   G_IO_ERROR_NOT_FOUND,
 | 
			
		||||
                   "Could not get session ID: %m");
 | 
			
		||||
      return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  proxy_path = get_escaped_dbus_path ("/org/freedesktop/login1/session", session_id);
 | 
			
		||||
 | 
			
		||||
@@ -68,31 +83,37 @@ get_session_proxy (GCancellable *cancellable)
 | 
			
		||||
                                                         G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
 | 
			
		||||
                                                         "org.freedesktop.login1",
 | 
			
		||||
                                                         proxy_path,
 | 
			
		||||
                                                         cancellable, NULL);
 | 
			
		||||
  free (proxy_path);
 | 
			
		||||
                                                         cancellable, error);
 | 
			
		||||
  if (!session_proxy)
 | 
			
		||||
    g_prefix_error(error, "Could not get session proxy: ");
 | 
			
		||||
 | 
			
		||||
  return session_proxy;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Login1Seat *
 | 
			
		||||
get_seat_proxy (GCancellable *cancellable)
 | 
			
		||||
get_seat_proxy (GCancellable *cancellable,
 | 
			
		||||
                GError      **error)
 | 
			
		||||
{
 | 
			
		||||
  return login1_seat_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
 | 
			
		||||
                                             G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
 | 
			
		||||
                                             "org.freedesktop.login1",
 | 
			
		||||
                                             "/org/freedesktop/login1/seat/self",
 | 
			
		||||
                                             cancellable, NULL);
 | 
			
		||||
  Login1Seat *seat = login1_seat_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
 | 
			
		||||
                                                         G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
 | 
			
		||||
                                                         "org.freedesktop.login1",
 | 
			
		||||
                                                         "/org/freedesktop/login1/seat/self",
 | 
			
		||||
                                                         cancellable, error);
 | 
			
		||||
  if (!seat)
 | 
			
		||||
    g_prefix_error(error, "Could not get seat proxy: ");
 | 
			
		||||
 | 
			
		||||
  return seat;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
session_unpause (void)
 | 
			
		||||
{
 | 
			
		||||
  ClutterBackend *backend;
 | 
			
		||||
  ClutterBackend *clutter_backend;
 | 
			
		||||
  CoglContext *cogl_context;
 | 
			
		||||
  CoglDisplay *cogl_display;
 | 
			
		||||
 | 
			
		||||
  backend = clutter_get_default_backend ();
 | 
			
		||||
  cogl_context = clutter_backend_get_cogl_context (backend);
 | 
			
		||||
  clutter_backend = clutter_get_default_backend ();
 | 
			
		||||
  cogl_context = clutter_backend_get_cogl_context (clutter_backend);
 | 
			
		||||
  cogl_display = cogl_context_get_display (cogl_context);
 | 
			
		||||
  cogl_kms_display_queue_modes_reset (cogl_display);
 | 
			
		||||
 | 
			
		||||
@@ -110,6 +131,7 @@ session_unpause (void)
 | 
			
		||||
 | 
			
		||||
    clutter_actor_queue_redraw (stage);
 | 
			
		||||
    meta_cursor_renderer_native_force_update (META_CURSOR_RENDERER_NATIVE (renderer));
 | 
			
		||||
    meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -128,9 +150,8 @@ take_device (Login1Session *session_proxy,
 | 
			
		||||
             GCancellable  *cancellable,
 | 
			
		||||
             GError       **error)
 | 
			
		||||
{
 | 
			
		||||
  gboolean ret = FALSE;
 | 
			
		||||
  GVariant *fd_variant = NULL;
 | 
			
		||||
  GUnixFDList *fd_list = NULL;
 | 
			
		||||
  g_autoptr (GVariant) fd_variant = NULL;
 | 
			
		||||
  g_autoptr (GUnixFDList) fd_list = NULL;
 | 
			
		||||
  int fd = -1;
 | 
			
		||||
 | 
			
		||||
  if (!login1_session_call_take_device_sync (session_proxy,
 | 
			
		||||
@@ -142,21 +163,14 @@ take_device (Login1Session *session_proxy,
 | 
			
		||||
                                             &fd_list,
 | 
			
		||||
                                             cancellable,
 | 
			
		||||
                                             error))
 | 
			
		||||
    goto out;
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  fd = g_unix_fd_list_get (fd_list, g_variant_get_handle (fd_variant), error);
 | 
			
		||||
  if (fd == -1)
 | 
			
		||||
    goto out;
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  *out_fd = fd;
 | 
			
		||||
  ret = TRUE;
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  if (fd_variant)
 | 
			
		||||
    g_variant_unref (fd_variant);
 | 
			
		||||
  if (fd_list)
 | 
			
		||||
    g_object_unref (fd_list);
 | 
			
		||||
  return ret;
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
@@ -164,22 +178,16 @@ get_device_info_from_path (const char *path,
 | 
			
		||||
                           int        *out_major,
 | 
			
		||||
                           int        *out_minor)
 | 
			
		||||
{
 | 
			
		||||
  gboolean ret = FALSE;
 | 
			
		||||
  int r;
 | 
			
		||||
  struct stat st;
 | 
			
		||||
 | 
			
		||||
  r = stat (path, &st);
 | 
			
		||||
  if (r < 0)
 | 
			
		||||
    goto out;
 | 
			
		||||
  if (!S_ISCHR (st.st_mode))
 | 
			
		||||
    goto out;
 | 
			
		||||
  if (r < 0 || !S_ISCHR (st.st_mode))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  *out_major = major (st.st_rdev);
 | 
			
		||||
  *out_minor = minor (st.st_rdev);
 | 
			
		||||
  ret = TRUE;
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  return ret;
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
@@ -187,22 +195,16 @@ get_device_info_from_fd (int  fd,
 | 
			
		||||
                         int *out_major,
 | 
			
		||||
                         int *out_minor)
 | 
			
		||||
{
 | 
			
		||||
  gboolean ret = FALSE;
 | 
			
		||||
  int r;
 | 
			
		||||
  struct stat st;
 | 
			
		||||
 | 
			
		||||
  r = fstat (fd, &st);
 | 
			
		||||
  if (r < 0)
 | 
			
		||||
    goto out;
 | 
			
		||||
  if (!S_ISCHR (st.st_mode))
 | 
			
		||||
    goto out;
 | 
			
		||||
  if (r < 0 || !S_ISCHR (st.st_mode))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  *out_major = major (st.st_rdev);
 | 
			
		||||
  *out_minor = minor (st.st_rdev);
 | 
			
		||||
  ret = TRUE;
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  return ret;
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
@@ -241,7 +243,7 @@ on_evdev_device_close (int      fd,
 | 
			
		||||
  if (!get_device_info_from_fd (fd, &major, &minor))
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("Could not get device info for fd %d: %m", fd);
 | 
			
		||||
      return;
 | 
			
		||||
      goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!login1_session_call_release_device_sync (self->session_proxy,
 | 
			
		||||
@@ -250,6 +252,9 @@ on_evdev_device_close (int      fd,
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("Could not release device %d,%d: %s", major, minor, error->message);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
  close (fd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -277,25 +282,111 @@ on_active_changed (Login1Session *session,
 | 
			
		||||
  sync_active (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gchar *
 | 
			
		||||
get_primary_gpu_path (const gchar *seat_name)
 | 
			
		||||
{
 | 
			
		||||
  const gchar *subsystems[] = {"drm", NULL};
 | 
			
		||||
  gchar *path = NULL;
 | 
			
		||||
  GList *devices, *tmp;
 | 
			
		||||
 | 
			
		||||
  g_autoptr (GUdevClient) gudev_client = g_udev_client_new (subsystems);
 | 
			
		||||
  g_autoptr (GUdevEnumerator) enumerator = g_udev_enumerator_new (gudev_client);
 | 
			
		||||
 | 
			
		||||
  g_udev_enumerator_add_match_name (enumerator, "card*");
 | 
			
		||||
  g_udev_enumerator_add_match_tag (enumerator, "seat");
 | 
			
		||||
 | 
			
		||||
  devices = g_udev_enumerator_execute (enumerator);
 | 
			
		||||
  if (!devices)
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  for (tmp = devices; tmp != NULL; tmp = tmp->next)
 | 
			
		||||
    {
 | 
			
		||||
      g_autoptr (GUdevDevice) platform_device = NULL;
 | 
			
		||||
      g_autoptr (GUdevDevice) pci_device = NULL;
 | 
			
		||||
      GUdevDevice *dev = tmp->data;
 | 
			
		||||
      gint boot_vga;
 | 
			
		||||
      const gchar *device_seat;
 | 
			
		||||
 | 
			
		||||
      /* filter out devices that are not character device, like card0-VGA-1 */
 | 
			
		||||
      if (g_udev_device_get_device_type (dev) != G_UDEV_DEVICE_TYPE_CHAR)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      device_seat = g_udev_device_get_property (dev, "ID_SEAT");
 | 
			
		||||
      if (!device_seat)
 | 
			
		||||
        {
 | 
			
		||||
          /* when ID_SEAT is not set, it means seat0 */
 | 
			
		||||
          device_seat = "seat0";
 | 
			
		||||
        }
 | 
			
		||||
      else if (g_strcmp0 (device_seat, "seat0") != 0)
 | 
			
		||||
        {
 | 
			
		||||
          /* if the device has been explicitly assigned other seat
 | 
			
		||||
           * than seat0, it is probably the right device to use */
 | 
			
		||||
          path = g_strdup (g_udev_device_get_device_file (dev));
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      /* skip devices that do not belong to our seat */
 | 
			
		||||
      if (g_strcmp0 (seat_name, device_seat))
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      platform_device = g_udev_device_get_parent_with_subsystem (dev, "platform", NULL);
 | 
			
		||||
      if (platform_device != NULL)
 | 
			
		||||
        {
 | 
			
		||||
          path = g_strdup (g_udev_device_get_device_file (dev));
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      pci_device = g_udev_device_get_parent_with_subsystem (dev, "pci", NULL);
 | 
			
		||||
      if (pci_device != NULL)
 | 
			
		||||
        {
 | 
			
		||||
          /* get value of boot_vga attribute or 0 if the device has no boot_vga */
 | 
			
		||||
          boot_vga = g_udev_device_get_sysfs_attr_as_int (pci_device, "boot_vga");
 | 
			
		||||
          if (boot_vga == 1)
 | 
			
		||||
            {
 | 
			
		||||
              /* found the boot_vga device */
 | 
			
		||||
              path = g_strdup (g_udev_device_get_device_file (dev));
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_list_free_full (devices, g_object_unref);
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
  return path;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
get_kms_fd (Login1Session *session_proxy,
 | 
			
		||||
            int *fd_out)
 | 
			
		||||
            const gchar   *seat_id,
 | 
			
		||||
            int           *fd_out,
 | 
			
		||||
            GError       **error)
 | 
			
		||||
{
 | 
			
		||||
  int major, minor;
 | 
			
		||||
  int fd;
 | 
			
		||||
  GError *error = NULL;
 | 
			
		||||
 | 
			
		||||
  /* XXX -- use udev to find the DRM master device */
 | 
			
		||||
  if (!get_device_info_from_path ("/dev/dri/card0", &major, &minor))
 | 
			
		||||
  g_autofree gchar *path = get_primary_gpu_path (seat_id);
 | 
			
		||||
  if (!path)
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("Could not stat /dev/dri/card0: %m");
 | 
			
		||||
      g_set_error (error,
 | 
			
		||||
                   G_IO_ERROR,
 | 
			
		||||
                   G_IO_ERROR_NOT_FOUND,
 | 
			
		||||
                   "could not find drm kms device");
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!take_device (session_proxy, major, minor, &fd, NULL, &error))
 | 
			
		||||
  if (!get_device_info_from_path (path, &major, &minor))
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("Could not open DRM device: %s\n", error->message);
 | 
			
		||||
      g_error_free (error);
 | 
			
		||||
      g_set_error (error,
 | 
			
		||||
                   G_IO_ERROR,
 | 
			
		||||
                   G_IO_ERROR_NOT_FOUND,
 | 
			
		||||
                   "Could not get device info for path %s: %m", path);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!take_device (session_proxy, major, minor, &fd, NULL, error))
 | 
			
		||||
    {
 | 
			
		||||
      g_prefix_error (error, "Could not open DRM device: ");
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -304,28 +395,72 @@ get_kms_fd (Login1Session *session_proxy,
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaLauncher *
 | 
			
		||||
meta_launcher_new (void)
 | 
			
		||||
static gchar *
 | 
			
		||||
get_seat_id (GError **error)
 | 
			
		||||
{
 | 
			
		||||
  MetaLauncher *self = NULL;
 | 
			
		||||
  Login1Session *session_proxy;
 | 
			
		||||
  GError *error = NULL;
 | 
			
		||||
  int kms_fd;
 | 
			
		||||
  g_autofree char *session_id = NULL;
 | 
			
		||||
  char *seat_id = NULL;
 | 
			
		||||
  int r;
 | 
			
		||||
 | 
			
		||||
  session_proxy = get_session_proxy (NULL);
 | 
			
		||||
  if (!login1_session_call_take_control_sync (session_proxy, FALSE, NULL, &error))
 | 
			
		||||
  r = sd_pid_get_session (0, &session_id);
 | 
			
		||||
  if (r < 0)
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("Could not take control: %s", error->message);
 | 
			
		||||
      g_error_free (error);
 | 
			
		||||
      goto out;
 | 
			
		||||
      g_set_error (error,
 | 
			
		||||
                   G_IO_ERROR,
 | 
			
		||||
                   G_IO_ERROR_NOT_FOUND,
 | 
			
		||||
                   "Could not get session for PID: %s", g_strerror (-r));
 | 
			
		||||
      return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!get_kms_fd (session_proxy, &kms_fd))
 | 
			
		||||
    goto out;
 | 
			
		||||
  r = sd_session_get_seat (session_id, &seat_id);
 | 
			
		||||
  if (r < 0)
 | 
			
		||||
    {
 | 
			
		||||
      g_set_error (error,
 | 
			
		||||
                   G_IO_ERROR,
 | 
			
		||||
                   G_IO_ERROR_NOT_FOUND,
 | 
			
		||||
                   "Could not get seat for session: %s", g_strerror (-r));
 | 
			
		||||
      return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return seat_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaLauncher *
 | 
			
		||||
meta_launcher_new (GError **error)
 | 
			
		||||
{
 | 
			
		||||
  MetaLauncher *self = NULL;
 | 
			
		||||
  g_autoptr (Login1Session) session_proxy = NULL;
 | 
			
		||||
  g_autoptr (Login1Seat) seat_proxy = NULL;
 | 
			
		||||
  g_autofree char *seat_id = NULL;
 | 
			
		||||
  gboolean have_control = FALSE;
 | 
			
		||||
  int kms_fd;
 | 
			
		||||
 | 
			
		||||
  session_proxy = get_session_proxy (NULL, error);
 | 
			
		||||
  if (!session_proxy)
 | 
			
		||||
    goto fail;
 | 
			
		||||
 | 
			
		||||
  if (!login1_session_call_take_control_sync (session_proxy, FALSE, NULL, error))
 | 
			
		||||
    {
 | 
			
		||||
      g_prefix_error (error, "Could not take control: ");
 | 
			
		||||
      goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  have_control = TRUE;
 | 
			
		||||
 | 
			
		||||
  seat_id = get_seat_id (error);
 | 
			
		||||
  if (!seat_id)
 | 
			
		||||
    goto fail;
 | 
			
		||||
 | 
			
		||||
  seat_proxy = get_seat_proxy (NULL, error);
 | 
			
		||||
  if (!seat_proxy)
 | 
			
		||||
    goto fail;
 | 
			
		||||
 | 
			
		||||
  if (!get_kms_fd (session_proxy, seat_id, &kms_fd, error))
 | 
			
		||||
    goto fail;
 | 
			
		||||
 | 
			
		||||
  self = g_slice_new0 (MetaLauncher);
 | 
			
		||||
  self->session_proxy = g_object_ref (session_proxy);
 | 
			
		||||
  self->seat_proxy = get_seat_proxy (NULL);
 | 
			
		||||
  self->seat_proxy = g_object_ref (seat_proxy);
 | 
			
		||||
 | 
			
		||||
  self->session_active = TRUE;
 | 
			
		||||
 | 
			
		||||
@@ -335,11 +470,12 @@ meta_launcher_new (void)
 | 
			
		||||
                                      self);
 | 
			
		||||
 | 
			
		||||
  g_signal_connect (self->session_proxy, "notify::active", G_CALLBACK (on_active_changed), self);
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
  g_object_unref (session_proxy);
 | 
			
		||||
 | 
			
		||||
  return self;
 | 
			
		||||
 | 
			
		||||
 fail:
 | 
			
		||||
  if (have_control)
 | 
			
		||||
    login1_session_call_release_control_sync (session_proxy, NULL, NULL);
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaLauncher MetaLauncher;
 | 
			
		||||
 | 
			
		||||
MetaLauncher     *meta_launcher_new                     (void);
 | 
			
		||||
MetaLauncher     *meta_launcher_new                     (GError       **error);
 | 
			
		||||
void              meta_launcher_free                    (MetaLauncher  *self);
 | 
			
		||||
 | 
			
		||||
gboolean          meta_launcher_activate_session        (MetaLauncher  *self,
 | 
			
		||||
 
 | 
			
		||||
@@ -42,6 +42,8 @@
 | 
			
		||||
 | 
			
		||||
#include <gudev/gudev.h>
 | 
			
		||||
 | 
			
		||||
#define ALL_TRANSFORMS (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  drmModeConnector *connector;
 | 
			
		||||
 | 
			
		||||
@@ -55,8 +57,22 @@ typedef struct {
 | 
			
		||||
 | 
			
		||||
  uint32_t dpms_prop_id;
 | 
			
		||||
  uint32_t edid_blob_id;
 | 
			
		||||
  uint32_t tile_blob_id;
 | 
			
		||||
 | 
			
		||||
  int suggested_x;
 | 
			
		||||
  int suggested_y;
 | 
			
		||||
  uint32_t hotplug_mode_update;
 | 
			
		||||
} MetaOutputKms;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  uint32_t underscan_prop_id;
 | 
			
		||||
  uint32_t underscan_hborder_prop_id;
 | 
			
		||||
  uint32_t underscan_vborder_prop_id;
 | 
			
		||||
  uint32_t primary_plane_id;
 | 
			
		||||
  uint32_t rotation_prop_id;
 | 
			
		||||
  uint32_t rotation_map[ALL_TRANSFORMS];
 | 
			
		||||
} MetaCRTCKms;
 | 
			
		||||
 | 
			
		||||
struct _MetaMonitorManagerKms
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManager parent_instance;
 | 
			
		||||
@@ -104,7 +120,7 @@ make_output_name (drmModeConnector *connector)
 | 
			
		||||
  static const char * const connector_type_names[] = {
 | 
			
		||||
    "unknown", "VGA", "DVII", "DVID", "DVID", "Composite",
 | 
			
		||||
    "SVIDEO", "LVDS", "Component", "9PinDIN", "DisplayPort",
 | 
			
		||||
    "HDMIA", "HDMIB", "TV", "eDP"
 | 
			
		||||
    "HDMIA", "HDMIB", "TV", "eDP", "Virtual", "DSI"
 | 
			
		||||
  };
 | 
			
		||||
  const char *connector_type_name;
 | 
			
		||||
 | 
			
		||||
@@ -137,6 +153,12 @@ meta_monitor_mode_destroy_notify (MetaMonitorMode *output)
 | 
			
		||||
  g_slice_free (drmModeModeInfo, output->driver_private);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_crtc_destroy_notify (MetaCRTC *crtc)
 | 
			
		||||
{
 | 
			
		||||
  g_free (crtc->driver_private);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
drm_mode_equal (gconstpointer one,
 | 
			
		||||
                gconstpointer two)
 | 
			
		||||
@@ -181,24 +203,67 @@ drm_mode_hash (gconstpointer ptr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
find_properties (MetaMonitorManagerKms *manager_kms,
 | 
			
		||||
                 MetaOutputKms         *output_kms)
 | 
			
		||||
find_connector_properties (MetaMonitorManagerKms *manager_kms,
 | 
			
		||||
                           MetaOutputKms         *output_kms)
 | 
			
		||||
{
 | 
			
		||||
  drmModePropertyPtr prop;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  output_kms->hotplug_mode_update = 0;
 | 
			
		||||
  output_kms->suggested_x = -1;
 | 
			
		||||
  output_kms->suggested_y = -1;
 | 
			
		||||
  for (i = 0; i < output_kms->connector->count_props; i++)
 | 
			
		||||
    {
 | 
			
		||||
      prop = drmModeGetProperty (manager_kms->fd, output_kms->connector->props[i]);
 | 
			
		||||
      drmModePropertyPtr prop = drmModeGetProperty (manager_kms->fd, output_kms->connector->props[i]);
 | 
			
		||||
      if (!prop)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if ((prop->flags & DRM_MODE_PROP_ENUM) &&
 | 
			
		||||
          strcmp(prop->name, "DPMS") == 0)
 | 
			
		||||
      if ((prop->flags & DRM_MODE_PROP_ENUM) && strcmp (prop->name, "DPMS") == 0)
 | 
			
		||||
        output_kms->dpms_prop_id = prop->prop_id;
 | 
			
		||||
      else if ((prop->flags & DRM_MODE_PROP_BLOB) &&
 | 
			
		||||
               strcmp (prop->name, "EDID") == 0)
 | 
			
		||||
      else if ((prop->flags & DRM_MODE_PROP_BLOB) && strcmp (prop->name, "EDID") == 0)
 | 
			
		||||
        output_kms->edid_blob_id = output_kms->connector->prop_values[i];
 | 
			
		||||
      else if ((prop->flags & DRM_MODE_PROP_BLOB) &&
 | 
			
		||||
               strcmp (prop->name, "TILE") == 0)
 | 
			
		||||
        output_kms->tile_blob_id = output_kms->connector->prop_values[i];
 | 
			
		||||
      else if ((prop->flags & DRM_MODE_PROP_RANGE) &&
 | 
			
		||||
               strcmp (prop->name, "suggested X") == 0)
 | 
			
		||||
        output_kms->suggested_x = output_kms->connector->prop_values[i];
 | 
			
		||||
      else if ((prop->flags & DRM_MODE_PROP_RANGE) &&
 | 
			
		||||
               strcmp (prop->name, "suggested Y") == 0)
 | 
			
		||||
        output_kms->suggested_y = output_kms->connector->prop_values[i];
 | 
			
		||||
      else if ((prop->flags & DRM_MODE_PROP_RANGE) &&
 | 
			
		||||
               strcmp (prop->name, "hotplug_mode_update") == 0)
 | 
			
		||||
        output_kms->hotplug_mode_update = output_kms->connector->prop_values[i];
 | 
			
		||||
      
 | 
			
		||||
      drmModeFreeProperty (prop);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
find_crtc_properties (MetaMonitorManagerKms *manager_kms,
 | 
			
		||||
                      MetaCRTC *meta_crtc)
 | 
			
		||||
{
 | 
			
		||||
  MetaCRTCKms *crtc_kms;
 | 
			
		||||
  drmModeObjectPropertiesPtr props;
 | 
			
		||||
  size_t i;
 | 
			
		||||
 | 
			
		||||
  crtc_kms = meta_crtc->driver_private;
 | 
			
		||||
 | 
			
		||||
  props = drmModeObjectGetProperties (manager_kms->fd, meta_crtc->crtc_id, DRM_MODE_OBJECT_CRTC);
 | 
			
		||||
  if (!props)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < props->count_props; i++)
 | 
			
		||||
    {
 | 
			
		||||
      drmModePropertyPtr prop = drmModeGetProperty (manager_kms->fd, props->props[i]);
 | 
			
		||||
      if (!prop)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if ((prop->flags & DRM_MODE_PROP_ENUM) && strcmp (prop->name, "underscan") == 0)
 | 
			
		||||
        crtc_kms->underscan_prop_id = prop->prop_id;
 | 
			
		||||
      else if ((prop->flags & DRM_MODE_PROP_RANGE) && strcmp (prop->name, "underscan hborder") == 0)
 | 
			
		||||
        crtc_kms->underscan_hborder_prop_id = prop->prop_id;
 | 
			
		||||
      else if ((prop->flags & DRM_MODE_PROP_RANGE) && strcmp (prop->name, "underscan vborder") == 0)
 | 
			
		||||
        crtc_kms->underscan_vborder_prop_id = prop->prop_id;
 | 
			
		||||
 | 
			
		||||
      drmModeFreeProperty (prop);
 | 
			
		||||
    }
 | 
			
		||||
@@ -233,6 +298,47 @@ read_output_edid (MetaMonitorManagerKms *manager_kms,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
output_get_tile_info (MetaMonitorManagerKms *manager_kms,
 | 
			
		||||
                      MetaOutput            *output)
 | 
			
		||||
{
 | 
			
		||||
  MetaOutputKms *output_kms = output->driver_private;
 | 
			
		||||
  drmModePropertyBlobPtr tile_blob = NULL;
 | 
			
		||||
  int ret;
 | 
			
		||||
 | 
			
		||||
  if (output_kms->tile_blob_id == 0)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  tile_blob = drmModeGetPropertyBlob (manager_kms->fd, output_kms->tile_blob_id);
 | 
			
		||||
  if (!tile_blob)
 | 
			
		||||
    {
 | 
			
		||||
      meta_warning ("Failed to read TILE of output %s: %s\n", output->name, strerror(errno));
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (tile_blob->length > 0)
 | 
			
		||||
    {
 | 
			
		||||
      ret = sscanf ((char *)tile_blob->data, "%d:%d:%d:%d:%d:%d:%d:%d",
 | 
			
		||||
                    &output->tile_info.group_id,
 | 
			
		||||
                    &output->tile_info.flags,
 | 
			
		||||
                    &output->tile_info.max_h_tiles,
 | 
			
		||||
                    &output->tile_info.max_v_tiles,
 | 
			
		||||
                    &output->tile_info.loc_h_tile,
 | 
			
		||||
                    &output->tile_info.loc_v_tile,
 | 
			
		||||
                    &output->tile_info.tile_w,
 | 
			
		||||
                    &output->tile_info.tile_h);
 | 
			
		||||
 | 
			
		||||
      if (ret != 8)
 | 
			
		||||
        return FALSE;
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      drmModeFreePropertyBlob (tile_blob);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaMonitorMode *
 | 
			
		||||
find_meta_mode (MetaMonitorManager    *manager,
 | 
			
		||||
                const drmModeModeInfo *drm_mode)
 | 
			
		||||
@@ -328,6 +434,137 @@ get_output_scale (MetaMonitorManager *manager,
 | 
			
		||||
    return compute_scale (output);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
find_property_index (MetaMonitorManager         *manager,
 | 
			
		||||
                     drmModeObjectPropertiesPtr  props,
 | 
			
		||||
                     const gchar                *prop_name,
 | 
			
		||||
                     drmModePropertyPtr         *found)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
 | 
			
		||||
  unsigned int i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < props->count_props; i++)
 | 
			
		||||
    {
 | 
			
		||||
      drmModePropertyPtr prop;
 | 
			
		||||
 | 
			
		||||
      prop = drmModeGetProperty (manager_kms->fd, props->props[i]);
 | 
			
		||||
      if (!prop)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (strcmp (prop->name, prop_name) == 0)
 | 
			
		||||
        {
 | 
			
		||||
          *found = prop;
 | 
			
		||||
          return i;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      drmModeFreeProperty (prop);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
parse_transforms (MetaMonitorManager *manager,
 | 
			
		||||
                  drmModePropertyPtr  prop,
 | 
			
		||||
                  MetaCRTC           *crtc)
 | 
			
		||||
{
 | 
			
		||||
  MetaCRTCKms *crtc_kms = crtc->driver_private;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < prop->count_enums; i++)
 | 
			
		||||
    {
 | 
			
		||||
      int cur = -1;
 | 
			
		||||
 | 
			
		||||
      if (strcmp (prop->enums[i].name, "rotate-0") == 0)
 | 
			
		||||
        cur = META_MONITOR_TRANSFORM_NORMAL;
 | 
			
		||||
      else if (strcmp (prop->enums[i].name, "rotate-90") == 0)
 | 
			
		||||
        cur = META_MONITOR_TRANSFORM_90;
 | 
			
		||||
      else if (strcmp (prop->enums[i].name, "rotate-180") == 0)
 | 
			
		||||
        cur = META_MONITOR_TRANSFORM_180;
 | 
			
		||||
      else if (strcmp (prop->enums[i].name, "rotate-270") == 0)
 | 
			
		||||
        cur = META_MONITOR_TRANSFORM_270;
 | 
			
		||||
 | 
			
		||||
      if (cur != -1)
 | 
			
		||||
        {
 | 
			
		||||
          crtc->all_transforms |= 1 << cur;
 | 
			
		||||
          crtc_kms->rotation_map[cur] = 1 << prop->enums[i].value;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
is_primary_plane (MetaMonitorManager         *manager,
 | 
			
		||||
                  drmModeObjectPropertiesPtr  props)
 | 
			
		||||
{
 | 
			
		||||
  drmModePropertyPtr prop;
 | 
			
		||||
  int idx;
 | 
			
		||||
 | 
			
		||||
  idx = find_property_index (manager, props, "type", &prop);
 | 
			
		||||
  if (idx < 0)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  drmModeFreeProperty (prop);
 | 
			
		||||
  return props->prop_values[idx] == DRM_PLANE_TYPE_PRIMARY;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
init_crtc_rotations (MetaMonitorManager *manager,
 | 
			
		||||
                     MetaCRTC           *crtc,
 | 
			
		||||
                     unsigned int        idx)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
 | 
			
		||||
  drmModeObjectPropertiesPtr props;
 | 
			
		||||
  drmModePlaneRes *planes;
 | 
			
		||||
  drmModePlane *drm_plane;
 | 
			
		||||
  MetaCRTCKms *crtc_kms;
 | 
			
		||||
  unsigned int i;
 | 
			
		||||
 | 
			
		||||
  crtc_kms = crtc->driver_private;
 | 
			
		||||
 | 
			
		||||
  planes = drmModeGetPlaneResources(manager_kms->fd);
 | 
			
		||||
  if (planes == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < planes->count_planes; i++)
 | 
			
		||||
    {
 | 
			
		||||
      drmModePropertyPtr prop;
 | 
			
		||||
 | 
			
		||||
      drm_plane = drmModeGetPlane (manager_kms->fd, planes->planes[i]);
 | 
			
		||||
 | 
			
		||||
      if (!drm_plane)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if ((drm_plane->possible_crtcs & (1 << idx)))
 | 
			
		||||
        {
 | 
			
		||||
          props = drmModeObjectGetProperties (manager_kms->fd,
 | 
			
		||||
                                              drm_plane->plane_id,
 | 
			
		||||
                                              DRM_MODE_OBJECT_PLANE);
 | 
			
		||||
 | 
			
		||||
          if (props && is_primary_plane (manager, props))
 | 
			
		||||
            {
 | 
			
		||||
              int rotation_idx;
 | 
			
		||||
 | 
			
		||||
              crtc_kms->primary_plane_id = drm_plane->plane_id;
 | 
			
		||||
              rotation_idx = find_property_index (manager, props, "rotation", &prop);
 | 
			
		||||
 | 
			
		||||
              if (rotation_idx >= 0)
 | 
			
		||||
                {
 | 
			
		||||
                  crtc_kms->rotation_prop_id = props->props[rotation_idx];
 | 
			
		||||
                  parse_transforms (manager, prop, crtc);
 | 
			
		||||
                  drmModeFreeProperty (prop);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          if (props)
 | 
			
		||||
            drmModeFreeObjectProperties (props);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      drmModeFreePlane (drm_plane);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  drmModeFreePlaneResources (planes);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
@@ -395,8 +632,18 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
 | 
			
		||||
      meta_mode->name = g_strndup (mode->name, DRM_DISPLAY_MODE_LEN);
 | 
			
		||||
      meta_mode->width = mode->hdisplay;
 | 
			
		||||
      meta_mode->height = mode->vdisplay;
 | 
			
		||||
      meta_mode->refresh_rate = (1000 * mode->clock /
 | 
			
		||||
                                 ((float)mode->htotal * mode->vtotal));
 | 
			
		||||
 | 
			
		||||
      /* Calculate refresh rate in milliHz first for extra precision. */
 | 
			
		||||
      meta_mode->refresh_rate = (mode->clock * 1000000LL) / mode->htotal;
 | 
			
		||||
      meta_mode->refresh_rate += (mode->vtotal / 2);
 | 
			
		||||
      meta_mode->refresh_rate /= mode->vtotal;
 | 
			
		||||
      if (mode->flags & DRM_MODE_FLAG_INTERLACE)
 | 
			
		||||
	meta_mode->refresh_rate *= 2;
 | 
			
		||||
      if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
 | 
			
		||||
        meta_mode->refresh_rate /= 2;
 | 
			
		||||
      if (mode->vscan > 1)
 | 
			
		||||
        meta_mode->refresh_rate /= mode->vscan;
 | 
			
		||||
      meta_mode->refresh_rate /= 1000.0;
 | 
			
		||||
 | 
			
		||||
      meta_mode->driver_private = g_slice_dup (drmModeModeInfo, mode);
 | 
			
		||||
      meta_mode->driver_notify = (GDestroyNotify)meta_monitor_mode_destroy_notify;
 | 
			
		||||
@@ -442,6 +689,11 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
 | 
			
		||||
          height = MAX (height, meta_crtc->rect.y + meta_crtc->rect.height);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      meta_crtc->driver_private = g_new0 (MetaCRTCKms, 1);
 | 
			
		||||
      meta_crtc->driver_notify = (GDestroyNotify) meta_crtc_destroy_notify;
 | 
			
		||||
      find_crtc_properties (manager_kms, meta_crtc);
 | 
			
		||||
      init_crtc_rotations (manager, meta_crtc, i);
 | 
			
		||||
 | 
			
		||||
      drmModeFreeCrtc (crtc);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -472,8 +724,6 @@ 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)
 | 
			
		||||
            {
 | 
			
		||||
@@ -498,11 +748,17 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
	  meta_output->preferred_mode = NULL;
 | 
			
		||||
	  meta_output->n_modes = connector->count_modes;
 | 
			
		||||
	  meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
 | 
			
		||||
	  for (j = 0; j < meta_output->n_modes; j++)
 | 
			
		||||
	  for (j = 0; j < meta_output->n_modes; j++) {
 | 
			
		||||
            meta_output->modes[j] = find_meta_mode (manager, &connector->modes[j]);
 | 
			
		||||
	  meta_output->preferred_mode = meta_output->modes[0];
 | 
			
		||||
            if (connector->modes[j].type & DRM_MODE_TYPE_PREFERRED)
 | 
			
		||||
              meta_output->preferred_mode = meta_output->modes[j];
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          if (!meta_output->preferred_mode)
 | 
			
		||||
            meta_output->preferred_mode = meta_output->modes[0];
 | 
			
		||||
 | 
			
		||||
          output_kms->connector = connector;
 | 
			
		||||
          output_kms->n_encoders = connector->count_encoders;
 | 
			
		||||
@@ -567,8 +823,11 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
 | 
			
		||||
              meta_output->is_presentation = FALSE;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          find_properties (manager_kms, output_kms);
 | 
			
		||||
 | 
			
		||||
          find_connector_properties (manager_kms, output_kms);
 | 
			
		||||
          meta_output->suggested_x = output_kms->suggested_x;
 | 
			
		||||
          meta_output->suggested_y = output_kms->suggested_y;
 | 
			
		||||
          meta_output->hotplug_mode_update = output_kms->hotplug_mode_update;
 | 
			
		||||
          
 | 
			
		||||
          edid = read_output_edid (manager_kms, meta_output);
 | 
			
		||||
          meta_output_parse_edid (meta_output, edid);
 | 
			
		||||
          g_bytes_unref (edid);
 | 
			
		||||
@@ -578,6 +837,8 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
 | 
			
		||||
 | 
			
		||||
          meta_output->scale = get_output_scale (manager, meta_output);
 | 
			
		||||
 | 
			
		||||
          output_get_tile_info (manager_kms, meta_output);
 | 
			
		||||
 | 
			
		||||
          /* FIXME: backlight is a very driver specific thing unfortunately,
 | 
			
		||||
             every DDX does its own thing, and the dumb KMS API does not include it.
 | 
			
		||||
 | 
			
		||||
@@ -723,8 +984,9 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
 | 
			
		||||
 | 
			
		||||
      if (output_kms->dpms_prop_id != 0)
 | 
			
		||||
        {
 | 
			
		||||
          int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->winsys_id,
 | 
			
		||||
                                               output_kms->dpms_prop_id, state);
 | 
			
		||||
          int ok = drmModeObjectSetProperty (manager_kms->fd, meta_output->winsys_id,
 | 
			
		||||
                                             DRM_MODE_OBJECT_CONNECTOR,
 | 
			
		||||
                                             output_kms->dpms_prop_id, state);
 | 
			
		||||
 | 
			
		||||
          if (ok < 0)
 | 
			
		||||
            meta_warning ("Failed to set power save mode for output %s: %s\n",
 | 
			
		||||
@@ -748,6 +1010,48 @@ crtc_free (CoglKmsCrtc *crtc)
 | 
			
		||||
  g_slice_free (CoglKmsCrtc, crtc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
set_underscan (MetaMonitorManagerKms *manager_kms,
 | 
			
		||||
               MetaOutput *output)
 | 
			
		||||
{
 | 
			
		||||
  if (!output->crtc)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  MetaCRTC *crtc = output->crtc;
 | 
			
		||||
  MetaCRTCKms *crtc_kms = crtc->driver_private;
 | 
			
		||||
  if (!crtc_kms->underscan_prop_id)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (output->is_underscanning)
 | 
			
		||||
    {
 | 
			
		||||
      drmModeObjectSetProperty (manager_kms->fd, crtc->crtc_id,
 | 
			
		||||
                                DRM_MODE_OBJECT_CRTC,
 | 
			
		||||
                                crtc_kms->underscan_prop_id, (uint64_t) 1);
 | 
			
		||||
 | 
			
		||||
      if (crtc_kms->underscan_hborder_prop_id)
 | 
			
		||||
        {
 | 
			
		||||
          uint64_t value = crtc->current_mode->width * 0.05;
 | 
			
		||||
          drmModeObjectSetProperty (manager_kms->fd, crtc->crtc_id,
 | 
			
		||||
                                    DRM_MODE_OBJECT_CRTC,
 | 
			
		||||
                                    crtc_kms->underscan_hborder_prop_id, value);
 | 
			
		||||
        }
 | 
			
		||||
      if (crtc_kms->underscan_vborder_prop_id)
 | 
			
		||||
        {
 | 
			
		||||
          uint64_t value = crtc->current_mode->height * 0.05;
 | 
			
		||||
          drmModeObjectSetProperty (manager_kms->fd, crtc->crtc_id,
 | 
			
		||||
                                    DRM_MODE_OBJECT_CRTC,
 | 
			
		||||
                                    crtc_kms->underscan_vborder_prop_id, value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      drmModeObjectSetProperty (manager_kms->fd, crtc->crtc_id,
 | 
			
		||||
                                DRM_MODE_OBJECT_CRTC,
 | 
			
		||||
                                crtc_kms->underscan_prop_id, (uint64_t) 0);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
 | 
			
		||||
                                              MetaCRTCInfo       **crtcs,
 | 
			
		||||
@@ -755,6 +1059,7 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
 | 
			
		||||
                                              MetaOutputInfo     **outputs,
 | 
			
		||||
                                              unsigned int         n_outputs)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
 | 
			
		||||
  ClutterBackend *backend;
 | 
			
		||||
  CoglContext *cogl_context;
 | 
			
		||||
  CoglDisplay *cogl_display;
 | 
			
		||||
@@ -770,6 +1075,7 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
 | 
			
		||||
    {
 | 
			
		||||
      MetaCRTCInfo *crtc_info = crtcs[i];
 | 
			
		||||
      MetaCRTC *crtc = crtc_info->crtc;
 | 
			
		||||
      MetaCRTCKms *crtc_kms = crtc->driver_private;
 | 
			
		||||
      CoglKmsCrtc *cogl_crtc;
 | 
			
		||||
 | 
			
		||||
      crtc->is_dirty = TRUE;
 | 
			
		||||
@@ -842,6 +1148,13 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
 | 
			
		||||
          crtc->current_mode = mode;
 | 
			
		||||
          crtc->transform = crtc_info->transform;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (crtc->all_transforms & (1 << crtc->transform))
 | 
			
		||||
        drmModeObjectSetProperty (manager_kms->fd,
 | 
			
		||||
                                  crtc_kms->primary_plane_id,
 | 
			
		||||
                                  DRM_MODE_OBJECT_PLANE,
 | 
			
		||||
                                  crtc_kms->rotation_prop_id,
 | 
			
		||||
                                  crtc_kms->rotation_map[crtc->transform]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* Disable CRTCs not mentioned in the list (they have is_dirty == FALSE,
 | 
			
		||||
@@ -900,6 +1213,9 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
 | 
			
		||||
 | 
			
		||||
      output->is_primary = output_info->is_primary;
 | 
			
		||||
      output->is_presentation = output_info->is_presentation;
 | 
			
		||||
      output->is_underscanning = output_info->is_underscanning;
 | 
			
		||||
 | 
			
		||||
      set_underscan (manager_kms, output);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* Disable outputs not mentioned in the list */
 | 
			
		||||
@@ -991,6 +1307,8 @@ meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
 | 
			
		||||
 | 
			
		||||
  manager_kms->fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
 | 
			
		||||
 | 
			
		||||
  drmSetClientCap (manager_kms->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
 | 
			
		||||
 | 
			
		||||
  const char *subsystems[2] = { "drm", NULL };
 | 
			
		||||
  manager_kms->udev = g_udev_client_new (subsystems);
 | 
			
		||||
  g_signal_connect (manager_kms->udev, "uevent",
 | 
			
		||||
 
 | 
			
		||||
@@ -40,12 +40,24 @@
 | 
			
		||||
#include "meta-idle-monitor-xsync.h"
 | 
			
		||||
#include "meta-monitor-manager-xrandr.h"
 | 
			
		||||
#include "backends/meta-monitor-manager-dummy.h"
 | 
			
		||||
#include "backends/x11/nested/meta-cursor-renderer-x11-nested.h"
 | 
			
		||||
#include "meta-cursor-renderer-x11.h"
 | 
			
		||||
#ifdef HAVE_WAYLAND
 | 
			
		||||
#include "wayland/meta-wayland.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <meta/util.h>
 | 
			
		||||
#include "display-private.h"
 | 
			
		||||
#include "compositor/compositor-private.h"
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  /* We're a traditional CM running under the host. */
 | 
			
		||||
  META_BACKEND_X11_MODE_COMPOSITOR,
 | 
			
		||||
 | 
			
		||||
  /* We're a nested X11 client */
 | 
			
		||||
  META_BACKEND_X11_MODE_NESTED,
 | 
			
		||||
} MetaBackendX11Mode;
 | 
			
		||||
 | 
			
		||||
struct _MetaBackendX11Private
 | 
			
		||||
{
 | 
			
		||||
  /* The host X11 display */
 | 
			
		||||
@@ -53,6 +65,8 @@ struct _MetaBackendX11Private
 | 
			
		||||
  xcb_connection_t *xcb;
 | 
			
		||||
  GSource *source;
 | 
			
		||||
 | 
			
		||||
  MetaBackendX11Mode mode;
 | 
			
		||||
 | 
			
		||||
  int xsync_event_base;
 | 
			
		||||
  int xsync_error_base;
 | 
			
		||||
 | 
			
		||||
@@ -68,6 +82,7 @@ struct _MetaBackendX11Private
 | 
			
		||||
  gchar *keymap_layouts;
 | 
			
		||||
  gchar *keymap_variants;
 | 
			
		||||
  gchar *keymap_options;
 | 
			
		||||
  int locked_group;
 | 
			
		||||
};
 | 
			
		||||
typedef struct _MetaBackendX11Private MetaBackendX11Private;
 | 
			
		||||
 | 
			
		||||
@@ -102,7 +117,7 @@ translate_device_event (MetaBackendX11 *x11,
 | 
			
		||||
      /* This codepath should only ever trigger as an X11 compositor,
 | 
			
		||||
       * and never under nested, as under nested all backend events
 | 
			
		||||
       * should be reported with respect to the stage window. */
 | 
			
		||||
      g_assert (!meta_is_wayland_compositor ());
 | 
			
		||||
      g_assert (priv->mode == META_BACKEND_X11_MODE_COMPOSITOR);
 | 
			
		||||
 | 
			
		||||
      device_event->event = stage_window;
 | 
			
		||||
 | 
			
		||||
@@ -133,6 +148,8 @@ static void
 | 
			
		||||
translate_crossing_event (MetaBackendX11 *x11,
 | 
			
		||||
                          XIEnterEvent   *enter_event)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
 | 
			
		||||
 | 
			
		||||
  /* Throw out weird events generated by grabs. */
 | 
			
		||||
  if (enter_event->mode == XINotifyGrab ||
 | 
			
		||||
      enter_event->mode == XINotifyUngrab)
 | 
			
		||||
@@ -141,7 +158,14 @@ translate_crossing_event (MetaBackendX11 *x11,
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  enter_event->event = meta_backend_x11_get_xwindow (x11);
 | 
			
		||||
  Window stage_window = meta_backend_x11_get_xwindow (x11);
 | 
			
		||||
  if (enter_event->event != stage_window &&
 | 
			
		||||
      priv->mode == META_BACKEND_X11_MODE_COMPOSITOR)
 | 
			
		||||
    {
 | 
			
		||||
      enter_event->event = meta_backend_x11_get_xwindow (x11);
 | 
			
		||||
      enter_event->event_x = enter_event->root_x;
 | 
			
		||||
      enter_event->event_y = enter_event->root_y;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -250,20 +274,47 @@ handle_host_xevent (MetaBackend *backend,
 | 
			
		||||
      }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (priv->mode == META_BACKEND_X11_MODE_NESTED && event->type == FocusIn)
 | 
			
		||||
    {
 | 
			
		||||
#ifdef HAVE_WAYLAND
 | 
			
		||||
      Window xwin = meta_backend_x11_get_xwindow(x11);
 | 
			
		||||
      XEvent xev;
 | 
			
		||||
 | 
			
		||||
      if (event->xfocus.window == xwin)
 | 
			
		||||
        {
 | 
			
		||||
          /* Since we've selected for KeymapStateMask, every FocusIn is followed immediately
 | 
			
		||||
           * by a KeymapNotify event */
 | 
			
		||||
          XMaskEvent(priv->xdisplay, KeymapStateMask, &xev);
 | 
			
		||||
          MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
 | 
			
		||||
          meta_wayland_compositor_update_key_state (compositor, xev.xkeymap.key_vector, 32, 8);
 | 
			
		||||
        }
 | 
			
		||||
#else
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (event->type == (priv->xsync_event_base + XSyncAlarmNotify))
 | 
			
		||||
    handle_alarm_notify (backend, event);
 | 
			
		||||
 | 
			
		||||
  if (event->type == priv->xkb_event_base)
 | 
			
		||||
    {
 | 
			
		||||
      XkbAnyEvent *xkb_ev = (XkbAnyEvent *) event;
 | 
			
		||||
      XkbEvent *xkb_ev = (XkbEvent *) event;
 | 
			
		||||
 | 
			
		||||
      if (xkb_ev->device == META_VIRTUAL_CORE_KEYBOARD_ID)
 | 
			
		||||
      if (xkb_ev->any.device == META_VIRTUAL_CORE_KEYBOARD_ID)
 | 
			
		||||
        {
 | 
			
		||||
          switch (xkb_ev->xkb_type)
 | 
			
		||||
          switch (xkb_ev->any.xkb_type)
 | 
			
		||||
            {
 | 
			
		||||
            case XkbNewKeyboardNotify:
 | 
			
		||||
            case XkbMapNotify:
 | 
			
		||||
              keymap_changed (backend);
 | 
			
		||||
              break;
 | 
			
		||||
            case XkbStateNotify:
 | 
			
		||||
              if (xkb_ev->state.changed & XkbGroupLockMask)
 | 
			
		||||
                {
 | 
			
		||||
                  if (priv->locked_group != xkb_ev->state.locked_group)
 | 
			
		||||
                    XkbLockGroup (priv->xdisplay, XkbUseCoreKbd, priv->locked_group);
 | 
			
		||||
                }
 | 
			
		||||
              break;
 | 
			
		||||
            default:
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
@@ -399,6 +450,7 @@ meta_backend_x11_post_init (MetaBackend *backend)
 | 
			
		||||
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
 | 
			
		||||
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
 | 
			
		||||
  int major, minor;
 | 
			
		||||
  gboolean has_xi = FALSE;
 | 
			
		||||
 | 
			
		||||
  priv->xdisplay = clutter_x11_get_default_display ();
 | 
			
		||||
 | 
			
		||||
@@ -408,29 +460,27 @@ meta_backend_x11_post_init (MetaBackend *backend)
 | 
			
		||||
      !XSyncInitialize (priv->xdisplay, &major, &minor))
 | 
			
		||||
    meta_fatal ("Could not initialize XSync");
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    int major = 2, minor = 3;
 | 
			
		||||
    gboolean has_xi = FALSE;
 | 
			
		||||
  if (XQueryExtension (priv->xdisplay,
 | 
			
		||||
                       "XInputExtension",
 | 
			
		||||
                       &priv->xinput_opcode,
 | 
			
		||||
                       &priv->xinput_error_base,
 | 
			
		||||
                       &priv->xinput_event_base))
 | 
			
		||||
    {
 | 
			
		||||
      major = 2; minor = 3;
 | 
			
		||||
      if (XIQueryVersion (priv->xdisplay, &major, &minor) == Success)
 | 
			
		||||
        {
 | 
			
		||||
          int version = (major * 10) + minor;
 | 
			
		||||
          if (version >= 22)
 | 
			
		||||
            has_xi = TRUE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (XQueryExtension (priv->xdisplay,
 | 
			
		||||
                         "XInputExtension",
 | 
			
		||||
                         &priv->xinput_opcode,
 | 
			
		||||
                         &priv->xinput_error_base,
 | 
			
		||||
                         &priv->xinput_event_base))
 | 
			
		||||
      {
 | 
			
		||||
        if (XIQueryVersion (priv->xdisplay, &major, &minor) == Success)
 | 
			
		||||
          {
 | 
			
		||||
            int version = (major * 10) + minor;
 | 
			
		||||
            if (version >= 22)
 | 
			
		||||
              has_xi = TRUE;
 | 
			
		||||
          }
 | 
			
		||||
      }
 | 
			
		||||
  if (!has_xi)
 | 
			
		||||
    meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
 | 
			
		||||
 | 
			
		||||
    if (!has_xi)
 | 
			
		||||
      meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  take_touch_grab (backend);
 | 
			
		||||
  /* We only take the passive touch grab if we are a X11 compositor */
 | 
			
		||||
  if (priv->mode == META_BACKEND_X11_MODE_COMPOSITOR)
 | 
			
		||||
    take_touch_grab (backend);
 | 
			
		||||
 | 
			
		||||
  priv->xcb = XGetXCBConnection (priv->xdisplay);
 | 
			
		||||
  if (!xkb_x11_setup_xkb_extension (priv->xcb,
 | 
			
		||||
@@ -461,19 +511,37 @@ meta_backend_x11_create_idle_monitor (MetaBackend *backend,
 | 
			
		||||
static MetaMonitorManager *
 | 
			
		||||
meta_backend_x11_create_monitor_manager (MetaBackend *backend)
 | 
			
		||||
{
 | 
			
		||||
  /* If we're a Wayland compositor using the X11 backend,
 | 
			
		||||
   * we're a nested configuration, so return the dummy
 | 
			
		||||
   * monitor setup. */
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
    return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL);
 | 
			
		||||
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
 | 
			
		||||
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
 | 
			
		||||
 | 
			
		||||
  return g_object_new (META_TYPE_MONITOR_MANAGER_XRANDR, NULL);
 | 
			
		||||
  switch (priv->mode)
 | 
			
		||||
    {
 | 
			
		||||
    case META_BACKEND_X11_MODE_COMPOSITOR:
 | 
			
		||||
      return g_object_new (META_TYPE_MONITOR_MANAGER_XRANDR, NULL);
 | 
			
		||||
    case META_BACKEND_X11_MODE_NESTED:
 | 
			
		||||
      return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL);
 | 
			
		||||
    default:
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaCursorRenderer *
 | 
			
		||||
meta_backend_x11_create_cursor_renderer (MetaBackend *backend)
 | 
			
		||||
{
 | 
			
		||||
  return g_object_new (META_TYPE_CURSOR_RENDERER_X11, NULL);
 | 
			
		||||
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
 | 
			
		||||
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
 | 
			
		||||
 | 
			
		||||
  switch (priv->mode)
 | 
			
		||||
    {
 | 
			
		||||
    case META_BACKEND_X11_MODE_COMPOSITOR:
 | 
			
		||||
      return g_object_new (META_TYPE_CURSOR_RENDERER_X11, NULL);
 | 
			
		||||
      break;
 | 
			
		||||
    case META_BACKEND_X11_MODE_NESTED:
 | 
			
		||||
      return g_object_new (META_TYPE_CURSOR_RENDERER_X11_NESTED, NULL);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
@@ -701,6 +769,9 @@ meta_backend_x11_get_keymap (MetaBackend *backend)
 | 
			
		||||
                                                     priv->xcb,
 | 
			
		||||
                                                     xkb_x11_get_core_keyboard_device_id (priv->xcb),
 | 
			
		||||
                                                     XKB_KEYMAP_COMPILE_NO_FLAGS);
 | 
			
		||||
      if (priv->keymap == NULL)
 | 
			
		||||
        priv->keymap = xkb_keymap_new_from_names (context, NULL, XKB_KEYMAP_COMPILE_NO_FLAGS);
 | 
			
		||||
 | 
			
		||||
      xkb_context_unref (context);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -714,6 +785,7 @@ meta_backend_x11_lock_layout_group (MetaBackend *backend,
 | 
			
		||||
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
 | 
			
		||||
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
 | 
			
		||||
 | 
			
		||||
  priv->locked_group = idx;
 | 
			
		||||
  XkbLockGroup (priv->xdisplay, XkbUseCoreKbd, idx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -721,7 +793,10 @@ static void
 | 
			
		||||
meta_backend_x11_update_screen_size (MetaBackend *backend,
 | 
			
		||||
                                     int width, int height)
 | 
			
		||||
{
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
 | 
			
		||||
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
 | 
			
		||||
 | 
			
		||||
  if (priv->mode == META_BACKEND_X11_MODE_NESTED)
 | 
			
		||||
    {
 | 
			
		||||
      /* For a nested wayland session, we want to go through Clutter to update the
 | 
			
		||||
       * toplevel window size, rather than doing it directly.
 | 
			
		||||
@@ -730,8 +805,6 @@ meta_backend_x11_update_screen_size (MetaBackend *backend,
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
 | 
			
		||||
      MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
 | 
			
		||||
      Window xwin = meta_backend_x11_get_xwindow (x11);
 | 
			
		||||
      XResizeWindow (priv->xdisplay, xwin, width, height);
 | 
			
		||||
    }
 | 
			
		||||
@@ -755,10 +828,36 @@ meta_backend_x11_select_stage_events (MetaBackend *backend)
 | 
			
		||||
  XISetMask (mask.mask, XI_FocusIn);
 | 
			
		||||
  XISetMask (mask.mask, XI_FocusOut);
 | 
			
		||||
  XISetMask (mask.mask, XI_Motion);
 | 
			
		||||
  XIClearMask (mask.mask, XI_TouchBegin);
 | 
			
		||||
  XIClearMask (mask.mask, XI_TouchEnd);
 | 
			
		||||
  XIClearMask (mask.mask, XI_TouchUpdate);
 | 
			
		||||
 | 
			
		||||
  if (priv->mode == META_BACKEND_X11_MODE_NESTED)
 | 
			
		||||
    {
 | 
			
		||||
      /* When we're an X11 compositor, we can't take these events or else
 | 
			
		||||
       * replaying events from our passive root window grab will cause
 | 
			
		||||
       * them to come back to us.
 | 
			
		||||
       *
 | 
			
		||||
       * When we're a nested application, we want to behave like any other
 | 
			
		||||
       * application, so select these events like normal apps do.
 | 
			
		||||
       */
 | 
			
		||||
      XISetMask (mask.mask, XI_TouchBegin);
 | 
			
		||||
      XISetMask (mask.mask, XI_TouchEnd);
 | 
			
		||||
      XISetMask (mask.mask, XI_TouchUpdate);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  XISelectEvents (priv->xdisplay, xwin, &mask, 1);
 | 
			
		||||
 | 
			
		||||
  if (priv->mode == META_BACKEND_X11_MODE_NESTED)
 | 
			
		||||
    {
 | 
			
		||||
      /* We have no way of tracking key changes when the stage doesn't have
 | 
			
		||||
       * focus, so we select for KeymapStateMask so that we get a complete
 | 
			
		||||
       * dump of the keyboard state in a KeymapNotify event that immediately
 | 
			
		||||
       * follows each FocusIn (and EnterNotify, but we ignore that.)
 | 
			
		||||
       */
 | 
			
		||||
      XWindowAttributes xwa;
 | 
			
		||||
 | 
			
		||||
      XGetWindowAttributes(priv->xdisplay, xwin, &xwa);
 | 
			
		||||
      XSelectInput(priv->xdisplay, xwin,
 | 
			
		||||
                   xwa.your_event_mask | FocusChangeMask | KeymapStateMask);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -783,8 +882,15 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
 | 
			
		||||
static void
 | 
			
		||||
meta_backend_x11_init (MetaBackendX11 *x11)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
 | 
			
		||||
 | 
			
		||||
  /* We do X11 event retrieval ourselves */
 | 
			
		||||
  clutter_x11_disable_event_retrieval ();
 | 
			
		||||
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
    priv->mode = META_BACKEND_X11_MODE_NESTED;
 | 
			
		||||
  else
 | 
			
		||||
    priv->mode = META_BACKEND_X11_MODE_COMPOSITOR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Display *
 | 
			
		||||
 
 | 
			
		||||
@@ -107,6 +107,7 @@ meta_barrier_impl_x11_new (MetaBarrier *barrier)
 | 
			
		||||
  MetaDisplay *display = barrier->priv->display;
 | 
			
		||||
  Display *dpy;
 | 
			
		||||
  Window root;
 | 
			
		||||
  unsigned int allowed_motion_dirs;
 | 
			
		||||
 | 
			
		||||
  if (display == NULL)
 | 
			
		||||
    {
 | 
			
		||||
@@ -121,12 +122,14 @@ meta_barrier_impl_x11_new (MetaBarrier *barrier)
 | 
			
		||||
  dpy = display->xdisplay;
 | 
			
		||||
  root = DefaultRootWindow (dpy);
 | 
			
		||||
 | 
			
		||||
  allowed_motion_dirs =
 | 
			
		||||
    meta_border_get_allows_directions (&barrier->priv->border);
 | 
			
		||||
  priv->xbarrier = XFixesCreatePointerBarrier (dpy, root,
 | 
			
		||||
                                               barrier->priv->x1,
 | 
			
		||||
                                               barrier->priv->y1,
 | 
			
		||||
                                               barrier->priv->x2,
 | 
			
		||||
                                               barrier->priv->y2,
 | 
			
		||||
                                               barrier->priv->directions,
 | 
			
		||||
                                               barrier->priv->border.line.a.x,
 | 
			
		||||
                                               barrier->priv->border.line.a.y,
 | 
			
		||||
                                               barrier->priv->border.line.b.x,
 | 
			
		||||
                                               barrier->priv->border.line.b.y,
 | 
			
		||||
                                               allowed_motion_dirs,
 | 
			
		||||
                                               0, NULL);
 | 
			
		||||
 | 
			
		||||
  g_hash_table_insert (display->xids, &priv->xbarrier, barrier);
 | 
			
		||||
 
 | 
			
		||||
@@ -40,25 +40,29 @@ typedef struct _MetaCursorRendererX11Private MetaCursorRendererX11Private;
 | 
			
		||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererX11, meta_cursor_renderer_x11, META_TYPE_CURSOR_RENDERER);
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_cursor_renderer_x11_update_cursor (MetaCursorRenderer *renderer)
 | 
			
		||||
meta_cursor_renderer_x11_update_cursor (MetaCursorRenderer *renderer,
 | 
			
		||||
                                        MetaCursorSprite   *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererX11 *x11 = META_CURSOR_RENDERER_X11 (renderer);
 | 
			
		||||
  MetaCursorRendererX11Private *priv = meta_cursor_renderer_x11_get_instance_private (x11);
 | 
			
		||||
 | 
			
		||||
  MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
 | 
			
		||||
  Window xwindow = meta_backend_x11_get_xwindow (backend);
 | 
			
		||||
 | 
			
		||||
  if (xwindow == None)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
 | 
			
		||||
 | 
			
		||||
  MetaCursorReference *cursor_ref = meta_cursor_renderer_get_cursor (renderer);
 | 
			
		||||
  if (xwindow == None)
 | 
			
		||||
    {
 | 
			
		||||
      if (cursor_sprite)
 | 
			
		||||
        meta_cursor_sprite_realize_texture (cursor_sprite);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  gboolean has_server_cursor = FALSE;
 | 
			
		||||
 | 
			
		||||
  if (cursor_ref)
 | 
			
		||||
  if (cursor_sprite)
 | 
			
		||||
    {
 | 
			
		||||
      MetaCursor cursor = meta_cursor_reference_get_meta_cursor (cursor_ref);
 | 
			
		||||
      MetaCursor cursor = meta_cursor_sprite_get_meta_cursor (cursor_sprite);
 | 
			
		||||
 | 
			
		||||
      if (cursor != META_CURSOR_NONE)
 | 
			
		||||
        {
 | 
			
		||||
          Cursor xcursor = meta_cursor_create_x_cursor (xdisplay, cursor);
 | 
			
		||||
@@ -80,6 +84,9 @@ meta_cursor_renderer_x11_update_cursor (MetaCursorRenderer *renderer)
 | 
			
		||||
      priv->server_cursor_visible = has_server_cursor;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!priv->server_cursor_visible && cursor_sprite)
 | 
			
		||||
    meta_cursor_sprite_realize_texture (cursor_sprite);
 | 
			
		||||
 | 
			
		||||
  return priv->server_cursor_visible;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -107,20 +107,6 @@ set_alarm_enabled (Display    *dpy,
 | 
			
		||||
  XSyncChangeAlarm (dpy, alarm, XSyncCAEvents, &attr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
check_x11_watch (gpointer data,
 | 
			
		||||
                 gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorWatchXSync *watch_xsync = data;
 | 
			
		||||
  MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_xsync;
 | 
			
		||||
  XSyncAlarm alarm = (XSyncAlarm) user_data;
 | 
			
		||||
 | 
			
		||||
  if (watch_xsync->xalarm != alarm)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  _meta_idle_monitor_watch_fire (watch);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *
 | 
			
		||||
counter_name_for_device (int device_id)
 | 
			
		||||
{
 | 
			
		||||
@@ -327,13 +313,38 @@ meta_idle_monitor_xsync_init (MetaIdleMonitorXSync *monitor_xsync)
 | 
			
		||||
  monitor_xsync->alarms = g_hash_table_new (NULL, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
check_x11_watches (MetaIdleMonitor *monitor,
 | 
			
		||||
                   XSyncAlarm       alarm)
 | 
			
		||||
{
 | 
			
		||||
  GList *node, *watch_ids;
 | 
			
		||||
 | 
			
		||||
  /* we get the keys and do explicit look ups in case
 | 
			
		||||
   * an early iteration of the loop ends up leading
 | 
			
		||||
   * to watches from later iterations getting invalidated
 | 
			
		||||
   */
 | 
			
		||||
  watch_ids = g_hash_table_get_keys (monitor->watches);
 | 
			
		||||
 | 
			
		||||
  for (node = watch_ids; node != NULL; node = node->next)
 | 
			
		||||
    {
 | 
			
		||||
      guint watch_id = GPOINTER_TO_UINT (node->data);
 | 
			
		||||
      MetaIdleMonitorWatchXSync *watch;
 | 
			
		||||
 | 
			
		||||
      watch = g_hash_table_lookup (monitor->watches, GUINT_TO_POINTER (watch_id));
 | 
			
		||||
 | 
			
		||||
      if (watch && watch->xalarm == alarm)
 | 
			
		||||
        _meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_list_free (watch_ids);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor       *monitor,
 | 
			
		||||
                                       XSyncAlarmNotifyEvent *alarm_event)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
 | 
			
		||||
  XSyncAlarm alarm;
 | 
			
		||||
  GList *watches;
 | 
			
		||||
  gboolean has_alarm;
 | 
			
		||||
 | 
			
		||||
  if (alarm_event->state != XSyncAlarmActive)
 | 
			
		||||
@@ -358,10 +369,5 @@ meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor       *monitor,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (has_alarm)
 | 
			
		||||
    {
 | 
			
		||||
      watches = g_hash_table_get_values (monitor->watches);
 | 
			
		||||
 | 
			
		||||
      g_list_foreach (watches, check_x11_watch, (gpointer) alarm);
 | 
			
		||||
      g_list_free (watches);
 | 
			
		||||
    }
 | 
			
		||||
    check_x11_watches (monitor, alarm);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@
 | 
			
		||||
#include "meta-backend-x11.h"
 | 
			
		||||
#include "meta-input-settings-x11.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <gdk/gdkx.h>
 | 
			
		||||
#include <X11/Xatom.h>
 | 
			
		||||
#include <X11/extensions/XInput2.h>
 | 
			
		||||
@@ -35,6 +36,41 @@
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaInputSettingsX11, meta_input_settings_x11, META_TYPE_INPUT_SETTINGS)
 | 
			
		||||
 | 
			
		||||
static void *
 | 
			
		||||
get_property (ClutterInputDevice *device,
 | 
			
		||||
              const gchar        *property,
 | 
			
		||||
              Atom                type,
 | 
			
		||||
              int                 format,
 | 
			
		||||
              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 = NULL;
 | 
			
		||||
 | 
			
		||||
  property_atom = XInternAtom (xdisplay, property, True);
 | 
			
		||||
  if (!property_atom)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  device_id = clutter_input_device_get_device_id (device);
 | 
			
		||||
 | 
			
		||||
  rc = XIGetProperty (xdisplay, device_id, property_atom,
 | 
			
		||||
                      0, 10, False, type, &type_ret, &format_ret,
 | 
			
		||||
                      &nitems_ret, &bytes_after_ret, &data_ret);
 | 
			
		||||
  if (rc == Success && type_ret == type && format_ret == format && nitems_ret >= nitems)
 | 
			
		||||
    {
 | 
			
		||||
      if (nitems_ret > nitems)
 | 
			
		||||
        g_warning ("Property '%s' for device '%s' returned %lu items, expected %lu",
 | 
			
		||||
                   property, clutter_input_device_get_device_name (device), nitems_ret, nitems);
 | 
			
		||||
      return data_ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_XFree (data_ret);
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
change_property (ClutterInputDevice *device,
 | 
			
		||||
                 const gchar        *property,
 | 
			
		||||
@@ -45,23 +81,23 @@ change_property (ClutterInputDevice *device,
 | 
			
		||||
{
 | 
			
		||||
  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;
 | 
			
		||||
  int device_id;
 | 
			
		||||
  Atom property_atom;
 | 
			
		||||
  guchar *data_ret;
 | 
			
		||||
 | 
			
		||||
  property_atom = XInternAtom (xdisplay, property, False);
 | 
			
		||||
  property_atom = XInternAtom (xdisplay, property, True);
 | 
			
		||||
  if (!property_atom)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  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);
 | 
			
		||||
  data_ret = get_property (device, property, type, format, nitems);
 | 
			
		||||
  if (!data_ret)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  XIChangeProperty (xdisplay, device_id, property_atom, type,
 | 
			
		||||
                    format, XIPropModeReplace, data, nitems);
 | 
			
		||||
  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
 | 
			
		||||
@@ -70,6 +106,12 @@ meta_input_settings_x11_set_send_events (MetaInputSettings        *settings,
 | 
			
		||||
                                         GDesktopDeviceSendEvents  mode)
 | 
			
		||||
{
 | 
			
		||||
  guchar values[2] = { 0 }; /* disabled, disabled-on-external-mouse */
 | 
			
		||||
  guchar *available;
 | 
			
		||||
 | 
			
		||||
  available = get_property (device, "libinput Send Events Modes Available",
 | 
			
		||||
                            XA_INTEGER, 8, 2);
 | 
			
		||||
  if (!available)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  switch (mode)
 | 
			
		||||
    {
 | 
			
		||||
@@ -83,8 +125,14 @@ meta_input_settings_x11_set_send_events (MetaInputSettings        *settings,
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  change_property (device, "libinput Send Events Mode Enabled",
 | 
			
		||||
                   XA_INTEGER, 8, &values, 2);
 | 
			
		||||
  if ((values[0] && !available[0]) || (values[1] && !available[1]))
 | 
			
		||||
    g_warning ("Device '%s' does not support sendevents mode %d\n",
 | 
			
		||||
               clutter_input_device_get_device_name (device), mode);
 | 
			
		||||
  else
 | 
			
		||||
    change_property (device, "libinput Send Events Mode Enabled",
 | 
			
		||||
                     XA_INTEGER, 8, &values, 2);
 | 
			
		||||
 | 
			
		||||
  meta_XFree (available);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -151,28 +199,35 @@ meta_input_settings_x11_set_invert_scroll (MetaInputSettings  *settings,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_input_settings_x11_set_scroll_method (MetaInputSettings            *settings,
 | 
			
		||||
                                           ClutterInputDevice           *device,
 | 
			
		||||
                                           GDesktopTouchpadScrollMethod  mode)
 | 
			
		||||
meta_input_settings_x11_set_edge_scroll (MetaInputSettings            *settings,
 | 
			
		||||
                                         ClutterInputDevice           *device,
 | 
			
		||||
                                         gboolean                      edge_scroll_enabled)
 | 
			
		||||
{
 | 
			
		||||
  guchar values[3] = { 0 }; /* 2fg, edge, button. The last value is unused */
 | 
			
		||||
  guchar *available;
 | 
			
		||||
 | 
			
		||||
  switch (mode)
 | 
			
		||||
  available = get_property (device, "libinput Scroll Methods Available",
 | 
			
		||||
                            XA_INTEGER, 8, 3);
 | 
			
		||||
  if (!available)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (available[0])
 | 
			
		||||
    {
 | 
			
		||||
    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 ();
 | 
			
		||||
    }
 | 
			
		||||
  else if (available[1] && edge_scroll_enabled)
 | 
			
		||||
    {
 | 
			
		||||
      values[1] = 1;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      /* Disabled */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  change_property (device, "libinput Scroll Method Enabled",
 | 
			
		||||
                   XA_INTEGER, 8, &values, 3);
 | 
			
		||||
 | 
			
		||||
  meta_XFree (available);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -180,7 +235,7 @@ meta_input_settings_x11_set_scroll_button (MetaInputSettings  *settings,
 | 
			
		||||
                                           ClutterInputDevice *device,
 | 
			
		||||
                                           guint               button)
 | 
			
		||||
{
 | 
			
		||||
  change_property (device, "libinput Scroll Method Enabled",
 | 
			
		||||
  change_property (device, "libinput Button Scrolling Button",
 | 
			
		||||
                   XA_INTEGER, 32, &button, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -190,16 +245,28 @@ meta_input_settings_x11_set_click_method (MetaInputSettings           *settings,
 | 
			
		||||
                                          GDesktopTouchpadClickMethod  mode)
 | 
			
		||||
{
 | 
			
		||||
  guchar values[2] = { 0 }; /* buttonareas, clickfinger */
 | 
			
		||||
  guchar *defaults, *available;
 | 
			
		||||
 | 
			
		||||
  available = get_property (device, "libinput Click Methods Available",
 | 
			
		||||
                            XA_INTEGER, 8, 2);
 | 
			
		||||
  if (!available)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  switch (mode)
 | 
			
		||||
    {
 | 
			
		||||
    case G_DESKTOP_TOUCHPAD_CLICK_METHOD_DEFAULT:
 | 
			
		||||
      defaults = get_property (device, "libinput Click Method Enabled Default",
 | 
			
		||||
                               XA_INTEGER, 8, 2);
 | 
			
		||||
      if (!defaults)
 | 
			
		||||
        break;
 | 
			
		||||
      memcpy (values, defaults, 2);
 | 
			
		||||
      meta_XFree (defaults);
 | 
			
		||||
      break;
 | 
			
		||||
    case G_DESKTOP_TOUCHPAD_CLICK_METHOD_NONE:
 | 
			
		||||
      break;
 | 
			
		||||
    case G_DESKTOP_TOUCHPAD_CLICK_METHOD_AREAS:
 | 
			
		||||
      values[0] = 1;
 | 
			
		||||
      break;
 | 
			
		||||
    case G_DESKTOP_TOUCHPAD_CLICK_METHOD_DEFAULT:
 | 
			
		||||
      /* XXX: We can't be much smarter yet, x11 doesn't expose default settings */
 | 
			
		||||
    case G_DESKTOP_TOUCHPAD_CLICK_METHOD_FINGERS:
 | 
			
		||||
      values[1] = 1;
 | 
			
		||||
      break;
 | 
			
		||||
@@ -208,8 +275,14 @@ meta_input_settings_x11_set_click_method (MetaInputSettings           *settings,
 | 
			
		||||
      return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  change_property (device, "libinput Click Method Enabled",
 | 
			
		||||
                   XA_INTEGER, 8, &values, 2);
 | 
			
		||||
  if ((values[0] && !available[0]) || (values[1] && !available[1]))
 | 
			
		||||
    g_warning ("Device '%s' does not support click method %d\n",
 | 
			
		||||
               clutter_input_device_get_device_name (device), mode);
 | 
			
		||||
  else
 | 
			
		||||
    change_property (device, "libinput Click Method Enabled",
 | 
			
		||||
                     XA_INTEGER, 8, &values, 2);
 | 
			
		||||
 | 
			
		||||
  meta_XFree(available);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -243,7 +316,7 @@ meta_input_settings_x11_class_init (MetaInputSettingsX11Class *klass)
 | 
			
		||||
  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_edge_scroll = meta_input_settings_x11_set_edge_scroll;
 | 
			
		||||
  input_settings_class->set_scroll_button = meta_input_settings_x11_set_scroll_button;
 | 
			
		||||
  input_settings_class->set_click_method = meta_input_settings_x11_set_click_method;
 | 
			
		||||
  input_settings_class->set_keyboard_repeat = meta_input_settings_x11_set_keyboard_repeat;
 | 
			
		||||
 
 | 
			
		||||
@@ -58,6 +58,7 @@ struct _MetaMonitorManagerXrandr
 | 
			
		||||
  XRRScreenResources *resources;
 | 
			
		||||
  int rr_event_base;
 | 
			
		||||
  int rr_error_base;
 | 
			
		||||
  gboolean has_randr15;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaMonitorManagerXrandrClass
 | 
			
		||||
@@ -194,11 +195,10 @@ static gboolean
 | 
			
		||||
output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                             MetaOutput *output, const char *propname)
 | 
			
		||||
{
 | 
			
		||||
  gboolean value = FALSE;
 | 
			
		||||
  Atom atom, actual_type;
 | 
			
		||||
  int actual_format;
 | 
			
		||||
  unsigned long nitems, bytes_after;
 | 
			
		||||
  unsigned char *buffer;
 | 
			
		||||
  g_autofree unsigned char *buffer = NULL;
 | 
			
		||||
 | 
			
		||||
  atom = XInternAtom (manager_xrandr->xdisplay, propname, False);
 | 
			
		||||
  XRRGetOutputProperty (manager_xrandr->xdisplay,
 | 
			
		||||
@@ -209,13 +209,9 @@ output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                        &nitems, &bytes_after, &buffer);
 | 
			
		||||
 | 
			
		||||
  if (actual_type != XA_CARDINAL || actual_format != 32 || nitems < 1)
 | 
			
		||||
    goto out;
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  value = ((int*)buffer)[0];
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  XFree (buffer);
 | 
			
		||||
  return value;
 | 
			
		||||
  return ((int*)buffer)[0];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
@@ -225,6 +221,76 @@ output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
  return output_get_boolean_property (manager_xrandr, output, "_MUTTER_PRESENTATION_OUTPUT");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
output_get_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                                 MetaOutput               *output)
 | 
			
		||||
{
 | 
			
		||||
  Atom atom, actual_type;
 | 
			
		||||
  int actual_format;
 | 
			
		||||
  unsigned long nitems, bytes_after;
 | 
			
		||||
  g_autofree unsigned char *buffer = NULL;
 | 
			
		||||
  g_autofree char *str = NULL;
 | 
			
		||||
 | 
			
		||||
  atom = XInternAtom (manager_xrandr->xdisplay, "underscan", 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)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  str = XGetAtomName (manager_xrandr->xdisplay, *(Atom *)buffer);
 | 
			
		||||
  return (strcmp (str, "on") == 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
output_get_supports_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                                          MetaOutput               *output)
 | 
			
		||||
{
 | 
			
		||||
  Atom atom, actual_type;
 | 
			
		||||
  int actual_format, i;
 | 
			
		||||
  unsigned long nitems, bytes_after;
 | 
			
		||||
  g_autofree unsigned char *buffer = NULL;
 | 
			
		||||
  XRRPropertyInfo *property_info;
 | 
			
		||||
  Atom *values;
 | 
			
		||||
  gboolean supports_underscanning = FALSE;
 | 
			
		||||
 | 
			
		||||
  atom = XInternAtom (manager_xrandr->xdisplay, "underscan", 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)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  property_info = XRRQueryOutputProperty (manager_xrandr->xdisplay,
 | 
			
		||||
                                          (XID) output->winsys_id,
 | 
			
		||||
                                          atom);
 | 
			
		||||
  values = (Atom *) property_info->values;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < property_info->num_values; i++)
 | 
			
		||||
    {
 | 
			
		||||
      /* The output supports underscanning if "on" is a valid value
 | 
			
		||||
       * for the underscan property.
 | 
			
		||||
       */
 | 
			
		||||
      char *name = XGetAtomName (manager_xrandr->xdisplay, values[i]);
 | 
			
		||||
      if (strcmp (name, "on") == 0)
 | 
			
		||||
        supports_underscanning = TRUE;
 | 
			
		||||
 | 
			
		||||
      XFree (name);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  XFree (property_info);
 | 
			
		||||
 | 
			
		||||
  return supports_underscanning;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
normalize_backlight (MetaOutput *output,
 | 
			
		||||
                     int         hw_value)
 | 
			
		||||
@@ -241,7 +307,7 @@ output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
  Atom atom, actual_type;
 | 
			
		||||
  int actual_format;
 | 
			
		||||
  unsigned long nitems, bytes_after;
 | 
			
		||||
  unsigned char *buffer;
 | 
			
		||||
  g_autofree unsigned char *buffer = NULL;
 | 
			
		||||
 | 
			
		||||
  atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
 | 
			
		||||
  XRRGetOutputProperty (manager_xrandr->xdisplay,
 | 
			
		||||
@@ -252,12 +318,9 @@ output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                        &nitems, &bytes_after, &buffer);
 | 
			
		||||
 | 
			
		||||
  if (actual_type != XA_INTEGER || actual_format != 32 || nitems < 1)
 | 
			
		||||
    goto out;
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  value = ((int*)buffer)[0];
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  XFree (buffer);
 | 
			
		||||
  if (value > 0)
 | 
			
		||||
    return normalize_backlight (output, value);
 | 
			
		||||
  else
 | 
			
		||||
@@ -270,7 +333,7 @@ output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
{
 | 
			
		||||
  Atom atom;
 | 
			
		||||
  xcb_connection_t *xcb_conn;
 | 
			
		||||
  xcb_randr_query_output_property_reply_t *reply;
 | 
			
		||||
  g_autofree xcb_randr_query_output_property_reply_t *reply;
 | 
			
		||||
 | 
			
		||||
  atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
 | 
			
		||||
 | 
			
		||||
@@ -288,15 +351,12 @@ output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
  if (!reply->range || reply->length != 2)
 | 
			
		||||
    {
 | 
			
		||||
      meta_verbose ("backlight %s was not range\n", output->name);
 | 
			
		||||
      goto out;
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  int32_t *values = xcb_randr_query_output_property_valid_values (reply);
 | 
			
		||||
  output->backlight_min = values[0];
 | 
			
		||||
  output->backlight_max = values[1];
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
  free (reply);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
@@ -359,12 +419,6 @@ read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
      result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!result)
 | 
			
		||||
    {
 | 
			
		||||
      edid_atom = XInternAtom (manager_xrandr->xdisplay, "XFree86_DDC_EDID1_RAWDATA", FALSE);
 | 
			
		||||
      result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (result)
 | 
			
		||||
    {
 | 
			
		||||
      if (len > 0 && len % 128 == 0)
 | 
			
		||||
@@ -376,6 +430,42 @@ read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
output_get_tile_info (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                      MetaOutput *output)
 | 
			
		||||
{
 | 
			
		||||
  Atom tile_atom;
 | 
			
		||||
  unsigned char *prop;
 | 
			
		||||
  unsigned long nitems, bytes_after;
 | 
			
		||||
  int actual_format;
 | 
			
		||||
  Atom actual_type;
 | 
			
		||||
 | 
			
		||||
  if (manager_xrandr->has_randr15 == FALSE)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  tile_atom = XInternAtom (manager_xrandr->xdisplay, "TILE", FALSE);
 | 
			
		||||
  XRRGetOutputProperty (manager_xrandr->xdisplay,
 | 
			
		||||
                        output->winsys_id,
 | 
			
		||||
                        tile_atom, 0, 100, False,
 | 
			
		||||
                        False, AnyPropertyType,
 | 
			
		||||
                        &actual_type, &actual_format,
 | 
			
		||||
                        &nitems, &bytes_after, &prop);
 | 
			
		||||
 | 
			
		||||
  if (actual_type == XA_INTEGER && actual_format == 32 && nitems == 8)
 | 
			
		||||
    {
 | 
			
		||||
      long *values = (long *)prop;
 | 
			
		||||
      output->tile_info.group_id = values[0];
 | 
			
		||||
      output->tile_info.flags = values[1];
 | 
			
		||||
      output->tile_info.max_h_tiles = values[2];
 | 
			
		||||
      output->tile_info.max_v_tiles = values[3];
 | 
			
		||||
      output->tile_info.loc_h_tile = values[4];
 | 
			
		||||
      output->tile_info.loc_v_tile = values[5];
 | 
			
		||||
      output->tile_info.tile_w = values[6];
 | 
			
		||||
      output->tile_info.tile_h = values[7];
 | 
			
		||||
    }
 | 
			
		||||
  XFree (prop);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                                MetaOutput               *output)
 | 
			
		||||
@@ -447,11 +537,10 @@ 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;
 | 
			
		||||
  g_autofree unsigned char *buffer = NULL;
 | 
			
		||||
 | 
			
		||||
  atom = XInternAtom (manager_xrandr->xdisplay, "ConnectorType", False);
 | 
			
		||||
  XRRGetOutputProperty (manager_xrandr->xdisplay,
 | 
			
		||||
@@ -462,14 +551,10 @@ output_get_connector_type_from_prop (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                        &nitems, &bytes_after, &buffer);
 | 
			
		||||
 | 
			
		||||
  if (actual_type != XA_ATOM || actual_format != 32 || nitems < 1)
 | 
			
		||||
    goto out;
 | 
			
		||||
    return META_CONNECTOR_TYPE_Unknown;
 | 
			
		||||
 | 
			
		||||
  connector_type_atom = ((Atom *) buffer)[0];
 | 
			
		||||
  ret = connector_type_from_atom (manager_xrandr, connector_type_atom);
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  meta_XFree (buffer);
 | 
			
		||||
  return ret;
 | 
			
		||||
  return connector_type_from_atom (manager_xrandr, connector_type_atom);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaConnectorType
 | 
			
		||||
@@ -506,7 +591,7 @@ output_get_connector_type_from_name (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
  if (g_str_has_prefix (name, "Virtual"))
 | 
			
		||||
    return META_CONNECTOR_TYPE_VIRTUAL;
 | 
			
		||||
  if (g_str_has_prefix (name, "Composite"))
 | 
			
		||||
    return META_CONNECTOR_TYPE_VGA;
 | 
			
		||||
    return META_CONNECTOR_TYPE_Composite;
 | 
			
		||||
  if (g_str_has_prefix (name, "S-video"))
 | 
			
		||||
    return META_CONNECTOR_TYPE_SVIDEO;
 | 
			
		||||
  if (g_str_has_prefix (name, "TV"))
 | 
			
		||||
@@ -546,6 +631,70 @@ output_get_connector_type (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
  return META_CONNECTOR_TYPE_Unknown;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
output_get_modes (MetaMonitorManager *manager,
 | 
			
		||||
                  MetaOutput         *meta_output,
 | 
			
		||||
                  XRROutputInfo      *output)
 | 
			
		||||
{
 | 
			
		||||
  guint j, k;
 | 
			
		||||
  guint n_actual_modes;
 | 
			
		||||
 | 
			
		||||
  meta_output->modes = g_new0 (MetaMonitorMode *, output->nmode);
 | 
			
		||||
 | 
			
		||||
  n_actual_modes = 0;
 | 
			
		||||
  for (j = 0; j < (guint)output->nmode; j++)
 | 
			
		||||
    {
 | 
			
		||||
      for (k = 0; k < manager->n_modes; k++)
 | 
			
		||||
        {
 | 
			
		||||
          if (output->modes[j] == (XID)manager->modes[k].mode_id)
 | 
			
		||||
            {
 | 
			
		||||
              meta_output->modes[n_actual_modes] = &manager->modes[k];
 | 
			
		||||
              n_actual_modes += 1;
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  meta_output->n_modes = n_actual_modes;
 | 
			
		||||
  if (n_actual_modes > 0)
 | 
			
		||||
    meta_output->preferred_mode = meta_output->modes[0];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
output_get_crtcs (MetaMonitorManager *manager,
 | 
			
		||||
                  MetaOutput         *meta_output,
 | 
			
		||||
                  XRROutputInfo      *output)
 | 
			
		||||
{
 | 
			
		||||
  guint j, k;
 | 
			
		||||
  guint n_actual_crtcs;
 | 
			
		||||
 | 
			
		||||
  meta_output->possible_crtcs = g_new0 (MetaCRTC *, output->ncrtc);
 | 
			
		||||
 | 
			
		||||
  n_actual_crtcs = 0;
 | 
			
		||||
  for (j = 0; j < (unsigned)output->ncrtc; j++)
 | 
			
		||||
    {
 | 
			
		||||
      for (k = 0; k < manager->n_crtcs; k++)
 | 
			
		||||
        {
 | 
			
		||||
          if ((XID)manager->crtcs[k].crtc_id == output->crtcs[j])
 | 
			
		||||
            {
 | 
			
		||||
              meta_output->possible_crtcs[n_actual_crtcs] = &manager->crtcs[k];
 | 
			
		||||
              n_actual_crtcs += 1;
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  meta_output->n_possible_crtcs = n_actual_crtcs;
 | 
			
		||||
 | 
			
		||||
  meta_output->crtc = NULL;
 | 
			
		||||
  for (j = 0; j < manager->n_crtcs; j++)
 | 
			
		||||
    {
 | 
			
		||||
      if ((XID)manager->crtcs[j].crtc_id == output->crtc)
 | 
			
		||||
        {
 | 
			
		||||
          meta_output->crtc = &manager->crtcs[j];
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *
 | 
			
		||||
get_xmode_name (XRRModeInfo *xmode)
 | 
			
		||||
{
 | 
			
		||||
@@ -682,6 +831,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
 | 
			
		||||
      MetaOutput *meta_output;
 | 
			
		||||
 | 
			
		||||
      output = XRRGetOutputInfo (manager_xrandr->xdisplay, resources, resources->outputs[i]);
 | 
			
		||||
      if (!output)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      meta_output = &manager->outputs[n_actual_outputs];
 | 
			
		||||
 | 
			
		||||
@@ -704,44 +855,9 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
 | 
			
		||||
	  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);
 | 
			
		||||
	  for (j = 0; j < meta_output->n_modes; j++)
 | 
			
		||||
	    {
 | 
			
		||||
	      for (k = 0; k < manager->n_modes; k++)
 | 
			
		||||
		{
 | 
			
		||||
		  if (output->modes[j] == (XID)manager->modes[k].mode_id)
 | 
			
		||||
		    {
 | 
			
		||||
		      meta_output->modes[j] = &manager->modes[k];
 | 
			
		||||
		      break;
 | 
			
		||||
		    }
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
	  meta_output->preferred_mode = meta_output->modes[0];
 | 
			
		||||
 | 
			
		||||
	  meta_output->n_possible_crtcs = output->ncrtc;
 | 
			
		||||
	  meta_output->possible_crtcs = g_new0 (MetaCRTC *, meta_output->n_possible_crtcs);
 | 
			
		||||
	  for (j = 0; j < (unsigned)output->ncrtc; j++)
 | 
			
		||||
	    {
 | 
			
		||||
	      for (k = 0; k < manager->n_crtcs; k++)
 | 
			
		||||
		{
 | 
			
		||||
		  if ((XID)manager->crtcs[k].crtc_id == output->crtcs[j])
 | 
			
		||||
		    {
 | 
			
		||||
		      meta_output->possible_crtcs[j] = &manager->crtcs[k];
 | 
			
		||||
		      break;
 | 
			
		||||
		    }
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	  meta_output->crtc = NULL;
 | 
			
		||||
	  for (j = 0; j < manager->n_crtcs; j++)
 | 
			
		||||
	    {
 | 
			
		||||
	      if ((XID)manager->crtcs[j].crtc_id == output->crtc)
 | 
			
		||||
		{
 | 
			
		||||
		  meta_output->crtc = &manager->crtcs[j];
 | 
			
		||||
		  break;
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
	  output_get_tile_info (manager_xrandr, meta_output);
 | 
			
		||||
	  output_get_modes (manager, meta_output, output);
 | 
			
		||||
          output_get_crtcs (manager, meta_output, output);
 | 
			
		||||
 | 
			
		||||
	  meta_output->n_possible_clones = output->nclone;
 | 
			
		||||
	  meta_output->possible_clones = g_new0 (MetaOutput *, meta_output->n_possible_clones);
 | 
			
		||||
@@ -756,6 +872,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
 | 
			
		||||
 | 
			
		||||
	  meta_output->is_primary = ((XID)meta_output->winsys_id == primary_output);
 | 
			
		||||
	  meta_output->is_presentation = output_get_presentation_xrandr (manager_xrandr, meta_output);
 | 
			
		||||
	  meta_output->is_underscanning = output_get_underscanning_xrandr (manager_xrandr, meta_output);
 | 
			
		||||
          meta_output->supports_underscanning = output_get_supports_underscanning_xrandr (manager_xrandr, meta_output);
 | 
			
		||||
	  output_get_backlight_limits_xrandr (manager_xrandr, meta_output);
 | 
			
		||||
 | 
			
		||||
	  if (!(meta_output->backlight_min == 0 && meta_output->backlight_max == 0))
 | 
			
		||||
@@ -763,7 +881,10 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
 | 
			
		||||
	  else
 | 
			
		||||
	    meta_output->backlight = -1;
 | 
			
		||||
 | 
			
		||||
	  n_actual_outputs++;
 | 
			
		||||
          if (meta_output->n_modes == 0 || meta_output->n_possible_crtcs == 0)
 | 
			
		||||
            meta_monitor_manager_clear_output (meta_output);
 | 
			
		||||
          else
 | 
			
		||||
            n_actual_outputs++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
      XRRFreeOutputInfo (output);
 | 
			
		||||
@@ -869,11 +990,58 @@ output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
  int value = presentation;
 | 
			
		||||
 | 
			
		||||
  atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
 | 
			
		||||
  XRRChangeOutputProperty (manager_xrandr->xdisplay,
 | 
			
		||||
                           (XID)output->winsys_id,
 | 
			
		||||
                           atom,
 | 
			
		||||
                           XA_CARDINAL, 32, PropModeReplace,
 | 
			
		||||
                           (unsigned char*) &value, 1);
 | 
			
		||||
 | 
			
		||||
  xcb_randr_change_output_property (XGetXCBConnection (manager_xrandr->xdisplay),
 | 
			
		||||
                                    (XID)output->winsys_id,
 | 
			
		||||
                                    atom, XCB_ATOM_CARDINAL, 32,
 | 
			
		||||
                                    XCB_PROP_MODE_REPLACE,
 | 
			
		||||
                                    1, &value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
output_set_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                                 MetaOutput               *output,
 | 
			
		||||
                                 gboolean                  underscanning)
 | 
			
		||||
{
 | 
			
		||||
  Atom prop, valueatom;
 | 
			
		||||
  const char *value;
 | 
			
		||||
 | 
			
		||||
  prop = XInternAtom (manager_xrandr->xdisplay, "underscan", False);
 | 
			
		||||
 | 
			
		||||
  value = underscanning ? "on" : "off";
 | 
			
		||||
  valueatom = XInternAtom (manager_xrandr->xdisplay, value, False);
 | 
			
		||||
 | 
			
		||||
  xcb_randr_change_output_property (XGetXCBConnection (manager_xrandr->xdisplay),
 | 
			
		||||
                                    (XID)output->winsys_id,
 | 
			
		||||
                                    prop, XCB_ATOM_ATOM, 32,
 | 
			
		||||
                                    XCB_PROP_MODE_REPLACE,
 | 
			
		||||
                                    1, &valueatom);
 | 
			
		||||
 | 
			
		||||
  /* Configure the border at the same time. Currently, we use a
 | 
			
		||||
   * 5% of the width/height of the mode. In the future, we should
 | 
			
		||||
   * make the border configurable. */
 | 
			
		||||
  if (underscanning)
 | 
			
		||||
    {
 | 
			
		||||
      uint32_t border_value;
 | 
			
		||||
 | 
			
		||||
      prop = XInternAtom (manager_xrandr->xdisplay, "underscan hborder", False);
 | 
			
		||||
      border_value = output->crtc->current_mode->width * 0.05;
 | 
			
		||||
 | 
			
		||||
      xcb_randr_change_output_property (XGetXCBConnection (manager_xrandr->xdisplay),
 | 
			
		||||
                                        (XID)output->winsys_id,
 | 
			
		||||
                                        prop, XCB_ATOM_INTEGER, 32,
 | 
			
		||||
                                        XCB_PROP_MODE_REPLACE,
 | 
			
		||||
                                        1, &border_value);
 | 
			
		||||
 | 
			
		||||
      prop = XInternAtom (manager_xrandr->xdisplay, "underscan vborder", False);
 | 
			
		||||
      border_value = output->crtc->current_mode->height * 0.05;
 | 
			
		||||
 | 
			
		||||
      xcb_randr_change_output_property (XGetXCBConnection (manager_xrandr->xdisplay),
 | 
			
		||||
                                        (XID)output->winsys_id,
 | 
			
		||||
                                        prop, XCB_ATOM_INTEGER, 32,
 | 
			
		||||
                                        XCB_PROP_MODE_REPLACE,
 | 
			
		||||
                                        1, &border_value);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -992,17 +1160,16 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
 | 
			
		||||
      if (crtc_info->mode != NULL)
 | 
			
		||||
        {
 | 
			
		||||
          MetaMonitorMode *mode;
 | 
			
		||||
          XID *outputs;
 | 
			
		||||
          unsigned int j, n_outputs;
 | 
			
		||||
          int width, height;
 | 
			
		||||
          g_autofree XID *output_ids = NULL;
 | 
			
		||||
          unsigned int j, n_output_ids;
 | 
			
		||||
          Status ok;
 | 
			
		||||
 | 
			
		||||
          mode = crtc_info->mode;
 | 
			
		||||
 | 
			
		||||
          n_outputs = crtc_info->outputs->len;
 | 
			
		||||
          outputs = g_new (XID, n_outputs);
 | 
			
		||||
          n_output_ids = crtc_info->outputs->len;
 | 
			
		||||
          output_ids = g_new (XID, n_output_ids);
 | 
			
		||||
 | 
			
		||||
          for (j = 0; j < n_outputs; j++)
 | 
			
		||||
          for (j = 0; j < n_output_ids; j++)
 | 
			
		||||
            {
 | 
			
		||||
              MetaOutput *output;
 | 
			
		||||
 | 
			
		||||
@@ -1011,7 +1178,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
 | 
			
		||||
              output->is_dirty = TRUE;
 | 
			
		||||
              output->crtc = crtc;
 | 
			
		||||
 | 
			
		||||
              outputs[j] = output->winsys_id;
 | 
			
		||||
              output_ids[j] = output->winsys_id;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
 | 
			
		||||
@@ -1021,7 +1188,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
 | 
			
		||||
                                 crtc_info->x, crtc_info->y,
 | 
			
		||||
                                 (XID)mode->mode_id,
 | 
			
		||||
                                 meta_monitor_transform_to_xrandr (crtc_info->transform),
 | 
			
		||||
                                 outputs, n_outputs);
 | 
			
		||||
                                 output_ids, n_output_ids);
 | 
			
		||||
 | 
			
		||||
          if (ok != Success)
 | 
			
		||||
            {
 | 
			
		||||
@@ -1029,7 +1196,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
 | 
			
		||||
                            (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);
 | 
			
		||||
              goto next;
 | 
			
		||||
              continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          if (meta_monitor_transform_is_rotated (crtc_info->transform))
 | 
			
		||||
@@ -1049,9 +1216,6 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
 | 
			
		||||
          crtc->rect.height = height;
 | 
			
		||||
          crtc->current_mode = mode;
 | 
			
		||||
          crtc->transform = crtc_info->transform;
 | 
			
		||||
 | 
			
		||||
        next:
 | 
			
		||||
          g_free (outputs);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1071,8 +1235,14 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
 | 
			
		||||
                                      output_info->output,
 | 
			
		||||
                                      output_info->is_presentation);
 | 
			
		||||
 | 
			
		||||
      if (output_get_supports_underscanning_xrandr (manager_xrandr, output_info->output))
 | 
			
		||||
        output_set_underscanning_xrandr (manager_xrandr,
 | 
			
		||||
                                         output_info->output,
 | 
			
		||||
                                         output_info->is_underscanning);
 | 
			
		||||
 | 
			
		||||
      output->is_primary = output_info->is_primary;
 | 
			
		||||
      output->is_presentation = output_info->is_presentation;
 | 
			
		||||
      output->is_underscanning = output_info->is_underscanning;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* Disable outputs not mentioned in the list */
 | 
			
		||||
@@ -1106,11 +1276,12 @@ meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
 | 
			
		||||
  hw_value = round ((double)value / 100.0 * output->backlight_max + output->backlight_min);
 | 
			
		||||
 | 
			
		||||
  atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
 | 
			
		||||
  XRRChangeOutputProperty (manager_xrandr->xdisplay,
 | 
			
		||||
                           (XID)output->winsys_id,
 | 
			
		||||
                           atom,
 | 
			
		||||
                           XA_INTEGER, 32, PropModeReplace,
 | 
			
		||||
                           (unsigned char *) &hw_value, 1);
 | 
			
		||||
 | 
			
		||||
  xcb_randr_change_output_property (XGetXCBConnection (manager_xrandr->xdisplay),
 | 
			
		||||
                                    (XID)output->winsys_id,
 | 
			
		||||
                                    atom, XCB_ATOM_INTEGER, 32,
 | 
			
		||||
                                    XCB_PROP_MODE_REPLACE,
 | 
			
		||||
                                    1, &hw_value);
 | 
			
		||||
 | 
			
		||||
  /* We're not selecting for property notifies, so update the value immediately */
 | 
			
		||||
  output->backlight = normalize_backlight (output, hw_value);
 | 
			
		||||
@@ -1158,6 +1329,88 @@ meta_monitor_manager_xrandr_set_crtc_gamma (MetaMonitorManager *manager,
 | 
			
		||||
  XRRFreeGamma (gamma);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_XRANDR15
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_xrandr_add_monitor(MetaMonitorManager *manager,
 | 
			
		||||
                                        MetaMonitorInfo *monitor)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
 | 
			
		||||
  XRRMonitorInfo *m;
 | 
			
		||||
  int o;
 | 
			
		||||
  Atom name;
 | 
			
		||||
  char name_buf[40];
 | 
			
		||||
 | 
			
		||||
  if (manager_xrandr->has_randr15 == FALSE)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (monitor->n_outputs <= 1)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (monitor->outputs[0]->product)
 | 
			
		||||
    snprintf (name_buf, 40, "%s-%d", monitor->outputs[0]->product, monitor->outputs[0]->tile_info.group_id);
 | 
			
		||||
  else
 | 
			
		||||
    snprintf (name_buf, 40, "Tiled-%d", monitor->outputs[0]->tile_info.group_id);
 | 
			
		||||
 | 
			
		||||
  name = XInternAtom (manager_xrandr->xdisplay, name_buf, False);
 | 
			
		||||
  monitor->monitor_winsys_xid = name;
 | 
			
		||||
  m = XRRAllocateMonitor (manager_xrandr->xdisplay, monitor->n_outputs);
 | 
			
		||||
  if (!m)
 | 
			
		||||
    return;
 | 
			
		||||
  m->name = name;
 | 
			
		||||
  m->primary = monitor->is_primary;
 | 
			
		||||
  m->automatic = True;
 | 
			
		||||
 | 
			
		||||
  for (o = 0; o < monitor->n_outputs; o++) {
 | 
			
		||||
    MetaOutput *output = monitor->outputs[o];
 | 
			
		||||
    m->outputs[o] = output->winsys_id;
 | 
			
		||||
  }
 | 
			
		||||
  XRRSetMonitor (manager_xrandr->xdisplay,
 | 
			
		||||
                 DefaultRootWindow (manager_xrandr->xdisplay),
 | 
			
		||||
                 m);
 | 
			
		||||
  XRRFreeMonitors (m);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_xrandr_delete_monitor(MetaMonitorManager *manager,
 | 
			
		||||
                                           int monitor_winsys_xid)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
 | 
			
		||||
 | 
			
		||||
  if (manager_xrandr->has_randr15 == FALSE)
 | 
			
		||||
    return;
 | 
			
		||||
  XRRDeleteMonitor (manager_xrandr->xdisplay,
 | 
			
		||||
                    DefaultRootWindow (manager_xrandr->xdisplay),
 | 
			
		||||
                    monitor_winsys_xid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_xrandr_init_monitors(MetaMonitorManagerXrandr *manager_xrandr)
 | 
			
		||||
{
 | 
			
		||||
  XRRMonitorInfo *m;
 | 
			
		||||
  int n, i;
 | 
			
		||||
 | 
			
		||||
  if (manager_xrandr->has_randr15 == FALSE)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  /* delete any tiled monitors setup, as mutter will want to recreate
 | 
			
		||||
     things in its image */
 | 
			
		||||
  m = XRRGetMonitors (manager_xrandr->xdisplay,
 | 
			
		||||
                      DefaultRootWindow (manager_xrandr->xdisplay),
 | 
			
		||||
                      FALSE, &n);
 | 
			
		||||
  if (n == -1)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n; i++)
 | 
			
		||||
    {
 | 
			
		||||
      if (m[i].noutput > 1)
 | 
			
		||||
        XRRDeleteMonitor (manager_xrandr->xdisplay,
 | 
			
		||||
                          DefaultRootWindow (manager_xrandr->xdisplay),
 | 
			
		||||
                          m[i].name);
 | 
			
		||||
    }
 | 
			
		||||
  XRRFreeMonitors (m);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
 | 
			
		||||
{
 | 
			
		||||
@@ -1173,6 +1426,7 @@ meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      int major_version, minor_version;
 | 
			
		||||
      /* We only use ScreenChangeNotify, but GDK uses the others,
 | 
			
		||||
	 and we don't want to step on its toes */
 | 
			
		||||
      XRRSelectInput (manager_xrandr->xdisplay,
 | 
			
		||||
@@ -1180,6 +1434,17 @@ meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
 | 
			
		||||
		      RRScreenChangeNotifyMask
 | 
			
		||||
		      | RRCrtcChangeNotifyMask
 | 
			
		||||
		      | RROutputPropertyNotifyMask);
 | 
			
		||||
 | 
			
		||||
      manager_xrandr->has_randr15 = FALSE;
 | 
			
		||||
      XRRQueryVersion (manager_xrandr->xdisplay, &major_version,
 | 
			
		||||
                       &minor_version);
 | 
			
		||||
#ifdef HAVE_XRANDR15
 | 
			
		||||
      if (major_version > 1 ||
 | 
			
		||||
          (major_version == 1 &&
 | 
			
		||||
           minor_version >= 5))
 | 
			
		||||
        manager_xrandr->has_randr15 = TRUE;
 | 
			
		||||
      meta_monitor_manager_xrandr_init_monitors (manager_xrandr);
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1210,6 +1475,10 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
 | 
			
		||||
  manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight;
 | 
			
		||||
  manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma;
 | 
			
		||||
  manager_class->set_crtc_gamma = meta_monitor_manager_xrandr_set_crtc_gamma;
 | 
			
		||||
#ifdef HAVE_XRANDR15
 | 
			
		||||
  manager_class->add_monitor = meta_monitor_manager_xrandr_add_monitor;
 | 
			
		||||
  manager_class->delete_monitor = meta_monitor_manager_xrandr_delete_monitor;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										89
									
								
								src/backends/x11/nested/meta-cursor-renderer-x11-nested.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/backends/x11/nested/meta-cursor-renderer-x11-nested.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,89 @@
 | 
			
		||||
/* -*- 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>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "backends/x11/nested/meta-cursor-renderer-x11-nested.h"
 | 
			
		||||
 | 
			
		||||
#include "backends/x11/meta-backend-x11.h"
 | 
			
		||||
 | 
			
		||||
struct _MetaCursorRendererX11Nested
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRenderer parent;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaCursorRendererX11Nested, meta_cursor_renderer_x11_nested,
 | 
			
		||||
               META_TYPE_CURSOR_RENDERER);
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_cursor_renderer_x11_nested_update_cursor (MetaCursorRenderer *renderer,
 | 
			
		||||
                                               MetaCursorSprite   *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  if (cursor_sprite)
 | 
			
		||||
    meta_cursor_sprite_realize_texture (cursor_sprite);
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Cursor
 | 
			
		||||
create_empty_cursor (Display *xdisplay)
 | 
			
		||||
{
 | 
			
		||||
  XcursorImage *image;
 | 
			
		||||
  XcursorPixel *pixels;
 | 
			
		||||
  Cursor xcursor;
 | 
			
		||||
 | 
			
		||||
  image = XcursorImageCreate (1, 1);
 | 
			
		||||
  if (image == NULL)
 | 
			
		||||
    return None;
 | 
			
		||||
 | 
			
		||||
  image->xhot = 0;
 | 
			
		||||
  image->yhot = 0;
 | 
			
		||||
 | 
			
		||||
  pixels = image->pixels;
 | 
			
		||||
  pixels[0] = 0;
 | 
			
		||||
 | 
			
		||||
  xcursor = XcursorImageLoadCursor (xdisplay, image);
 | 
			
		||||
  XcursorImageDestroy (image);
 | 
			
		||||
 | 
			
		||||
  return xcursor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_cursor_renderer_x11_nested_init (MetaCursorRendererX11Nested *x11_nested)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
 | 
			
		||||
  Window xwindow = meta_backend_x11_get_xwindow (backend);
 | 
			
		||||
  Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
 | 
			
		||||
 | 
			
		||||
  Cursor empty_xcursor = create_empty_cursor (xdisplay);
 | 
			
		||||
  XDefineCursor (xdisplay, xwindow, empty_xcursor);
 | 
			
		||||
  XFreeCursor (xdisplay, empty_xcursor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_cursor_renderer_x11_nested_class_init (MetaCursorRendererX11NestedClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  renderer_class->update_cursor = meta_cursor_renderer_x11_nested_update_cursor;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								src/backends/x11/nested/meta-cursor-renderer-x11-nested.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/backends/x11/nested/meta-cursor-renderer-x11-nested.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
/* -*- 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_CURSOR_RENDERER_X11_NESTED_NESTED_H
 | 
			
		||||
#define META_CURSOR_RENDERER_X11_NESTED_NESTED_H
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
 | 
			
		||||
#include "backends/meta-cursor-renderer.h"
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_CURSOR_RENDERER_X11_NESTED (meta_cursor_renderer_x11_nested_get_type ())
 | 
			
		||||
G_DECLARE_FINAL_TYPE (MetaCursorRendererX11Nested,
 | 
			
		||||
                      meta_cursor_renderer_x11_nested,
 | 
			
		||||
                      META, CURSOR_RENDERER_X11_NESTED,
 | 
			
		||||
                      MetaCursorRenderer);
 | 
			
		||||
 | 
			
		||||
#endif /* META_CURSOR_RENDERER_X11_NESTED_NESTED_H */
 | 
			
		||||
@@ -15,7 +15,8 @@ struct _MetaCompositor
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay    *display;
 | 
			
		||||
 | 
			
		||||
  guint           repaint_func_id;
 | 
			
		||||
  guint           pre_paint_func_id;
 | 
			
		||||
  guint           post_paint_func_id;
 | 
			
		||||
 | 
			
		||||
  gint64          server_time_query_time;
 | 
			
		||||
  gint64          server_time_offset;
 | 
			
		||||
@@ -40,6 +41,7 @@ struct _MetaCompositor
 | 
			
		||||
  MetaPluginManager *plugin_mgr;
 | 
			
		||||
 | 
			
		||||
  gboolean frame_has_updated_xsurfaces;
 | 
			
		||||
  gboolean have_x11_sync_object;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Wait 2ms after vblank before starting to draw next frame */
 | 
			
		||||
 
 | 
			
		||||
@@ -37,11 +37,6 @@
 | 
			
		||||
 * compositor needs to delay hiding the windows until the switch
 | 
			
		||||
 * workspace animation completes.
 | 
			
		||||
 *
 | 
			
		||||
 * meta_compositor_maximize_window() and meta_compositor_unmaximize_window()
 | 
			
		||||
 * are transitions within the visible state. The window is resized __before__
 | 
			
		||||
 * the call, so it may be necessary to readjust the display based on the
 | 
			
		||||
 * old_rect to start the animation.
 | 
			
		||||
 *
 | 
			
		||||
 * # Containers #
 | 
			
		||||
 *
 | 
			
		||||
 * There's two containers in the stage that are used to place window actors, here
 | 
			
		||||
@@ -79,6 +74,7 @@
 | 
			
		||||
#include "frame.h"
 | 
			
		||||
#include <X11/extensions/shape.h>
 | 
			
		||||
#include <X11/extensions/Xcomposite.h>
 | 
			
		||||
#include "meta-sync-ring.h"
 | 
			
		||||
 | 
			
		||||
#include "backends/x11/meta-backend-x11.h"
 | 
			
		||||
 | 
			
		||||
@@ -125,7 +121,11 @@ meta_switch_workspace_completed (MetaCompositor *compositor)
 | 
			
		||||
void
 | 
			
		||||
meta_compositor_destroy (MetaCompositor *compositor)
 | 
			
		||||
{
 | 
			
		||||
  clutter_threads_remove_repaint_func (compositor->repaint_func_id);
 | 
			
		||||
  clutter_threads_remove_repaint_func (compositor->pre_paint_func_id);
 | 
			
		||||
  clutter_threads_remove_repaint_func (compositor->post_paint_func_id);
 | 
			
		||||
 | 
			
		||||
  if (compositor->have_x11_sync_object)
 | 
			
		||||
    meta_sync_ring_destroy ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -468,13 +468,11 @@ meta_compositor_manage (MetaCompositor *compositor)
 | 
			
		||||
  MetaDisplay *display = compositor->display;
 | 
			
		||||
  Display *xdisplay = display->xdisplay;
 | 
			
		||||
  MetaScreen *screen = display->screen;
 | 
			
		||||
  MetaBackend *backend = meta_get_backend ();
 | 
			
		||||
 | 
			
		||||
  meta_screen_set_cm_selection (display->screen);
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    MetaBackend *backend = meta_get_backend ();
 | 
			
		||||
    compositor->stage = meta_backend_get_stage (backend);
 | 
			
		||||
  }
 | 
			
		||||
  compositor->stage = meta_backend_get_stage (backend);
 | 
			
		||||
 | 
			
		||||
  /* We use connect_after() here to accomodate code in GNOME Shell that,
 | 
			
		||||
   * when benchmarking drawing performance, connects to ::after-paint
 | 
			
		||||
@@ -510,7 +508,7 @@ meta_compositor_manage (MetaCompositor *compositor)
 | 
			
		||||
 | 
			
		||||
      compositor->output = screen->composite_overlay_window;
 | 
			
		||||
 | 
			
		||||
      xwin = meta_backend_x11_get_xwindow (META_BACKEND_X11 (meta_get_backend ()));
 | 
			
		||||
      xwin = meta_backend_x11_get_xwindow (META_BACKEND_X11 (backend));
 | 
			
		||||
 | 
			
		||||
      XReparentWindow (xdisplay, xwin, compositor->output, 0, 0);
 | 
			
		||||
 | 
			
		||||
@@ -530,6 +528,8 @@ meta_compositor_manage (MetaCompositor *compositor)
 | 
			
		||||
       * contents until we show the stage.
 | 
			
		||||
       */
 | 
			
		||||
      XMapWindow (xdisplay, compositor->output);
 | 
			
		||||
 | 
			
		||||
      compositor->have_x11_sync_object = meta_sync_ring_init (xdisplay);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  redirect_windows (display->screen);
 | 
			
		||||
@@ -731,6 +731,9 @@ meta_compositor_process_event (MetaCompositor *compositor,
 | 
			
		||||
        process_damage (compositor, (XDamageNotifyEvent *) event, window);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (compositor->have_x11_sync_object)
 | 
			
		||||
    meta_sync_ring_handle_event (event);
 | 
			
		||||
 | 
			
		||||
  /* Clutter needs to know about MapNotify events otherwise it will
 | 
			
		||||
     think the stage is invisible */
 | 
			
		||||
  if (!meta_is_wayland_compositor () && event->type == MapNotify)
 | 
			
		||||
@@ -769,23 +772,14 @@ meta_compositor_hide_window (MetaCompositor *compositor,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_compositor_maximize_window (MetaCompositor    *compositor,
 | 
			
		||||
                                 MetaWindow        *window,
 | 
			
		||||
				 MetaRectangle	   *old_rect,
 | 
			
		||||
				 MetaRectangle	   *new_rect)
 | 
			
		||||
meta_compositor_size_change_window (MetaCompositor    *compositor,
 | 
			
		||||
                                    MetaWindow        *window,
 | 
			
		||||
                                    MetaSizeChange     which_change,
 | 
			
		||||
                                    MetaRectangle     *old_frame_rect,
 | 
			
		||||
                                    MetaRectangle     *old_buffer_rect)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
  meta_window_actor_maximize (window_actor, old_rect, new_rect);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_compositor_unmaximize_window (MetaCompositor    *compositor,
 | 
			
		||||
                                   MetaWindow        *window,
 | 
			
		||||
				   MetaRectangle     *old_rect,
 | 
			
		||||
				   MetaRectangle     *new_rect)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
  meta_window_actor_unmaximize (window_actor, old_rect, new_rect);
 | 
			
		||||
  meta_window_actor_size_change (window_actor, which_change, old_frame_rect, old_buffer_rect);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -1044,11 +1038,12 @@ frame_callback (CoglOnscreen  *onscreen,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
pre_paint_windows (MetaCompositor *compositor)
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_pre_paint_func (gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  GList *l;
 | 
			
		||||
  MetaWindowActor *top_window;
 | 
			
		||||
  MetaCompositor *compositor = data;
 | 
			
		||||
 | 
			
		||||
  if (compositor->onscreen == NULL)
 | 
			
		||||
    {
 | 
			
		||||
@@ -1060,7 +1055,7 @@ pre_paint_windows (MetaCompositor *compositor)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (compositor->windows == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  top_window = g_list_last (compositor->windows)->data;
 | 
			
		||||
 | 
			
		||||
@@ -1077,10 +1072,12 @@ pre_paint_windows (MetaCompositor *compositor)
 | 
			
		||||
    {
 | 
			
		||||
      /* We need to make sure that any X drawing that happens before
 | 
			
		||||
       * the XDamageSubtract() for each window above is visible to
 | 
			
		||||
       * subsequent GL rendering; the only standardized way to do this
 | 
			
		||||
       * is EXT_x11_sync_object, which isn't yet widely available. For
 | 
			
		||||
       * now, we count on details of Xorg and the open source drivers,
 | 
			
		||||
       * and hope for the best otherwise.
 | 
			
		||||
       * subsequent GL rendering; the standardized way to do this is
 | 
			
		||||
       * GL_EXT_X11_sync_object. Since this isn't implemented yet in
 | 
			
		||||
       * mesa, we also have a path that relies on the implementation
 | 
			
		||||
       * of the open source drivers.
 | 
			
		||||
       *
 | 
			
		||||
       * Anything else, we just hope for the best.
 | 
			
		||||
       *
 | 
			
		||||
       * Xorg and open source driver specifics:
 | 
			
		||||
       *
 | 
			
		||||
@@ -1095,17 +1092,28 @@ pre_paint_windows (MetaCompositor *compositor)
 | 
			
		||||
       * round trip request at this point is sufficient to flush the
 | 
			
		||||
       * GLX buffers.
 | 
			
		||||
       */
 | 
			
		||||
      XSync (compositor->display->xdisplay, False);
 | 
			
		||||
 | 
			
		||||
      compositor->frame_has_updated_xsurfaces = FALSE;
 | 
			
		||||
      if (compositor->have_x11_sync_object)
 | 
			
		||||
        compositor->have_x11_sync_object = meta_sync_ring_insert_wait ();
 | 
			
		||||
      else
 | 
			
		||||
        XSync (compositor->display->xdisplay, False);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_repaint_func (gpointer data)
 | 
			
		||||
meta_post_paint_func (gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  MetaCompositor *compositor = data;
 | 
			
		||||
  pre_paint_windows (compositor);
 | 
			
		||||
 | 
			
		||||
  if (compositor->frame_has_updated_xsurfaces)
 | 
			
		||||
    {
 | 
			
		||||
      if (compositor->have_x11_sync_object)
 | 
			
		||||
        compositor->have_x11_sync_object = meta_sync_ring_after_frame ();
 | 
			
		||||
 | 
			
		||||
      compositor->frame_has_updated_xsurfaces = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1140,10 +1148,16 @@ meta_compositor_new (MetaDisplay *display)
 | 
			
		||||
                    G_CALLBACK (on_shadow_factory_changed),
 | 
			
		||||
                    compositor);
 | 
			
		||||
 | 
			
		||||
  compositor->repaint_func_id = clutter_threads_add_repaint_func (meta_repaint_func,
 | 
			
		||||
                                                                  compositor,
 | 
			
		||||
                                                                  NULL);
 | 
			
		||||
 | 
			
		||||
  compositor->pre_paint_func_id =
 | 
			
		||||
    clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_PRE_PAINT,
 | 
			
		||||
                                           meta_pre_paint_func,
 | 
			
		||||
                                           compositor,
 | 
			
		||||
                                           NULL);
 | 
			
		||||
  compositor->post_paint_func_id =
 | 
			
		||||
    clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
 | 
			
		||||
                                           meta_post_paint_func,
 | 
			
		||||
                                           compositor,
 | 
			
		||||
                                           NULL);
 | 
			
		||||
  return compositor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,8 @@
 | 
			
		||||
#include "meta-background-private.h"
 | 
			
		||||
#include "cogl-utils.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
  CHANGED,
 | 
			
		||||
@@ -71,6 +73,8 @@ enum
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaBackground, meta_background, G_TYPE_OBJECT)
 | 
			
		||||
 | 
			
		||||
static gboolean texture_has_alpha (CoglTexture *texture);
 | 
			
		||||
 | 
			
		||||
static GSList *all_backgrounds = NULL;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -474,7 +478,7 @@ get_texture_area (MetaBackground          *self,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
static gboolean
 | 
			
		||||
draw_texture (MetaBackground        *self,
 | 
			
		||||
              CoglFramebuffer       *framebuffer,
 | 
			
		||||
              CoglPipeline          *pipeline,
 | 
			
		||||
@@ -483,6 +487,7 @@ draw_texture (MetaBackground        *self,
 | 
			
		||||
{
 | 
			
		||||
  MetaBackgroundPrivate *priv = self->priv;
 | 
			
		||||
  cairo_rectangle_int_t texture_area;
 | 
			
		||||
  gboolean bare_region_visible;
 | 
			
		||||
 | 
			
		||||
  get_texture_area (self, monitor_area, texture, &texture_area);
 | 
			
		||||
 | 
			
		||||
@@ -503,6 +508,9 @@ draw_texture (MetaBackground        *self,
 | 
			
		||||
                                                - texture_area.y / (float)texture_area.height,
 | 
			
		||||
                                                (monitor_area->width - texture_area.x) / (float)texture_area.width,
 | 
			
		||||
                                                (monitor_area->height - texture_area.y) / (float)texture_area.height);
 | 
			
		||||
 | 
			
		||||
      bare_region_visible = texture_has_alpha (texture);
 | 
			
		||||
 | 
			
		||||
      /* Draw just the texture */
 | 
			
		||||
      break;
 | 
			
		||||
    case G_DESKTOP_BACKGROUND_STYLE_CENTERED:
 | 
			
		||||
@@ -513,11 +521,16 @@ draw_texture (MetaBackground        *self,
 | 
			
		||||
                                                texture_area.x + texture_area.width,
 | 
			
		||||
                                                texture_area.y + texture_area.height,
 | 
			
		||||
                                                0, 0, 1.0, 1.0);
 | 
			
		||||
      bare_region_visible = texture_has_alpha (texture) || memcmp (&texture_area, monitor_area, sizeof (cairo_rectangle_int_t)) != 0;
 | 
			
		||||
      break;
 | 
			
		||||
    case G_DESKTOP_BACKGROUND_STYLE_NONE:
 | 
			
		||||
      bare_region_visible = TRUE;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      g_return_if_reached();
 | 
			
		||||
      g_return_val_if_reached(FALSE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return bare_region_visible;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -748,6 +761,7 @@ meta_background_get_texture (MetaBackground         *self,
 | 
			
		||||
  if (monitor->dirty)
 | 
			
		||||
    {
 | 
			
		||||
      CoglError *catch_error = NULL;
 | 
			
		||||
      gboolean bare_region_visible = FALSE;
 | 
			
		||||
 | 
			
		||||
      if (monitor->texture == NULL)
 | 
			
		||||
        {
 | 
			
		||||
@@ -783,9 +797,9 @@ meta_background_get_texture (MetaBackground         *self,
 | 
			
		||||
          cogl_pipeline_set_layer_texture (pipeline, 0, texture2);
 | 
			
		||||
          cogl_pipeline_set_layer_wrap_mode (pipeline, 0, get_wrap_mode (priv->style));
 | 
			
		||||
 | 
			
		||||
          draw_texture (self,
 | 
			
		||||
                        monitor->fbo, pipeline,
 | 
			
		||||
                        texture2, &monitor_area);
 | 
			
		||||
          bare_region_visible = draw_texture (self,
 | 
			
		||||
                                              monitor->fbo, pipeline,
 | 
			
		||||
                                              texture2, &monitor_area);
 | 
			
		||||
 | 
			
		||||
          cogl_object_unref (pipeline);
 | 
			
		||||
        }
 | 
			
		||||
@@ -796,8 +810,7 @@ meta_background_get_texture (MetaBackground         *self,
 | 
			
		||||
                                    0.0, 0.0, 0.0, 0.0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (texture1 != NULL &&
 | 
			
		||||
          !(texture2 != NULL && priv->blend_factor == 1.0 && !texture_has_alpha (texture2)))
 | 
			
		||||
      if (texture1 != NULL && priv->blend_factor != 1.0)
 | 
			
		||||
        {
 | 
			
		||||
          CoglPipeline *pipeline = create_pipeline (PIPELINE_ADD);
 | 
			
		||||
          cogl_pipeline_set_color4f (pipeline,
 | 
			
		||||
@@ -808,15 +821,14 @@ meta_background_get_texture (MetaBackground         *self,
 | 
			
		||||
          cogl_pipeline_set_layer_texture (pipeline, 0, texture1);
 | 
			
		||||
          cogl_pipeline_set_layer_wrap_mode (pipeline, 0, get_wrap_mode (priv->style));
 | 
			
		||||
 | 
			
		||||
          draw_texture (self,
 | 
			
		||||
                        monitor->fbo, pipeline,
 | 
			
		||||
                        texture1, &monitor_area);
 | 
			
		||||
          bare_region_visible = bare_region_visible || draw_texture (self,
 | 
			
		||||
                                                                     monitor->fbo, pipeline,
 | 
			
		||||
                                                                     texture1, &monitor_area);
 | 
			
		||||
 | 
			
		||||
          cogl_object_unref (pipeline);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (!((texture2 != NULL && priv->blend_factor == 1.0 && !texture_has_alpha (texture2)) ||
 | 
			
		||||
            (texture1 != NULL && !texture_has_alpha (texture1))))
 | 
			
		||||
      if (bare_region_visible)
 | 
			
		||||
        {
 | 
			
		||||
          CoglPipeline *pipeline = create_pipeline (PIPELINE_OVER_REVERSE);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -187,7 +187,7 @@ meta_feedback_actor_set_anchor (MetaFeedbackActor *self,
 | 
			
		||||
  if (priv->anchor_x == anchor_x && priv->anchor_y == anchor_y)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (priv->anchor_x != anchor_y)
 | 
			
		||||
  if (priv->anchor_x != anchor_x)
 | 
			
		||||
    {
 | 
			
		||||
      priv->anchor_x = anchor_x;
 | 
			
		||||
      g_object_notify (G_OBJECT (self), "anchor-x");
 | 
			
		||||
 
 | 
			
		||||
@@ -149,7 +149,7 @@ meta_plugin_manager_kill_switch_workspace (MetaPluginManager *plugin_mgr)
 | 
			
		||||
gboolean
 | 
			
		||||
meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
 | 
			
		||||
                                  MetaWindowActor   *actor,
 | 
			
		||||
                                  unsigned long      event)
 | 
			
		||||
                                  MetaPluginEffect   event)
 | 
			
		||||
{
 | 
			
		||||
  MetaPlugin *plugin = plugin_mgr->plugin;
 | 
			
		||||
  MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
 | 
			
		||||
@@ -196,67 +196,32 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
 | 
			
		||||
        }
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      g_warning ("Incorrect handler called for event %lu", event);
 | 
			
		||||
      g_warning ("Incorrect handler called for event %d", event);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The public method that the compositor hooks into for maximize and unmaximize
 | 
			
		||||
 * events.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns TRUE if the plugin handled the event type (i.e.,
 | 
			
		||||
 * if the return value is FALSE, there will be no subsequent call to the
 | 
			
		||||
 * manager completed() callback, and the compositor must ensure that any
 | 
			
		||||
 * appropriate post-effect cleanup is carried out.
 | 
			
		||||
 */
 | 
			
		||||
gboolean
 | 
			
		||||
meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
 | 
			
		||||
                                    MetaWindowActor   *actor,
 | 
			
		||||
                                    unsigned long      event,
 | 
			
		||||
                                    gint               target_x,
 | 
			
		||||
                                    gint               target_y,
 | 
			
		||||
                                    gint               target_width,
 | 
			
		||||
                                    gint               target_height)
 | 
			
		||||
meta_plugin_manager_event_size_change (MetaPluginManager *plugin_mgr,
 | 
			
		||||
                                       MetaWindowActor   *actor,
 | 
			
		||||
                                       MetaSizeChange     which_change,
 | 
			
		||||
                                       MetaRectangle     *old_frame_rect,
 | 
			
		||||
                                       MetaRectangle     *old_buffer_rect)
 | 
			
		||||
{
 | 
			
		||||
  MetaPlugin *plugin = plugin_mgr->plugin;
 | 
			
		||||
  MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
 | 
			
		||||
  MetaDisplay *display = plugin_mgr->compositor->display;
 | 
			
		||||
  gboolean retval = FALSE;
 | 
			
		||||
 | 
			
		||||
  if (display->display_opening)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  switch (event)
 | 
			
		||||
    {
 | 
			
		||||
    case META_PLUGIN_MAXIMIZE:
 | 
			
		||||
      if (klass->maximize)
 | 
			
		||||
        {
 | 
			
		||||
          retval = TRUE;
 | 
			
		||||
          meta_plugin_manager_kill_window_effects (plugin_mgr,
 | 
			
		||||
                                                   actor);
 | 
			
		||||
          klass->maximize (plugin, actor,
 | 
			
		||||
                           target_x, target_y,
 | 
			
		||||
                           target_width, target_height);
 | 
			
		||||
        }
 | 
			
		||||
      break;
 | 
			
		||||
    case META_PLUGIN_UNMAXIMIZE:
 | 
			
		||||
      if (klass->unmaximize)
 | 
			
		||||
        {
 | 
			
		||||
          retval = TRUE;
 | 
			
		||||
          meta_plugin_manager_kill_window_effects (plugin_mgr,
 | 
			
		||||
                                                   actor);
 | 
			
		||||
          klass->unmaximize (plugin, actor,
 | 
			
		||||
                             target_x, target_y,
 | 
			
		||||
                             target_width, target_height);
 | 
			
		||||
        }
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      g_warning ("Incorrect handler called for event %lu", event);
 | 
			
		||||
    }
 | 
			
		||||
  if (!klass->size_change)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  return retval;
 | 
			
		||||
  meta_plugin_manager_kill_window_effects (plugin_mgr, actor);
 | 
			
		||||
  klass->size_change (plugin, actor, which_change, old_frame_rect, old_buffer_rect);
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -24,20 +24,17 @@
 | 
			
		||||
 | 
			
		||||
#include <meta/types.h>
 | 
			
		||||
#include <meta/screen.h>
 | 
			
		||||
 | 
			
		||||
#define  META_PLUGIN_FROM_MANAGER_
 | 
			
		||||
#include <meta/meta-plugin.h>
 | 
			
		||||
#undef   META_PLUGIN_FROM_MANAGER_
 | 
			
		||||
 | 
			
		||||
#define META_PLUGIN_MINIMIZE         (1<<0)
 | 
			
		||||
#define META_PLUGIN_MAXIMIZE         (1<<1)
 | 
			
		||||
#define META_PLUGIN_UNMAXIMIZE       (1<<2)
 | 
			
		||||
#define META_PLUGIN_MAP              (1<<3)
 | 
			
		||||
#define META_PLUGIN_DESTROY          (1<<4)
 | 
			
		||||
#define META_PLUGIN_SWITCH_WORKSPACE (1<<5)
 | 
			
		||||
#define META_PLUGIN_UNMINIMIZE       (1<<6)
 | 
			
		||||
 | 
			
		||||
#define META_PLUGIN_ALL_EFFECTS      (~0)
 | 
			
		||||
typedef enum {
 | 
			
		||||
  META_PLUGIN_NONE,
 | 
			
		||||
  META_PLUGIN_MINIMIZE,
 | 
			
		||||
  META_PLUGIN_MAP,
 | 
			
		||||
  META_PLUGIN_DESTROY,
 | 
			
		||||
  META_PLUGIN_SWITCH_WORKSPACE,
 | 
			
		||||
  META_PLUGIN_UNMINIMIZE,
 | 
			
		||||
  META_PLUGIN_SIZE_CHANGE,
 | 
			
		||||
} MetaPluginEffect;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MetaPluginManager: (skip)
 | 
			
		||||
@@ -51,15 +48,13 @@ void     meta_plugin_manager_load         (const gchar       *plugin_name);
 | 
			
		||||
 | 
			
		||||
gboolean meta_plugin_manager_event_simple (MetaPluginManager *mgr,
 | 
			
		||||
                                           MetaWindowActor   *actor,
 | 
			
		||||
                                           unsigned long      event);
 | 
			
		||||
                                           MetaPluginEffect   event);
 | 
			
		||||
 | 
			
		||||
gboolean meta_plugin_manager_event_maximize    (MetaPluginManager *mgr,
 | 
			
		||||
                                                MetaWindowActor   *actor,
 | 
			
		||||
                                                unsigned long      event,
 | 
			
		||||
                                                gint               target_x,
 | 
			
		||||
                                                gint               target_y,
 | 
			
		||||
                                                gint               target_width,
 | 
			
		||||
                                                gint               target_height);
 | 
			
		||||
gboolean meta_plugin_manager_event_size_change    (MetaPluginManager *mgr,
 | 
			
		||||
                                                   MetaWindowActor   *actor,
 | 
			
		||||
                                                   MetaSizeChange     which_change,
 | 
			
		||||
                                                   MetaRectangle     *old_frame_rect,
 | 
			
		||||
                                                   MetaRectangle     *old_buffer_rect);
 | 
			
		||||
 | 
			
		||||
gboolean meta_plugin_manager_switch_workspace (MetaPluginManager   *mgr,
 | 
			
		||||
                                               gint                 from,
 | 
			
		||||
 
 | 
			
		||||
@@ -118,17 +118,10 @@ meta_plugin_unminimize_completed (MetaPlugin      *plugin,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_plugin_maximize_completed (MetaPlugin      *plugin,
 | 
			
		||||
                                MetaWindowActor *actor)
 | 
			
		||||
meta_plugin_size_change_completed (MetaPlugin      *plugin,
 | 
			
		||||
                                   MetaWindowActor *actor)
 | 
			
		||||
{
 | 
			
		||||
  meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MAXIMIZE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_plugin_unmaximize_completed (MetaPlugin      *plugin,
 | 
			
		||||
                                  MetaWindowActor *actor)
 | 
			
		||||
{
 | 
			
		||||
  meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_UNMAXIMIZE);
 | 
			
		||||
  meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_SIZE_CHANGE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
 
 | 
			
		||||
@@ -1,66 +0,0 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * MetaShadowFactory:
 | 
			
		||||
 *
 | 
			
		||||
 * Create and cache shadow textures for arbitrary window shapes
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2010 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/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __META_SHADOW_FACTORY_PRIVATE_H__
 | 
			
		||||
#define __META_SHADOW_FACTORY_PRIVATE_H__
 | 
			
		||||
 | 
			
		||||
#include <cairo.h>
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
#include "meta-window-shape.h"
 | 
			
		||||
#include <meta/meta-shadow-factory.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MetaShadow:
 | 
			
		||||
 * #MetaShadow holds a shadow texture along with information about how to
 | 
			
		||||
 * apply that texture to draw a window texture. (E.g., it knows how big the
 | 
			
		||||
 * unscaled borders are on each side of the shadow texture.)
 | 
			
		||||
 */
 | 
			
		||||
typedef struct _MetaShadow MetaShadow;
 | 
			
		||||
 | 
			
		||||
MetaShadow *meta_shadow_ref         (MetaShadow            *shadow);
 | 
			
		||||
void        meta_shadow_unref       (MetaShadow            *shadow);
 | 
			
		||||
CoglTexture*meta_shadow_get_texture (MetaShadow            *shadow);
 | 
			
		||||
void        meta_shadow_paint       (MetaShadow            *shadow,
 | 
			
		||||
                                     int                    window_x,
 | 
			
		||||
                                     int                    window_y,
 | 
			
		||||
                                     int                    window_width,
 | 
			
		||||
                                     int                    window_height,
 | 
			
		||||
                                     guint8                 opacity,
 | 
			
		||||
                                     cairo_region_t        *clip,
 | 
			
		||||
                                     gboolean               clip_strictly);
 | 
			
		||||
void        meta_shadow_get_bounds  (MetaShadow            *shadow,
 | 
			
		||||
                                     int                    window_x,
 | 
			
		||||
                                     int                    window_y,
 | 
			
		||||
                                     int                    window_width,
 | 
			
		||||
                                     int                    window_height,
 | 
			
		||||
                                     cairo_rectangle_int_t *bounds);
 | 
			
		||||
 | 
			
		||||
MetaShadowFactory *meta_shadow_factory_new (void);
 | 
			
		||||
 | 
			
		||||
MetaShadow *meta_shadow_factory_get_shadow (MetaShadowFactory *factory,
 | 
			
		||||
                                            MetaWindowShape   *shape,
 | 
			
		||||
                                            int                width,
 | 
			
		||||
                                            int                height,
 | 
			
		||||
                                            const char        *class_name,
 | 
			
		||||
                                            gboolean           focused);
 | 
			
		||||
 | 
			
		||||
#endif /* __META_SHADOW_FACTORY_PRIVATE_H__ */
 | 
			
		||||
@@ -26,8 +26,9 @@
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <meta/meta-shadow-factory.h>
 | 
			
		||||
 | 
			
		||||
#include "cogl-utils.h"
 | 
			
		||||
#include "meta-shadow-factory-private.h"
 | 
			
		||||
#include "region-utils.h"
 | 
			
		||||
 | 
			
		||||
/* This file implements blurring the shape of a window to produce a
 | 
			
		||||
@@ -1048,3 +1049,6 @@ meta_shadow_factory_get_params (MetaShadowFactory *factory,
 | 
			
		||||
  if (params)
 | 
			
		||||
    *params = *stored_params;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
G_DEFINE_BOXED_TYPE (MetaShadow, meta_shadow,
 | 
			
		||||
                     meta_shadow_ref, meta_shadow_unref)
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,9 @@
 | 
			
		||||
ClutterActor *meta_shaped_texture_new (void);
 | 
			
		||||
void meta_shaped_texture_set_texture (MetaShapedTexture *stex,
 | 
			
		||||
                                      CoglTexture       *texture);
 | 
			
		||||
void meta_shaped_texture_set_fallback_size (MetaShapedTexture *stex,
 | 
			
		||||
                                            guint              fallback_width,
 | 
			
		||||
                                            guint              fallback_height);
 | 
			
		||||
gboolean meta_shaped_texture_is_obscured (MetaShapedTexture *self);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -86,6 +86,7 @@ struct _MetaShapedTexturePrivate
 | 
			
		||||
  cairo_region_t *unobscured_region;
 | 
			
		||||
 | 
			
		||||
  guint tex_width, tex_height;
 | 
			
		||||
  guint fallback_width, fallback_height;
 | 
			
		||||
 | 
			
		||||
  guint create_mipmaps : 1;
 | 
			
		||||
};
 | 
			
		||||
@@ -136,7 +137,20 @@ set_unobscured_region (MetaShapedTexture *self,
 | 
			
		||||
  g_clear_pointer (&priv->unobscured_region, (GDestroyNotify) cairo_region_destroy);
 | 
			
		||||
  if (unobscured_region)
 | 
			
		||||
    {
 | 
			
		||||
      cairo_rectangle_int_t bounds = { 0, 0, priv->tex_width, priv->tex_height };
 | 
			
		||||
      guint width, height;
 | 
			
		||||
 | 
			
		||||
      if (priv->texture)
 | 
			
		||||
        {
 | 
			
		||||
          width = priv->tex_width;
 | 
			
		||||
          height = priv->tex_height;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          width = priv->fallback_width;
 | 
			
		||||
          height = priv->fallback_height;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      cairo_rectangle_int_t bounds = { 0, 0, width, height };
 | 
			
		||||
      priv->unobscured_region = cairo_region_copy (unobscured_region);
 | 
			
		||||
      cairo_region_intersect_rectangle (priv->unobscured_region, &bounds);
 | 
			
		||||
    }
 | 
			
		||||
@@ -173,10 +187,25 @@ meta_shaped_texture_dispose (GObject *object)
 | 
			
		||||
  G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static CoglPipeline *
 | 
			
		||||
get_base_pipeline (CoglContext *ctx)
 | 
			
		||||
{
 | 
			
		||||
  static CoglPipeline *template = NULL;
 | 
			
		||||
  if (G_UNLIKELY (template == NULL))
 | 
			
		||||
    {
 | 
			
		||||
      template = cogl_pipeline_new (ctx);
 | 
			
		||||
      cogl_pipeline_set_layer_wrap_mode_s (template, 0, COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
 | 
			
		||||
      cogl_pipeline_set_layer_wrap_mode_t (template, 0, COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
 | 
			
		||||
      cogl_pipeline_set_layer_wrap_mode_s (template, 1, COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
 | 
			
		||||
      cogl_pipeline_set_layer_wrap_mode_t (template, 1, COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
 | 
			
		||||
    }
 | 
			
		||||
  return template;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static CoglPipeline *
 | 
			
		||||
get_unmasked_pipeline (CoglContext *ctx)
 | 
			
		||||
{
 | 
			
		||||
  return cogl_pipeline_new (ctx);
 | 
			
		||||
  return get_base_pipeline (ctx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static CoglPipeline *
 | 
			
		||||
@@ -185,13 +214,13 @@ get_masked_pipeline (CoglContext *ctx)
 | 
			
		||||
  static CoglPipeline *template = NULL;
 | 
			
		||||
  if (G_UNLIKELY (template == NULL))
 | 
			
		||||
    {
 | 
			
		||||
      template = cogl_pipeline_new (ctx);
 | 
			
		||||
      template = cogl_pipeline_copy (get_base_pipeline (ctx));
 | 
			
		||||
      cogl_pipeline_set_layer_combine (template, 1,
 | 
			
		||||
                                       "RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
 | 
			
		||||
                                       NULL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return cogl_pipeline_copy (template);
 | 
			
		||||
  return template;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static CoglPipeline *
 | 
			
		||||
@@ -201,7 +230,7 @@ get_unblended_pipeline (CoglContext *ctx)
 | 
			
		||||
  if (G_UNLIKELY (template == NULL))
 | 
			
		||||
    {
 | 
			
		||||
      CoglColor color;
 | 
			
		||||
      template = cogl_pipeline_new (ctx);
 | 
			
		||||
      template = cogl_pipeline_copy (get_base_pipeline (ctx));
 | 
			
		||||
      cogl_color_init_from_4ub (&color, 255, 255, 255, 255);
 | 
			
		||||
      cogl_pipeline_set_blend (template,
 | 
			
		||||
                               "RGBA = ADD (SRC_COLOR, 0)",
 | 
			
		||||
@@ -209,7 +238,7 @@ get_unblended_pipeline (CoglContext *ctx)
 | 
			
		||||
      cogl_pipeline_set_color (template, &color);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return cogl_pipeline_copy (template);
 | 
			
		||||
  return template;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -420,8 +449,6 @@ meta_shaped_texture_paint (ClutterActor *actor)
 | 
			
		||||
              cairo_region_get_rectangle (region, i, &rect);
 | 
			
		||||
              paint_clipped_rectangle (fb, opaque_pipeline, &rect, &alloc);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          cogl_object_unref (opaque_pipeline);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      cairo_region_destroy (region);
 | 
			
		||||
@@ -484,8 +511,6 @@ meta_shaped_texture_paint (ClutterActor *actor)
 | 
			
		||||
                                           alloc.x2 - alloc.x1,
 | 
			
		||||
                                           alloc.y2 - alloc.y1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      cogl_object_unref (blended_pipeline);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (blended_region != NULL)
 | 
			
		||||
@@ -498,17 +523,18 @@ meta_shaped_texture_get_preferred_width (ClutterActor *self,
 | 
			
		||||
                                         gfloat       *min_width_p,
 | 
			
		||||
                                         gfloat       *natural_width_p)
 | 
			
		||||
{
 | 
			
		||||
  MetaShapedTexturePrivate *priv;
 | 
			
		||||
  MetaShapedTexturePrivate *priv = META_SHAPED_TEXTURE (self)->priv;
 | 
			
		||||
  guint width;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (META_IS_SHAPED_TEXTURE (self));
 | 
			
		||||
 | 
			
		||||
  priv = META_SHAPED_TEXTURE (self)->priv;
 | 
			
		||||
  if (priv->texture)
 | 
			
		||||
    width = priv->tex_width;
 | 
			
		||||
  else
 | 
			
		||||
    width = priv->fallback_width;
 | 
			
		||||
 | 
			
		||||
  if (min_width_p)
 | 
			
		||||
    *min_width_p = priv->tex_width;
 | 
			
		||||
 | 
			
		||||
    *min_width_p = width;
 | 
			
		||||
  if (natural_width_p)
 | 
			
		||||
    *natural_width_p = priv->tex_width;
 | 
			
		||||
    *natural_width_p = width;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -517,17 +543,18 @@ meta_shaped_texture_get_preferred_height (ClutterActor *self,
 | 
			
		||||
                                          gfloat       *min_height_p,
 | 
			
		||||
                                          gfloat       *natural_height_p)
 | 
			
		||||
{
 | 
			
		||||
  MetaShapedTexturePrivate *priv;
 | 
			
		||||
  MetaShapedTexturePrivate *priv = META_SHAPED_TEXTURE (self)->priv;
 | 
			
		||||
  guint height;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (META_IS_SHAPED_TEXTURE (self));
 | 
			
		||||
 | 
			
		||||
  priv = META_SHAPED_TEXTURE (self)->priv;
 | 
			
		||||
  if (priv->texture)
 | 
			
		||||
    height = priv->tex_height;
 | 
			
		||||
  else
 | 
			
		||||
    height = priv->fallback_height;
 | 
			
		||||
 | 
			
		||||
  if (min_height_p)
 | 
			
		||||
    *min_height_p = priv->tex_height;
 | 
			
		||||
 | 
			
		||||
    *min_height_p = height;
 | 
			
		||||
  if (natural_height_p)
 | 
			
		||||
    *natural_height_p = priv->tex_height;
 | 
			
		||||
    *natural_height_p = height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static cairo_region_t *
 | 
			
		||||
@@ -860,6 +887,17 @@ meta_shaped_texture_get_image (MetaShapedTexture     *stex,
 | 
			
		||||
  return surface;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_shaped_texture_set_fallback_size (MetaShapedTexture *self,
 | 
			
		||||
                                       guint              fallback_width,
 | 
			
		||||
                                       guint              fallback_height)
 | 
			
		||||
{
 | 
			
		||||
  MetaShapedTexturePrivate *priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  priv->fallback_width = fallback_width;
 | 
			
		||||
  priv->fallback_height = fallback_height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_shaped_texture_cull_out (MetaCullable   *cullable,
 | 
			
		||||
                              cairo_region_t *unobscured_region,
 | 
			
		||||
 
 | 
			
		||||
@@ -26,16 +26,28 @@
 | 
			
		||||
 | 
			
		||||
#include "meta-surface-actor-wayland.h"
 | 
			
		||||
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <cogl/cogl-wayland-server.h>
 | 
			
		||||
#include "meta-shaped-texture-private.h"
 | 
			
		||||
 | 
			
		||||
#include "wayland/meta-wayland-buffer.h"
 | 
			
		||||
#include "wayland/meta-wayland-private.h"
 | 
			
		||||
#include "wayland/meta-window-wayland.h"
 | 
			
		||||
 | 
			
		||||
#include "compositor/region-utils.h"
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
  PAINTING,
 | 
			
		||||
 | 
			
		||||
  LAST_SIGNAL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static guint signals[LAST_SIGNAL];
 | 
			
		||||
 | 
			
		||||
struct _MetaSurfaceActorWaylandPrivate
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandSurface *surface;
 | 
			
		||||
  struct wl_list frame_callback_list;
 | 
			
		||||
};
 | 
			
		||||
typedef struct _MetaSurfaceActorWaylandPrivate MetaSurfaceActorWaylandPrivate;
 | 
			
		||||
 | 
			
		||||
@@ -80,53 +92,89 @@ meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor)
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
get_output_scale (int winsys_id)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManager *monitor_manager = meta_monitor_manager_get ();
 | 
			
		||||
  MetaOutput *outputs;
 | 
			
		||||
  guint n_outputs, i;
 | 
			
		||||
  int output_scale = 1;
 | 
			
		||||
 | 
			
		||||
  outputs = meta_monitor_manager_get_outputs (monitor_manager, &n_outputs);
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      if (outputs[i].winsys_id == winsys_id)
 | 
			
		||||
        {
 | 
			
		||||
          output_scale = outputs[i].scale;
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return output_scale;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
double
 | 
			
		||||
meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor)
 | 
			
		||||
{
 | 
			
		||||
   MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (actor);
 | 
			
		||||
   MetaWaylandSurface *surface = priv->surface;
 | 
			
		||||
   MetaWindow *window = surface->window;
 | 
			
		||||
   MetaWindow *window;
 | 
			
		||||
   int output_scale = 1;
 | 
			
		||||
 | 
			
		||||
   while (surface)
 | 
			
		||||
    {
 | 
			
		||||
      if (surface->window)
 | 
			
		||||
        {
 | 
			
		||||
          window = surface->window;
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
      surface = surface->sub.parent;
 | 
			
		||||
    }
 | 
			
		||||
   if (!surface)
 | 
			
		||||
     return 1;
 | 
			
		||||
 | 
			
		||||
   window = meta_wayland_surface_get_toplevel_window (surface);
 | 
			
		||||
 | 
			
		||||
   /* XXX: We do not handle x11 clients yet */
 | 
			
		||||
   if (window && window->client_type != META_WINDOW_CLIENT_TYPE_X11)
 | 
			
		||||
     output_scale = get_output_scale (window->monitor->winsys_id);
 | 
			
		||||
     output_scale = meta_window_wayland_get_main_monitor_scale (window);
 | 
			
		||||
 | 
			
		||||
   return (double)output_scale / (double)priv->surface->scale;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
logical_to_actor_position (MetaSurfaceActorWayland *self,
 | 
			
		||||
                           int                     *x,
 | 
			
		||||
                           int                     *y)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
 | 
			
		||||
  MetaWindow *toplevel_window;
 | 
			
		||||
  int monitor_scale = 1;
 | 
			
		||||
 | 
			
		||||
  toplevel_window = meta_wayland_surface_get_toplevel_window (surface);
 | 
			
		||||
  if (toplevel_window)
 | 
			
		||||
    monitor_scale = meta_window_wayland_get_main_monitor_scale (toplevel_window);
 | 
			
		||||
 | 
			
		||||
  *x = *x * monitor_scale;
 | 
			
		||||
  *y = *y * monitor_scale;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert the current actor state to the corresponding subsurface rectangle
 | 
			
		||||
 * in logical pixel coordinate space. */
 | 
			
		||||
void
 | 
			
		||||
meta_surface_actor_wayland_get_subsurface_rect (MetaSurfaceActorWayland *self,
 | 
			
		||||
                                                MetaRectangle           *rect)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
 | 
			
		||||
  CoglTexture *texture = surface->buffer->texture;
 | 
			
		||||
  MetaWindow *toplevel_window;
 | 
			
		||||
  int monitor_scale;
 | 
			
		||||
  float x, y;
 | 
			
		||||
 | 
			
		||||
  toplevel_window = meta_wayland_surface_get_toplevel_window (surface);
 | 
			
		||||
  monitor_scale = meta_window_wayland_get_main_monitor_scale (toplevel_window);
 | 
			
		||||
 | 
			
		||||
  clutter_actor_get_position (CLUTTER_ACTOR (self), &x, &y);
 | 
			
		||||
  *rect = (MetaRectangle) {
 | 
			
		||||
    .x = x / monitor_scale,
 | 
			
		||||
    .y = y / monitor_scale,
 | 
			
		||||
    .width = cogl_texture_get_width (texture) / surface->scale,
 | 
			
		||||
    .height = cogl_texture_get_height (texture) / surface->scale,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_surface_actor_wayland_sync_subsurface_state (MetaSurfaceActorWayland *self)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
 | 
			
		||||
  MetaWindow *window;
 | 
			
		||||
  int x = surface->offset_x + surface->sub.x;
 | 
			
		||||
  int y = surface->offset_y + surface->sub.y;
 | 
			
		||||
 | 
			
		||||
  window = meta_wayland_surface_get_toplevel_window (surface);
 | 
			
		||||
  if (window && window->client_type == META_WINDOW_CLIENT_TYPE_X11)
 | 
			
		||||
    {
 | 
			
		||||
      /* Bail directly if this is part of a Xwayland window and warn
 | 
			
		||||
       * if there happen to be offsets anyway since that is not supposed
 | 
			
		||||
       * to happen. */
 | 
			
		||||
      g_warn_if_fail (x == 0 && y == 0);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  logical_to_actor_position (self, &x, &y);
 | 
			
		||||
  clutter_actor_set_position (CLUTTER_ACTOR (self), x, y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_surface_actor_wayland_sync_state (MetaSurfaceActorWayland *self)
 | 
			
		||||
{
 | 
			
		||||
@@ -158,6 +206,10 @@ meta_surface_actor_wayland_sync_state (MetaSurfaceActorWayland *self)
 | 
			
		||||
                                           scaled_input_region);
 | 
			
		||||
      cairo_region_destroy (scaled_input_region);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      meta_surface_actor_set_input_region (META_SURFACE_ACTOR (self), NULL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* Opaque region */
 | 
			
		||||
  if (surface->opaque_region)
 | 
			
		||||
@@ -173,31 +225,88 @@ meta_surface_actor_wayland_sync_state (MetaSurfaceActorWayland *self)
 | 
			
		||||
                                            scaled_opaque_region);
 | 
			
		||||
      cairo_region_destroy (scaled_opaque_region);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      meta_surface_actor_set_opaque_region (META_SURFACE_ACTOR (self), NULL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_surface_actor_wayland_sync_subsurface_state (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_surface_actor_wayland_sync_state_recursive (MetaSurfaceActorWayland *self)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
 | 
			
		||||
  MetaWindow *window = meta_wayland_surface_get_toplevel_window (surface);
 | 
			
		||||
  GList *iter;
 | 
			
		||||
 | 
			
		||||
  meta_surface_actor_wayland_sync_state (self);
 | 
			
		||||
 | 
			
		||||
  for (iter = surface->subsurfaces; iter != NULL; iter = iter->next)
 | 
			
		||||
  if (window && window->client_type != META_WINDOW_CLIENT_TYPE_X11)
 | 
			
		||||
    {
 | 
			
		||||
      MetaWaylandSurface *subsurf = iter->data;
 | 
			
		||||
      for (iter = surface->subsurfaces; iter != NULL; iter = iter->next)
 | 
			
		||||
        {
 | 
			
		||||
          MetaWaylandSurface *subsurf = iter->data;
 | 
			
		||||
 | 
			
		||||
      meta_surface_actor_wayland_sync_state_recursive (
 | 
			
		||||
        META_SURFACE_ACTOR_WAYLAND (subsurf->surface_actor));
 | 
			
		||||
          meta_surface_actor_wayland_sync_state_recursive (
 | 
			
		||||
            META_SURFACE_ACTOR_WAYLAND (subsurf->surface_actor));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_surface_actor_wayland_is_on_monitor (MetaSurfaceActorWayland *self,
 | 
			
		||||
                                          MetaMonitorInfo         *monitor)
 | 
			
		||||
{
 | 
			
		||||
  float x, y, width, height;
 | 
			
		||||
  cairo_rectangle_int_t actor_rect;
 | 
			
		||||
  cairo_region_t *region;
 | 
			
		||||
  gboolean is_on_monitor;
 | 
			
		||||
 | 
			
		||||
  clutter_actor_get_transformed_position (CLUTTER_ACTOR (self), &x, &y);
 | 
			
		||||
  clutter_actor_get_transformed_size (CLUTTER_ACTOR (self), &width, &height);
 | 
			
		||||
 | 
			
		||||
  actor_rect.x = (int)roundf (x);
 | 
			
		||||
  actor_rect.y = (int)roundf (y);
 | 
			
		||||
  actor_rect.width = (int)roundf (x + width) - actor_rect.x;
 | 
			
		||||
  actor_rect.height = (int)roundf (y + height) - actor_rect.y;
 | 
			
		||||
 | 
			
		||||
  /* Calculate the scaled surface actor region. */
 | 
			
		||||
  region = cairo_region_create_rectangle (&actor_rect);
 | 
			
		||||
 | 
			
		||||
  cairo_region_intersect_rectangle (region,
 | 
			
		||||
				    &((cairo_rectangle_int_t) {
 | 
			
		||||
				      .x = monitor->rect.x,
 | 
			
		||||
				      .y = monitor->rect.y,
 | 
			
		||||
				      .width = monitor->rect.width,
 | 
			
		||||
				      .height = monitor->rect.height,
 | 
			
		||||
				    }));
 | 
			
		||||
 | 
			
		||||
  is_on_monitor = !cairo_region_is_empty (region);
 | 
			
		||||
  cairo_region_destroy (region);
 | 
			
		||||
 | 
			
		||||
  return is_on_monitor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_surface_actor_wayland_add_frame_callbacks (MetaSurfaceActorWayland *self,
 | 
			
		||||
                                                struct wl_list *frame_callbacks)
 | 
			
		||||
{
 | 
			
		||||
  MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
  wl_list_insert_list (&priv->frame_callback_list, frame_callbacks);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaWindow *
 | 
			
		||||
meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
 | 
			
		||||
{
 | 
			
		||||
  MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (META_SURFACE_ACTOR_WAYLAND (actor));
 | 
			
		||||
  MetaWaylandSurface *surface = priv->surface;
 | 
			
		||||
 | 
			
		||||
  return priv->surface->window;
 | 
			
		||||
  if (!surface)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  return surface->window;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -236,6 +345,26 @@ meta_surface_actor_wayland_get_preferred_height  (ClutterActor *self,
 | 
			
		||||
    *natural_height_p *= scale;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_surface_actor_wayland_paint (ClutterActor *actor)
 | 
			
		||||
{
 | 
			
		||||
  MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
 | 
			
		||||
  MetaSurfaceActorWaylandPrivate *priv =
 | 
			
		||||
    meta_surface_actor_wayland_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
  if (priv->surface)
 | 
			
		||||
    {
 | 
			
		||||
      MetaWaylandCompositor *compositor = priv->surface->compositor;
 | 
			
		||||
 | 
			
		||||
      wl_list_insert_list (&compositor->frame_callbacks, &priv->frame_callback_list);
 | 
			
		||||
      wl_list_init (&priv->frame_callback_list);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_signal_emit (actor, signals[PAINTING], 0);
 | 
			
		||||
 | 
			
		||||
  CLUTTER_ACTOR_CLASS (meta_surface_actor_wayland_parent_class)->paint (actor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_surface_actor_wayland_dispose (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
@@ -255,6 +384,7 @@ meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
 | 
			
		||||
 | 
			
		||||
  actor_class->get_preferred_width = meta_surface_actor_wayland_get_preferred_width;
 | 
			
		||||
  actor_class->get_preferred_height = meta_surface_actor_wayland_get_preferred_height;
 | 
			
		||||
  actor_class->paint = meta_surface_actor_wayland_paint;
 | 
			
		||||
 | 
			
		||||
  surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
 | 
			
		||||
  surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint;
 | 
			
		||||
@@ -267,6 +397,13 @@ meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
 | 
			
		||||
  surface_actor_class->get_window = meta_surface_actor_wayland_get_window;
 | 
			
		||||
 | 
			
		||||
  object_class->dispose = meta_surface_actor_wayland_dispose;
 | 
			
		||||
 | 
			
		||||
  signals[PAINTING] = g_signal_new ("painting",
 | 
			
		||||
                                    G_TYPE_FROM_CLASS (object_class),
 | 
			
		||||
                                    G_SIGNAL_RUN_LAST,
 | 
			
		||||
                                    0,
 | 
			
		||||
                                    NULL, NULL, NULL,
 | 
			
		||||
                                    G_TYPE_NONE, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -282,6 +419,7 @@ meta_surface_actor_wayland_new (MetaWaylandSurface *surface)
 | 
			
		||||
 | 
			
		||||
  g_assert (meta_is_wayland_compositor ());
 | 
			
		||||
 | 
			
		||||
  wl_list_init (&priv->frame_callback_list);
 | 
			
		||||
  priv->surface = surface;
 | 
			
		||||
 | 
			
		||||
  return META_SURFACE_ACTOR (self);
 | 
			
		||||
@@ -301,3 +439,18 @@ meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self)
 | 
			
		||||
  MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
 | 
			
		||||
  return priv->surface;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_surface_actor_wayland_surface_destroyed (MetaSurfaceActorWayland *self)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandFrameCallback *callback, *next;
 | 
			
		||||
  MetaSurfaceActorWaylandPrivate *priv =
 | 
			
		||||
    meta_surface_actor_wayland_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
  wl_list_for_each_safe (callback, next, &priv->frame_callback_list, link)
 | 
			
		||||
    {
 | 
			
		||||
      wl_resource_destroy (callback->resource);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  priv->surface = NULL;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,9 @@
 | 
			
		||||
#include "meta-surface-actor.h"
 | 
			
		||||
 | 
			
		||||
#include "wayland/meta-wayland.h"
 | 
			
		||||
#include "wayland/meta-wayland-private.h"
 | 
			
		||||
 | 
			
		||||
#include "backends/meta-monitor-manager-private.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
@@ -57,16 +60,28 @@ GType meta_surface_actor_wayland_get_type (void);
 | 
			
		||||
 | 
			
		||||
MetaSurfaceActor * meta_surface_actor_wayland_new (MetaWaylandSurface *surface);
 | 
			
		||||
MetaWaylandSurface * meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self);
 | 
			
		||||
void meta_surface_actor_wayland_surface_destroyed (MetaSurfaceActorWayland *self);
 | 
			
		||||
 | 
			
		||||
void meta_surface_actor_wayland_set_texture (MetaSurfaceActorWayland *self,
 | 
			
		||||
                                             CoglTexture *texture);
 | 
			
		||||
 | 
			
		||||
double meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor);
 | 
			
		||||
 | 
			
		||||
void meta_surface_actor_wayland_get_subsurface_rect (MetaSurfaceActorWayland *self,
 | 
			
		||||
                                                     MetaRectangle           *rect);
 | 
			
		||||
 | 
			
		||||
void meta_surface_actor_wayland_sync_state (MetaSurfaceActorWayland *self);
 | 
			
		||||
 | 
			
		||||
void meta_surface_actor_wayland_sync_state_recursive (MetaSurfaceActorWayland *self);
 | 
			
		||||
 | 
			
		||||
void meta_surface_actor_wayland_sync_subsurface_state (MetaSurfaceActorWayland *self);
 | 
			
		||||
 | 
			
		||||
gboolean meta_surface_actor_wayland_is_on_monitor (MetaSurfaceActorWayland *self,
 | 
			
		||||
                                                   MetaMonitorInfo         *monitor);
 | 
			
		||||
 | 
			
		||||
void meta_surface_actor_wayland_add_frame_callbacks (MetaSurfaceActorWayland *self,
 | 
			
		||||
                                                     struct wl_list *frame_callbacks);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */
 | 
			
		||||
 
 | 
			
		||||
@@ -416,6 +416,7 @@ meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
 | 
			
		||||
                                 int width, int height)
 | 
			
		||||
{
 | 
			
		||||
  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
 | 
			
		||||
  MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
 | 
			
		||||
 | 
			
		||||
  if (priv->last_width == width &&
 | 
			
		||||
      priv->last_height == height)
 | 
			
		||||
@@ -424,4 +425,5 @@ meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
 | 
			
		||||
  priv->size_changed = TRUE;
 | 
			
		||||
  priv->last_width = width;
 | 
			
		||||
  priv->last_height = height;
 | 
			
		||||
  meta_shaped_texture_set_fallback_size (stex, width, height);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										592
									
								
								src/compositor/meta-sync-ring.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										592
									
								
								src/compositor/meta-sync-ring.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,592 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This is based on an original C++ implementation for compiz that
 | 
			
		||||
 * carries the following copyright notice:
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright © 2011 NVIDIA Corporation
 | 
			
		||||
 *
 | 
			
		||||
 * Permission to use, copy, modify, distribute, and sell this software
 | 
			
		||||
 * and its documentation for any purpose is hereby granted without
 | 
			
		||||
 * fee, provided that the above copyright notice appear in all copies
 | 
			
		||||
 * and that both that copyright notice and this permission notice
 | 
			
		||||
 * appear in supporting documentation, and that the name of NVIDIA
 | 
			
		||||
 * Corporation not be used in advertising or publicity pertaining to
 | 
			
		||||
 * distribution of the software without specific, written prior
 | 
			
		||||
 * permission.  NVIDIA Corporation makes no representations about the
 | 
			
		||||
 * suitability of this software for any purpose. It is provided "as
 | 
			
		||||
 * is" without express or implied warranty.
 | 
			
		||||
 *
 | 
			
		||||
 * NVIDIA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
 | 
			
		||||
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 | 
			
		||||
 * FITNESS, IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY
 | 
			
		||||
 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
 | 
			
		||||
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * Authors: James Jones <jajones@nvidia.com>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <GL/gl.h>
 | 
			
		||||
#include <GL/glx.h>
 | 
			
		||||
#include <X11/extensions/sync.h>
 | 
			
		||||
 | 
			
		||||
#include <cogl/cogl.h>
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
 | 
			
		||||
#include <meta/util.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-sync-ring.h"
 | 
			
		||||
 | 
			
		||||
/* Theory of operation:
 | 
			
		||||
 *
 | 
			
		||||
 * We use a ring of NUM_SYNCS fence objects. On each frame we advance
 | 
			
		||||
 * to the next fence in the ring. For each fence we do:
 | 
			
		||||
 *
 | 
			
		||||
 * 1. fence is XSyncTriggerFence()'d and glWaitSync()'d
 | 
			
		||||
 * 2. NUM_SYNCS / 2 frames later, fence should be triggered
 | 
			
		||||
 * 3. fence is XSyncResetFence()'d
 | 
			
		||||
 * 4. NUM_SYNCS / 2 frames later, fence should be reset
 | 
			
		||||
 * 5. go back to 1 and re-use fence
 | 
			
		||||
 *
 | 
			
		||||
 * glClientWaitSync() and XAlarms are used in steps 2 and 4,
 | 
			
		||||
 * respectively, to double-check the expectections.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define NUM_SYNCS 10
 | 
			
		||||
#define MAX_SYNC_WAIT_TIME (1 * 1000 * 1000 * 1000) /* one sec */
 | 
			
		||||
#define MAX_REBOOT_ATTEMPTS 2
 | 
			
		||||
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
  META_SYNC_STATE_READY,
 | 
			
		||||
  META_SYNC_STATE_WAITING,
 | 
			
		||||
  META_SYNC_STATE_DONE,
 | 
			
		||||
  META_SYNC_STATE_RESET_PENDING,
 | 
			
		||||
} MetaSyncState;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  Display *xdisplay;
 | 
			
		||||
 | 
			
		||||
  XSyncFence xfence;
 | 
			
		||||
  GLsync gl_x11_sync;
 | 
			
		||||
  GLsync gpu_fence;
 | 
			
		||||
 | 
			
		||||
  XSyncCounter xcounter;
 | 
			
		||||
  XSyncAlarm xalarm;
 | 
			
		||||
  XSyncValue next_counter_value;
 | 
			
		||||
 | 
			
		||||
  MetaSyncState state;
 | 
			
		||||
} MetaSync;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  Display *xdisplay;
 | 
			
		||||
  int xsync_event_base;
 | 
			
		||||
  int xsync_error_base;
 | 
			
		||||
 | 
			
		||||
  GHashTable *alarm_to_sync;
 | 
			
		||||
 | 
			
		||||
  MetaSync *syncs_array[NUM_SYNCS];
 | 
			
		||||
  guint current_sync_idx;
 | 
			
		||||
  MetaSync *current_sync;
 | 
			
		||||
  guint warmup_syncs;
 | 
			
		||||
 | 
			
		||||
  guint reboots;
 | 
			
		||||
} MetaSyncRing;
 | 
			
		||||
 | 
			
		||||
static MetaSyncRing meta_sync_ring = { 0 };
 | 
			
		||||
 | 
			
		||||
static XSyncValue SYNC_VALUE_ZERO;
 | 
			
		||||
static XSyncValue SYNC_VALUE_ONE;
 | 
			
		||||
 | 
			
		||||
static const char*      (*meta_gl_get_string) (GLenum name);
 | 
			
		||||
static void             (*meta_gl_get_integerv) (GLenum  pname,
 | 
			
		||||
                                                 GLint  *params);
 | 
			
		||||
static const char*      (*meta_gl_get_stringi) (GLenum name,
 | 
			
		||||
                                                GLuint index);
 | 
			
		||||
static void             (*meta_gl_delete_sync) (GLsync sync);
 | 
			
		||||
static GLenum           (*meta_gl_client_wait_sync) (GLsync sync,
 | 
			
		||||
                                                     GLbitfield flags,
 | 
			
		||||
                                                     GLuint64 timeout);
 | 
			
		||||
static void             (*meta_gl_wait_sync) (GLsync sync,
 | 
			
		||||
                                              GLbitfield flags,
 | 
			
		||||
                                              GLuint64 timeout);
 | 
			
		||||
static GLsync           (*meta_gl_import_sync) (GLenum external_sync_type,
 | 
			
		||||
                                                GLintptr external_sync,
 | 
			
		||||
                                                GLbitfield flags);
 | 
			
		||||
static GLsync           (*meta_gl_fence_sync) (GLenum condition,
 | 
			
		||||
                                               GLbitfield flags);
 | 
			
		||||
 | 
			
		||||
static MetaSyncRing *
 | 
			
		||||
meta_sync_ring_get (void)
 | 
			
		||||
{
 | 
			
		||||
  if (meta_sync_ring.reboots > MAX_REBOOT_ATTEMPTS)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  return &meta_sync_ring;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
load_gl_symbol (const char  *name,
 | 
			
		||||
                void       **func)
 | 
			
		||||
{
 | 
			
		||||
  *func = cogl_get_proc_address (name);
 | 
			
		||||
  if (!*func)
 | 
			
		||||
    {
 | 
			
		||||
      meta_verbose ("MetaSyncRing: failed to resolve required GL symbol \"%s\"\n", name);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
check_gl_extensions (void)
 | 
			
		||||
{
 | 
			
		||||
  ClutterBackend *backend;
 | 
			
		||||
  CoglContext *cogl_context;
 | 
			
		||||
  CoglDisplay *cogl_display;
 | 
			
		||||
  CoglRenderer *cogl_renderer;
 | 
			
		||||
 | 
			
		||||
  backend = clutter_get_default_backend ();
 | 
			
		||||
  cogl_context = clutter_backend_get_cogl_context (backend);
 | 
			
		||||
  cogl_display = cogl_context_get_display (cogl_context);
 | 
			
		||||
  cogl_renderer = cogl_display_get_renderer (cogl_display);
 | 
			
		||||
 | 
			
		||||
  switch (cogl_renderer_get_driver (cogl_renderer))
 | 
			
		||||
    {
 | 
			
		||||
    case COGL_DRIVER_GL3:
 | 
			
		||||
      {
 | 
			
		||||
        int num_extensions, i;
 | 
			
		||||
        gboolean arb_sync = FALSE;
 | 
			
		||||
        gboolean x11_sync_object = FALSE;
 | 
			
		||||
 | 
			
		||||
        meta_gl_get_integerv (GL_NUM_EXTENSIONS, &num_extensions);
 | 
			
		||||
 | 
			
		||||
        for (i = 0; i < num_extensions; ++i)
 | 
			
		||||
          {
 | 
			
		||||
            const char *ext = meta_gl_get_stringi (GL_EXTENSIONS, i);
 | 
			
		||||
 | 
			
		||||
            if (g_strcmp0 ("GL_ARB_sync", ext) == 0)
 | 
			
		||||
              arb_sync = TRUE;
 | 
			
		||||
            else if (g_strcmp0 ("GL_EXT_x11_sync_object", ext) == 0)
 | 
			
		||||
              x11_sync_object = TRUE;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
        return arb_sync && x11_sync_object;
 | 
			
		||||
      }
 | 
			
		||||
    case COGL_DRIVER_GL:
 | 
			
		||||
      {
 | 
			
		||||
        const char *extensions = meta_gl_get_string (GL_EXTENSIONS);
 | 
			
		||||
        return (extensions != NULL &&
 | 
			
		||||
                strstr (extensions, "GL_ARB_sync") != NULL &&
 | 
			
		||||
                strstr (extensions, "GL_EXT_x11_sync_object") != NULL);
 | 
			
		||||
      }
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
load_required_symbols (void)
 | 
			
		||||
{
 | 
			
		||||
  static gboolean success = FALSE;
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  /* We don't link against libGL directly because cogl may want to
 | 
			
		||||
   * use something else. This assumes that cogl has been initialized
 | 
			
		||||
   * and dynamically loaded libGL at this point.
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  if (!load_gl_symbol ("glGetString", (void **) &meta_gl_get_string))
 | 
			
		||||
    goto out;
 | 
			
		||||
  if (!load_gl_symbol ("glGetIntegerv", (void **) &meta_gl_get_integerv))
 | 
			
		||||
    goto out;
 | 
			
		||||
  if (!load_gl_symbol ("glGetStringi", (void **) &meta_gl_get_stringi))
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  if (!check_gl_extensions ())
 | 
			
		||||
    {
 | 
			
		||||
      meta_verbose ("MetaSyncRing: couldn't find required GL extensions\n");
 | 
			
		||||
      goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!load_gl_symbol ("glDeleteSync", (void **) &meta_gl_delete_sync))
 | 
			
		||||
    goto out;
 | 
			
		||||
  if (!load_gl_symbol ("glClientWaitSync", (void **) &meta_gl_client_wait_sync))
 | 
			
		||||
    goto out;
 | 
			
		||||
  if (!load_gl_symbol ("glWaitSync", (void **) &meta_gl_wait_sync))
 | 
			
		||||
    goto out;
 | 
			
		||||
  if (!load_gl_symbol ("glImportSyncEXT", (void **) &meta_gl_import_sync))
 | 
			
		||||
    goto out;
 | 
			
		||||
  if (!load_gl_symbol ("glFenceSync", (void **) &meta_gl_fence_sync))
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  success = TRUE;
 | 
			
		||||
 out:
 | 
			
		||||
  return success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_sync_insert (MetaSync *self)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (self->state == META_SYNC_STATE_READY);
 | 
			
		||||
 | 
			
		||||
  XSyncTriggerFence (self->xdisplay, self->xfence);
 | 
			
		||||
  XFlush (self->xdisplay);
 | 
			
		||||
 | 
			
		||||
  meta_gl_wait_sync (self->gl_x11_sync, 0, GL_TIMEOUT_IGNORED);
 | 
			
		||||
  self->gpu_fence = meta_gl_fence_sync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
 | 
			
		||||
 | 
			
		||||
  self->state = META_SYNC_STATE_WAITING;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GLenum
 | 
			
		||||
meta_sync_check_update_finished (MetaSync *self,
 | 
			
		||||
                                 GLuint64  timeout)
 | 
			
		||||
{
 | 
			
		||||
  GLenum status = GL_WAIT_FAILED;
 | 
			
		||||
 | 
			
		||||
  switch (self->state)
 | 
			
		||||
    {
 | 
			
		||||
    case META_SYNC_STATE_DONE:
 | 
			
		||||
      status = GL_ALREADY_SIGNALED;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_SYNC_STATE_WAITING:
 | 
			
		||||
      status = meta_gl_client_wait_sync (self->gpu_fence, 0, timeout);
 | 
			
		||||
      if (status == GL_ALREADY_SIGNALED || status == GL_CONDITION_SATISFIED)
 | 
			
		||||
        {
 | 
			
		||||
          self->state = META_SYNC_STATE_DONE;
 | 
			
		||||
          meta_gl_delete_sync (self->gpu_fence);
 | 
			
		||||
          self->gpu_fence = 0;
 | 
			
		||||
        }
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_warn_if_fail (status != GL_WAIT_FAILED);
 | 
			
		||||
 | 
			
		||||
  return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_sync_reset (MetaSync *self)
 | 
			
		||||
{
 | 
			
		||||
  XSyncAlarmAttributes attrs;
 | 
			
		||||
  int overflow;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (self->state == META_SYNC_STATE_DONE);
 | 
			
		||||
 | 
			
		||||
  XSyncResetFence (self->xdisplay, self->xfence);
 | 
			
		||||
 | 
			
		||||
  attrs.trigger.wait_value = self->next_counter_value;
 | 
			
		||||
 | 
			
		||||
  XSyncChangeAlarm (self->xdisplay, self->xalarm, XSyncCAValue, &attrs);
 | 
			
		||||
  XSyncSetCounter (self->xdisplay, self->xcounter, self->next_counter_value);
 | 
			
		||||
 | 
			
		||||
  XSyncValueAdd (&self->next_counter_value,
 | 
			
		||||
                 self->next_counter_value,
 | 
			
		||||
                 SYNC_VALUE_ONE,
 | 
			
		||||
                 &overflow);
 | 
			
		||||
 | 
			
		||||
  self->state = META_SYNC_STATE_RESET_PENDING;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_sync_handle_event (MetaSync              *self,
 | 
			
		||||
                        XSyncAlarmNotifyEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (event->alarm == self->xalarm);
 | 
			
		||||
  g_return_if_fail (self->state == META_SYNC_STATE_RESET_PENDING);
 | 
			
		||||
 | 
			
		||||
  self->state = META_SYNC_STATE_READY;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaSync *
 | 
			
		||||
meta_sync_new (Display *xdisplay)
 | 
			
		||||
{
 | 
			
		||||
  MetaSync *self;
 | 
			
		||||
  XSyncAlarmAttributes attrs;
 | 
			
		||||
 | 
			
		||||
  self = g_malloc0 (sizeof (MetaSync));
 | 
			
		||||
 | 
			
		||||
  self->xdisplay = xdisplay;
 | 
			
		||||
 | 
			
		||||
  self->xfence = XSyncCreateFence (xdisplay, DefaultRootWindow (xdisplay), FALSE);
 | 
			
		||||
  self->gl_x11_sync = 0;
 | 
			
		||||
  self->gpu_fence = 0;
 | 
			
		||||
 | 
			
		||||
  self->xcounter = XSyncCreateCounter (xdisplay, SYNC_VALUE_ZERO);
 | 
			
		||||
 | 
			
		||||
  attrs.trigger.counter = self->xcounter;
 | 
			
		||||
  attrs.trigger.value_type = XSyncAbsolute;
 | 
			
		||||
  attrs.trigger.wait_value = SYNC_VALUE_ONE;
 | 
			
		||||
  attrs.trigger.test_type = XSyncPositiveTransition;
 | 
			
		||||
  attrs.events = TRUE;
 | 
			
		||||
  self->xalarm = XSyncCreateAlarm (xdisplay,
 | 
			
		||||
                                   XSyncCACounter |
 | 
			
		||||
                                   XSyncCAValueType |
 | 
			
		||||
                                   XSyncCAValue |
 | 
			
		||||
                                   XSyncCATestType |
 | 
			
		||||
                                   XSyncCAEvents,
 | 
			
		||||
                                   &attrs);
 | 
			
		||||
 | 
			
		||||
  XSyncIntToValue (&self->next_counter_value, 1);
 | 
			
		||||
 | 
			
		||||
  self->state = META_SYNC_STATE_READY;
 | 
			
		||||
 | 
			
		||||
  return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_sync_import (MetaSync *self)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (self->gl_x11_sync == 0);
 | 
			
		||||
  self->gl_x11_sync = meta_gl_import_sync (GL_SYNC_X11_FENCE_EXT, self->xfence, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Bool
 | 
			
		||||
alarm_event_predicate (Display  *dpy,
 | 
			
		||||
                       XEvent   *event,
 | 
			
		||||
                       XPointer  data)
 | 
			
		||||
{
 | 
			
		||||
  MetaSyncRing *ring = meta_sync_ring_get ();
 | 
			
		||||
 | 
			
		||||
  if (!ring)
 | 
			
		||||
    return False;
 | 
			
		||||
 | 
			
		||||
  if (event->type == ring->xsync_event_base + XSyncAlarmNotify)
 | 
			
		||||
    {
 | 
			
		||||
      if (((MetaSync *) data)->xalarm == ((XSyncAlarmNotifyEvent *) event)->alarm)
 | 
			
		||||
        return True;
 | 
			
		||||
    }
 | 
			
		||||
  return False;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_sync_free (MetaSync *self)
 | 
			
		||||
{
 | 
			
		||||
  /* When our assumptions don't hold, something has gone wrong but we
 | 
			
		||||
   * don't know what, so we reboot the ring. While doing that, we
 | 
			
		||||
   * trigger fences before deleting them to try to get ourselves out
 | 
			
		||||
   * of a potentially stuck GPU state.
 | 
			
		||||
   */
 | 
			
		||||
  switch (self->state)
 | 
			
		||||
    {
 | 
			
		||||
    case META_SYNC_STATE_WAITING:
 | 
			
		||||
      meta_gl_delete_sync (self->gpu_fence);
 | 
			
		||||
      break;
 | 
			
		||||
    case META_SYNC_STATE_DONE:
 | 
			
		||||
      /* nothing to do */
 | 
			
		||||
      break;
 | 
			
		||||
    case META_SYNC_STATE_RESET_PENDING:
 | 
			
		||||
      {
 | 
			
		||||
        XEvent event;
 | 
			
		||||
        XIfEvent (self->xdisplay, &event, alarm_event_predicate, (XPointer) self);
 | 
			
		||||
        meta_sync_handle_event (self, (XSyncAlarmNotifyEvent *) &event);
 | 
			
		||||
      }
 | 
			
		||||
      /* fall through */
 | 
			
		||||
    case META_SYNC_STATE_READY:
 | 
			
		||||
      XSyncTriggerFence (self->xdisplay, self->xfence);
 | 
			
		||||
      XFlush (self->xdisplay);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_gl_delete_sync (self->gl_x11_sync);
 | 
			
		||||
  XSyncDestroyFence (self->xdisplay, self->xfence);
 | 
			
		||||
  XSyncDestroyCounter (self->xdisplay, self->xcounter);
 | 
			
		||||
  XSyncDestroyAlarm (self->xdisplay, self->xalarm);
 | 
			
		||||
 | 
			
		||||
  g_free (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_sync_ring_init (Display *xdisplay)
 | 
			
		||||
{
 | 
			
		||||
  gint major, minor;
 | 
			
		||||
  guint i;
 | 
			
		||||
  MetaSyncRing *ring = meta_sync_ring_get ();
 | 
			
		||||
 | 
			
		||||
  if (!ring)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (xdisplay != NULL, FALSE);
 | 
			
		||||
  g_return_val_if_fail (ring->xdisplay == NULL, FALSE);
 | 
			
		||||
 | 
			
		||||
  if (!load_required_symbols ())
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (!XSyncQueryExtension (xdisplay, &ring->xsync_event_base, &ring->xsync_error_base) ||
 | 
			
		||||
      !XSyncInitialize (xdisplay, &major, &minor))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  XSyncIntToValue (&SYNC_VALUE_ZERO, 0);
 | 
			
		||||
  XSyncIntToValue (&SYNC_VALUE_ONE, 1);
 | 
			
		||||
 | 
			
		||||
  ring->xdisplay = xdisplay;
 | 
			
		||||
 | 
			
		||||
  ring->alarm_to_sync = g_hash_table_new (NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < NUM_SYNCS; ++i)
 | 
			
		||||
    {
 | 
			
		||||
      MetaSync *sync = meta_sync_new (ring->xdisplay);
 | 
			
		||||
      ring->syncs_array[i] = sync;
 | 
			
		||||
      g_hash_table_replace (ring->alarm_to_sync, (gpointer) sync->xalarm, sync);
 | 
			
		||||
    }
 | 
			
		||||
  /* Since the connection we create the X fences on isn't the same as
 | 
			
		||||
   * the one used for the GLX context, we need to XSync() here to
 | 
			
		||||
   * ensure glImportSync() succeeds. */
 | 
			
		||||
  XSync (xdisplay, False);
 | 
			
		||||
  for (i = 0; i < NUM_SYNCS; ++i)
 | 
			
		||||
    meta_sync_import (ring->syncs_array[i]);
 | 
			
		||||
 | 
			
		||||
  ring->current_sync_idx = 0;
 | 
			
		||||
  ring->current_sync = ring->syncs_array[0];
 | 
			
		||||
  ring->warmup_syncs = 0;
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_sync_ring_destroy (void)
 | 
			
		||||
{
 | 
			
		||||
  guint i;
 | 
			
		||||
  MetaSyncRing *ring = meta_sync_ring_get ();
 | 
			
		||||
 | 
			
		||||
  if (!ring)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (ring->xdisplay != NULL);
 | 
			
		||||
 | 
			
		||||
  ring->current_sync_idx = 0;
 | 
			
		||||
  ring->current_sync = NULL;
 | 
			
		||||
  ring->warmup_syncs = 0;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < NUM_SYNCS; ++i)
 | 
			
		||||
    meta_sync_free (ring->syncs_array[i]);
 | 
			
		||||
 | 
			
		||||
  g_hash_table_destroy (ring->alarm_to_sync);
 | 
			
		||||
 | 
			
		||||
  ring->xsync_event_base = 0;
 | 
			
		||||
  ring->xsync_error_base = 0;
 | 
			
		||||
  ring->xdisplay = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_sync_ring_reboot (Display *xdisplay)
 | 
			
		||||
{
 | 
			
		||||
  MetaSyncRing *ring = meta_sync_ring_get ();
 | 
			
		||||
 | 
			
		||||
  if (!ring)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  meta_sync_ring_destroy ();
 | 
			
		||||
 | 
			
		||||
  ring->reboots += 1;
 | 
			
		||||
 | 
			
		||||
  if (!meta_sync_ring_get ())
 | 
			
		||||
    {
 | 
			
		||||
      meta_warning ("MetaSyncRing: Too many reboots -- disabling\n");
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return meta_sync_ring_init (xdisplay);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_sync_ring_after_frame (void)
 | 
			
		||||
{
 | 
			
		||||
  MetaSyncRing *ring = meta_sync_ring_get ();
 | 
			
		||||
 | 
			
		||||
  if (!ring)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (ring->xdisplay != NULL, FALSE);
 | 
			
		||||
 | 
			
		||||
  if (ring->warmup_syncs >= NUM_SYNCS / 2)
 | 
			
		||||
    {
 | 
			
		||||
      guint reset_sync_idx = (ring->current_sync_idx + NUM_SYNCS - (NUM_SYNCS / 2)) % NUM_SYNCS;
 | 
			
		||||
      MetaSync *sync_to_reset = ring->syncs_array[reset_sync_idx];
 | 
			
		||||
 | 
			
		||||
      GLenum status = meta_sync_check_update_finished (sync_to_reset, 0);
 | 
			
		||||
      if (status == GL_TIMEOUT_EXPIRED)
 | 
			
		||||
        {
 | 
			
		||||
          meta_warning ("MetaSyncRing: We should never wait for a sync -- add more syncs?\n");
 | 
			
		||||
          status = meta_sync_check_update_finished (sync_to_reset, MAX_SYNC_WAIT_TIME);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (status != GL_ALREADY_SIGNALED && status != GL_CONDITION_SATISFIED)
 | 
			
		||||
        {
 | 
			
		||||
          meta_warning ("MetaSyncRing: Timed out waiting for sync object.\n");
 | 
			
		||||
          return meta_sync_ring_reboot (ring->xdisplay);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      meta_sync_reset (sync_to_reset);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      ring->warmup_syncs += 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  ring->current_sync_idx += 1;
 | 
			
		||||
  ring->current_sync_idx %= NUM_SYNCS;
 | 
			
		||||
 | 
			
		||||
  ring->current_sync = ring->syncs_array[ring->current_sync_idx];
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_sync_ring_insert_wait (void)
 | 
			
		||||
{
 | 
			
		||||
  MetaSyncRing *ring = meta_sync_ring_get ();
 | 
			
		||||
 | 
			
		||||
  if (!ring)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (ring->xdisplay != NULL, FALSE);
 | 
			
		||||
 | 
			
		||||
  if (ring->current_sync->state != META_SYNC_STATE_READY)
 | 
			
		||||
    {
 | 
			
		||||
      meta_warning ("MetaSyncRing: Sync object is not ready -- were events handled properly?\n");
 | 
			
		||||
      if (!meta_sync_ring_reboot (ring->xdisplay))
 | 
			
		||||
        return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_sync_insert (ring->current_sync);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_sync_ring_handle_event (XEvent *xevent)
 | 
			
		||||
{
 | 
			
		||||
  XSyncAlarmNotifyEvent *event;
 | 
			
		||||
  MetaSync *sync;
 | 
			
		||||
  MetaSyncRing *ring = meta_sync_ring_get ();
 | 
			
		||||
 | 
			
		||||
  if (!ring)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (ring->xdisplay != NULL);
 | 
			
		||||
 | 
			
		||||
  if (xevent->type != (ring->xsync_event_base + XSyncAlarmNotify))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  event = (XSyncAlarmNotifyEvent *) xevent;
 | 
			
		||||
 | 
			
		||||
  sync = g_hash_table_lookup (ring->alarm_to_sync, (gpointer) event->alarm);
 | 
			
		||||
  if (sync)
 | 
			
		||||
    meta_sync_handle_event (sync, event);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								src/compositor/meta-sync-ring.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/compositor/meta-sync-ring.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
#ifndef _META_SYNC_RING_H_
 | 
			
		||||
#define _META_SYNC_RING_H_
 | 
			
		||||
 | 
			
		||||
#include <glib.h>
 | 
			
		||||
 | 
			
		||||
#include <X11/Xlib.h>
 | 
			
		||||
 | 
			
		||||
gboolean meta_sync_ring_init (Display *dpy);
 | 
			
		||||
void meta_sync_ring_destroy (void);
 | 
			
		||||
gboolean meta_sync_ring_after_frame (void);
 | 
			
		||||
gboolean meta_sync_ring_insert_wait (void);
 | 
			
		||||
void meta_sync_ring_handle_event (XEvent *event);
 | 
			
		||||
 | 
			
		||||
#endif  /* _META_SYNC_RING_H_ */
 | 
			
		||||
@@ -8,6 +8,7 @@
 | 
			
		||||
#include <X11/extensions/Xdamage.h>
 | 
			
		||||
#include <meta/compositor-mutter.h>
 | 
			
		||||
#include "meta-surface-actor.h"
 | 
			
		||||
#include "meta-plugin-manager.h"
 | 
			
		||||
 | 
			
		||||
MetaWindowActor *meta_window_actor_new (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
@@ -18,12 +19,10 @@ void meta_window_actor_show (MetaWindowActor *self,
 | 
			
		||||
void meta_window_actor_hide (MetaWindowActor *self,
 | 
			
		||||
                             MetaCompEffect   effect);
 | 
			
		||||
 | 
			
		||||
void meta_window_actor_maximize   (MetaWindowActor *self,
 | 
			
		||||
                                   MetaRectangle   *old_rect,
 | 
			
		||||
                                   MetaRectangle   *new_rect);
 | 
			
		||||
void meta_window_actor_unmaximize (MetaWindowActor *self,
 | 
			
		||||
                                   MetaRectangle   *old_rect,
 | 
			
		||||
                                   MetaRectangle   *new_rect);
 | 
			
		||||
void meta_window_actor_size_change   (MetaWindowActor *self,
 | 
			
		||||
                                      MetaSizeChange   which_change,
 | 
			
		||||
                                      MetaRectangle   *old_frame_rect,
 | 
			
		||||
                                      MetaRectangle   *old_buffer_rect);
 | 
			
		||||
 | 
			
		||||
void meta_window_actor_process_x11_damage (MetaWindowActor    *self,
 | 
			
		||||
                                           XDamageNotifyEvent *event);
 | 
			
		||||
@@ -55,8 +54,8 @@ void     meta_window_actor_sync_updates_frozen (MetaWindowActor *self);
 | 
			
		||||
void     meta_window_actor_queue_frame_drawn   (MetaWindowActor *self,
 | 
			
		||||
                                                gboolean         no_delay_frame);
 | 
			
		||||
 | 
			
		||||
void meta_window_actor_effect_completed (MetaWindowActor *actor,
 | 
			
		||||
                                         gulong           event);
 | 
			
		||||
void meta_window_actor_effect_completed (MetaWindowActor  *actor,
 | 
			
		||||
                                         MetaPluginEffect  event);
 | 
			
		||||
 | 
			
		||||
MetaSurfaceActor *meta_window_actor_get_surface (MetaWindowActor *self);
 | 
			
		||||
void meta_window_actor_update_surface (MetaWindowActor *self);
 | 
			
		||||
 
 | 
			
		||||
@@ -20,10 +20,11 @@
 | 
			
		||||
#include "frame.h"
 | 
			
		||||
#include <meta/window.h>
 | 
			
		||||
#include <meta/meta-shaped-texture.h>
 | 
			
		||||
#include <meta/meta-enum-types.h>
 | 
			
		||||
#include <meta/meta-shadow-factory.h>
 | 
			
		||||
 | 
			
		||||
#include "compositor-private.h"
 | 
			
		||||
#include "meta-shaped-texture-private.h"
 | 
			
		||||
#include "meta-shadow-factory-private.h"
 | 
			
		||||
#include "meta-window-actor-private.h"
 | 
			
		||||
#include "meta-texture-rectangle.h"
 | 
			
		||||
#include "region-utils.h"
 | 
			
		||||
@@ -74,6 +75,8 @@ struct _MetaWindowActorPrivate
 | 
			
		||||
  MetaWindowShape  *shadow_shape;
 | 
			
		||||
  char *            shadow_class;
 | 
			
		||||
 | 
			
		||||
  MetaShadowMode    shadow_mode;
 | 
			
		||||
 | 
			
		||||
  guint             send_frame_messages_timer;
 | 
			
		||||
  gint64            frame_drawn_time;
 | 
			
		||||
 | 
			
		||||
@@ -87,8 +90,7 @@ struct _MetaWindowActorPrivate
 | 
			
		||||
   */
 | 
			
		||||
  gint              minimize_in_progress;
 | 
			
		||||
  gint              unminimize_in_progress;
 | 
			
		||||
  gint              maximize_in_progress;
 | 
			
		||||
  gint              unmaximize_in_progress;
 | 
			
		||||
  gint              size_change_in_progress;
 | 
			
		||||
  gint              map_in_progress;
 | 
			
		||||
  gint              destroy_in_progress;
 | 
			
		||||
 | 
			
		||||
@@ -110,8 +112,6 @@ struct _MetaWindowActorPrivate
 | 
			
		||||
 | 
			
		||||
  guint		    needs_destroy	   : 1;
 | 
			
		||||
 | 
			
		||||
  guint             no_shadow              : 1;
 | 
			
		||||
 | 
			
		||||
  guint             updates_frozen         : 1;
 | 
			
		||||
  guint             first_frame_state      : 2; /* FirstFrameState */
 | 
			
		||||
};
 | 
			
		||||
@@ -147,7 +147,7 @@ static guint signals[LAST_SIGNAL] = { 0 };
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
  PROP_META_WINDOW = 1,
 | 
			
		||||
  PROP_NO_SHADOW,
 | 
			
		||||
  PROP_SHADOW_MODE,
 | 
			
		||||
  PROP_SHADOW_CLASS
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -245,14 +245,15 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
 | 
			
		||||
                                   PROP_META_WINDOW,
 | 
			
		||||
                                   pspec);
 | 
			
		||||
 | 
			
		||||
  pspec = g_param_spec_boolean ("no-shadow",
 | 
			
		||||
                                "No shadow",
 | 
			
		||||
                                "Do not add shaddow to this window",
 | 
			
		||||
                                FALSE,
 | 
			
		||||
                                G_PARAM_READWRITE);
 | 
			
		||||
  pspec = g_param_spec_enum ("shadow-mode",
 | 
			
		||||
                             "Shadow mode",
 | 
			
		||||
                             "Decides when to paint shadows",
 | 
			
		||||
                             META_TYPE_SHADOW_MODE,
 | 
			
		||||
                             META_SHADOW_MODE_AUTO,
 | 
			
		||||
                             G_PARAM_READWRITE);
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (object_class,
 | 
			
		||||
                                   PROP_NO_SHADOW,
 | 
			
		||||
                                   PROP_SHADOW_MODE,
 | 
			
		||||
                                   pspec);
 | 
			
		||||
 | 
			
		||||
  pspec = g_param_spec_string ("shadow-class",
 | 
			
		||||
@@ -510,14 +511,14 @@ meta_window_actor_set_property (GObject      *object,
 | 
			
		||||
      g_signal_connect_object (priv->window, "notify::appears-focused",
 | 
			
		||||
                               G_CALLBACK (window_appears_focused_notify), self, 0);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_NO_SHADOW:
 | 
			
		||||
    case PROP_SHADOW_MODE:
 | 
			
		||||
      {
 | 
			
		||||
        gboolean newv = g_value_get_boolean (value);
 | 
			
		||||
        MetaShadowMode newv = g_value_get_enum (value);
 | 
			
		||||
 | 
			
		||||
        if (newv == priv->no_shadow)
 | 
			
		||||
        if (newv == priv->shadow_mode)
 | 
			
		||||
          return;
 | 
			
		||||
 | 
			
		||||
        priv->no_shadow = newv;
 | 
			
		||||
        priv->shadow_mode = newv;
 | 
			
		||||
 | 
			
		||||
        meta_window_actor_invalidate_shadow (self);
 | 
			
		||||
      }
 | 
			
		||||
@@ -554,8 +555,8 @@ meta_window_actor_get_property (GObject      *object,
 | 
			
		||||
    case PROP_META_WINDOW:
 | 
			
		||||
      g_value_set_object (value, priv->window);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_NO_SHADOW:
 | 
			
		||||
      g_value_set_boolean (value, priv->no_shadow);
 | 
			
		||||
    case PROP_SHADOW_MODE:
 | 
			
		||||
      g_value_set_enum (value, priv->shadow_mode);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_SHADOW_CLASS:
 | 
			
		||||
      g_value_set_string (value, priv->shadow_class);
 | 
			
		||||
@@ -615,8 +616,10 @@ meta_window_actor_get_shape_bounds (MetaWindowActor       *self,
 | 
			
		||||
#ifdef HAVE_WAYLAND
 | 
			
		||||
  if (META_IS_SURFACE_ACTOR_WAYLAND (priv->surface))
 | 
			
		||||
    {
 | 
			
		||||
      double scale = priv->surface ?
 | 
			
		||||
                     meta_surface_actor_wayland_get_scale (META_SURFACE_ACTOR_WAYLAND (priv->surface)) : 1.;
 | 
			
		||||
      MetaSurfaceActorWayland *surface_actor =
 | 
			
		||||
        META_SURFACE_ACTOR_WAYLAND (priv->surface);
 | 
			
		||||
      double scale = meta_surface_actor_wayland_get_scale (surface_actor);
 | 
			
		||||
 | 
			
		||||
      bounds->x *= scale;
 | 
			
		||||
      bounds->y *= scale;
 | 
			
		||||
      bounds->width *= scale;
 | 
			
		||||
@@ -802,8 +805,10 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  if (priv->no_shadow)
 | 
			
		||||
  if (priv->shadow_mode == META_SHADOW_MODE_FORCED_OFF)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
  if (priv->shadow_mode == META_SHADOW_MODE_FORCED_ON)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  /* Leaving out shadows for maximized and fullscreen windows is an effeciency
 | 
			
		||||
   * win and also prevents the unsightly effect of the shadow of maximized
 | 
			
		||||
@@ -827,21 +832,23 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * Do not add shadows to non-opaque windows; eventually we should generate
 | 
			
		||||
   * a shadow from the input shape for such windows.
 | 
			
		||||
   * Do not add shadows to non-opaque (ARGB32) windows, as we can't easily
 | 
			
		||||
   * generate shadows for them.
 | 
			
		||||
   */
 | 
			
		||||
  if (is_non_opaque (self))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * Add shadows to override redirect windows on X11 unless the toolkit
 | 
			
		||||
   * indicates that it is handling shadows itself (e.g., Gtk menus).
 | 
			
		||||
   * If a window specifies that it has custom frame extents, that likely
 | 
			
		||||
   * means that it is drawing a shadow itself. Don't draw our own.
 | 
			
		||||
   */
 | 
			
		||||
  if (priv->window->override_redirect &&
 | 
			
		||||
      !priv->window->has_custom_frame_extents)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
  if (priv->window->has_custom_frame_extents)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
  /*
 | 
			
		||||
   * Generate shadows for all other windows.
 | 
			
		||||
   */
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -1036,20 +1043,18 @@ gboolean
 | 
			
		||||
meta_window_actor_effect_in_progress (MetaWindowActor *self)
 | 
			
		||||
{
 | 
			
		||||
  return (self->priv->minimize_in_progress ||
 | 
			
		||||
	  self->priv->maximize_in_progress ||
 | 
			
		||||
	  self->priv->unmaximize_in_progress ||
 | 
			
		||||
	  self->priv->size_change_in_progress ||
 | 
			
		||||
	  self->priv->map_in_progress ||
 | 
			
		||||
	  self->priv->destroy_in_progress);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
is_freeze_thaw_effect (gulong event)
 | 
			
		||||
is_freeze_thaw_effect (MetaPluginEffect event)
 | 
			
		||||
{
 | 
			
		||||
  switch (event)
 | 
			
		||||
  {
 | 
			
		||||
  case META_PLUGIN_DESTROY:
 | 
			
		||||
  case META_PLUGIN_MAXIMIZE:
 | 
			
		||||
  case META_PLUGIN_UNMAXIMIZE:
 | 
			
		||||
  case META_PLUGIN_SIZE_CHANGE:
 | 
			
		||||
    return TRUE;
 | 
			
		||||
    break;
 | 
			
		||||
  default:
 | 
			
		||||
@@ -1058,8 +1063,8 @@ is_freeze_thaw_effect (gulong event)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
start_simple_effect (MetaWindowActor *self,
 | 
			
		||||
                     gulong        event)
 | 
			
		||||
start_simple_effect (MetaWindowActor  *self,
 | 
			
		||||
                     MetaPluginEffect  event)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
  MetaCompositor *compositor = priv->compositor;
 | 
			
		||||
@@ -1068,6 +1073,8 @@ start_simple_effect (MetaWindowActor *self,
 | 
			
		||||
 | 
			
		||||
  switch (event)
 | 
			
		||||
  {
 | 
			
		||||
  case META_PLUGIN_NONE:
 | 
			
		||||
    return FALSE;
 | 
			
		||||
  case META_PLUGIN_MINIMIZE:
 | 
			
		||||
    counter = &priv->minimize_in_progress;
 | 
			
		||||
    break;
 | 
			
		||||
@@ -1080,8 +1087,7 @@ start_simple_effect (MetaWindowActor *self,
 | 
			
		||||
  case META_PLUGIN_DESTROY:
 | 
			
		||||
    counter = &priv->destroy_in_progress;
 | 
			
		||||
    break;
 | 
			
		||||
  case META_PLUGIN_UNMAXIMIZE:
 | 
			
		||||
  case META_PLUGIN_MAXIMIZE:
 | 
			
		||||
  case META_PLUGIN_SIZE_CHANGE:
 | 
			
		||||
  case META_PLUGIN_SWITCH_WORKSPACE:
 | 
			
		||||
    g_assert_not_reached ();
 | 
			
		||||
    break;
 | 
			
		||||
@@ -1123,8 +1129,8 @@ meta_window_actor_after_effects (MetaWindowActor *self)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_window_actor_effect_completed (MetaWindowActor *self,
 | 
			
		||||
                                    gulong           event)
 | 
			
		||||
meta_window_actor_effect_completed (MetaWindowActor  *self,
 | 
			
		||||
                                    MetaPluginEffect  event)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActorPrivate *priv   = self->priv;
 | 
			
		||||
 | 
			
		||||
@@ -1134,6 +1140,8 @@ meta_window_actor_effect_completed (MetaWindowActor *self,
 | 
			
		||||
 | 
			
		||||
  switch (event)
 | 
			
		||||
  {
 | 
			
		||||
  case META_PLUGIN_NONE:
 | 
			
		||||
    break;
 | 
			
		||||
  case META_PLUGIN_MINIMIZE:
 | 
			
		||||
    {
 | 
			
		||||
      priv->minimize_in_progress--;
 | 
			
		||||
@@ -1176,20 +1184,12 @@ meta_window_actor_effect_completed (MetaWindowActor *self,
 | 
			
		||||
	priv->destroy_in_progress = 0;
 | 
			
		||||
      }
 | 
			
		||||
    break;
 | 
			
		||||
  case META_PLUGIN_UNMAXIMIZE:
 | 
			
		||||
    priv->unmaximize_in_progress--;
 | 
			
		||||
    if (priv->unmaximize_in_progress < 0)
 | 
			
		||||
  case META_PLUGIN_SIZE_CHANGE:
 | 
			
		||||
    priv->size_change_in_progress--;
 | 
			
		||||
    if (priv->size_change_in_progress < 0)
 | 
			
		||||
      {
 | 
			
		||||
	g_warning ("Error in unmaximize accounting.");
 | 
			
		||||
	priv->unmaximize_in_progress = 0;
 | 
			
		||||
      }
 | 
			
		||||
    break;
 | 
			
		||||
  case META_PLUGIN_MAXIMIZE:
 | 
			
		||||
    priv->maximize_in_progress--;
 | 
			
		||||
    if (priv->maximize_in_progress < 0)
 | 
			
		||||
      {
 | 
			
		||||
	g_warning ("Error in maximize accounting.");
 | 
			
		||||
	priv->maximize_in_progress = 0;
 | 
			
		||||
	g_warning ("Error in size change accounting.");
 | 
			
		||||
	priv->size_change_in_progress = 0;
 | 
			
		||||
      }
 | 
			
		||||
    break;
 | 
			
		||||
  case META_PLUGIN_SWITCH_WORKSPACE:
 | 
			
		||||
@@ -1300,7 +1300,7 @@ meta_window_actor_show (MetaWindowActor   *self,
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
  MetaCompositor *compositor = priv->compositor;
 | 
			
		||||
  gulong event = 0;
 | 
			
		||||
  MetaPluginEffect event;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (!priv->visible);
 | 
			
		||||
 | 
			
		||||
@@ -1315,14 +1315,13 @@ meta_window_actor_show (MetaWindowActor   *self,
 | 
			
		||||
      event = META_PLUGIN_UNMINIMIZE;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_COMP_EFFECT_NONE:
 | 
			
		||||
      event = META_PLUGIN_NONE;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_COMP_EFFECT_DESTROY:
 | 
			
		||||
    case META_COMP_EFFECT_MINIMIZE:
 | 
			
		||||
    default:
 | 
			
		||||
      g_assert_not_reached();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (compositor->switch_workspace_in_progress ||
 | 
			
		||||
      event == 0 ||
 | 
			
		||||
      !start_simple_effect (self, event))
 | 
			
		||||
    {
 | 
			
		||||
      clutter_actor_show (CLUTTER_ACTOR (self));
 | 
			
		||||
@@ -1335,7 +1334,7 @@ meta_window_actor_hide (MetaWindowActor *self,
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
  MetaCompositor *compositor = priv->compositor;
 | 
			
		||||
  gulong event = 0;
 | 
			
		||||
  MetaPluginEffect event;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (priv->visible);
 | 
			
		||||
 | 
			
		||||
@@ -1357,70 +1356,32 @@ meta_window_actor_hide (MetaWindowActor *self,
 | 
			
		||||
      event = META_PLUGIN_MINIMIZE;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_COMP_EFFECT_NONE:
 | 
			
		||||
      event = META_PLUGIN_NONE;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_COMP_EFFECT_UNMINIMIZE:
 | 
			
		||||
    case META_COMP_EFFECT_CREATE:
 | 
			
		||||
    default:
 | 
			
		||||
      g_assert_not_reached();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (event == 0 ||
 | 
			
		||||
      !start_simple_effect (self, event))
 | 
			
		||||
  if (!start_simple_effect (self, event))
 | 
			
		||||
    clutter_actor_hide (CLUTTER_ACTOR (self));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_window_actor_maximize (MetaWindowActor    *self,
 | 
			
		||||
                            MetaRectangle      *old_rect,
 | 
			
		||||
                            MetaRectangle      *new_rect)
 | 
			
		||||
meta_window_actor_size_change (MetaWindowActor    *self,
 | 
			
		||||
                               MetaSizeChange      which_change,
 | 
			
		||||
                               MetaRectangle      *old_frame_rect,
 | 
			
		||||
                               MetaRectangle      *old_buffer_rect)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
  MetaCompositor *compositor = priv->compositor;
 | 
			
		||||
 | 
			
		||||
  /* The window has already been resized (in order to compute new_rect),
 | 
			
		||||
   * which by side effect caused the actor to be resized. Restore it to the
 | 
			
		||||
   * old size and position */
 | 
			
		||||
  clutter_actor_set_position (CLUTTER_ACTOR (self), old_rect->x, old_rect->y);
 | 
			
		||||
  clutter_actor_set_size (CLUTTER_ACTOR (self), old_rect->width, old_rect->height);
 | 
			
		||||
 | 
			
		||||
  self->priv->maximize_in_progress++;
 | 
			
		||||
  self->priv->size_change_in_progress++;
 | 
			
		||||
  meta_window_actor_freeze (self);
 | 
			
		||||
 | 
			
		||||
  if (!meta_plugin_manager_event_maximize (compositor->plugin_mgr,
 | 
			
		||||
                                           self,
 | 
			
		||||
                                           META_PLUGIN_MAXIMIZE,
 | 
			
		||||
                                           new_rect->x, new_rect->y,
 | 
			
		||||
                                           new_rect->width, new_rect->height))
 | 
			
		||||
 | 
			
		||||
  if (!meta_plugin_manager_event_size_change (compositor->plugin_mgr, self,
 | 
			
		||||
                                              which_change, old_frame_rect, old_buffer_rect))
 | 
			
		||||
    {
 | 
			
		||||
      self->priv->maximize_in_progress--;
 | 
			
		||||
      meta_window_actor_thaw (self);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_window_actor_unmaximize (MetaWindowActor   *self,
 | 
			
		||||
                              MetaRectangle     *old_rect,
 | 
			
		||||
                              MetaRectangle     *new_rect)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
  MetaCompositor *compositor = priv->compositor;
 | 
			
		||||
 | 
			
		||||
  /* The window has already been resized (in order to compute new_rect),
 | 
			
		||||
   * which by side effect caused the actor to be resized. Restore it to the
 | 
			
		||||
   * old size and position */
 | 
			
		||||
  clutter_actor_set_position (CLUTTER_ACTOR (self), old_rect->x, old_rect->y);
 | 
			
		||||
  clutter_actor_set_size (CLUTTER_ACTOR (self), old_rect->width, old_rect->height);
 | 
			
		||||
 | 
			
		||||
  self->priv->unmaximize_in_progress++;
 | 
			
		||||
  meta_window_actor_freeze (self);
 | 
			
		||||
 | 
			
		||||
  if (!meta_plugin_manager_event_maximize (compositor->plugin_mgr,
 | 
			
		||||
                                           self,
 | 
			
		||||
                                           META_PLUGIN_UNMAXIMIZE,
 | 
			
		||||
                                           new_rect->x, new_rect->y,
 | 
			
		||||
                                           new_rect->width, new_rect->height))
 | 
			
		||||
    {
 | 
			
		||||
      self->priv->unmaximize_in_progress--;
 | 
			
		||||
      self->priv->size_change_in_progress--;
 | 
			
		||||
      meta_window_actor_thaw (self);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -58,9 +58,7 @@ meta_window_group_paint (ClutterActor *actor)
 | 
			
		||||
  cairo_region_t *clip_region;
 | 
			
		||||
  cairo_region_t *unobscured_region;
 | 
			
		||||
  cairo_rectangle_int_t visible_rect, clip_rect;
 | 
			
		||||
  int paint_x_offset, paint_y_offset;
 | 
			
		||||
  int paint_x_origin, paint_y_origin;
 | 
			
		||||
  int actor_x_origin, actor_y_origin;
 | 
			
		||||
  int screen_width, screen_height;
 | 
			
		||||
 | 
			
		||||
  MetaWindowGroup *window_group = META_WINDOW_GROUP (actor);
 | 
			
		||||
@@ -82,7 +80,7 @@ meta_window_group_paint (ClutterActor *actor)
 | 
			
		||||
   * on the stage.
 | 
			
		||||
   */
 | 
			
		||||
  if (!meta_actor_painting_untransformed (screen_width, screen_height, &paint_x_origin, &paint_y_origin) ||
 | 
			
		||||
      !meta_actor_is_untransformed (actor, &actor_x_origin, &actor_y_origin))
 | 
			
		||||
      !meta_actor_is_untransformed (actor, NULL, NULL))
 | 
			
		||||
    {
 | 
			
		||||
      CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor);
 | 
			
		||||
      return;
 | 
			
		||||
@@ -105,9 +103,7 @@ meta_window_group_paint (ClutterActor *actor)
 | 
			
		||||
 | 
			
		||||
  clip_region = cairo_region_create_rectangle (&clip_rect);
 | 
			
		||||
 | 
			
		||||
  paint_x_offset = paint_x_origin - actor_x_origin;
 | 
			
		||||
  paint_y_offset = paint_y_origin - actor_y_origin;
 | 
			
		||||
  cairo_region_translate (clip_region, -paint_x_offset, -paint_y_offset);
 | 
			
		||||
  cairo_region_translate (clip_region, -paint_x_origin, -paint_y_origin);
 | 
			
		||||
 | 
			
		||||
  meta_cullable_cull_out (META_CULLABLE (window_group), unobscured_region, clip_region);
 | 
			
		||||
 | 
			
		||||
@@ -145,6 +141,36 @@ meta_window_group_get_paint_volume (ClutterActor       *self,
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This is a workaround for Clutter's awful allocation tracking.
 | 
			
		||||
 * Without this, any time the window group changed size, which is
 | 
			
		||||
 * any time windows are dragged around, we'll do a full repaint
 | 
			
		||||
 * of the window group, which includes the background actor, meaning
 | 
			
		||||
 * a full-stage repaint.
 | 
			
		||||
 *
 | 
			
		||||
 * Since actors are allowed to paint outside their allocation, and
 | 
			
		||||
 * since child actors are allowed to be outside their parents, this
 | 
			
		||||
 * doesn't affect anything, but it means that we'll get much more
 | 
			
		||||
 * sane and consistent clipped repaints from Clutter. */
 | 
			
		||||
static void
 | 
			
		||||
meta_window_group_get_preferred_width (ClutterActor *actor,
 | 
			
		||||
                                       gfloat        for_height,
 | 
			
		||||
                                       gfloat       *min_width,
 | 
			
		||||
                                       gfloat       *nat_width)
 | 
			
		||||
{
 | 
			
		||||
  *min_width = 0;
 | 
			
		||||
  *nat_width = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_window_group_get_preferred_height (ClutterActor *actor,
 | 
			
		||||
                                        gfloat        for_width,
 | 
			
		||||
                                        gfloat       *min_height,
 | 
			
		||||
                                        gfloat       *nat_height)
 | 
			
		||||
{
 | 
			
		||||
  *min_height = 0;
 | 
			
		||||
  *nat_height = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_window_group_class_init (MetaWindowGroupClass *klass)
 | 
			
		||||
{
 | 
			
		||||
@@ -152,6 +178,8 @@ meta_window_group_class_init (MetaWindowGroupClass *klass)
 | 
			
		||||
 | 
			
		||||
  actor_class->paint = meta_window_group_paint;
 | 
			
		||||
  actor_class->get_paint_volume = meta_window_group_get_paint_volume;
 | 
			
		||||
  actor_class->get_preferred_width = meta_window_group_get_preferred_width;
 | 
			
		||||
  actor_class->get_preferred_height = meta_window_group_get_preferred_height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * MetaWindowShape
 | 
			
		||||
 *
 | 
			
		||||
@@ -19,9 +20,12 @@
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-window-shape.h"
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include <meta/meta-window-shape.h>
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "region-utils.h"
 | 
			
		||||
 | 
			
		||||
struct _MetaWindowShape
 | 
			
		||||
@@ -250,3 +254,5 @@ meta_window_shape_to_region (MetaWindowShape *shape,
 | 
			
		||||
  return region;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
G_DEFINE_BOXED_TYPE (MetaWindowShape, meta_window_shape,
 | 
			
		||||
                     meta_window_shape_ref, meta_window_shape_unref)
 | 
			
		||||
 
 | 
			
		||||
@@ -255,6 +255,31 @@ get_actor_private (MetaWindowActor *actor)
 | 
			
		||||
  return priv;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ClutterTimeline *
 | 
			
		||||
actor_animate (ClutterActor         *actor,
 | 
			
		||||
               ClutterAnimationMode  mode,
 | 
			
		||||
               guint                 duration,
 | 
			
		||||
               const gchar          *first_property,
 | 
			
		||||
               ...)
 | 
			
		||||
{
 | 
			
		||||
  va_list args;
 | 
			
		||||
  ClutterTransition *transition;
 | 
			
		||||
 | 
			
		||||
  clutter_actor_save_easing_state (actor);
 | 
			
		||||
  clutter_actor_set_easing_mode (actor, mode);
 | 
			
		||||
  clutter_actor_set_easing_duration (actor, duration);
 | 
			
		||||
 | 
			
		||||
  va_start (args, first_property);
 | 
			
		||||
  g_object_set_valist (G_OBJECT (actor), first_property, args);
 | 
			
		||||
  va_end (args);
 | 
			
		||||
 | 
			
		||||
  transition = clutter_actor_get_transition (actor, first_property);
 | 
			
		||||
 | 
			
		||||
  clutter_actor_restore_easing_state (actor);
 | 
			
		||||
 | 
			
		||||
  return CLUTTER_TIMELINE (transition);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_switch_workspace_effect_complete (ClutterTimeline *timeline, gpointer data)
 | 
			
		||||
{
 | 
			
		||||
@@ -271,7 +296,10 @@ on_switch_workspace_effect_complete (ClutterTimeline *timeline, gpointer data)
 | 
			
		||||
 | 
			
		||||
      if (apriv->orig_parent)
 | 
			
		||||
        {
 | 
			
		||||
          clutter_actor_reparent (a, apriv->orig_parent);
 | 
			
		||||
          g_object_ref (a);
 | 
			
		||||
          clutter_actor_remove_child (clutter_actor_get_parent (a), a);
 | 
			
		||||
          clutter_actor_add_child (apriv->orig_parent, a);
 | 
			
		||||
          g_object_unref (a);
 | 
			
		||||
          apriv->orig_parent = NULL;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -360,11 +388,10 @@ switch_workspace (MetaPlugin *plugin,
 | 
			
		||||
  MetaScreen *screen;
 | 
			
		||||
  MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
 | 
			
		||||
  GList        *l;
 | 
			
		||||
  ClutterActor *workspace0  = clutter_group_new ();
 | 
			
		||||
  ClutterActor *workspace1  = clutter_group_new ();
 | 
			
		||||
  ClutterActor *workspace0  = clutter_actor_new ();
 | 
			
		||||
  ClutterActor *workspace1  = clutter_actor_new ();
 | 
			
		||||
  ClutterActor *stage;
 | 
			
		||||
  int           screen_width, screen_height;
 | 
			
		||||
  ClutterAnimation *animation;
 | 
			
		||||
 | 
			
		||||
  screen = meta_plugin_get_screen (plugin);
 | 
			
		||||
  stage = meta_get_stage_for_screen (screen);
 | 
			
		||||
@@ -373,17 +400,15 @@ switch_workspace (MetaPlugin *plugin,
 | 
			
		||||
                        &screen_width,
 | 
			
		||||
                        &screen_height);
 | 
			
		||||
 | 
			
		||||
  clutter_actor_set_anchor_point (workspace1,
 | 
			
		||||
                                  screen_width,
 | 
			
		||||
                                  screen_height);
 | 
			
		||||
  clutter_actor_set_pivot_point (workspace1, 1.0, 1.0);
 | 
			
		||||
  clutter_actor_set_position (workspace1,
 | 
			
		||||
                              screen_width,
 | 
			
		||||
                              screen_height);
 | 
			
		||||
 | 
			
		||||
  clutter_actor_set_scale (workspace1, 0.0, 0.0);
 | 
			
		||||
 | 
			
		||||
  clutter_container_add_actor (CLUTTER_CONTAINER (stage), workspace1);
 | 
			
		||||
  clutter_container_add_actor (CLUTTER_CONTAINER (stage), workspace0);
 | 
			
		||||
  clutter_actor_add_child (stage, workspace1);
 | 
			
		||||
  clutter_actor_add_child (stage, workspace0);
 | 
			
		||||
 | 
			
		||||
  if (from == to)
 | 
			
		||||
    {
 | 
			
		||||
@@ -406,12 +431,15 @@ switch_workspace (MetaPlugin *plugin,
 | 
			
		||||
 | 
			
		||||
      if (win_workspace == to || win_workspace == from)
 | 
			
		||||
        {
 | 
			
		||||
          ClutterActor *parent = win_workspace == to ? workspace1 : workspace0;
 | 
			
		||||
          apriv->orig_parent = clutter_actor_get_parent (actor);
 | 
			
		||||
 | 
			
		||||
          clutter_actor_reparent (actor,
 | 
			
		||||
				  win_workspace == to ? workspace1 : workspace0);
 | 
			
		||||
          clutter_actor_show_all (actor);
 | 
			
		||||
          clutter_actor_raise_top (actor);
 | 
			
		||||
          g_object_ref (actor);
 | 
			
		||||
          clutter_actor_remove_child (clutter_actor_get_parent (actor), actor);
 | 
			
		||||
          clutter_actor_add_child (parent, actor);
 | 
			
		||||
          clutter_actor_show (actor);
 | 
			
		||||
          clutter_actor_set_child_below_sibling (parent, actor, NULL);
 | 
			
		||||
          g_object_unref (actor);
 | 
			
		||||
        }
 | 
			
		||||
      else if (win_workspace < 0)
 | 
			
		||||
        {
 | 
			
		||||
@@ -431,23 +459,21 @@ switch_workspace (MetaPlugin *plugin,
 | 
			
		||||
  priv->desktop1 = workspace0;
 | 
			
		||||
  priv->desktop2 = workspace1;
 | 
			
		||||
 | 
			
		||||
  animation = clutter_actor_animate (workspace0, CLUTTER_EASE_IN_SINE,
 | 
			
		||||
                                     SWITCH_TIMEOUT,
 | 
			
		||||
                                     "scale-x", 1.0,
 | 
			
		||||
                                     "scale-y", 1.0,
 | 
			
		||||
                                     NULL);
 | 
			
		||||
  priv->tml_switch_workspace1 = clutter_animation_get_timeline (animation);
 | 
			
		||||
  priv->tml_switch_workspace1 = actor_animate (workspace0, CLUTTER_EASE_IN_SINE,
 | 
			
		||||
                                               SWITCH_TIMEOUT,
 | 
			
		||||
                                               "scale-x", 1.0,
 | 
			
		||||
                                               "scale-y", 1.0,
 | 
			
		||||
                                               NULL);
 | 
			
		||||
  g_signal_connect (priv->tml_switch_workspace1,
 | 
			
		||||
                    "completed",
 | 
			
		||||
                    G_CALLBACK (on_switch_workspace_effect_complete),
 | 
			
		||||
                    plugin);
 | 
			
		||||
 | 
			
		||||
  animation = clutter_actor_animate (workspace1, CLUTTER_EASE_IN_SINE,
 | 
			
		||||
                                     SWITCH_TIMEOUT,
 | 
			
		||||
                                     "scale-x", 0.0,
 | 
			
		||||
                                     "scale-y", 0.0,
 | 
			
		||||
                                     NULL);
 | 
			
		||||
  priv->tml_switch_workspace2 = clutter_animation_get_timeline (animation);
 | 
			
		||||
  priv->tml_switch_workspace2 = actor_animate (workspace1, CLUTTER_EASE_IN_SINE,
 | 
			
		||||
                                               SWITCH_TIMEOUT,
 | 
			
		||||
                                               "scale-x", 0.0,
 | 
			
		||||
                                               "scale-y", 0.0,
 | 
			
		||||
                                               NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -504,19 +530,17 @@ minimize (MetaPlugin *plugin, MetaWindowActor *window_actor)
 | 
			
		||||
 | 
			
		||||
  if (type == META_WINDOW_NORMAL)
 | 
			
		||||
    {
 | 
			
		||||
      ClutterAnimation *animation;
 | 
			
		||||
      EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
 | 
			
		||||
      ActorPrivate *apriv = get_actor_private (window_actor);
 | 
			
		||||
 | 
			
		||||
      animation = clutter_actor_animate (actor,
 | 
			
		||||
                                         CLUTTER_EASE_IN_SINE,
 | 
			
		||||
                                         MINIMIZE_TIMEOUT,
 | 
			
		||||
                                         "scale-x", 0.0,
 | 
			
		||||
                                         "scale-y", 0.0,
 | 
			
		||||
                                         "x", (double)icon_geometry.x,
 | 
			
		||||
                                         "y", (double)icon_geometry.y,
 | 
			
		||||
                                         NULL);
 | 
			
		||||
      apriv->tml_minimize = clutter_animation_get_timeline (animation);
 | 
			
		||||
      apriv->tml_minimize = actor_animate (actor,
 | 
			
		||||
                                           CLUTTER_EASE_IN_SINE,
 | 
			
		||||
                                           MINIMIZE_TIMEOUT,
 | 
			
		||||
                                           "scale-x", 0.0,
 | 
			
		||||
                                           "scale-y", 0.0,
 | 
			
		||||
                                           "x", (double)icon_geometry.x,
 | 
			
		||||
                                           "y", (double)icon_geometry.y,
 | 
			
		||||
                                           NULL);
 | 
			
		||||
      data->plugin = plugin;
 | 
			
		||||
      data->actor = actor;
 | 
			
		||||
      g_signal_connect (apriv->tml_minimize, "completed",
 | 
			
		||||
@@ -561,7 +585,6 @@ map (MetaPlugin *plugin, MetaWindowActor *window_actor)
 | 
			
		||||
 | 
			
		||||
  if (type == META_WINDOW_NORMAL)
 | 
			
		||||
    {
 | 
			
		||||
      ClutterAnimation *animation;
 | 
			
		||||
      EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
 | 
			
		||||
      ActorPrivate *apriv = get_actor_private (window_actor);
 | 
			
		||||
 | 
			
		||||
@@ -570,14 +593,13 @@ map (MetaPlugin *plugin, MetaWindowActor *window_actor)
 | 
			
		||||
      clutter_actor_set_scale (actor, 0.5, 0.5);
 | 
			
		||||
      clutter_actor_show (actor);
 | 
			
		||||
 | 
			
		||||
      animation = clutter_actor_animate (actor,
 | 
			
		||||
                                         CLUTTER_EASE_OUT_QUAD,
 | 
			
		||||
                                         MAP_TIMEOUT,
 | 
			
		||||
                                         "opacity", 255,
 | 
			
		||||
                                         "scale-x", 1.0,
 | 
			
		||||
                                         "scale-y", 1.0,
 | 
			
		||||
                                         NULL);
 | 
			
		||||
      apriv->tml_map = clutter_animation_get_timeline (animation);
 | 
			
		||||
      apriv->tml_map = actor_animate (actor,
 | 
			
		||||
                                      CLUTTER_EASE_OUT_QUAD,
 | 
			
		||||
                                      MAP_TIMEOUT,
 | 
			
		||||
                                      "opacity", 255,
 | 
			
		||||
                                      "scale-x", 1.0,
 | 
			
		||||
                                      "scale-y", 1.0,
 | 
			
		||||
                                      NULL);
 | 
			
		||||
      data->actor = actor;
 | 
			
		||||
      data->plugin = plugin;
 | 
			
		||||
      g_signal_connect (apriv->tml_map, "completed",
 | 
			
		||||
@@ -618,18 +640,16 @@ destroy (MetaPlugin *plugin, MetaWindowActor *window_actor)
 | 
			
		||||
 | 
			
		||||
  if (type == META_WINDOW_NORMAL)
 | 
			
		||||
    {
 | 
			
		||||
      ClutterAnimation *animation;
 | 
			
		||||
      EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
 | 
			
		||||
      ActorPrivate *apriv = get_actor_private (window_actor);
 | 
			
		||||
 | 
			
		||||
      animation = clutter_actor_animate (actor,
 | 
			
		||||
                                         CLUTTER_EASE_OUT_QUAD,
 | 
			
		||||
                                         DESTROY_TIMEOUT,
 | 
			
		||||
                                         "opacity", 0,
 | 
			
		||||
                                         "scale-x", 0.8,
 | 
			
		||||
                                         "scale-y", 0.8,
 | 
			
		||||
                                         NULL);
 | 
			
		||||
      apriv->tml_destroy = clutter_animation_get_timeline (animation);
 | 
			
		||||
      apriv->tml_destroy = actor_animate (actor,
 | 
			
		||||
                                          CLUTTER_EASE_OUT_QUAD,
 | 
			
		||||
                                          DESTROY_TIMEOUT,
 | 
			
		||||
                                          "opacity", 0,
 | 
			
		||||
                                          "scale-x", 0.8,
 | 
			
		||||
                                          "scale-y", 0.8,
 | 
			
		||||
                                          NULL);
 | 
			
		||||
      data->plugin = plugin;
 | 
			
		||||
      data->actor = actor;
 | 
			
		||||
      g_signal_connect (apriv->tml_destroy, "completed",
 | 
			
		||||
@@ -689,7 +709,7 @@ show_tile_preview (MetaPlugin    *plugin,
 | 
			
		||||
  ScreenTilePreview *preview = get_screen_tile_preview (screen);
 | 
			
		||||
  ClutterActor *window_actor;
 | 
			
		||||
 | 
			
		||||
  if (CLUTTER_ACTOR_IS_VISIBLE (preview->actor)
 | 
			
		||||
  if (clutter_actor_is_visible (preview->actor)
 | 
			
		||||
      && preview->tile_rect.x == tile_rect->x
 | 
			
		||||
      && preview->tile_rect.y == tile_rect->y
 | 
			
		||||
      && preview->tile_rect.width == tile_rect->width
 | 
			
		||||
@@ -702,7 +722,9 @@ show_tile_preview (MetaPlugin    *plugin,
 | 
			
		||||
  clutter_actor_show (preview->actor);
 | 
			
		||||
 | 
			
		||||
  window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
  clutter_actor_lower (preview->actor, window_actor);
 | 
			
		||||
  clutter_actor_set_child_below_sibling (clutter_actor_get_parent (preview->actor),
 | 
			
		||||
                                         preview->actor,
 | 
			
		||||
                                         window_actor);
 | 
			
		||||
 | 
			
		||||
  preview->tile_rect = *tile_rect;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -493,11 +493,10 @@ place_window_if_needed(MetaWindow     *window,
 | 
			
		||||
  if (window->placed || did_placement)
 | 
			
		||||
    {
 | 
			
		||||
      if (window->maximize_horizontally_after_placement ||
 | 
			
		||||
          window->maximize_vertically_after_placement   ||
 | 
			
		||||
          window->fullscreen_after_placement)
 | 
			
		||||
          window->maximize_vertically_after_placement)
 | 
			
		||||
        {
 | 
			
		||||
          /* define a sane saved_rect so that the user can unmaximize or
 | 
			
		||||
           * make unfullscreen to something reasonable.
 | 
			
		||||
          /* define a sane saved_rect so that the user can unmaximize to
 | 
			
		||||
           * something reasonable.
 | 
			
		||||
           */
 | 
			
		||||
          if (info->current.width >= info->work_area_monitor.width)
 | 
			
		||||
            {
 | 
			
		||||
@@ -525,15 +524,6 @@ place_window_if_needed(MetaWindow     *window,
 | 
			
		||||
                (window->maximize_vertically_after_placement ?
 | 
			
		||||
                 META_MAXIMIZE_VERTICAL : 0), &info->current);
 | 
			
		||||
 | 
			
		||||
          if (window->fullscreen_after_placement)
 | 
			
		||||
            {
 | 
			
		||||
              window->saved_rect = info->current;
 | 
			
		||||
              window->fullscreen = TRUE;
 | 
			
		||||
              window->fullscreen_after_placement = FALSE;
 | 
			
		||||
 | 
			
		||||
              g_object_notify (G_OBJECT (window), "fullscreen");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          window->maximize_horizontally_after_placement = FALSE;
 | 
			
		||||
          window->maximize_vertically_after_placement = FALSE;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -172,18 +172,6 @@ meta_core_toggle_maximize (Display *xdisplay,
 | 
			
		||||
    meta_window_maximize (window, META_MAXIMIZE_BOTH);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_core_change_workspace (Display *xdisplay,
 | 
			
		||||
                            Window   frame_xwindow,
 | 
			
		||||
                            int      new_workspace)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindow *window = get_window (xdisplay, frame_xwindow);
 | 
			
		||||
 | 
			
		||||
  meta_window_change_workspace (window,
 | 
			
		||||
                                meta_screen_get_workspace_by_index (window->screen,
 | 
			
		||||
                                                                    new_workspace));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_core_show_window_menu (Display            *xdisplay,
 | 
			
		||||
                            Window              frame_xwindow,
 | 
			
		||||
@@ -217,19 +205,6 @@ meta_core_show_window_menu_for_rect (Display            *xdisplay,
 | 
			
		||||
  meta_window_show_menu_for_rect (window, menu, rect);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char*
 | 
			
		||||
meta_core_get_workspace_name_with_index (Display *xdisplay,
 | 
			
		||||
                                         Window   xroot,
 | 
			
		||||
                                         int      index)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display;
 | 
			
		||||
  MetaWorkspace *workspace;
 | 
			
		||||
 | 
			
		||||
  display = meta_display_for_x_display (xdisplay);
 | 
			
		||||
  workspace = meta_screen_get_workspace_by_index (display->screen, index);
 | 
			
		||||
  return workspace ? meta_workspace_get_name (workspace) : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_core_begin_grab_op (Display    *xdisplay,
 | 
			
		||||
                         Window      frame_xwindow,
 | 
			
		||||
 
 | 
			
		||||
@@ -41,15 +41,6 @@ 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_change_workspace (Display *xdisplay,
 | 
			
		||||
                                 Window   frame_xwindow,
 | 
			
		||||
                                 int      new_workspace);
 | 
			
		||||
 | 
			
		||||
int meta_core_get_frame_workspace (Display *xdisplay,
 | 
			
		||||
                                   Window frame_xwindow);
 | 
			
		||||
const char* meta_core_get_workspace_name_with_index (Display *xdisplay,
 | 
			
		||||
                                                     Window xroot,
 | 
			
		||||
                                                     int    index);
 | 
			
		||||
 | 
			
		||||
void meta_core_show_window_menu (Display            *xdisplay,
 | 
			
		||||
                                 Window              frame_xwindow,
 | 
			
		||||
 
 | 
			
		||||
@@ -160,12 +160,7 @@ void
 | 
			
		||||
meta_window_set_alive (MetaWindow *window,
 | 
			
		||||
                       gboolean    is_alive)
 | 
			
		||||
{
 | 
			
		||||
  if (window->is_alive == is_alive)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  window->is_alive = is_alive;
 | 
			
		||||
 | 
			
		||||
  if (window->is_alive)
 | 
			
		||||
  if (is_alive)
 | 
			
		||||
    kill_delete_dialog (window);
 | 
			
		||||
  else
 | 
			
		||||
    show_delete_dialog (window, CurrentTime);
 | 
			
		||||
@@ -185,34 +180,6 @@ meta_window_delete (MetaWindow  *window,
 | 
			
		||||
  META_WINDOW_GET_CLASS (window)->delete (window, timestamp);
 | 
			
		||||
 | 
			
		||||
  meta_window_check_alive (window, timestamp);
 | 
			
		||||
 | 
			
		||||
  if (window->has_focus)
 | 
			
		||||
    {
 | 
			
		||||
      /* FIXME Clean this up someday
 | 
			
		||||
       * http://bugzilla.gnome.org/show_bug.cgi?id=108706
 | 
			
		||||
       */
 | 
			
		||||
#if 0
 | 
			
		||||
      /* This is unfortunately going to result in weirdness
 | 
			
		||||
       * if the window doesn't respond to the delete event.
 | 
			
		||||
       * I don't know how to avoid that though.
 | 
			
		||||
       */
 | 
			
		||||
      meta_topic (META_DEBUG_FOCUS,
 | 
			
		||||
                  "Focusing default window because focus window %s was deleted/killed\n",
 | 
			
		||||
                  window->desc);
 | 
			
		||||
      meta_workspace_focus_default_window (window->screen->active_workspace,
 | 
			
		||||
                                           window);
 | 
			
		||||
#else
 | 
			
		||||
      meta_topic (META_DEBUG_FOCUS,
 | 
			
		||||
                  "Not unfocusing %s on delete/kill\n",
 | 
			
		||||
                  window->desc);
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      meta_topic (META_DEBUG_FOCUS,
 | 
			
		||||
                  "Window %s was deleted/killed but didn't have focus\n",
 | 
			
		||||
                  window->desc);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
 
 | 
			
		||||
@@ -35,6 +35,7 @@
 | 
			
		||||
#include <meta/boxes.h>
 | 
			
		||||
#include <meta/display.h>
 | 
			
		||||
#include "keybindings-private.h"
 | 
			
		||||
#include "startup-notification-private.h"
 | 
			
		||||
#include "meta-gesture-tracker-private.h"
 | 
			
		||||
#include <meta/prefs.h>
 | 
			
		||||
#include <meta/barrier.h>
 | 
			
		||||
@@ -121,7 +122,7 @@ struct _MetaDisplay
 | 
			
		||||
   * class is constructed.
 | 
			
		||||
   */
 | 
			
		||||
#define item(x)  Atom atom_##x;
 | 
			
		||||
#include <meta/atomnames.h>
 | 
			
		||||
#include <x11/atomnames.h>
 | 
			
		||||
#undef item
 | 
			
		||||
 | 
			
		||||
  /* The window and serial of the most recent FocusIn event. */
 | 
			
		||||
@@ -217,9 +218,6 @@ struct _MetaDisplay
 | 
			
		||||
  guint       grab_have_pointer : 1;
 | 
			
		||||
  guint       grab_have_keyboard : 1;
 | 
			
		||||
  guint       grab_frame_action : 1;
 | 
			
		||||
  /* During a resize operation, the directions in which we've broken
 | 
			
		||||
   * out of the initial maximization state */
 | 
			
		||||
  guint       grab_resize_unmaximize : 2; /* MetaMaximizeFlags */
 | 
			
		||||
  MetaRectangle grab_initial_window_pos;
 | 
			
		||||
  int         grab_initial_x, grab_initial_y;  /* These are only relevant for */
 | 
			
		||||
  gboolean    grab_threshold_movement_reached; /* raise_on_click == FALSE.    */
 | 
			
		||||
@@ -279,9 +277,8 @@ struct _MetaDisplay
 | 
			
		||||
  int xinput_event_base;
 | 
			
		||||
  int xinput_opcode;
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_STARTUP_NOTIFICATION
 | 
			
		||||
  SnDisplay *sn_display;
 | 
			
		||||
#endif
 | 
			
		||||
  MetaStartupNotification *startup_notification;
 | 
			
		||||
 | 
			
		||||
  int xsync_event_base;
 | 
			
		||||
  int xsync_error_base;
 | 
			
		||||
  int shape_event_base;
 | 
			
		||||
 
 | 
			
		||||
@@ -46,7 +46,7 @@
 | 
			
		||||
#include <meta/compositor.h>
 | 
			
		||||
#include <meta/compositor-mutter.h>
 | 
			
		||||
#include <X11/Xatom.h>
 | 
			
		||||
#include "mutter-enum-types.h"
 | 
			
		||||
#include <meta/meta-enum-types.h>
 | 
			
		||||
#include "meta-idle-monitor-dbus.h"
 | 
			
		||||
#include "meta-cursor-tracker-private.h"
 | 
			
		||||
#include <meta/meta-backend.h>
 | 
			
		||||
@@ -400,28 +400,6 @@ meta_display_remove_pending_pings_for_window (MetaDisplay *display,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_STARTUP_NOTIFICATION
 | 
			
		||||
static void
 | 
			
		||||
sn_error_trap_push (SnDisplay *sn_display,
 | 
			
		||||
                    Display   *xdisplay)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display;
 | 
			
		||||
  display = meta_display_for_x_display (xdisplay);
 | 
			
		||||
  if (display != NULL)
 | 
			
		||||
    meta_error_trap_push (display);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
sn_error_trap_pop (SnDisplay *sn_display,
 | 
			
		||||
                   Display   *xdisplay)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display;
 | 
			
		||||
  display = meta_display_for_x_display (xdisplay);
 | 
			
		||||
  if (display != NULL)
 | 
			
		||||
    meta_error_trap_pop (display);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
enable_compositor (MetaDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
@@ -527,6 +505,20 @@ gesture_tracker_state_changed (MetaGestureTracker   *tracker,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_startup_notification_changed (MetaStartupNotification *sn,
 | 
			
		||||
                                 gpointer                 sequence,
 | 
			
		||||
                                 MetaDisplay             *display)
 | 
			
		||||
{
 | 
			
		||||
  if (!display->screen)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  g_slist_free (display->screen->startup_sequences);
 | 
			
		||||
  display->screen->startup_sequences =
 | 
			
		||||
    meta_startup_notification_get_sequences (display->startup_notification);
 | 
			
		||||
  g_signal_emit_by_name (display->screen, "startup-sequence-changed", sequence);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_display_open:
 | 
			
		||||
 *
 | 
			
		||||
@@ -547,9 +539,9 @@ meta_display_open (void)
 | 
			
		||||
  guint32 timestamp;
 | 
			
		||||
 | 
			
		||||
  /* A list of all atom names, so that we can intern them in one go. */
 | 
			
		||||
  char *atom_names[] = {
 | 
			
		||||
  const char *atom_names[] = {
 | 
			
		||||
#define item(x) #x,
 | 
			
		||||
#include <meta/atomnames.h>
 | 
			
		||||
#include <x11/atomnames.h>
 | 
			
		||||
#undef item
 | 
			
		||||
  };
 | 
			
		||||
  Atom atoms[G_N_ELEMENTS(atom_names)];
 | 
			
		||||
@@ -605,14 +597,13 @@ meta_display_open (void)
 | 
			
		||||
  meta_prefs_add_listener (prefs_changed_callback, display);
 | 
			
		||||
 | 
			
		||||
  meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
 | 
			
		||||
  XInternAtoms (display->xdisplay, atom_names, G_N_ELEMENTS (atom_names),
 | 
			
		||||
  XInternAtoms (display->xdisplay, (char **)atom_names, G_N_ELEMENTS (atom_names),
 | 
			
		||||
                False, atoms);
 | 
			
		||||
  {
 | 
			
		||||
    int i = 0;
 | 
			
		||||
 | 
			
		||||
  i = 0;
 | 
			
		||||
#define item(x) display->atom_##x = atoms[i++];
 | 
			
		||||
#include <meta/atomnames.h>
 | 
			
		||||
#include <x11/atomnames.h>
 | 
			
		||||
#undef item
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  display->prop_hooks = NULL;
 | 
			
		||||
  meta_display_init_window_prop_hooks (display);
 | 
			
		||||
@@ -631,12 +622,6 @@ meta_display_open (void)
 | 
			
		||||
 | 
			
		||||
  display->screen = NULL;
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_STARTUP_NOTIFICATION
 | 
			
		||||
  display->sn_display = sn_display_new (display->xdisplay,
 | 
			
		||||
                                        sn_error_trap_push,
 | 
			
		||||
                                        sn_error_trap_pop);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  /* Get events */
 | 
			
		||||
  meta_display_init_events (display);
 | 
			
		||||
  meta_display_init_events_x11 (display);
 | 
			
		||||
@@ -917,6 +902,10 @@ meta_display_open (void)
 | 
			
		||||
 | 
			
		||||
  display->screen = screen;
 | 
			
		||||
 | 
			
		||||
  display->startup_notification = meta_startup_notification_get (display);
 | 
			
		||||
  g_signal_connect (display->startup_notification, "changed",
 | 
			
		||||
                    G_CALLBACK (on_startup_notification_changed), display);
 | 
			
		||||
 | 
			
		||||
  meta_screen_init_workspaces (screen);
 | 
			
		||||
 | 
			
		||||
  enable_compositor (display);
 | 
			
		||||
@@ -1101,6 +1090,7 @@ meta_display_close (MetaDisplay *display,
 | 
			
		||||
 | 
			
		||||
  meta_display_remove_autoraise_callback (display);
 | 
			
		||||
 | 
			
		||||
  g_clear_object (&display->startup_notification);
 | 
			
		||||
  g_clear_object (&display->gesture_tracker);
 | 
			
		||||
 | 
			
		||||
  if (display->focus_timeout_id)
 | 
			
		||||
@@ -1113,14 +1103,6 @@ meta_display_close (MetaDisplay *display,
 | 
			
		||||
 | 
			
		||||
  meta_screen_free (display->screen, timestamp);
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_STARTUP_NOTIFICATION
 | 
			
		||||
  if (display->sn_display)
 | 
			
		||||
    {
 | 
			
		||||
      sn_display_unref (display->sn_display);
 | 
			
		||||
      display->sn_display = NULL;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  /* Must be after all calls to meta_window_unmanage() since they
 | 
			
		||||
   * unregister windows
 | 
			
		||||
   */
 | 
			
		||||
@@ -1922,7 +1904,6 @@ meta_display_begin_grab_op (MetaDisplay *display,
 | 
			
		||||
  display->grab_last_moveresize_time.tv_usec = 0;
 | 
			
		||||
  display->grab_last_user_action_was_snap = FALSE;
 | 
			
		||||
  display->grab_frame_action = frame_action;
 | 
			
		||||
  display->grab_resize_unmaximize = 0;
 | 
			
		||||
 | 
			
		||||
  meta_display_update_cursor (display);
 | 
			
		||||
 | 
			
		||||
@@ -1965,9 +1946,12 @@ meta_display_end_grab_op (MetaDisplay *display,
 | 
			
		||||
  meta_topic (META_DEBUG_WINDOW_OPS,
 | 
			
		||||
              "Ending grab op %u at time %u\n", grab_op, timestamp);
 | 
			
		||||
 | 
			
		||||
  if (display->event_route == META_EVENT_ROUTE_NORMAL)
 | 
			
		||||
  if (display->event_route == META_EVENT_ROUTE_NORMAL ||
 | 
			
		||||
      display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  g_assert (grab_window != NULL);
 | 
			
		||||
 | 
			
		||||
  g_signal_emit (display, display_signals[GRAB_OP_END], 0,
 | 
			
		||||
                 display->screen, grab_window, grab_op);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,13 @@
 | 
			
		||||
#endif
 | 
			
		||||
#include "meta-surface-actor.h"
 | 
			
		||||
 | 
			
		||||
#define IS_GESTURE_EVENT(e) ((e)->type == CLUTTER_TOUCHPAD_SWIPE || \
 | 
			
		||||
                             (e)->type == CLUTTER_TOUCHPAD_PINCH || \
 | 
			
		||||
                             (e)->type == CLUTTER_TOUCH_BEGIN || \
 | 
			
		||||
                             (e)->type == CLUTTER_TOUCH_UPDATE || \
 | 
			
		||||
                             (e)->type == CLUTTER_TOUCH_END || \
 | 
			
		||||
                             (e)->type == CLUTTER_TOUCH_CANCEL)
 | 
			
		||||
 | 
			
		||||
static MetaWindow *
 | 
			
		||||
get_window_for_event (MetaDisplay        *display,
 | 
			
		||||
                      const ClutterEvent *event)
 | 
			
		||||
@@ -93,6 +100,15 @@ handle_idletime_for_event (const ClutterEvent *event)
 | 
			
		||||
      if (device == NULL)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
      if (event->any.flags & CLUTTER_EVENT_FLAG_SYNTHETIC ||
 | 
			
		||||
          event->type == CLUTTER_ENTER ||
 | 
			
		||||
          event->type == CLUTTER_LEAVE ||
 | 
			
		||||
          event->type == CLUTTER_STAGE_STATE ||
 | 
			
		||||
          event->type == CLUTTER_DESTROY_NOTIFY ||
 | 
			
		||||
          event->type == CLUTTER_CLIENT_MESSAGE ||
 | 
			
		||||
          event->type == CLUTTER_DELETE)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
      device_id = clutter_input_device_get_device_id (device);
 | 
			
		||||
 | 
			
		||||
      core_monitor = meta_idle_monitor_get_core ();
 | 
			
		||||
@@ -166,10 +182,25 @@ meta_display_handle_event (MetaDisplay        *display,
 | 
			
		||||
  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;
 | 
			
		||||
  if (event->type == CLUTTER_TOUCH_BEGIN)
 | 
			
		||||
    {
 | 
			
		||||
      if (sequence_is_pointer_emulated (display, event))
 | 
			
		||||
        {
 | 
			
		||||
          /* This is the new pointer emulating sequence */
 | 
			
		||||
          display->pointer_emulating_sequence = sequence;
 | 
			
		||||
        }
 | 
			
		||||
      else if (display->pointer_emulating_sequence == sequence)
 | 
			
		||||
        {
 | 
			
		||||
          /* This sequence was "pointer emulating" in a prior incarnation,
 | 
			
		||||
           * but now it isn't. We unset the pointer emulating sequence at
 | 
			
		||||
           * this point so the current sequence is not mistaken as pointer
 | 
			
		||||
           * emulating, while we've ensured that it's been deemed
 | 
			
		||||
           * "pointer emulating" throughout all of the event processing
 | 
			
		||||
           * of the previous incarnation.
 | 
			
		||||
           */
 | 
			
		||||
          display->pointer_emulating_sequence = NULL;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_WAYLAND
 | 
			
		||||
  MetaWaylandCompositor *compositor = NULL;
 | 
			
		||||
@@ -190,8 +221,9 @@ meta_display_handle_event (MetaDisplay        *display,
 | 
			
		||||
 | 
			
		||||
  if (meta_is_wayland_compositor () && event->type == CLUTTER_MOTION)
 | 
			
		||||
    {
 | 
			
		||||
      MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (NULL);
 | 
			
		||||
      meta_cursor_tracker_update_position (tracker, event->motion.x, event->motion.y);
 | 
			
		||||
      meta_cursor_tracker_update_position (meta_cursor_tracker_get_for_screen (NULL),
 | 
			
		||||
                                           event->motion.x, event->motion.y);
 | 
			
		||||
      display->monitor_cache_invalidated = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  handle_idletime_for_event (event);
 | 
			
		||||
@@ -255,15 +287,18 @@ meta_display_handle_event (MetaDisplay        *display,
 | 
			
		||||
 | 
			
		||||
  if (window)
 | 
			
		||||
    {
 | 
			
		||||
      if (!clutter_event_get_event_sequence (event))
 | 
			
		||||
        {
 | 
			
		||||
          /* Swallow all non-touch events on windows that come our way.
 | 
			
		||||
           * Touch events that reach here aren't yet in an accepted state,
 | 
			
		||||
           * so Clutter must see them to maybe trigger gestures into
 | 
			
		||||
           * recognition.
 | 
			
		||||
           */
 | 
			
		||||
          bypass_clutter = TRUE;
 | 
			
		||||
        }
 | 
			
		||||
      /* Events that are likely to trigger compositor gestures should
 | 
			
		||||
       * be known to clutter so they can propagate along the hierarchy.
 | 
			
		||||
       * Gesture-wise, there's two groups of events we should be getting
 | 
			
		||||
       * here:
 | 
			
		||||
       * - CLUTTER_TOUCH_* with a touch sequence that's not yet accepted
 | 
			
		||||
       *   by the gesture tracker, these might trigger gesture actions
 | 
			
		||||
       *   into recognition. Already accepted touch sequences are handled
 | 
			
		||||
       *   directly by meta_gesture_tracker_handle_event().
 | 
			
		||||
       * - CLUTTER_TOUCHPAD_* events over windows. These can likewise
 | 
			
		||||
       *   trigger ::captured-event handlers along the way.
 | 
			
		||||
       */
 | 
			
		||||
      bypass_clutter = !IS_GESTURE_EVENT (event);
 | 
			
		||||
 | 
			
		||||
      meta_window_handle_ungrabbed_event (window, event);
 | 
			
		||||
 | 
			
		||||
@@ -315,11 +350,6 @@ 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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,7 @@
 | 
			
		||||
#include <gio/gio.h>
 | 
			
		||||
#include <meta/keybindings.h>
 | 
			
		||||
#include <xkbcommon/xkbcommon.h>
 | 
			
		||||
#include "meta-accel-parse.h"
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaKeyHandler MetaKeyHandler;
 | 
			
		||||
struct _MetaKeyHandler
 | 
			
		||||
@@ -53,7 +54,6 @@ typedef struct _MetaResolvedKeyCombo {
 | 
			
		||||
 * @keycode: keycode
 | 
			
		||||
 * @modifiers: modifiers
 | 
			
		||||
 */
 | 
			
		||||
typedef struct _MetaKeyCombo MetaKeyCombo;
 | 
			
		||||
struct _MetaKeyCombo
 | 
			
		||||
{
 | 
			
		||||
  unsigned int keysym;
 | 
			
		||||
 
 | 
			
		||||
@@ -188,7 +188,7 @@ reload_modmap (MetaKeyBindingManager *keys)
 | 
			
		||||
 | 
			
		||||
  /* Modifiers to find. */
 | 
			
		||||
  struct {
 | 
			
		||||
    char *name;
 | 
			
		||||
    const char *name;
 | 
			
		||||
    xkb_mod_mask_t *mask_p;
 | 
			
		||||
  } mods[] = {
 | 
			
		||||
    { "ScrollLock", &scroll_lock_mask },
 | 
			
		||||
@@ -3186,7 +3186,7 @@ handle_move_to_monitor (MetaDisplay    *display,
 | 
			
		||||
  gint which = binding->handler->data;
 | 
			
		||||
  const MetaMonitorInfo *current, *new;
 | 
			
		||||
 | 
			
		||||
  current = meta_screen_get_monitor_for_window (screen, window);
 | 
			
		||||
  current = window->monitor;
 | 
			
		||||
  new = meta_screen_get_monitor_neighbor (screen, current->number, which);
 | 
			
		||||
 | 
			
		||||
  if (new == NULL)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										104
									
								
								src/core/main.c
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								src/core/main.c
									
									
									
									
									
								
							@@ -80,6 +80,10 @@
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_WAYLAND
 | 
			
		||||
#include "wayland/meta-wayland.h"
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
#if defined(HAVE_NATIVE_BACKEND) && defined(HAVE_WAYLAND)
 | 
			
		||||
#include <systemd/sd-login.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -291,6 +295,95 @@ on_sigterm (gpointer user_data)
 | 
			
		||||
  return G_SOURCE_REMOVE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(HAVE_WAYLAND) && defined(HAVE_NATIVE_BACKEND)
 | 
			
		||||
static char *
 | 
			
		||||
find_logind_session_type (void)
 | 
			
		||||
{
 | 
			
		||||
  char **sessions;
 | 
			
		||||
  char *session_id;
 | 
			
		||||
  char *session_type;
 | 
			
		||||
  int ret, i;
 | 
			
		||||
 | 
			
		||||
  ret = sd_pid_get_session (0, &session_id);
 | 
			
		||||
 | 
			
		||||
  if (ret == 0 && session_id != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      ret = sd_session_get_type (session_id, &session_type);
 | 
			
		||||
      free (session_id);
 | 
			
		||||
 | 
			
		||||
      if (ret < 0)
 | 
			
		||||
        session_type = NULL;
 | 
			
		||||
 | 
			
		||||
      goto out;
 | 
			
		||||
    }
 | 
			
		||||
  session_type = NULL;
 | 
			
		||||
 | 
			
		||||
  ret = sd_uid_get_sessions (getuid (), TRUE, &sessions);
 | 
			
		||||
 | 
			
		||||
  if (ret < 0 || sessions == NULL)
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; sessions[i] != NULL; i++)
 | 
			
		||||
    {
 | 
			
		||||
      ret = sd_session_get_type (sessions[i], &session_type);
 | 
			
		||||
 | 
			
		||||
      if (ret < 0)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (g_strcmp0 (session_type, "x11") == 0||
 | 
			
		||||
          g_strcmp0 (session_type, "wayland") == 0)
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      g_clear_pointer (&session_type, (GDestroyNotify) free);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  for (i = 0; sessions[i] != NULL; i++)
 | 
			
		||||
    free (sessions[i]);
 | 
			
		||||
  free (sessions);
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
  return session_type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
check_for_wayland_session_type (void)
 | 
			
		||||
{
 | 
			
		||||
  char *session_type = NULL;
 | 
			
		||||
  gboolean is_wayland = FALSE;
 | 
			
		||||
 | 
			
		||||
  session_type = find_logind_session_type ();
 | 
			
		||||
 | 
			
		||||
  if (session_type != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      is_wayland = g_strcmp0 (session_type, "wayland") == 0;
 | 
			
		||||
      free (session_type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return is_wayland;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
init_backend (void)
 | 
			
		||||
{
 | 
			
		||||
  gboolean session_type_is_wayland = FALSE;
 | 
			
		||||
 | 
			
		||||
#if defined(HAVE_WAYLAND) && defined(HAVE_NATIVE_BACKEND)
 | 
			
		||||
  session_type_is_wayland = check_for_wayland_session_type ();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(CLUTTER_WINDOWING_EGL) && defined(HAVE_NATIVE_BACKEND)
 | 
			
		||||
  if (opt_display_server || session_type_is_wayland)
 | 
			
		||||
    clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
 | 
			
		||||
  else
 | 
			
		||||
#endif
 | 
			
		||||
    clutter_set_windowing_backend (CLUTTER_WINDOWING_X11);
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_WAYLAND
 | 
			
		||||
  meta_set_is_wayland_compositor (opt_wayland || session_type_is_wayland);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_init: (skip)
 | 
			
		||||
 *
 | 
			
		||||
@@ -323,16 +416,7 @@ meta_init (void)
 | 
			
		||||
  if (g_getenv ("MUTTER_DEBUG"))
 | 
			
		||||
    meta_set_debugging (TRUE);
 | 
			
		||||
 | 
			
		||||
#if defined(CLUTTER_WINDOWING_EGL) && defined(HAVE_NATIVE_BACKEND)
 | 
			
		||||
  if (opt_display_server)
 | 
			
		||||
    clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
 | 
			
		||||
  else
 | 
			
		||||
#endif
 | 
			
		||||
    clutter_set_windowing_backend (CLUTTER_WINDOWING_X11);
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_WAYLAND
 | 
			
		||||
  meta_set_is_wayland_compositor (opt_wayland);
 | 
			
		||||
#endif
 | 
			
		||||
  init_backend ();
 | 
			
		||||
 | 
			
		||||
  if (g_get_home_dir ())
 | 
			
		||||
    if (chdir (g_get_home_dir ()) < 0)
 | 
			
		||||
 
 | 
			
		||||
@@ -176,7 +176,6 @@ static gboolean
 | 
			
		||||
accelerator_parse (const gchar         *accelerator,
 | 
			
		||||
                   MetaKeyCombo        *combo)
 | 
			
		||||
{
 | 
			
		||||
  gboolean error = FALSE;
 | 
			
		||||
  guint keyval, keycode;
 | 
			
		||||
  MetaVirtualModifier mods;
 | 
			
		||||
  gint len;
 | 
			
		||||
@@ -186,10 +185,7 @@ accelerator_parse (const gchar         *accelerator,
 | 
			
		||||
  combo->modifiers = 0;
 | 
			
		||||
 | 
			
		||||
  if (accelerator == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      error = TRUE;
 | 
			
		||||
      goto out;
 | 
			
		||||
    }
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  keyval = 0;
 | 
			
		||||
  keycode = 0;
 | 
			
		||||
@@ -310,10 +306,7 @@ accelerator_parse (const gchar         *accelerator,
 | 
			
		||||
                  g_free (with_xf86);
 | 
			
		||||
 | 
			
		||||
                  if (keyval == XKB_KEY_NoSymbol)
 | 
			
		||||
                    {
 | 
			
		||||
                      error = TRUE;
 | 
			
		||||
                      goto out;
 | 
			
		||||
                    }
 | 
			
		||||
                    return FALSE;
 | 
			
		||||
                }
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
@@ -322,14 +315,10 @@ accelerator_parse (const gchar         *accelerator,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
  if (error)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  combo->keysym = keyval;
 | 
			
		||||
  combo->keycode = keycode;
 | 
			
		||||
  combo->modifiers = mods;
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										154
									
								
								src/core/meta-border.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								src/core/meta-border.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,154 @@
 | 
			
		||||
/* -*- 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>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "core/meta-border.h"
 | 
			
		||||
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
static inline float
 | 
			
		||||
meta_vector2_cross_product (const MetaVector2 a,
 | 
			
		||||
                            const MetaVector2 b)
 | 
			
		||||
{
 | 
			
		||||
  return a.x * b.y - a.y * b.x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline MetaVector2
 | 
			
		||||
meta_vector2_add (const MetaVector2 a,
 | 
			
		||||
                  const MetaVector2 b)
 | 
			
		||||
{
 | 
			
		||||
  return (MetaVector2) {
 | 
			
		||||
    .x = a.x + b.x,
 | 
			
		||||
    .y = a.y + b.y,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline MetaVector2
 | 
			
		||||
meta_vector2_multiply_constant (const float       c,
 | 
			
		||||
                                const MetaVector2 a)
 | 
			
		||||
{
 | 
			
		||||
  return (MetaVector2) {
 | 
			
		||||
    .x = c * a.x,
 | 
			
		||||
    .y = c * a.y,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_line2_intersects_with (const MetaLine2 *line1,
 | 
			
		||||
                            const MetaLine2 *line2,
 | 
			
		||||
                            MetaVector2     *intersection)
 | 
			
		||||
{
 | 
			
		||||
  MetaVector2 p = line1->a;
 | 
			
		||||
  MetaVector2 r = meta_vector2_subtract (line1->b, line1->a);
 | 
			
		||||
  MetaVector2 q = line2->a;
 | 
			
		||||
  MetaVector2 s = meta_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 = meta_vector2_cross_product (r, s);
 | 
			
		||||
  sxr = meta_vector2_cross_product (s, r);
 | 
			
		||||
 | 
			
		||||
  /* If r × s = 0 then the lines are either parallel or collinear. */
 | 
			
		||||
  if (fabsf (rxs) < FLT_MIN)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  t = meta_vector2_cross_product (meta_vector2_subtract (q, p), s) / rxs;
 | 
			
		||||
  u = meta_vector2_cross_product (meta_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 = meta_vector2_add (p, meta_vector2_multiply_constant (t, r));
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_border_is_horizontal (MetaBorder *border)
 | 
			
		||||
{
 | 
			
		||||
  return border->line.a.y == border->line.b.y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_border_is_blocking_directions (MetaBorder               *border,
 | 
			
		||||
                                    MetaBorderMotionDirection directions)
 | 
			
		||||
{
 | 
			
		||||
  if (meta_border_is_horizontal (border))
 | 
			
		||||
    {
 | 
			
		||||
      if ((directions & (META_BORDER_MOTION_DIRECTION_POSITIVE_Y |
 | 
			
		||||
                         META_BORDER_MOTION_DIRECTION_NEGATIVE_Y)) == 0)
 | 
			
		||||
        return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      if ((directions & (META_BORDER_MOTION_DIRECTION_POSITIVE_X |
 | 
			
		||||
                         META_BORDER_MOTION_DIRECTION_NEGATIVE_X)) == 0)
 | 
			
		||||
        return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return (~border->blocking_directions & directions) != directions;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned int
 | 
			
		||||
meta_border_get_allows_directions (MetaBorder *border)
 | 
			
		||||
{
 | 
			
		||||
  return ~border->blocking_directions &
 | 
			
		||||
    (META_BORDER_MOTION_DIRECTION_POSITIVE_X |
 | 
			
		||||
     META_BORDER_MOTION_DIRECTION_POSITIVE_Y |
 | 
			
		||||
     META_BORDER_MOTION_DIRECTION_NEGATIVE_X |
 | 
			
		||||
     META_BORDER_MOTION_DIRECTION_NEGATIVE_Y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_border_set_allows_directions (MetaBorder *border, unsigned int directions)
 | 
			
		||||
{
 | 
			
		||||
  border->blocking_directions =
 | 
			
		||||
    ~directions & (META_BORDER_MOTION_DIRECTION_POSITIVE_X |
 | 
			
		||||
                   META_BORDER_MOTION_DIRECTION_POSITIVE_Y |
 | 
			
		||||
                   META_BORDER_MOTION_DIRECTION_NEGATIVE_X |
 | 
			
		||||
                   META_BORDER_MOTION_DIRECTION_NEGATIVE_Y);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										84
									
								
								src/core/meta-border.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								src/core/meta-border.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
			
		||||
/* -*- 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_BORDER_H
 | 
			
		||||
#define META_BORDER_H
 | 
			
		||||
 | 
			
		||||
#include <glib.h>
 | 
			
		||||
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
  META_BORDER_MOTION_DIRECTION_POSITIVE_X = 1 << 0,
 | 
			
		||||
  META_BORDER_MOTION_DIRECTION_POSITIVE_Y = 1 << 1,
 | 
			
		||||
  META_BORDER_MOTION_DIRECTION_NEGATIVE_X = 1 << 2,
 | 
			
		||||
  META_BORDER_MOTION_DIRECTION_NEGATIVE_Y = 1 << 3,
 | 
			
		||||
} MetaBorderMotionDirection;
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaVector2
 | 
			
		||||
{
 | 
			
		||||
  float x;
 | 
			
		||||
  float y;
 | 
			
		||||
} MetaVector2;
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaLine2
 | 
			
		||||
{
 | 
			
		||||
  MetaVector2 a;
 | 
			
		||||
  MetaVector2 b;
 | 
			
		||||
} MetaLine2;
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaBorder
 | 
			
		||||
{
 | 
			
		||||
  MetaLine2 line;
 | 
			
		||||
  MetaBorderMotionDirection blocking_directions;
 | 
			
		||||
} MetaBorder;
 | 
			
		||||
 | 
			
		||||
static inline MetaVector2
 | 
			
		||||
meta_vector2_subtract (const MetaVector2 a,
 | 
			
		||||
                       const MetaVector2 b)
 | 
			
		||||
{
 | 
			
		||||
  return (MetaVector2) {
 | 
			
		||||
    .x = a.x - b.x,
 | 
			
		||||
    .y = a.y - b.y,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_line2_intersects_with (const MetaLine2 *line1,
 | 
			
		||||
                            const MetaLine2 *line2,
 | 
			
		||||
                            MetaVector2     *intersection);
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_border_is_horizontal (MetaBorder *border);
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_border_is_blocking_directions (MetaBorder               *border,
 | 
			
		||||
                                    MetaBorderMotionDirection directions);
 | 
			
		||||
 | 
			
		||||
unsigned int
 | 
			
		||||
meta_border_get_allows_directions (MetaBorder *border);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_border_set_allows_directions (MetaBorder *border, unsigned int directions);
 | 
			
		||||
 | 
			
		||||
#endif /* META_BORDER_H */
 | 
			
		||||
@@ -44,7 +44,7 @@ print_version (const gchar    *option_name,
 | 
			
		||||
  exit (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gchar *plugin = "default";
 | 
			
		||||
static const char *plugin = "default";
 | 
			
		||||
 | 
			
		||||
GOptionEntry mutter_options[] = {
 | 
			
		||||
  {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										121
									
								
								src/core/prefs.c
									
									
									
									
									
								
							
							
						
						
									
										121
									
								
								src/core/prefs.c
									
									
									
									
									
								
							@@ -96,6 +96,10 @@ static gboolean bell_is_audible = TRUE;
 | 
			
		||||
static gboolean gnome_accessibility = FALSE;
 | 
			
		||||
static gboolean gnome_animations = TRUE;
 | 
			
		||||
static char *cursor_theme = NULL;
 | 
			
		||||
/* cursor_size will, when running as an X11 compositing window manager, be the
 | 
			
		||||
 * actual cursor size, multiplied with the global window scaling factor. On
 | 
			
		||||
 * Wayland, it will be the actual cursor size retrieved from gsettings.
 | 
			
		||||
 */
 | 
			
		||||
static int   cursor_size = 24;
 | 
			
		||||
static int   draggable_border_width = 10;
 | 
			
		||||
static int   drag_threshold;
 | 
			
		||||
@@ -123,6 +127,9 @@ static gboolean update_binding         (MetaKeyPref *binding,
 | 
			
		||||
static gboolean update_key_binding     (const char  *key,
 | 
			
		||||
                                        gchar      **strokes);
 | 
			
		||||
 | 
			
		||||
static void wayland_settings_changed (GSettings      *settings,
 | 
			
		||||
                                      gchar          *key,
 | 
			
		||||
                                      gpointer        data);
 | 
			
		||||
static void settings_changed (GSettings      *settings,
 | 
			
		||||
                              gchar          *key,
 | 
			
		||||
                              gpointer        data);
 | 
			
		||||
@@ -134,9 +141,10 @@ static void shell_shows_app_menu_changed (GtkSettings *settings,
 | 
			
		||||
                                          GParamSpec  *pspec,
 | 
			
		||||
                                          gpointer     data);
 | 
			
		||||
 | 
			
		||||
static void update_cursor_size (GtkSettings *settings,
 | 
			
		||||
                                GParamSpec *pspec,
 | 
			
		||||
                                gpointer data);
 | 
			
		||||
static void update_cursor_size_from_gtk (GtkSettings *settings,
 | 
			
		||||
                                         GParamSpec *pspec,
 | 
			
		||||
                                         gpointer data);
 | 
			
		||||
static void update_cursor_size (void);
 | 
			
		||||
 | 
			
		||||
static void queue_changed (MetaPreference  pref);
 | 
			
		||||
 | 
			
		||||
@@ -161,8 +169,8 @@ typedef struct
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  char *key;
 | 
			
		||||
  char *schema;
 | 
			
		||||
  const char *key;
 | 
			
		||||
  const char *schema;
 | 
			
		||||
  MetaPreference pref;
 | 
			
		||||
} MetaBasePreference;
 | 
			
		||||
 | 
			
		||||
@@ -963,14 +971,18 @@ meta_prefs_init (void)
 | 
			
		||||
                    G_CALLBACK (settings_changed), NULL);
 | 
			
		||||
  g_signal_connect (settings, "changed::" KEY_GNOME_CURSOR_THEME,
 | 
			
		||||
                    G_CALLBACK (settings_changed), NULL);
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
    g_signal_connect (settings, "changed::cursor-size",
 | 
			
		||||
                      G_CALLBACK (wayland_settings_changed), NULL);
 | 
			
		||||
  g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_INTERFACE), settings);
 | 
			
		||||
 | 
			
		||||
  g_signal_connect (gtk_settings_get_default (),
 | 
			
		||||
                    "notify::gtk-shell-shows-app-menu",
 | 
			
		||||
                    G_CALLBACK (shell_shows_app_menu_changed), NULL);
 | 
			
		||||
 | 
			
		||||
  g_signal_connect (gtk_settings_get_default (), "notify::gtk-cursor-theme-size",
 | 
			
		||||
                    G_CALLBACK (update_cursor_size), NULL);
 | 
			
		||||
  if (!meta_is_wayland_compositor ())
 | 
			
		||||
    g_signal_connect (gtk_settings_get_default (), "notify::gtk-cursor-theme-size",
 | 
			
		||||
                      G_CALLBACK (update_cursor_size_from_gtk), NULL);
 | 
			
		||||
 | 
			
		||||
  settings = g_settings_new (SCHEMA_INPUT_SOURCES);
 | 
			
		||||
  g_signal_connect (settings, "changed::" KEY_XKB_OPTIONS,
 | 
			
		||||
@@ -992,7 +1004,7 @@ meta_prefs_init (void)
 | 
			
		||||
  handle_preference_init_string_array ();
 | 
			
		||||
  handle_preference_init_int ();
 | 
			
		||||
 | 
			
		||||
  update_cursor_size (gtk_settings_get_default (), NULL, NULL);
 | 
			
		||||
  update_cursor_size ();
 | 
			
		||||
  shell_shows_app_menu_changed (gtk_settings_get_default (), NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  init_bindings ();
 | 
			
		||||
@@ -1133,6 +1145,20 @@ meta_prefs_override_preference_schema (const char *key, const char *schema)
 | 
			
		||||
/****************************************************************************/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
wayland_settings_changed (GSettings      *settings,
 | 
			
		||||
                          gchar          *key,
 | 
			
		||||
                          gpointer        data)
 | 
			
		||||
{
 | 
			
		||||
  GVariant *value = g_settings_get_value (settings, key);
 | 
			
		||||
  const GVariantType *type = g_variant_get_type (value);
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (g_variant_type_equal (type, G_VARIANT_TYPE_INT32));
 | 
			
		||||
  g_return_if_fail (g_str_equal (key, "cursor-size"));
 | 
			
		||||
 | 
			
		||||
  update_cursor_size ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
settings_changed (GSettings *settings,
 | 
			
		||||
                  gchar *key,
 | 
			
		||||
@@ -1216,9 +1242,29 @@ shell_shows_app_menu_changed (GtkSettings *settings,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_cursor_size (GtkSettings *settings,
 | 
			
		||||
                    GParamSpec *pspec,
 | 
			
		||||
                    gpointer data)
 | 
			
		||||
update_cursor_size (void)
 | 
			
		||||
{
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
    {
 | 
			
		||||
      /* When running as a Wayland compositor, since we size of the cursor
 | 
			
		||||
       * depends on what output it is on, we cannot use the GTK+
 | 
			
		||||
       * "gtk-cursor-theme-size" setting because it has already been multiplied
 | 
			
		||||
       * by the primary monitor scale. So, instead get the non-premultiplied
 | 
			
		||||
       * cursor size value directly from gsettings instead.
 | 
			
		||||
       */
 | 
			
		||||
      cursor_size =
 | 
			
		||||
        g_settings_get_int (SETTINGS (SCHEMA_INTERFACE), "cursor-size");
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      update_cursor_size_from_gtk (gtk_settings_get_default (), NULL, NULL);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_cursor_size_from_gtk (GtkSettings *settings,
 | 
			
		||||
                             GParamSpec *pspec,
 | 
			
		||||
                             gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  GdkScreen *screen = gdk_screen_get_default ();
 | 
			
		||||
  GValue value = G_VALUE_INIT;
 | 
			
		||||
@@ -1431,42 +1477,11 @@ button_function_from_string (const char *str)
 | 
			
		||||
    return META_BUTTON_FUNCTION_MAXIMIZE;
 | 
			
		||||
  else if (strcmp (str, "close") == 0)
 | 
			
		||||
    return META_BUTTON_FUNCTION_CLOSE;
 | 
			
		||||
  else if (strcmp (str, "shade") == 0)
 | 
			
		||||
    return META_BUTTON_FUNCTION_SHADE;
 | 
			
		||||
  else if (strcmp (str, "above") == 0)
 | 
			
		||||
    return META_BUTTON_FUNCTION_ABOVE;
 | 
			
		||||
  else if (strcmp (str, "stick") == 0)
 | 
			
		||||
    return META_BUTTON_FUNCTION_STICK;
 | 
			
		||||
  else
 | 
			
		||||
    /* don't know; give up */
 | 
			
		||||
    return META_BUTTON_FUNCTION_LAST;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaButtonFunction
 | 
			
		||||
button_opposite_function (MetaButtonFunction ofwhat)
 | 
			
		||||
{
 | 
			
		||||
  switch (ofwhat)
 | 
			
		||||
    {
 | 
			
		||||
    case META_BUTTON_FUNCTION_SHADE:
 | 
			
		||||
      return META_BUTTON_FUNCTION_UNSHADE;
 | 
			
		||||
    case META_BUTTON_FUNCTION_UNSHADE:
 | 
			
		||||
      return META_BUTTON_FUNCTION_SHADE;
 | 
			
		||||
 | 
			
		||||
    case META_BUTTON_FUNCTION_ABOVE:
 | 
			
		||||
      return META_BUTTON_FUNCTION_UNABOVE;
 | 
			
		||||
    case META_BUTTON_FUNCTION_UNABOVE:
 | 
			
		||||
      return META_BUTTON_FUNCTION_ABOVE;
 | 
			
		||||
 | 
			
		||||
    case META_BUTTON_FUNCTION_STICK:
 | 
			
		||||
      return META_BUTTON_FUNCTION_UNSTICK;
 | 
			
		||||
    case META_BUTTON_FUNCTION_UNSTICK:
 | 
			
		||||
      return META_BUTTON_FUNCTION_STICK;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      return META_BUTTON_FUNCTION_LAST;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
button_layout_handler (GVariant *value,
 | 
			
		||||
                       gpointer *result,
 | 
			
		||||
@@ -1510,12 +1525,6 @@ button_layout_handler (GVariant *value,
 | 
			
		||||
          if (i > 0 && strcmp("spacer", buttons[b]) == 0)
 | 
			
		||||
            {
 | 
			
		||||
              new_layout.left_buttons_has_spacer[i-1] = TRUE;
 | 
			
		||||
              f = button_opposite_function (f);
 | 
			
		||||
 | 
			
		||||
              if (f != META_BUTTON_FUNCTION_LAST)
 | 
			
		||||
                {
 | 
			
		||||
                  new_layout.left_buttons_has_spacer[i-2] = TRUE;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
            {
 | 
			
		||||
@@ -1524,11 +1533,6 @@ button_layout_handler (GVariant *value,
 | 
			
		||||
                  new_layout.left_buttons[i] = f;
 | 
			
		||||
                  used[f] = TRUE;
 | 
			
		||||
                  ++i;
 | 
			
		||||
 | 
			
		||||
                  f = button_opposite_function (f);
 | 
			
		||||
 | 
			
		||||
                  if (f != META_BUTTON_FUNCTION_LAST)
 | 
			
		||||
                      new_layout.left_buttons[i++] = f;
 | 
			
		||||
                }
 | 
			
		||||
              else
 | 
			
		||||
                {
 | 
			
		||||
@@ -1572,11 +1576,6 @@ button_layout_handler (GVariant *value,
 | 
			
		||||
          if (i > 0 && strcmp("spacer", buttons[b]) == 0)
 | 
			
		||||
            {
 | 
			
		||||
              new_layout.right_buttons_has_spacer[i-1] = TRUE;
 | 
			
		||||
              f = button_opposite_function (f);
 | 
			
		||||
              if (f != META_BUTTON_FUNCTION_LAST)
 | 
			
		||||
                {
 | 
			
		||||
                  new_layout.right_buttons_has_spacer[i-2] = TRUE;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
            {
 | 
			
		||||
@@ -1585,12 +1584,6 @@ button_layout_handler (GVariant *value,
 | 
			
		||||
                  new_layout.right_buttons[i] = f;
 | 
			
		||||
                  used[f] = TRUE;
 | 
			
		||||
                  ++i;
 | 
			
		||||
 | 
			
		||||
                  f = button_opposite_function (f);
 | 
			
		||||
 | 
			
		||||
                  if (f != META_BUTTON_FUNCTION_LAST)
 | 
			
		||||
                      new_layout.right_buttons[i++] = f;
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
              else
 | 
			
		||||
                {
 | 
			
		||||
 
 | 
			
		||||
@@ -41,14 +41,6 @@
 | 
			
		||||
typedef void (* MetaScreenWindowFunc) (MetaWindow *window,
 | 
			
		||||
                                       gpointer    user_data);
 | 
			
		||||
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
  META_SCREEN_UP,
 | 
			
		||||
  META_SCREEN_DOWN,
 | 
			
		||||
  META_SCREEN_LEFT,
 | 
			
		||||
  META_SCREEN_RIGHT
 | 
			
		||||
} MetaScreenDirection;
 | 
			
		||||
 | 
			
		||||
#define META_WIREFRAME_XOR_LINE_WIDTH 2
 | 
			
		||||
 | 
			
		||||
struct _MetaScreen
 | 
			
		||||
@@ -93,11 +85,7 @@ struct _MetaScreen
 | 
			
		||||
  /* Cache the current monitor */
 | 
			
		||||
  int last_monitor_index;
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_STARTUP_NOTIFICATION
 | 
			
		||||
  SnMonitorContext *sn_context;
 | 
			
		||||
  GSList *startup_sequences;
 | 
			
		||||
  guint startup_sequence_timeout;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  Window wm_cm_selection_window;
 | 
			
		||||
  guint work_area_later;
 | 
			
		||||
@@ -157,8 +145,12 @@ const MetaMonitorInfo* meta_screen_get_current_monitor_info_for_pos   (MetaScree
 | 
			
		||||
                                                                       int y);
 | 
			
		||||
const MetaMonitorInfo* meta_screen_get_monitor_for_rect   (MetaScreen    *screen,
 | 
			
		||||
                                                           MetaRectangle *rect);
 | 
			
		||||
const MetaMonitorInfo* meta_screen_get_monitor_for_window (MetaScreen    *screen,
 | 
			
		||||
                                                           MetaWindow    *window);
 | 
			
		||||
const MetaMonitorInfo* meta_screen_calculate_monitor_for_window (MetaScreen    *screen,
 | 
			
		||||
                                                                 MetaWindow    *window);
 | 
			
		||||
 | 
			
		||||
const MetaMonitorInfo* meta_screen_get_monitor_for_point (MetaScreen    *screen,
 | 
			
		||||
                                                          int            x,
 | 
			
		||||
                                                          int            y);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const MetaMonitorInfo* meta_screen_get_monitor_neighbor (MetaScreen *screen,
 | 
			
		||||
 
 | 
			
		||||
@@ -40,9 +40,10 @@
 | 
			
		||||
#include "keybindings-private.h"
 | 
			
		||||
#include "stack.h"
 | 
			
		||||
#include <meta/compositor.h>
 | 
			
		||||
#include "mutter-enum-types.h"
 | 
			
		||||
#include <meta/meta-enum-types.h>
 | 
			
		||||
#include "core.h"
 | 
			
		||||
#include "meta-cursor-tracker-private.h"
 | 
			
		||||
#include "boxes-private.h"
 | 
			
		||||
 | 
			
		||||
#include <X11/extensions/Xinerama.h>
 | 
			
		||||
#include <X11/extensions/Xcomposite.h>
 | 
			
		||||
@@ -70,11 +71,6 @@ static void prefs_changed_callback (MetaPreference pref,
 | 
			
		||||
static void set_desktop_geometry_hint (MetaScreen *screen);
 | 
			
		||||
static void set_desktop_viewport_hint (MetaScreen *screen);
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_STARTUP_NOTIFICATION
 | 
			
		||||
static void meta_screen_sn_event   (SnMonitorEvent *event,
 | 
			
		||||
                                    void           *user_data);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void on_monitors_changed (MetaMonitorManager *manager,
 | 
			
		||||
                                 MetaScreen         *screen);
 | 
			
		||||
 | 
			
		||||
@@ -294,7 +290,7 @@ set_supported_hint (MetaScreen *screen)
 | 
			
		||||
  Atom atoms[] = {
 | 
			
		||||
#define EWMH_ATOMS_ONLY
 | 
			
		||||
#define item(x)  screen->display->atom_##x,
 | 
			
		||||
#include <meta/atomnames.h>
 | 
			
		||||
#include <x11/atomnames.h>
 | 
			
		||||
#undef item
 | 
			
		||||
#undef EWMH_ATOMS_ONLY
 | 
			
		||||
 | 
			
		||||
@@ -729,17 +725,6 @@ meta_screen_new (MetaDisplay *display,
 | 
			
		||||
 | 
			
		||||
  meta_prefs_add_listener (prefs_changed_callback, screen);
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_STARTUP_NOTIFICATION
 | 
			
		||||
  screen->sn_context =
 | 
			
		||||
    sn_monitor_context_new (screen->display->sn_display,
 | 
			
		||||
                            screen->number,
 | 
			
		||||
                            meta_screen_sn_event,
 | 
			
		||||
                            screen,
 | 
			
		||||
                            NULL);
 | 
			
		||||
  screen->startup_sequences = NULL;
 | 
			
		||||
  screen->startup_sequence_timeout = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
 | 
			
		||||
                screen->number, screen->screen_name, screen->xroot);
 | 
			
		||||
 | 
			
		||||
@@ -750,7 +735,7 @@ void
 | 
			
		||||
meta_screen_init_workspaces (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  MetaWorkspace *current_workspace;
 | 
			
		||||
  gulong current_workspace_index = 0;
 | 
			
		||||
  uint32_t current_workspace_index = 0;
 | 
			
		||||
  guint32 timestamp;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (META_IS_SCREEN (screen));
 | 
			
		||||
@@ -799,24 +784,6 @@ meta_screen_free (MetaScreen *screen,
 | 
			
		||||
 | 
			
		||||
  meta_screen_ungrab_keys (screen);
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_STARTUP_NOTIFICATION
 | 
			
		||||
  g_slist_foreach (screen->startup_sequences,
 | 
			
		||||
                   (GFunc) sn_startup_sequence_unref, NULL);
 | 
			
		||||
  g_slist_free (screen->startup_sequences);
 | 
			
		||||
  screen->startup_sequences = NULL;
 | 
			
		||||
 | 
			
		||||
  if (screen->startup_sequence_timeout != 0)
 | 
			
		||||
    {
 | 
			
		||||
      g_source_remove (screen->startup_sequence_timeout);
 | 
			
		||||
      screen->startup_sequence_timeout = 0;
 | 
			
		||||
    }
 | 
			
		||||
  if (screen->sn_context)
 | 
			
		||||
    {
 | 
			
		||||
      sn_monitor_context_unref (screen->sn_context);
 | 
			
		||||
      screen->sn_context = NULL;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  meta_ui_free (screen->ui);
 | 
			
		||||
 | 
			
		||||
  meta_stack_free (screen->stack);
 | 
			
		||||
@@ -1166,7 +1133,7 @@ update_num_workspaces (MetaScreen *screen,
 | 
			
		||||
  if (meta_prefs_get_dynamic_workspaces ())
 | 
			
		||||
    {
 | 
			
		||||
      int n_items;
 | 
			
		||||
      gulong *list;
 | 
			
		||||
      uint32_t *list;
 | 
			
		||||
 | 
			
		||||
      n_items = 0;
 | 
			
		||||
      list = NULL;
 | 
			
		||||
@@ -1255,21 +1222,47 @@ update_num_workspaces (MetaScreen *screen,
 | 
			
		||||
  g_object_notify (G_OBJECT (screen), "n-workspaces");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
root_cursor_prepare_at (MetaCursorSprite *cursor_sprite,
 | 
			
		||||
                        int x,
 | 
			
		||||
                        int y,
 | 
			
		||||
                        MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  const MetaMonitorInfo *monitor;
 | 
			
		||||
 | 
			
		||||
  monitor = meta_screen_get_monitor_for_point (screen, x, y);
 | 
			
		||||
 | 
			
		||||
  /* Reload the cursor texture if the scale has changed. */
 | 
			
		||||
  meta_cursor_sprite_set_theme_scale (cursor_sprite, monitor->scale);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
manage_root_cursor_sprite_scale (MetaScreen *screen,
 | 
			
		||||
                                 MetaCursorSprite *cursor_sprite)
 | 
			
		||||
{
 | 
			
		||||
  g_signal_connect_object (cursor_sprite,
 | 
			
		||||
                           "prepare-at",
 | 
			
		||||
                           G_CALLBACK (root_cursor_prepare_at),
 | 
			
		||||
                           screen,
 | 
			
		||||
                           0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_screen_update_cursor (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display = screen->display;
 | 
			
		||||
  MetaCursor cursor = screen->current_cursor;
 | 
			
		||||
  Cursor xcursor;
 | 
			
		||||
  MetaCursorReference *cursor_ref;
 | 
			
		||||
  MetaCursorSprite *cursor_sprite;
 | 
			
		||||
  MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (screen);
 | 
			
		||||
 | 
			
		||||
  cursor_ref = meta_cursor_reference_from_theme (cursor);
 | 
			
		||||
  if (cursor_ref == NULL)
 | 
			
		||||
    meta_fatal ("Could not find cursor. Perhaps set XCURSOR_PATH?");
 | 
			
		||||
  cursor_sprite = meta_cursor_sprite_from_theme (cursor);
 | 
			
		||||
 | 
			
		||||
  meta_cursor_tracker_set_root_cursor (tracker, cursor_ref);
 | 
			
		||||
  meta_cursor_reference_unref (cursor_ref);
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
    manage_root_cursor_sprite_scale (screen, cursor_sprite);
 | 
			
		||||
 | 
			
		||||
  meta_cursor_tracker_set_root_cursor (tracker, cursor_sprite);
 | 
			
		||||
  g_object_unref (cursor_sprite);
 | 
			
		||||
 | 
			
		||||
  /* Set a cursor for X11 applications that don't specify their own */
 | 
			
		||||
  xcursor = meta_display_create_x_cursor (display, cursor);
 | 
			
		||||
@@ -1439,8 +1432,8 @@ meta_screen_get_monitor_for_rect (MetaScreen    *screen,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const MetaMonitorInfo*
 | 
			
		||||
meta_screen_get_monitor_for_window (MetaScreen *screen,
 | 
			
		||||
                                    MetaWindow *window)
 | 
			
		||||
meta_screen_calculate_monitor_for_window (MetaScreen *screen,
 | 
			
		||||
                                          MetaWindow *window)
 | 
			
		||||
{
 | 
			
		||||
  MetaRectangle window_rect;
 | 
			
		||||
 | 
			
		||||
@@ -1457,6 +1450,25 @@ meta_screen_get_monitor_index_for_rect (MetaScreen    *screen,
 | 
			
		||||
  return monitor->number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const MetaMonitorInfo *
 | 
			
		||||
meta_screen_get_monitor_for_point (MetaScreen *screen,
 | 
			
		||||
                                   int         x,
 | 
			
		||||
                                   int         y)
 | 
			
		||||
{
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  if (screen->n_monitor_infos == 1)
 | 
			
		||||
    return &screen->monitor_infos[0];
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < screen->n_monitor_infos; i++)
 | 
			
		||||
    {
 | 
			
		||||
      if (POINT_IN_RECT (x, y, screen->monitor_infos[i].rect))
 | 
			
		||||
        return &screen->monitor_infos[i];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const MetaMonitorInfo*
 | 
			
		||||
meta_screen_get_monitor_neighbor (MetaScreen         *screen,
 | 
			
		||||
                                  int                 which_monitor,
 | 
			
		||||
@@ -1490,6 +1502,16 @@ meta_screen_get_monitor_neighbor (MetaScreen         *screen,
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
meta_screen_get_monitor_neighbor_index (MetaScreen         *screen,
 | 
			
		||||
                                        int                 which_monitor,
 | 
			
		||||
                                        MetaScreenDirection direction)
 | 
			
		||||
{
 | 
			
		||||
  const MetaMonitorInfo *monitor;
 | 
			
		||||
  monitor = meta_screen_get_monitor_neighbor (screen, which_monitor, direction);
 | 
			
		||||
  return monitor ? monitor->number : -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_screen_get_natural_monitor_list (MetaScreen *screen,
 | 
			
		||||
                                      int**       monitors_list,
 | 
			
		||||
@@ -1745,7 +1767,7 @@ meta_screen_get_monitor_geometry (MetaScreen    *screen,
 | 
			
		||||
void
 | 
			
		||||
meta_screen_update_workspace_layout (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  gulong *list;
 | 
			
		||||
  uint32_t *list;
 | 
			
		||||
  int n_items;
 | 
			
		||||
 | 
			
		||||
  if (screen->workspace_layout_overridden)
 | 
			
		||||
@@ -2044,7 +2066,7 @@ meta_screen_queue_workarea_recalc (MetaScreen *screen)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef WITH_VERBOSE_MODE
 | 
			
		||||
static char *
 | 
			
		||||
static const char *
 | 
			
		||||
meta_screen_corner_to_string (MetaScreenCorner corner)
 | 
			
		||||
{
 | 
			
		||||
  switch (corner)
 | 
			
		||||
@@ -2378,12 +2400,12 @@ on_monitors_changed (MetaMonitorManager *manager,
 | 
			
		||||
                       &changes);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* Queue a resize on all the windows */
 | 
			
		||||
  meta_screen_foreach_window (screen, META_LIST_DEFAULT, meta_screen_resize_func, 0);
 | 
			
		||||
 | 
			
		||||
  /* Fix up monitor for all windows on this screen */
 | 
			
		||||
  meta_screen_foreach_window (screen, META_LIST_INCLUDE_OVERRIDE_REDIRECT, (MetaScreenWindowFunc) meta_window_update_for_monitors_changed, 0);
 | 
			
		||||
 | 
			
		||||
  /* Queue a resize on all the windows */
 | 
			
		||||
  meta_screen_foreach_window (screen, META_LIST_DEFAULT, meta_screen_resize_func, 0);
 | 
			
		||||
 | 
			
		||||
  meta_screen_queue_check_fullscreen (screen);
 | 
			
		||||
 | 
			
		||||
  g_signal_emit (screen, screen_signals[MONITORS_CHANGED], 0);
 | 
			
		||||
@@ -2482,208 +2504,6 @@ meta_screen_unshow_desktop (MetaScreen *screen)
 | 
			
		||||
  meta_screen_update_showing_desktop_hint (screen);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_STARTUP_NOTIFICATION
 | 
			
		||||
static gboolean startup_sequence_timeout (void *data);
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_startup_feedback (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  if (screen->startup_sequences != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      meta_topic (META_DEBUG_STARTUP,
 | 
			
		||||
                  "Setting busy cursor\n");
 | 
			
		||||
      meta_screen_set_cursor (screen, META_CURSOR_BUSY);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      meta_topic (META_DEBUG_STARTUP,
 | 
			
		||||
                  "Setting default cursor\n");
 | 
			
		||||
      meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
add_sequence (MetaScreen        *screen,
 | 
			
		||||
              SnStartupSequence *sequence)
 | 
			
		||||
{
 | 
			
		||||
  meta_topic (META_DEBUG_STARTUP,
 | 
			
		||||
              "Adding sequence %s\n",
 | 
			
		||||
              sn_startup_sequence_get_id (sequence));
 | 
			
		||||
  sn_startup_sequence_ref (sequence);
 | 
			
		||||
  screen->startup_sequences = g_slist_prepend (screen->startup_sequences,
 | 
			
		||||
                                               sequence);
 | 
			
		||||
 | 
			
		||||
  /* our timeout just polls every second, instead of bothering
 | 
			
		||||
   * to compute exactly when we may next time out
 | 
			
		||||
   */
 | 
			
		||||
  if (screen->startup_sequence_timeout == 0)
 | 
			
		||||
    {
 | 
			
		||||
      screen->startup_sequence_timeout = g_timeout_add_seconds (1,
 | 
			
		||||
                                                                startup_sequence_timeout,
 | 
			
		||||
                                                                screen);
 | 
			
		||||
      g_source_set_name_by_id (screen->startup_sequence_timeout,
 | 
			
		||||
                               "[mutter] startup_sequence_timeout");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  update_startup_feedback (screen);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
remove_sequence (MetaScreen        *screen,
 | 
			
		||||
                 SnStartupSequence *sequence)
 | 
			
		||||
{
 | 
			
		||||
  meta_topic (META_DEBUG_STARTUP,
 | 
			
		||||
              "Removing sequence %s\n",
 | 
			
		||||
              sn_startup_sequence_get_id (sequence));
 | 
			
		||||
 | 
			
		||||
  screen->startup_sequences = g_slist_remove (screen->startup_sequences,
 | 
			
		||||
                                              sequence);
 | 
			
		||||
 | 
			
		||||
  if (screen->startup_sequences == NULL &&
 | 
			
		||||
      screen->startup_sequence_timeout != 0)
 | 
			
		||||
    {
 | 
			
		||||
      g_source_remove (screen->startup_sequence_timeout);
 | 
			
		||||
      screen->startup_sequence_timeout = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  update_startup_feedback (screen);
 | 
			
		||||
 | 
			
		||||
  sn_startup_sequence_unref (sequence);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  GSList *list;
 | 
			
		||||
  GTimeVal now;
 | 
			
		||||
} CollectTimedOutData;
 | 
			
		||||
 | 
			
		||||
/* This should be fairly long, as it should never be required unless
 | 
			
		||||
 * apps or .desktop files are buggy, and it's confusing if
 | 
			
		||||
 * OpenOffice or whatever seems to stop launching - people
 | 
			
		||||
 * might decide they need to launch it again.
 | 
			
		||||
 */
 | 
			
		||||
#define STARTUP_TIMEOUT 15000
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
collect_timed_out_foreach (void *element,
 | 
			
		||||
                           void *data)
 | 
			
		||||
{
 | 
			
		||||
  CollectTimedOutData *ctod = data;
 | 
			
		||||
  SnStartupSequence *sequence = element;
 | 
			
		||||
  long tv_sec, tv_usec;
 | 
			
		||||
  double elapsed;
 | 
			
		||||
 | 
			
		||||
  sn_startup_sequence_get_last_active_time (sequence, &tv_sec, &tv_usec);
 | 
			
		||||
 | 
			
		||||
  elapsed =
 | 
			
		||||
    ((((double)ctod->now.tv_sec - tv_sec) * G_USEC_PER_SEC +
 | 
			
		||||
      (ctod->now.tv_usec - tv_usec))) / 1000.0;
 | 
			
		||||
 | 
			
		||||
  meta_topic (META_DEBUG_STARTUP,
 | 
			
		||||
              "Sequence used %g seconds vs. %g max: %s\n",
 | 
			
		||||
              elapsed, (double) STARTUP_TIMEOUT,
 | 
			
		||||
              sn_startup_sequence_get_id (sequence));
 | 
			
		||||
 | 
			
		||||
  if (elapsed > STARTUP_TIMEOUT)
 | 
			
		||||
    ctod->list = g_slist_prepend (ctod->list, sequence);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
startup_sequence_timeout (void *data)
 | 
			
		||||
{
 | 
			
		||||
  MetaScreen *screen = data;
 | 
			
		||||
  CollectTimedOutData ctod;
 | 
			
		||||
  GSList *l;
 | 
			
		||||
 | 
			
		||||
  ctod.list = NULL;
 | 
			
		||||
  g_get_current_time (&ctod.now);
 | 
			
		||||
  g_slist_foreach (screen->startup_sequences,
 | 
			
		||||
                   collect_timed_out_foreach,
 | 
			
		||||
                   &ctod);
 | 
			
		||||
 | 
			
		||||
  for (l = ctod.list; l != NULL; l = l->next)
 | 
			
		||||
    {
 | 
			
		||||
      SnStartupSequence *sequence = l->data;
 | 
			
		||||
 | 
			
		||||
      meta_topic (META_DEBUG_STARTUP,
 | 
			
		||||
                  "Timed out sequence %s\n",
 | 
			
		||||
                  sn_startup_sequence_get_id (sequence));
 | 
			
		||||
 | 
			
		||||
      sn_startup_sequence_complete (sequence);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_slist_free (ctod.list);
 | 
			
		||||
 | 
			
		||||
  if (screen->startup_sequences != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      /* remove */
 | 
			
		||||
      screen->startup_sequence_timeout = 0;
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_screen_sn_event (SnMonitorEvent *event,
 | 
			
		||||
                      void           *user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaScreen *screen;
 | 
			
		||||
  SnStartupSequence *sequence;
 | 
			
		||||
 | 
			
		||||
  screen = user_data;
 | 
			
		||||
 | 
			
		||||
  sequence = sn_monitor_event_get_startup_sequence (event);
 | 
			
		||||
 | 
			
		||||
  sn_startup_sequence_ref (sequence);
 | 
			
		||||
 | 
			
		||||
  switch (sn_monitor_event_get_type (event))
 | 
			
		||||
    {
 | 
			
		||||
    case SN_MONITOR_EVENT_INITIATED:
 | 
			
		||||
      {
 | 
			
		||||
        const char *wmclass;
 | 
			
		||||
 | 
			
		||||
        wmclass = sn_startup_sequence_get_wmclass (sequence);
 | 
			
		||||
 | 
			
		||||
        meta_topic (META_DEBUG_STARTUP,
 | 
			
		||||
                    "Received startup initiated for %s wmclass %s\n",
 | 
			
		||||
                    sn_startup_sequence_get_id (sequence),
 | 
			
		||||
                    wmclass ? wmclass : "(unset)");
 | 
			
		||||
        add_sequence (screen, sequence);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case SN_MONITOR_EVENT_COMPLETED:
 | 
			
		||||
      {
 | 
			
		||||
        meta_topic (META_DEBUG_STARTUP,
 | 
			
		||||
                    "Received startup completed for %s\n",
 | 
			
		||||
                    sn_startup_sequence_get_id (sequence));
 | 
			
		||||
        remove_sequence (screen,
 | 
			
		||||
                         sn_monitor_event_get_startup_sequence (event));
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case SN_MONITOR_EVENT_CHANGED:
 | 
			
		||||
      meta_topic (META_DEBUG_STARTUP,
 | 
			
		||||
                  "Received startup changed for %s\n",
 | 
			
		||||
                  sn_startup_sequence_get_id (sequence));
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case SN_MONITOR_EVENT_CANCELED:
 | 
			
		||||
      meta_topic (META_DEBUG_STARTUP,
 | 
			
		||||
                  "Received startup canceled for %s\n",
 | 
			
		||||
                  sn_startup_sequence_get_id (sequence));
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_signal_emit (G_OBJECT (screen), screen_signals[STARTUP_SEQUENCE_CHANGED], 0, sequence);
 | 
			
		||||
 | 
			
		||||
  sn_startup_sequence_unref (sequence);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_screen_get_startup_sequences: (skip)
 | 
			
		||||
 * @screen:
 | 
			
		||||
@@ -2695,7 +2515,6 @@ meta_screen_get_startup_sequences (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  return screen->startup_sequences;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Sets the initial_timestamp and initial_workspace properties
 | 
			
		||||
 * of a window according to information given us by the
 | 
			
		||||
 
 | 
			
		||||
@@ -288,8 +288,7 @@ windows_on_different_monitor (MetaWindow *a,
 | 
			
		||||
  if (a->screen != b->screen)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  return meta_screen_get_monitor_for_window (a->screen, a) !=
 | 
			
		||||
    meta_screen_get_monitor_for_window (b->screen, b);
 | 
			
		||||
  return a->monitor != b->monitor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get layer ignoring any transient or group relationships */
 | 
			
		||||
@@ -1056,7 +1055,7 @@ stack_sync_to_xserver (MetaStack *stack)
 | 
			
		||||
  all_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (guint64));
 | 
			
		||||
  x11_hidden_stack_ids = g_array_new (FALSE, FALSE, sizeof (guint64));
 | 
			
		||||
 | 
			
		||||
  meta_topic (META_DEBUG_STACK, "Top to bottom: ");
 | 
			
		||||
  meta_topic (META_DEBUG_STACK, "Bottom to top: ");
 | 
			
		||||
  meta_push_no_msg_prefix ();
 | 
			
		||||
 | 
			
		||||
  for (tmp = g_list_last(stack->sorted); tmp != NULL; tmp = tmp->prev)
 | 
			
		||||
@@ -1089,11 +1088,7 @@ stack_sync_to_xserver (MetaStack *stack)
 | 
			
		||||
      if (w->hidden)
 | 
			
		||||
	{
 | 
			
		||||
          if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
 | 
			
		||||
            {
 | 
			
		||||
              guint64 stack_id = top_level_window;
 | 
			
		||||
 | 
			
		||||
              g_array_append_val (x11_hidden_stack_ids, stack_id);
 | 
			
		||||
            }
 | 
			
		||||
            g_array_append_val (x11_hidden_stack_ids, top_level_window);
 | 
			
		||||
	  continue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -1239,24 +1234,10 @@ get_default_focus_window (MetaStack     *stack,
 | 
			
		||||
{
 | 
			
		||||
  /* Find the topmost, focusable, mapped, window.
 | 
			
		||||
   * not_this_one is being unfocused or going away, so exclude it.
 | 
			
		||||
   * Also, prefer to focus transient parent of not_this_one,
 | 
			
		||||
   * or top window in same group as not_this_one.
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  MetaWindow *transient_parent;
 | 
			
		||||
  MetaWindow *topmost_in_group;
 | 
			
		||||
  MetaWindow *topmost_overall;
 | 
			
		||||
  MetaGroup *not_this_one_group;
 | 
			
		||||
  GList *l;
 | 
			
		||||
 | 
			
		||||
  transient_parent = NULL;
 | 
			
		||||
  topmost_in_group = NULL;
 | 
			
		||||
  topmost_overall = NULL;
 | 
			
		||||
  if (not_this_one)
 | 
			
		||||
    not_this_one_group = meta_window_get_group (not_this_one);
 | 
			
		||||
  else
 | 
			
		||||
    not_this_one_group = NULL;
 | 
			
		||||
 | 
			
		||||
  stack_ensure_sorted (stack);
 | 
			
		||||
 | 
			
		||||
  /* top of this layer is at the front of the list */
 | 
			
		||||
@@ -1273,49 +1254,25 @@ get_default_focus_window (MetaStack     *stack,
 | 
			
		||||
      if (window->unmaps_pending > 0)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (window->minimized)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (window->unmanaging)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (!(window->input || window->take_focus))
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (workspace != NULL && !meta_window_located_on_workspace (window, workspace))
 | 
			
		||||
      if (!meta_window_should_be_showing (window))
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (must_be_at_point && !window_contains_point (window, root_x, root_y))
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (not_this_one != NULL)
 | 
			
		||||
        {
 | 
			
		||||
          if (transient_parent == NULL &&
 | 
			
		||||
              meta_window_get_transient_for (not_this_one) == window)
 | 
			
		||||
            transient_parent = window;
 | 
			
		||||
      if (window->type == META_WINDOW_DOCK)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
          if (topmost_in_group == NULL &&
 | 
			
		||||
              not_this_one_group != NULL &&
 | 
			
		||||
              not_this_one_group == meta_window_get_group (window))
 | 
			
		||||
            topmost_in_group = window;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (topmost_overall == NULL && window->type != META_WINDOW_DOCK)
 | 
			
		||||
        topmost_overall = window;
 | 
			
		||||
 | 
			
		||||
      /* We could try to bail out early here for efficiency in
 | 
			
		||||
       * some cases, but it's just not worth the code.
 | 
			
		||||
       */
 | 
			
		||||
      return window;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (transient_parent)
 | 
			
		||||
    return transient_parent;
 | 
			
		||||
  else if (topmost_in_group)
 | 
			
		||||
    return topmost_in_group;
 | 
			
		||||
  else if (topmost_overall)
 | 
			
		||||
    return topmost_overall;
 | 
			
		||||
  else
 | 
			
		||||
    return NULL;
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaWindow*
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										48
									
								
								src/core/startup-notification-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/core/startup-notification-private.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001, 2002 Havoc Pennington
 | 
			
		||||
 * Copyright (C) 2002, 2003 Red Hat Inc.
 | 
			
		||||
 * Some ICCCM manager selection code derived from fvwm2,
 | 
			
		||||
 * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team
 | 
			
		||||
 * Copyright (C) 2003 Rob Adams
 | 
			
		||||
 * Copyright (C) 2004-2006 Elijah Newren
 | 
			
		||||
 *
 | 
			
		||||
 * 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/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef META_STARTUP_NOTIFICATION_PRIVATE_H
 | 
			
		||||
#define META_STARTUP_NOTIFICATION_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include "display-private.h"
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_STARTUP_NOTIFICATION (meta_startup_notification_get_type ())
 | 
			
		||||
 | 
			
		||||
G_DECLARE_FINAL_TYPE (MetaStartupNotification,
 | 
			
		||||
                      meta_startup_notification,
 | 
			
		||||
                      META, STARTUP_NOTIFICATION,
 | 
			
		||||
                      GObject)
 | 
			
		||||
 | 
			
		||||
MetaStartupNotification *
 | 
			
		||||
         meta_startup_notification_get             (MetaDisplay             *display);
 | 
			
		||||
 | 
			
		||||
gboolean meta_startup_notification_handle_xevent   (MetaStartupNotification *sn,
 | 
			
		||||
                                                    XEvent                  *xevent);
 | 
			
		||||
 | 
			
		||||
void     meta_startup_notification_remove_sequence (MetaStartupNotification *sn,
 | 
			
		||||
                                                    const gchar             *id);
 | 
			
		||||
 | 
			
		||||
GSList * meta_startup_notification_get_sequences   (MetaStartupNotification *sn);
 | 
			
		||||
 | 
			
		||||
#endif /* META_STARTUP_NOTIFICATION_PRIVATE_H */
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user