Compare commits
	
		
			527 Commits
		
	
	
		
			3.11.1-way
			...
			3.11.92-wa
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 56e8c3b625 | ||
|   | ce3d9fb89f | ||
|   | 27c018ab98 | ||
|   | a1427c7130 | ||
|   | 91ad92c968 | ||
|   | f0c7b518e6 | ||
|   | 5fa5ace5e6 | ||
|   | 044c06bff3 | ||
|   | a3ccc4fd1c | ||
|   | 0a20f7458c | ||
|   | 9c94f8ae47 | ||
|   | f940292cfe | ||
|   | 48a36356dd | ||
|   | f05983be42 | ||
|   | dfcefd3315 | ||
|   | 3fe755e684 | ||
|   | 0eb86de807 | ||
|   | ff635bad3b | ||
|   | 43a409dec4 | ||
|   | b087fce062 | ||
|   | 420f322910 | ||
|   | 4bf6e0ae8c | ||
|   | 97872e70a5 | ||
|   | be57308663 | ||
|   | 33f1bd96f5 | ||
|   | 9ba49358e5 | ||
|   | 8b2b65246a | ||
|   | 4fdbb466e1 | ||
|   | da48b18188 | ||
|   | a5f1790828 | ||
|   | 6efcf2526d | ||
|   | d6a27195d3 | ||
|   | 8f151842fb | ||
|   | 6f7023bc6b | ||
|   | 63b158e4da | ||
|   | b3364cad3e | ||
|   | 3502cfba34 | ||
|   | 5cc6becb63 | ||
|   | ae8f21a3dc | ||
|   | 0cdf3bd383 | ||
|   | 3de58189c0 | ||
|   | 5270c469a3 | ||
|   | 7504f16e59 | ||
|   | cdb7947dd1 | ||
|   | cdfc6f5b53 | ||
|   | fcb2ab41b2 | ||
|   | f5bd7c5f50 | ||
|   | cb549154aa | ||
|   | ada9610e30 | ||
|   | f11bf44525 | ||
|   | 1f15c85c00 | ||
|   | 8b4c5459c0 | ||
|   | d07d5d1328 | ||
|   | 535685742a | ||
|   | 62e45b6d5e | ||
|   | 3c6dd5bf6d | ||
|   | 0f85986340 | ||
|   | 93ac0329db | ||
|   | c539dfe0d7 | ||
|   | 1502d2a79f | ||
|   | a9d8107c3d | ||
|   | a5d2c51392 | ||
|   | d1ea17e6a4 | ||
|   | b37ad66e9d | ||
|   | c1f15348a5 | ||
|   | 857561baed | ||
|   | a44cc9ef47 | ||
|   | d47b7ba038 | ||
|   | f21312e2fd | ||
|   | 394af33607 | ||
|   | 7314cdac94 | ||
|   | 81025e37ea | ||
|   | 1bb9f1e333 | ||
|   | b11c75c1c9 | ||
|   | 757b626aee | ||
|   | fb3df5243f | ||
|   | e34792d9f0 | ||
|   | f397c32192 | ||
|   | f79314d7b5 | ||
|   | 55c61259d8 | ||
|   | 5298cf0a3a | ||
|   | f1dc1a0cbc | ||
|   | 2cf80bc647 | ||
|   | 40c15f6e2a | ||
|   | a8849621c9 | ||
|   | 49c0be11d6 | ||
|   | 9df8e831be | ||
|   | 84c6b2a3fa | ||
|   | 06cd669ccb | ||
|   | 81eb7d9537 | ||
|   | dd8d8e436d | ||
|   | d6b6b363ad | ||
|   | 254e2e993c | ||
|   | c595a9c29f | ||
|   | dfc7f7222b | ||
|   | ef278eb547 | ||
|   | 38e26e5cc3 | ||
|   | 9773a879c3 | ||
|   | abd2abcde6 | ||
|   | a8f4651c72 | ||
|   | 54df7934ea | ||
|   | 9052efb0d9 | ||
|   | b346f98eb0 | ||
|   | 365af53797 | ||
|   | bee59ec0e1 | ||
|   | 91384a32b4 | ||
|   | 72bd5fb814 | ||
|   | 46af3ef9f6 | ||
|   | d417c615d5 | ||
|   | 46cbd0bf48 | ||
|   | f3b6fead4d | ||
|   | 80de8ec643 | ||
|   | 4f7e2a9f3f | ||
|   | 701e06d55d | ||
|   | 94f39a493f | ||
|   | ddc171220a | ||
|   | 0313b38dd6 | ||
|   | d41fba6558 | ||
|   | 770b58b367 | ||
|   | 77838c2ca3 | ||
|   | e56cbfbd0f | ||
|   | a27fb19473 | ||
|   | 674bcef6da | ||
|   | 86c1c30245 | ||
|   | 283546b379 | ||
|   | 98e3e5e50f | ||
|   | b6a0d4d368 | ||
|   | 28859c604f | ||
|   | 9e51d98f4a | ||
|   | 268a4c92ba | ||
|   | 71367e14d5 | ||
|   | 5c99eae8a9 | ||
|   | 89aa5df711 | ||
|   | b9a5d710b7 | ||
|   | 65dd54a4db | ||
|   | b00fa70d91 | ||
|   | 360d423faa | ||
|   | 394b44a2c2 | ||
|   | ed6821a819 | ||
|   | 23b0f7be43 | ||
|   | 7f195aec7a | ||
|   | da13e3d237 | ||
|   | 75184d4c55 | ||
|   | eb75306f8a | ||
|   | 98c4b82907 | ||
|   | 640102c03b | ||
|   | c0d791cd6e | ||
|   | 41d5e69de5 | ||
|   | 2dc7371944 | ||
|   | ec2c3e1438 | ||
|   | c5c3806a04 | ||
|   | ac0c7df4a3 | ||
|   | d85845426c | ||
|   | 060e60f2a0 | ||
|   | 26cf75d5a4 | ||
|   | 9f5087e97d | ||
|   | 45624f2edf | ||
|   | 153f843ea6 | ||
|   | f0cd9b0687 | ||
|   | 1783bf20ec | ||
|   | 9b24ae2033 | ||
|   | 0be4622e14 | ||
|   | bcd5446cdc | ||
|   | 04b5232960 | ||
|   | f860df4b2d | ||
|   | ff8c4b1bcf | ||
|   | 337c69e223 | ||
|   | 14841475b5 | ||
|   | 7283fb320f | ||
|   | 020cfa7283 | ||
|   | 83aca0b53d | ||
|   | 0b055fae2e | ||
|   | bc79259398 | ||
|   | 7ebf5aa69a | ||
|   | 7499621ecb | ||
|   | 4de3f7ca29 | ||
|   | 17462c21e8 | ||
|   | c964ef4e01 | ||
|   | 0dccc440b6 | ||
|   | 48f7232492 | ||
|   | ff5867e4d3 | ||
|   | a5d950f453 | ||
|   | 7615d17293 | ||
|   | 374e30043b | ||
|   | f771bb88d6 | ||
|   | 7ef8d21e48 | ||
|   | c251eb8ec0 | ||
|   | 1e6b3faa83 | ||
|   | e62fe956fd | ||
|   | 24c5290d7f | ||
|   | 00c8d3c897 | ||
|   | cc13f8f65e | ||
|   | 47f4c9db7b | ||
|   | 4c621cc30f | ||
|   | 756a412436 | ||
|   | be16c2fe71 | ||
|   | a364c2a96b | ||
|   | 414259a7f8 | ||
|   | 283a81eac0 | ||
|   | 2a145262c7 | ||
|   | 57728b4322 | ||
|   | ef24fb6296 | ||
|   | 86f057a712 | ||
|   | dcd628d289 | ||
|   | 6038877c4c | ||
|   | 4e6321c239 | ||
|   | 304a525744 | ||
|   | f26de405dd | ||
|   | ed18580118 | ||
|   | b65649186d | ||
|   | 515dc08a97 | ||
|   | 2e7a56a28f | ||
|   | c485637a61 | ||
|   | f9f2a82e18 | ||
|   | 2f4563132a | ||
|   | e3a0f2c546 | ||
|   | d39baeb8ad | ||
|   | f27f6aab78 | ||
|   | a66060e21a | ||
|   | 11aa3c030b | ||
|   | bd1bec5617 | ||
|   | d9659d4b36 | ||
|   | d043d9943b | ||
|   | a0ef7c7142 | ||
|   | 4efe4483fb | ||
|   | aec3edb1cc | ||
|   | 0c5a6ad775 | ||
|   | 2be5401b1e | ||
|   | f16e9b2ee7 | ||
|   | 06380938d4 | ||
|   | 87b20d7f2a | ||
|   | 593db0baee | ||
|   | 6b66553493 | ||
|   | ddaae9c923 | ||
|   | 0c7a7d7527 | ||
|   | 6561b53346 | ||
|   | def5e86673 | ||
|   | 0c213c8fee | ||
|   | 912a0abd26 | ||
|   | d694260ad2 | ||
|   | 8566566451 | ||
|   | 0ce64e46e8 | ||
|   | a8336669a3 | ||
|   | f6db756326 | ||
|   | 27ab516f41 | ||
|   | 9542b464bf | ||
|   | 1ebaaa1950 | ||
|   | 71efbf0330 | ||
|   | a6539463be | ||
|   | b8e096db82 | ||
|   | 3e98ffaf99 | ||
|   | 0a9754f305 | ||
|   | 965a784c8a | ||
|   | 2db9f55669 | ||
|   | 3e73babaf7 | ||
|   | 66c4555dc7 | ||
|   | 183ad75603 | ||
|   | 66fc32ee14 | ||
|   | d6396cf2c4 | ||
|   | c9b7104117 | ||
|   | 6bf1a66b7c | ||
|   | 7e7b671b8e | ||
|   | e04a55d1a2 | ||
|   | 8905bd2280 | ||
|   | b09e1399c0 | ||
|   | 59c8b949ad | ||
|   | 6dbb3fddce | ||
|   | f166240225 | ||
|   | 91b789c707 | ||
|   | 14db280fab | ||
|   | f7097e6f66 | ||
|   | ff89f1e271 | ||
|   | 6a8a4bfdcd | ||
|   | cd35982d4e | ||
|   | 2f6f0f252c | ||
|   | 13651949ed | ||
|   | fdeb72224c | ||
|   | 92e36e7076 | ||
|   | d74796ee80 | ||
|   | 3e35cac67a | ||
|   | 1f7a6bf845 | ||
|   | 365442c1ff | ||
|   | c8d185fc74 | ||
|   | 9567fa9c6a | ||
|   | 7a8de0c0af | ||
|   | 10fead9ba1 | ||
|   | d5d5c2167a | ||
|   | b9755ea725 | ||
|   | 39fee9f5a2 | ||
|   | d6282716b2 | ||
|   | 60d9bee3bf | ||
|   | a09fa3b0e4 | ||
|   | 9edff6f250 | ||
|   | 7d3012fd67 | ||
|   | 225e20a898 | ||
|   | 1a62ac9276 | ||
|   | 45cb151443 | ||
|   | 55b18f9671 | ||
|   | 4f4b1bfc37 | ||
|   | 9348c9bd4b | ||
|   | 16de7f66fb | ||
|   | 799c27484d | ||
|   | c3b0faec82 | ||
|   | 9c876722a0 | ||
|   | 96fc93d744 | ||
|   | 20545941fa | ||
|   | 59f79e8294 | ||
|   | ac32b9ef95 | ||
|   | ba484be754 | ||
|   | a318198ab4 | ||
|   | e6391c2896 | ||
|   | 7ea537fad7 | ||
|   | 03146c2967 | ||
|   | 0a81314337 | ||
|   | fa7a5782c6 | ||
|   | e3b64912b6 | ||
|   | a0fe392665 | ||
|   | 0e5f365d55 | ||
|   | bfc906cbc4 | ||
|   | 8e6f8087e8 | ||
|   | 56207ddb6a | ||
|   | 8cb9cfb7b8 | ||
|   | be698b597b | ||
|   | 1d61a0f9b5 | ||
|   | 788bd59857 | ||
|   | 2391606cc5 | ||
|   | 7155d7e043 | ||
|   | 419dfd333a | ||
|   | b4535f2622 | ||
|   | 9b21346427 | ||
|   | 7b15d21e40 | ||
|   | 7b597b8c62 | ||
|   | 7a4adce44f | ||
|   | a5f0db5ecb | ||
|   | 577624adef | ||
|   | af46ef3b96 | ||
|   | 39d26be941 | ||
|   | 7bfc9109f7 | ||
|   | becbad56ef | ||
|   | 384a34c27d | ||
|   | 002c5b8f87 | ||
|   | 1d3dbea20c | ||
|   | ebe6e3180e | ||
|   | a3de799939 | ||
|   | 0caf7381bb | ||
|   | a42305edab | ||
|   | 732c059235 | ||
|   | ef2b6e7d00 | ||
|   | 9c1b972ca1 | ||
|   | cb33e1942a | ||
|   | 7009d1e470 | ||
|   | c54a19825b | ||
|   | 8131f34eb6 | ||
|   | f29241d90e | ||
|   | bad48ea815 | ||
|   | 66af41f4a9 | ||
|   | e30be380dd | ||
|   | 65f2e29375 | ||
|   | 98dbba1e17 | ||
|   | 422648e2eb | ||
|   | f0fa4d831a | ||
|   | 1b600f5867 | ||
|   | fd8cc9b7a8 | ||
|   | ca5b5e6bc4 | ||
|   | ee683ff187 | ||
|   | 57602adfe7 | ||
|   | 1481836ed6 | ||
|   | 309f78ff52 | ||
|   | 6436459381 | ||
|   | 65b39212d5 | ||
|   | 283649b8d7 | ||
|   | fa65c380db | ||
|   | 58b39233f5 | ||
|   | 82066e02c5 | ||
|   | c36aa5e696 | ||
|   | 29197d40c6 | ||
|   | 8d5ab6b5b3 | ||
|   | a796938b39 | ||
|   | 3813113f1a | ||
|   | 1be117e430 | ||
|   | 622c7a021b | ||
|   | 4d2d2f285b | ||
|   | 0924c7d61b | ||
|   | 2746608eb2 | ||
|   | fe26cb5989 | ||
|   | 602307e694 | ||
|   | b2c18c4a78 | ||
|   | 1e211722c7 | ||
|   | 461f74ef18 | ||
|   | 3f022ca963 | ||
|   | 20e92c5a72 | ||
|   | 0850da44d7 | ||
|   | 37ba264190 | ||
|   | 6c12c928df | ||
|   | 9c5733caf0 | ||
|   | 21d8b8310a | ||
|   | c46af91d54 | ||
|   | d44574f738 | ||
|   | a9424255a5 | ||
|   | 5089a63d76 | ||
|   | f9a2c64460 | ||
|   | 7841042a85 | ||
|   | ea1b8cdc22 | ||
|   | 52b48cfbef | ||
|   | 644f3e1275 | ||
|   | 304005e04f | ||
|   | 025ab35af7 | ||
|   | a27744503b | ||
|   | 1011331caf | ||
|   | 0ccef81789 | ||
|   | 4780f74a40 | ||
|   | 57866fb267 | ||
|   | d3bc7570d0 | ||
|   | 74e43a4702 | ||
|   | 0764b2058a | ||
|   | 7a787d7946 | ||
|   | eec0f5df47 | ||
|   | ba3968a822 | ||
|   | 762fa0e116 | ||
|   | 0be57b621b | ||
|   | 7d88b3593b | ||
|   | 858db7081a | ||
|   | 5af7f619c8 | ||
|   | e5e35e5a7f | ||
|   | 6d639ac528 | ||
|   | aa3643cdde | ||
|   | 8a3501ffe1 | ||
|   | 5ea443eb4b | ||
|   | a37a8c6497 | ||
|   | ebf6862a10 | ||
|   | 6c0e16c482 | ||
|   | 40b1e7312d | ||
|   | 1c0e6f26e2 | ||
|   | f4fc498e65 | ||
|   | a8632c2546 | ||
|   | 600a0f836f | ||
|   | 0ac142d39e | ||
|   | abd368be00 | ||
|   | a8ac2cc275 | ||
|   | 2f14b5cc3f | ||
|   | 2930612e64 | ||
|   | 2952d3671d | ||
|   | 1b5ace8256 | ||
|   | 2ebecc5370 | ||
|   | 02144d17e9 | ||
|   | 71496c8909 | ||
|   | 594b15abf1 | ||
|   | bbe3641844 | ||
|   | 0cc5cf940b | ||
|   | 153d8efcf5 | ||
|   | be744775c1 | ||
|   | 5959457c73 | ||
|   | 0824eb7c96 | ||
|   | d945501be6 | ||
|   | ca342c4573 | ||
|   | 4326d0bf3a | ||
|   | a6ebc70170 | ||
|   | 3025cb7c48 | ||
|   | 17f48baf3a | ||
|   | 333661a9d8 | ||
|   | b9da43b753 | ||
|   | 097ee776c7 | ||
|   | a4a8f1f863 | ||
|   | f36a627330 | ||
|   | a1087c3f30 | ||
|   | aad275b9a2 | ||
|   | f0397eab94 | ||
|   | 392e224831 | ||
|   | 6867d44573 | ||
|   | a841fff2ac | ||
|   | 26aa10a974 | ||
|   | f6144082b1 | ||
|   | 957513242c | ||
|   | 17fd25e216 | ||
|   | e91268a250 | ||
|   | 82cb4e8267 | ||
|   | 68eb87cc58 | ||
|   | f3e52d5b18 | ||
|   | 2b2b2d3191 | ||
|   | 9461c612de | ||
|   | f0280a8868 | ||
|   | c749f7b6fb | ||
|   | 74462133ca | ||
|   | 7c45d6594c | ||
|   | ea916b6c49 | ||
|   | a02d734243 | ||
|   | 735b736110 | ||
|   | bbbb9ac53c | ||
|   | 8dd97b4998 | ||
|   | 73a9082062 | ||
|   | 4091f5493d | ||
|   | d96b053c9d | ||
|   | 1f569bef76 | ||
|   | 1a88176cc0 | ||
|   | 662c9729bc | ||
|   | 56a0dd6b2c | ||
|   | 9dc6028b3d | ||
|   | 932e913d88 | ||
|   | b72315e27a | ||
|   | 3c7cd1f38c | ||
|   | 1946c548bf | ||
|   | cf181fe109 | ||
|   | 63b9110f93 | ||
|   | ae44bff0b1 | ||
|   | 23ba3e527f | ||
|   | 08df9bf559 | ||
|   | 648639fffe | ||
|   | 6cc014a941 | ||
|   | b7b95123ed | ||
|   | 153463790a | ||
|   | 875bbec949 | ||
|   | 666e5f1f98 | ||
|   | e6790038dd | ||
|   | e86c53230f | ||
|   | 4ea4658abf | ||
|   | 58f6ab0a27 | ||
|   | 9c0cc664d1 | ||
|   | 84d26e31f1 | ||
|   | 64a848fcb7 | ||
|   | 429583ae8b | ||
|   | 93ae868987 | ||
|   | 72a900787f | ||
|   | 7186841db0 | ||
|   | ab080e3e6b | ||
|   | ad84aef766 | ||
|   | 7908eca579 | ||
|   | 237d990dea | 
							
								
								
									
										19
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -78,12 +78,12 @@ src/stamp-mutter-marshal.h | ||||
| src/meta-dbus-xrandr.[ch] | ||||
| src/meta-dbus-idle-monitor.[ch] | ||||
| src/mutter-plugins.pc | ||||
| src/wayland/gtk-shell-protocol.c | ||||
| src/wayland/gtk-shell-client-protocol.h | ||||
| src/wayland/gtk-shell-server-protocol.h | ||||
| src/wayland/xserver-protocol.c | ||||
| src/wayland/xserver-client-protocol.h | ||||
| src/wayland/xserver-server-protocol.h | ||||
| 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 | ||||
| doc/reference/*.args | ||||
| doc/reference/*.bak | ||||
| doc/reference/*.hierarchy | ||||
| @@ -101,3 +101,10 @@ doc/reference/meta-undocumented.txt | ||||
| doc/reference/meta-unused.txt | ||||
| doc/reference/meta-docs.sgml | ||||
| doc/reference/meta.types | ||||
| gtk-doc.m4 | ||||
| intltool.m4 | ||||
| libtool.m4 | ||||
| ltoptions.m4 | ||||
| ltsugar.m4 | ||||
| ltversion.m4 | ||||
| lt~obsolete.m4 | ||||
|   | ||||
							
								
								
									
										159
									
								
								COMPLIANCE
									
									
									
									
									
								
							
							
						
						
									
										159
									
								
								COMPLIANCE
									
									
									
									
									
								
							| @@ -1,159 +0,0 @@ | ||||
| Metacity Standards Compliance | ||||
| ============================= | ||||
| $Id$ | ||||
|  | ||||
| 1) Introduction | ||||
| 2) EWMH Compliance | ||||
|   a. Root Window Properties | ||||
|   b. Root Window Messages | ||||
|   c. Application Window Properties | ||||
|   d. Window Manager Protocols | ||||
| 3) ICCCM Compliance | ||||
|  | ||||
| 1) Introduction | ||||
| --------------- | ||||
|  | ||||
| This document details metacity compliance with the relevent standards. | ||||
| The format of this document is as follows: | ||||
|  | ||||
| [-/+?] Hint Name/Feature Name (Version number) | ||||
|        Errata/Comments | ||||
|  | ||||
| The first character indicates the level of compliance as follows: | ||||
|     -   none | ||||
|     /   partial | ||||
|     +   complete | ||||
|     ?   unknown | ||||
|  | ||||
| The title indicates a feature or a hint in the specification, and the | ||||
| version number indicates the minimum version of the specification | ||||
| supported by metacity.  Later versions may be supported if no | ||||
| incompatible changes have been made in the specification. | ||||
|  | ||||
| 2) EWMH Compliance | ||||
| ------------------ | ||||
|  | ||||
| The EWMH, or Extended Window Manager Hints is a freedesktop.org- | ||||
| developed standard to support a number of conventions for | ||||
| communication between the window manager and clients.  It builds on | ||||
| and extends the ICCCM (See Section 3).  A copy of the current EWMH | ||||
| standard is available at http://freedesktop.org/Standards/wm-spec/ | ||||
|  | ||||
|   a. Root Window Properties | ||||
|   ------------------------- | ||||
|  | ||||
| + _NET_SUPPORTED (1.3) | ||||
|  | ||||
| + _NET_CLIENT_LIST (1.3) | ||||
|  | ||||
| + _NET_NUMBER_OF_DESKTOPS (1.3) | ||||
|  | ||||
| + _NET_DESKTOP_GEOMETRY (1.3) | ||||
|   Metacity does not implement large desktops, so this is kept set to | ||||
|   the screen size. | ||||
|  | ||||
| + _NET_DESKTOP_VIEWPORT (1.3) | ||||
|   Metacity does not implement viewports, so this is a constant (0,0). | ||||
|  | ||||
| + _NET_CURRENT_DESKTOP (1.3) | ||||
|  | ||||
| + _NET_DESKTOP_NAMES (1.3) | ||||
|  | ||||
| + _NET_ACTIVE_WINDOW (1.3) | ||||
|  | ||||
| + _NET_WORKAREA (1.3) | ||||
|  | ||||
| + _NET_SUPPORTING_WM_CHECK (1.3) | ||||
|  | ||||
| + _NET_VIRTUAL_ROOTS (1.3) | ||||
|   Metacity does not read or set this property, but it does not use | ||||
|   virtual roots to implement virtual desktops, so it complies with the | ||||
|   specification. | ||||
|  | ||||
| + _NET_DESKTOP_LAYOUT (1.3) | ||||
|  | ||||
| + _NET_SHOWING_DESKTOP (1.3) | ||||
|  | ||||
|   b. Root Window Messages | ||||
|   ----------------------- | ||||
|  | ||||
| + _NET_CLOSE_WINDOW (1.3) | ||||
|  | ||||
| - _NET_MOVERESIZE_WINDOW (1.3) | ||||
|   Metacity supports this message, but the specification is unclear on | ||||
|   the layout of the detail value, and as such it is #if 0'd in the code | ||||
|  | ||||
| + _NET_WM_MOVERESIZE (1.3) | ||||
|  | ||||
| - _NET_RESTACK_WINDOW (1.3) | ||||
|   Metacity will raise or lower windows in response to this message, | ||||
|   but the sibling restack modes are not supported, and it is currently | ||||
|   #if 0'd in the code. | ||||
|  | ||||
| + _NET_REQUEST_FRAME_EXTENTS (1.3)   | ||||
|  | ||||
|   c. Application Window Properties | ||||
|   -------------------------------- | ||||
|  | ||||
| + _NET_WM_NAME (1.3) | ||||
|  | ||||
| + _NET_WM_VISIBLE_NAME (1.3) | ||||
|   Metacity does not set this property, but metacity will never display | ||||
|   a name different from _NET_WM_NAME | ||||
|  | ||||
| + _NET_WM_ICON_NAME (1.3) | ||||
|  | ||||
| + _NET_WM_VISIBLE_ICON_NAME (1.3) | ||||
|   Metacity does not set this property, but metacity will never display | ||||
|   a name different from _NET_WM_NAME | ||||
|  | ||||
| + _NET_WM_DESKTOP (1.3) | ||||
|  | ||||
| + _NET_WM_WINDOW_TYPE (1.3) | ||||
|  | ||||
| / _NET_WM_STATE (1.3) | ||||
|   This property is read and updated according to the specification, | ||||
|   but see caveat below. | ||||
|   Metacity does not recognize separate vertical and horizontal | ||||
|   maximization states.  Currently metacity will do a two-dimensional | ||||
|   maximization if either property is set. | ||||
|   See: http://bugzilla.gnome.org/show_bug.cgi?id=113601 | ||||
|   Metacity doesn't implement viewports so _NET_WM_STATE_STICKY is | ||||
|   unimplemented. | ||||
|  | ||||
| + _NET_WM_ALLOWED_ACTIONS (1.3) | ||||
|   Metacity keeps this hint up to date.  The code is somewhat crufty | ||||
|   and should be rewritten, though it is functional. | ||||
|   See: http://bugzilla.gnome.org/show_bug.cgi?id=90420 | ||||
|  | ||||
| + _NET_WM_STRUT (1.3) | ||||
|  | ||||
| + _NET_WM_STRUT_PARTIAL (1.3) | ||||
|  | ||||
| + _NET_WM_ICON_GEOMETRY (1.3) | ||||
|   Metacity uses this property to draw minimize/restore animations | ||||
|  | ||||
| + _NET_WM_ICON (1.3) | ||||
|  | ||||
| + _NET_WM_PID (1.3) | ||||
|  | ||||
| + _NET_WM_HANDLED_ICONS (1.3) | ||||
|   Metacity does not read or set this property.  However, metacity | ||||
|   never manages iconified windows, and so has no need to do so. | ||||
|  | ||||
| + _NET_WM_USER_TIME (1.3) | ||||
|   Metacity uses this property to prevent applications from stealing | ||||
|   focus if supported by the toolkit. | ||||
|  | ||||
| + _NET_FRAME_EXTENTS (1.3) | ||||
|   If set in response to a _NET_REQUEST_FRAME_EXTENTS message received | ||||
|   prior to the window being mapped, this may be an estimate.  This is, | ||||
|   however, expressly allowed by the specification. | ||||
|  | ||||
|   d. Window Manager Protocols | ||||
|   --------------------------- | ||||
| + _NET_WM_PING (1.3) | ||||
|  | ||||
| 3) ICCCM Compliance | ||||
| ------------------- | ||||
| TODO | ||||
							
								
								
									
										41
									
								
								COPYING
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								COPYING
									
									
									
									
									
								
							| @@ -1,12 +1,12 @@ | ||||
| 		    GNU GENERAL PUBLIC LICENSE | ||||
| 		       Version 2, June 1991 | ||||
|                     GNU GENERAL PUBLIC LICENSE | ||||
|                        Version 2, June 1991 | ||||
|  | ||||
|  Copyright (C) 1989, 1991 Free Software Foundation, Inc. | ||||
|      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  Copyright (C) 1989, 1991 Free Software Foundation, Inc., | ||||
|  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||
|  Everyone is permitted to copy and distribute verbatim copies | ||||
|  of this license document, but changing it is not allowed. | ||||
|  | ||||
| 			    Preamble | ||||
|                             Preamble | ||||
|  | ||||
|   The licenses for most software are designed to take away your | ||||
| freedom to share and change it.  By contrast, the GNU General Public | ||||
| @@ -15,7 +15,7 @@ software--to make sure the software is free for all its users.  This | ||||
| General Public License applies to most of the Free Software | ||||
| Foundation's software and to any other program whose authors commit to | ||||
| using it.  (Some other Free Software Foundation software is covered by | ||||
| the GNU Library General Public License instead.)  You can apply it to | ||||
| the GNU Lesser General Public License instead.)  You can apply it to | ||||
| your programs, too. | ||||
|  | ||||
|   When we speak of free software, we are referring to freedom, not | ||||
| @@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all. | ||||
|  | ||||
|   The precise terms and conditions for copying, distribution and | ||||
| modification follow. | ||||
|  | ||||
| 		    GNU GENERAL PUBLIC LICENSE | ||||
|  | ||||
|                     GNU GENERAL PUBLIC LICENSE | ||||
|    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | ||||
|  | ||||
|   0. This License applies to any program or other work which contains | ||||
| @@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions: | ||||
|     License.  (Exception: if the Program itself is interactive but | ||||
|     does not normally print such an announcement, your work based on | ||||
|     the Program is not required to print an announcement.) | ||||
|  | ||||
|  | ||||
| These requirements apply to the modified work as a whole.  If | ||||
| identifiable sections of that work are not derived from the Program, | ||||
| and can be reasonably considered independent and separate works in | ||||
| @@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent | ||||
| access to copy the source code from the same place counts as | ||||
| distribution of the source code, even though third parties are not | ||||
| compelled to copy the source along with the object code. | ||||
|  | ||||
|  | ||||
|   4. You may not copy, modify, sublicense, or distribute the Program | ||||
| except as expressly provided under this License.  Any attempt | ||||
| otherwise to copy, modify, sublicense or distribute the Program is | ||||
| @@ -225,7 +225,7 @@ impose that choice. | ||||
|  | ||||
| This section is intended to make thoroughly clear what is believed to | ||||
| be a consequence of the rest of this License. | ||||
|  | ||||
|  | ||||
|   8. If the distribution and/or use of the Program is restricted in | ||||
| certain countries either by patents or by copyrighted interfaces, the | ||||
| original copyright holder who places the Program under this License | ||||
| @@ -255,7 +255,7 @@ make exceptions for this.  Our decision will be guided by the two goals | ||||
| of preserving the free status of all derivatives of our free software and | ||||
| of promoting the sharing and reuse of software generally. | ||||
|  | ||||
| 			    NO WARRANTY | ||||
|                             NO WARRANTY | ||||
|  | ||||
|   11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY | ||||
| FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN | ||||
| @@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER | ||||
| PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE | ||||
| POSSIBILITY OF SUCH DAMAGES. | ||||
|  | ||||
| 		     END OF TERMS AND CONDITIONS | ||||
|  | ||||
| 	    How to Apply These Terms to Your New Programs | ||||
|                      END OF TERMS AND CONDITIONS | ||||
|  | ||||
|             How to Apply These Terms to Your New Programs | ||||
|  | ||||
|   If you develop a new program, and you want it to be of the greatest | ||||
| possible use to the public, the best way to achieve this is to make it | ||||
| @@ -303,17 +303,16 @@ the "copyright" line and a pointer to where the full notice is found. | ||||
|     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 | ||||
|  | ||||
|     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., | ||||
|     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| Also add information on how to contact you by electronic and paper mail. | ||||
|  | ||||
| If the program is interactive, make it output a short notice like this | ||||
| when it starts in an interactive mode: | ||||
|  | ||||
|     Gnomovision version 69, Copyright (C) year  name of author | ||||
|     Gnomovision version 69, Copyright (C) year name of author | ||||
|     Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | ||||
|     This is free software, and you are welcome to redistribute it | ||||
|     under certain conditions; type `show c' for details. | ||||
| @@ -336,5 +335,5 @@ necessary.  Here is a sample; alter the names: | ||||
| This General Public License does not permit incorporating your program into | ||||
| proprietary programs.  If your program is a subroutine library, you may | ||||
| consider it more useful to permit linking proprietary applications with the | ||||
| library.  If this is what you want to do, use the GNU Library General | ||||
| library.  If this is what you want to do, use the GNU Lesser General | ||||
| Public License instead of this License. | ||||
|   | ||||
							
								
								
									
										298
									
								
								HACKING
									
									
									
									
									
								
							
							
						
						
									
										298
									
								
								HACKING
									
									
									
									
									
								
							| @@ -1,298 +0,0 @@ | ||||
| Intro... | ||||
|  | ||||
| Window managers have a few ways in which they are significantly different | ||||
| from other applications.  This file, combined with the code overview in | ||||
| doc/code-overview.txt, should hopefully provide a series of relatively | ||||
| quick pointers (hopefully only a few minutes each) to some of the places | ||||
| one can look to orient themselves and get started.  Some of this will be | ||||
| general to window managers on X, much will be specific to Metacity, and | ||||
| there's probably some information that's common to programs in general but | ||||
| is nonetheless useful. | ||||
|  | ||||
| Overview | ||||
|   Administrative issues | ||||
|   Minimal Building/Testing Environment | ||||
|   Relevant standards and X properties | ||||
|   Debugging and testing | ||||
|     Debugging logs | ||||
|     Adding information to the log | ||||
|     Valgrind | ||||
|     Testing Utilities | ||||
|   Technical gotchas to keep in mind | ||||
|   Other important reading | ||||
|     Extra reading | ||||
|     Ideas for tasks to work on | ||||
|  | ||||
|  | ||||
| Administrative issues | ||||
|   Don't commit substantive code in here without asking hp@redhat.com. | ||||
|   Adding translations, no-brainer typo fixes, etc. is fine. | ||||
|  | ||||
|   The code could use cleanup in a lot of places, feel free to do so. | ||||
|  | ||||
|   See http://developer.gnome.org/dotplan/for_maintainers.html for | ||||
|   information on how to make a release.  The only difference from those | ||||
|   instructions is that the minor version number of a Metacity release | ||||
|   should always be a number from the Fibonacci sequence. | ||||
|  | ||||
| Minimal Building/Testing Environment | ||||
|   You do not need to _install_ a development version of Metacity to | ||||
|   build, run and test it; you can run it from some temporary | ||||
|   directory.  Also, you do not need to build all of Gnome in order to | ||||
|   build a development version of Metacity -- odds are, you may be able | ||||
|   to build metacity from CVS without building any other modules. | ||||
|  | ||||
|   As long as you have gtk+ >= 3.0 and GIO >= 2.25.10 with your distro | ||||
|   (gtk+ >= 2.6 if you manually revert the change from bug 348633), you | ||||
|   should be able to install your distro's development packages | ||||
|   (e.g. gtk2-devel, glib-devel, startup-notification-devel on | ||||
|   Fedora; also, remember to install the gnome-common package which is | ||||
|   needed for building cvs versions of Gnome modules like Metacity) as | ||||
|   well as the standard development tools (gcc, autoconf, automake, | ||||
|   pkg-config, intltool, and libtool) and be ready to build and test | ||||
|   Metacity.  Steps to do so: | ||||
|  | ||||
|   $ svn checkout http://svn.gnome.org/svn/metacity/trunk metacity | ||||
|   $ cd metacity | ||||
|   $ ./autogen.sh --prefix /usr | ||||
|   $ make | ||||
|   $ ./src/metacity --replace | ||||
|  | ||||
|   Again, note that you do not need to run 'make install'. | ||||
|  | ||||
| Relevant standards and X properties | ||||
|   There are two documents that describe some basics about how window | ||||
|   managers should behave: the ICCCM (Inter-Client Communication Conventions | ||||
|   Manual) and EWMH (Extended Window Manager Hints).  You can find these at | ||||
|   the following locations: | ||||
|     ICCCM - http://tronche.com/gui/x/icccm/ | ||||
|     EWMH  - :pserver:anoncvs@pdx.freedesktop.org:/cvs | ||||
|   The ICCCM is usually available in RPM or DEB format as well.  There is | ||||
|   actually an online version of the EWMH, but it is almost always woefully | ||||
|   out of date.  Just get it from cvs with these commands (the backslash | ||||
|   means include the stuff from the next line): | ||||
|     cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/icccm-extensions login | ||||
|     cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/icccm-extensions \ | ||||
|       checkout wm-spec | ||||
|  | ||||
|   DO NOT GO AND READ THOSE THINGS.  THEY ARE REALLY, REALLY BORING. | ||||
|  | ||||
|   If you do, you'll probably end up catching up on your sleep instead of | ||||
|   hacking on Metacity. ;-)  Instead, just look at the table of contents and | ||||
|   glance at a page or two to get an idea of what's in there.  Then only | ||||
|   refer to it if you see something weird in the code and you don't know | ||||
|   what it is but has some funny looking name like you see in one of those | ||||
|   two documents. | ||||
|  | ||||
|   You can refer to the COMPLIANCE file for additional information on these | ||||
|   specifications and Metacity's compliance therewith. | ||||
|  | ||||
|   One of the major things those documents cover that are useful to learn | ||||
|   about immediately are X properties.  The right way to learn about those, | ||||
|   though, is through hand on experimentation with the xprop command (and | ||||
|   then look up things you find from xprop in those two manuals if you're | ||||
|   curious enough).  First, try running | ||||
|     xprop | ||||
|   in a terminal and click on one of the windows on your screen.  That gives | ||||
|   you the x properties for that window.  Look through them and get a basic | ||||
|   idea of what's there for kicks.  Note that you can get rid of some of the | ||||
|   verboseness by grepping out the _NET_WM_ICON stuff, i.e. | ||||
|     xprop | grep -v _NET_WM_ICON | ||||
|   Next, try running | ||||
|     xprop -root | ||||
|   in a terminal.  There's all the properties of the root window (which you | ||||
|   can think of as the "main" Xserver window).  You can also manually | ||||
|   specify individual windows that you want the properties of with | ||||
|     xprop -id <id> | ||||
|   if you know the id of the window in question.  You can get the id of a | ||||
|   given window by either running xwininfo, e.g. | ||||
|     xwininfo | grep "Window id" | cut -f 4 -d ' ' | ||||
|   or by looking at the _NET_CLIENT_STACKING property of the root | ||||
|   window.  Finally, it can also be useful to add "-spy" (without the | ||||
|   quotes) to the xprop command to get it to continually monitor that | ||||
|   window and report any changes to you. | ||||
|  | ||||
| Debugging information | ||||
|   Trying to run a window manager under a typical debugger, such as gdb, | ||||
|   unfortunately just doesn't work very well.  So, we have to resort to | ||||
|   other methods. | ||||
|  | ||||
|   Debugging logs | ||||
|  | ||||
|   First, note that you can start a new version of metacity to replace the | ||||
|   existing one by running | ||||
|     metacity --replace | ||||
|   (which also comes in handy in the form "./src/metacity --replace" when | ||||
|   trying to quickly test a small change while hacking on metacity without | ||||
|   doing a full "make install", though I'm going off topic...)  This will | ||||
|   allow you to see any warnings printed at the terminal.  Sometimes it's | ||||
|   useful to have these directed to a logfile instead, which you can do by | ||||
|   running | ||||
|     METACITY_USE_LOGFILE=1 metacity --replace | ||||
|   The logfile it uses will be printed in the terminal.  Sometimes, it's | ||||
|   useful to get more information than just warnings.  You can set | ||||
|   METACITY_VERBOSE to do that, like so: | ||||
|     METACITY_VERBOSE=1 METACITY_USE_LOGFILE=1 metacity --replace | ||||
|   (note that METACITY_VERBOSE=1 can be problematic without | ||||
|   METACITY_USE_LOGFILE=1; avoid it unless running in from something that | ||||
|   won't be managed by the new Metacity--see bug 305091 for more details). | ||||
|   There are also other flags, such as METACITY_DEBUG, most of which I | ||||
|   haven't tried and don't know what they do.  Go to the source code | ||||
|   directory and run | ||||
|     grep "METACITY_" * | grep getenv | ||||
|   to find out what the other ones are. | ||||
|  | ||||
|   Adding information to the log | ||||
|  | ||||
|   Since we can't single step with a debugger, we often have to fall back to | ||||
|   the primitive method of getting information we want to know: adding | ||||
|   "print" statements.  Metacity has a fairly structured way to do this, | ||||
|   using the functions meta_warning, meta_topic, and meta_verbose.  All | ||||
|   three have the same basic format as printf, except that meta_topic also | ||||
|   takes a leading enumeration parameter to specify the type of message | ||||
|   being shown (makes it easier for grepping in a verbose log).  You'll find | ||||
|   tons of examples in the source code if you need them; just do a quick | ||||
|   grep or look in most any file.  Note that meta_topic and meta_verbose | ||||
|   messages only appear if verbosity is turned on.  I tend to frequently add | ||||
|   temporary meta_warning statements (or switch meta_topic or meta_verbose | ||||
|   ones to meta_warning ones) and then undo the changes once I've learned | ||||
|   the info that I needed. | ||||
|  | ||||
|   There is also a meta_print_backtrace (which again is only active if | ||||
|   verbosity is turned on) that can also be useful if you want to learn how | ||||
|   a particular line of code gets called.  And, of course, there's always | ||||
|   g_assert if you want to make sure some section isn't executed (or isn't | ||||
|   executed under certain conditions). | ||||
|  | ||||
|   Valgrind | ||||
|  | ||||
|   Valgrind is awesome for finding memory leaks or corruption and | ||||
|   uninitialized variables.  But I also tend to use it in a non-traditional | ||||
|   way as a partial substitute for a normal debugger: it can provide me with | ||||
|   a stack trace of where metacity is crashing if I made a change that | ||||
|   caused it to do so, which is one of the major uses of debuggers.  (And, | ||||
|   what makes it cooler than a debugger is that there will also often be | ||||
|   warnings pinpointing the cause of the crash from either some kind of | ||||
|   simple memory corruption or an uninitialized variable).  Sometimes, when | ||||
|   I merely want to know what is calling a particular function I'll just | ||||
|   throw in an "int i; printf("%d\n", i);" just because valgrind will give | ||||
|   me a full stacktrace whenever it sees that uninitialized variable being | ||||
|   used (yes, I could use meta_print_backtrace, but that means I have to | ||||
|   turn verbosity on). | ||||
|  | ||||
|   To run metacity under valgrind, use options typical for any Gnome | ||||
|   program, such as | ||||
|     valgrind --log-file=metacity.log --tool=memcheck --num-callers=48 \ | ||||
|     --leak-check=yes --leak-resolution=high --show-reachable=yes     \ | ||||
|     ./src/metacity --replace | ||||
|   where, again, the backslashes mean to join all the stuff on the following | ||||
|   line with the previous one. | ||||
|  | ||||
|   However, there is a downside.  Things run a little bit slowly, and it | ||||
|   appears that you'll need about 1.5GB of ram, which unfortunately prevents | ||||
|   most people from trying this. | ||||
|  | ||||
|   Testing Utilities | ||||
|  | ||||
|   src/run-metacity.sh | ||||
|     The script src/run-metacity.sh is useful to hack on the window manager.  | ||||
|     It runs metacity in an Xnest. e.g.: | ||||
|       CLIENTS=3 ./run-metacity.sh | ||||
|     or  | ||||
|       DEBUG=memprof ./run-metacity.sh | ||||
|     or | ||||
|       DEBUG_TEST=1 ./run-metacity-sh | ||||
|     or whatever. | ||||
|  | ||||
|   metacity-message | ||||
|     The tool metacity-message can be used as follows: | ||||
|       metacity-message reload-theme | ||||
|       metacity-message restart | ||||
|       metacity-message enable-keybindings | ||||
|       metacity-message disable-keybindings | ||||
|     The first of these is useful for testing themes, the second is just | ||||
|     another way (besides the --restart flag to metacity itself) of | ||||
|     restarting metacity, and the third is useful for testing Metacity when | ||||
|     running it under an Xnest (typically, the Metacity under the Xnest | ||||
|     wouldn't get keybinding notifications--making keyboard navigation not | ||||
|     work--but if you disable the keybindings for the global Metacity then | ||||
|     the Metacity under the Xnest can then get those keybinding notifications). | ||||
|  | ||||
|   metacity-window-demo | ||||
|     metacity-window-demo is good for trying behavior of various kinds | ||||
|     of window without launching a full desktop. | ||||
|  | ||||
| Technical gotchas to keep in mind | ||||
|   Files that include gdk.h or gtk.h are not supposed to include | ||||
|   display.h or window.h or other core files.  Files in the core | ||||
|   (display.[hc], window.[hc]) are not supposed to include gdk.h or | ||||
|   gtk.h.  Reasons: | ||||
|  | ||||
|     "Basically you don't want GDK most of the time. It adds | ||||
|     abstractions that cause problems, because they aren't designed to | ||||
|     be used in a WM where we do weird stuff (display grabs, and just | ||||
|     being the WM). At best GDK adds inefficiency, at worst it breaks | ||||
|     things in weird ways where you have to be a GDK guru to figure | ||||
|     them out. Owen also told me that they didn't want to start adding | ||||
|     a lot of hacks to GDK to let a WM use it; we both agreed back in | ||||
|     the mists of time that metacity would only use it for the "UI" | ||||
|     bits as it does. | ||||
|  | ||||
|     Having the split in the source code contains and makes very clear | ||||
|     the interface between the WM and GDK/GTK. This keeps people from | ||||
|     introducing extra GDK/GTK usage when it isn't needed or | ||||
|     appropriate. Also, it speeds up the compilation a bit, though this | ||||
|     was perhaps more relevant 5 years ago than it is now. | ||||
|  | ||||
|     There was also a very old worry that the GDK stuff might have to | ||||
|     be in a separate process to work right; that turned out to be | ||||
|     untrue. Though who knows what issues the CM will introduce." | ||||
|  | ||||
|   Remember that strings stored in X properties are not in UTF-8, and they | ||||
|   have to end up in UTF-8 before we try putting them through Pango. | ||||
|  | ||||
|   If you make any X request involving a client window, you have to | ||||
|   meta_error_trap_push() around the call; this is not necessary for X | ||||
|   requests on the frame windows. | ||||
|  | ||||
|   Remember that not all windows have frames, and window->frame can be NULL. | ||||
|  | ||||
| Other important reading & where to get started | ||||
|   Extra reading | ||||
|  | ||||
|   There are some other important things to read to get oriented as well. | ||||
|   These are: | ||||
|     http://pobox.com/~hp/features.html | ||||
|     rationales.txt | ||||
|     doc/code-overview.txt | ||||
|  | ||||
|   It pays to read http://pobox.com/~hp/features.html in order | ||||
|   to understand the philosophy of Metacity. | ||||
|  | ||||
|   The rationales.txt file has two things: (1) a list of design choices with | ||||
|   links in the form of bugzilla bugs that discuss the issue, and (2) a list | ||||
|   outstanding bug categories, each of which is tracked by a particular | ||||
|   tracker bug in bugzilla from which you can find several closely related | ||||
|   bug reports. | ||||
|  | ||||
|   doc/code-overview.txt provides a fairly good overview of the code, | ||||
|   including coverage of the function of the various files, the main | ||||
|   structures and their relationships, and places to start looking in the | ||||
|   code tailored to general categories of tasks. | ||||
|  | ||||
|   Ideas for tasks to work on | ||||
|  | ||||
|   There are a variety of things you could work on in the code.  You may | ||||
|   have ideas of your own, but in case you don't, let me provide a list of | ||||
|   ideas you could choose from: | ||||
|  | ||||
|   If you're ambitious, there's a list of things Havoc made that he'd really | ||||
|   like to see tackled, which you can find at | ||||
|   http://log.ometer.com/2004-05.html.  Be sure to double check with someone | ||||
|   to make sure the item is still relevant if you're interested in one of | ||||
|   these.  Another place to look for ideas, of course, is bugzilla.  One can | ||||
|   just do queries and look for things that look fixable. | ||||
|  | ||||
|   However, perhaps the best way of getting ideas of related tasks to work | ||||
|   on, is to look at the second half of the rationales.txt file, which tries | ||||
|   to group bugs by type. | ||||
| @@ -1,8 +0,0 @@ | ||||
| Tomas Frydrych | ||||
| Email: tf linux intel com | ||||
| Userid: tomasf | ||||
|  | ||||
| Owen Taylor | ||||
| Email: otaylor redhat com | ||||
| Userid: otaylor | ||||
|  | ||||
| @@ -1,43 +0,0 @@ | ||||
| Currently active maintainers | ||||
| -------------------------------- | ||||
|  | ||||
| Elijah Newren | ||||
| Email: newren gmail com | ||||
| Userid: newren | ||||
|  | ||||
|   - Usually won't touch the theme bugs (isn't interested) or the | ||||
|     compositor (until open source nvidia drivers are up to snuff). | ||||
|     Tends to be most interested in libwnck/gtk interactions, focus | ||||
|     issues, constraints problems, and raising/stacking, but works on | ||||
|     just about anything other than themes and the compositor. | ||||
|  | ||||
| Thomas Thurman | ||||
| Email: thomas thurman org uk | ||||
| Userid: tthurman | ||||
|  | ||||
|   - Responsible for all theme bugs and the compositor (thank goodness | ||||
|     Thomas got involved, eh?).  I'm sure he'll replace this sentence | ||||
|     with his interests when he reads it.  ;-) | ||||
|  | ||||
|  | ||||
| Semi-active maintainers | ||||
| -------------------------------- | ||||
|  | ||||
| Havoc Pennington | ||||
| Email: hp  redhat com | ||||
| Userid: hp | ||||
|   - Original author.  Doesn't patch metacity anymore, but is active in | ||||
|     answering questions, responding to bugs, providing very helpful | ||||
|     suggestions and insight, and even assisting with debugging. | ||||
|  | ||||
|  | ||||
| Important historical figureheads | ||||
| -------------------------------- | ||||
|  | ||||
| Rob Adams (readams  readams net) | ||||
|   - Was the main maintainer of metacity for a while; particular areas | ||||
|     of focus included xinerama, placement, and an older version of the | ||||
|     constraints code.  Still responds to bugs every once in a while. | ||||
|  | ||||
| Søren Sandmann (sandmann  redhat com) | ||||
|   - Wrote most of the current compositing manager code + libcm | ||||
| @@ -1,7 +1,5 @@ | ||||
|  | ||||
| SUBDIRS=src protocol po doc | ||||
|  | ||||
| EXTRA_DIST = HACKING MAINTAINERS rationales.txt | ||||
| SUBDIRS=src po doc | ||||
|  | ||||
| DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache | ||||
|  | ||||
|   | ||||
							
								
								
									
										94
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										94
									
								
								NEWS
									
									
									
									
									
								
							| @@ -1,3 +1,97 @@ | ||||
| 3.11.92 | ||||
| ======= | ||||
| * Fix identification of CSD windows [Owen; #723029] | ||||
| * Update keyboard state unconditionally [Rui; #722847] | ||||
| * Misc bug fixes and cleanups [Owen, Rui, Giovanni, Matthias, Adel, Ryan, | ||||
|   Jasper, Marek, Florian; #723580, #726123, #726683] | ||||
|  | ||||
| Contributors: | ||||
|   Giovanni Campagna, Marek Chalupa, Matthias Clasen, Adel Gadllah, Ryan Lortie, | ||||
|   Rui Matos, Florian Müllner, Jasper St. Pierre, Owen W. Taylor | ||||
|  | ||||
| 3.11.91 | ||||
| ======= | ||||
| * Don't use keysym to match keybindings [Rui; #678001] | ||||
| * Fix message tray icons showing up blank (again) [Adel; #725180] | ||||
| * Improve keybinding lookups [Rui; #725588] | ||||
| * Fix dynamic updates of titlebar style properties [Owen; #725751] | ||||
| * Fix positioning of manually positioned windows [Owen; #724049] | ||||
| * Misc bug fixes and cleanups [Jasper, Carlos, Adel, Giovanni, Florian; #720631, | ||||
|   #724969, #725216, #724402, #722266, #725338, #725525] | ||||
|  | ||||
| Contributors: | ||||
|   Giovanni Campagna, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner, | ||||
|   Jasper St. Pierre, Owen W. Taylor | ||||
|  | ||||
| 3.11.90 | ||||
| ======= | ||||
| * Fix double-scaling on high DPI resolutions [Adel; #723931] | ||||
| * Make tile previews a compositor effect [Stefano, Florian; #665758] | ||||
| * Misc. bug fixes and cleanups [Ryan, Giovanni, Jasper, Adel; #722530, #724257, | ||||
|   #724258, #720631, #724364, #724472] | ||||
|  | ||||
| Contributors: | ||||
|   Giovanni Campagna, Marek Chalupa, Stefano Facchini, Adel Gadllah, | ||||
|   Ryan Lortie, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz | ||||
|  | ||||
| 3.11.5 | ||||
| ====== | ||||
| * Fix CSD titlebars being placed off-screen [Jasper; #719772] | ||||
| * Add support for subsurfaces [Jonas; #705502] | ||||
| * Expose MetaWindow:skip-taskbar property [Florian; #723307] | ||||
| * Fix legacy tray icons showing up blank [Adel; #721596] | ||||
| * Fix configuration of cloned monitors [Adel; #710610] | ||||
| * Misc bug fixes and cleanups [Jasper, Adel, Marek, Jonas; #720631, #723468, | ||||
|   #720818, #723563, #723564] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl, Marek Ch, Adel Gadllah, Florian Müllner, Jasper St. Pierre | ||||
|  | ||||
| 3.11.4 | ||||
| ====== | ||||
| * Don't leave focus on windows that are being unmanaged [Owen; #711618] | ||||
| * Reduce server grabs [Daniel Drake; #721345, #721709] | ||||
| * Improve heuristic to determine display output name [Cosimo Cecchi; #721674] | ||||
| * Atomically unmaximize both directions [Jasper; #722108] | ||||
| * Misc bug fixes [Debarshi, Andika, Florian; #721517, #721674, #722347] | ||||
|  | ||||
| Contributors: | ||||
|   Cosimo Cecchi, Daniel Drake, Florian Müllner, Debarshi Ray, Jasper St. Pierre, | ||||
|   Andika Triwidada, Owen W. Taylor | ||||
|  | ||||
| 3.11.3 | ||||
| ====== | ||||
| * Fix focus issues with external OSKs[Jasper; #715030] | ||||
| * Add a MetaCullable interface [Jasper; #714706] | ||||
| * Fix window keybindings [Rui; #719724] | ||||
| * Fix settings keyboard/pointer focus for new clients [Rui; #719725] | ||||
| * Fix window group paint volume [Owen; #719669] | ||||
| * Fix frame extents problems [Owen; #714707] | ||||
| * Add shortcut to move windows between monitors [Florian; #671054] | ||||
| * Fix problems with focus tracking [Owen; #720558] | ||||
| * Misc. bug fixes and cleanups: [Rui, Colin, Lionel, Jasper, Owen; #712833, | ||||
|   #719557, #719695, #719833, #678989, #720417, #720630] | ||||
|  | ||||
| Contributors: | ||||
|   Lionel Landwerlin, Rui Matos, Alberto Milone, Florian Müllner, | ||||
|   Jasper St. Pierre, Rico Tzschichholz, Owen W. Taylor, Colin Walters | ||||
|  | ||||
| 3.11.2 | ||||
| ====== | ||||
| * Support setting a NULL opaque region [Andreas; #711518] | ||||
| * Sync keymap from X to wayland [Giovanni; #707446] | ||||
| * Implement support for subsurfaces [Jonas; #705502] | ||||
| * Don't focus the no-focus-window for globally active windows [Jasper; #710296] | ||||
| * Support "hotplug_mode_update" property [Marc-André; #711216] | ||||
| * Fix resize operations using mouse-button-modifier [Lionel; #710251] | ||||
| * Fix position of attached modals for CSD windows [Giovanni, Owen; #707194] | ||||
| * Misc. bug fixes [Rui, Jasper, Neil, Florian; #712247, #711731] | ||||
|  | ||||
| Contributors: | ||||
|   Giovanni Campagna, Andreas Heider, Lionel Landwerlin, Marc-André Lureau, | ||||
|   Rui Matos, Florian Müllner, Neil Roberts, Sindhu S, Jasper St. Pierre, | ||||
|   Rico Tzschichholz, Owen W. Taylor, Jonas Ådahl | ||||
|  | ||||
| 3.11.1 | ||||
| ====== | ||||
| * Fix tile previews getting stuck on right click during drags [Lionel; #704759] | ||||
|   | ||||
							
								
								
									
										416
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										416
									
								
								README
									
									
									
									
									
								
							| @@ -1,416 +0,0 @@ | ||||
| The original codebase named "Metacity" is not a meta-City as in an | ||||
| urban center, but rather Meta-ness as in the state of being | ||||
| meta. i.e. metacity : meta as opacity : opaque. Also it may have | ||||
| something to do with the Meta key on UNIX keyboards. | ||||
|  | ||||
| Since then, it has been renamed mutter after a rebase on top of | ||||
| clutter as a compositing manager. | ||||
|  | ||||
| COMPILING MUTTER | ||||
| === | ||||
|  | ||||
| You need GTK+ 2.2.  For startup notification to work you need | ||||
| libstartup-notification at | ||||
| http://www.freedesktop.org/software/startup-notification/ or on the | ||||
| GNOME ftp site. | ||||
| You need Clutter 1.0. You need gobject-introspection 0.6.3. | ||||
|  | ||||
| REPORTING BUGS AND SUBMITTING PATCHES | ||||
| === | ||||
|  | ||||
| Report new bugs on http://bugzilla.gnome.org. Please check for | ||||
| duplicates, *especially* if you are reporting a feature request.  | ||||
|  | ||||
| Please do *not* add "me too!" or "yes I really want this!" comments to | ||||
| feature requests in bugzilla. Please read | ||||
| http://pobox.com/~hp/features.html prior to adding any kind of flame | ||||
| about missing features or misfeatures. | ||||
|  | ||||
| Feel free to send patches too; Metacity is relatively small and | ||||
| simple, so if you find a bug or want to add a feature it should be | ||||
| pretty easy.  Send me mail, or put the patch in bugzilla. | ||||
|  | ||||
| See the HACKING file for some notes on hacking Mutter. | ||||
|  | ||||
| MUTTER FEATURES | ||||
| === | ||||
|  | ||||
|  - Uses GTK+ 2.0 for drawing window frames. This means colors, fonts,  | ||||
|    etc. come from GTK+ theme. | ||||
|  | ||||
|  - Does not expose the concept of "window manager" to the user.  Some | ||||
|    of the features in the GNOME control panel and other parts of the | ||||
|    desktop happen to be implemented in metacity, such as changing your | ||||
|    window border theme, or changing your window navigation shortcuts, | ||||
|    but the user doesn't need to know this. | ||||
|  | ||||
|  - Includes only the window manager; does not try to be a desktop | ||||
|    environment. The pager, configuration, etc. are all separate and | ||||
|    modular. The "libwnck" library (which I also wrote) is available | ||||
|    for writing metacity extensions, pagers, and so on. (But libwnck | ||||
|    isn't metacity specific, or GNOME-dependent; it requires only GTK, | ||||
|    and should work with KWin, fvwm2, and other EWMH-compliant WMs.) | ||||
|  | ||||
|  - Has a simple theme system and a couple of extra themes come with it. | ||||
|    Change themes via gsettings: | ||||
|      gsettings set org.gnome.desktop.wm.preferences theme Crux | ||||
|      gsettings set org.gnome.desktop.wm.preferences theme Gorilla | ||||
|      gsettings set org.gnome.desktop.wm.preferences theme Atlanta | ||||
|      gsettings set org.gnome.desktop.wm.preferences theme Bright | ||||
|  | ||||
|    See theme-format.txt for docs on the theme format. Use  | ||||
|    metacity-theme-viewer to preview themes. | ||||
|  | ||||
|  - Change number of workspaces via gsettings: | ||||
|      gsettings set org.gnome.desktop.wm.preferences num-workspaces 5 | ||||
|  | ||||
|    Can also change workspaces from GNOME 2 pager. | ||||
|  | ||||
|  - Change focus mode: | ||||
|      gsettings set org.gnome.desktop.wm.preferences focus-mode mouse | ||||
|      gsettings set org.gnome.desktop.wm.preferences focus-mode sloppy | ||||
|      gsettings set org.gnome.desktop.wm.preferences focus-mode click | ||||
|  | ||||
|  - Global keybinding defaults include:    | ||||
|  | ||||
|     Alt-Tab                forward cycle window focus | ||||
|     Alt-Shift-Tab          backward cycle focus | ||||
|     Alt-Ctrl-Tab           forward cycle focus among panels | ||||
|     Alt-Ctrl-Shift-Tab     backward cycle focus among panels | ||||
|     Alt-Escape             cycle window focus without a popup thingy | ||||
|     Ctrl-Alt-Left Arrow    previous workspace | ||||
|     Ctrl-Alt-Right Arrow   next workspace | ||||
|     Ctrl-Alt-D             minimize/unminimize all, to show desktop | ||||
|  | ||||
|    Change keybindings for example: | ||||
|  | ||||
|      gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-1 '[<Alt>F1]' | ||||
|     | ||||
|    Also try the GNOME keyboard shortcuts control panel. | ||||
|  | ||||
|  - Window keybindings: | ||||
|  | ||||
|     Alt-space         window menu | ||||
|  | ||||
|     Mnemonics work in the menu. That is, Alt-space then underlined | ||||
|     letter in the menu item works. | ||||
|  | ||||
|     Choose Move from menu, and arrow keys to move the window. | ||||
|  | ||||
|     While moving, hold down Control to move slower, and  | ||||
|       Shift to snap to edges. | ||||
|  | ||||
|     Choose Resize from menu, and nothing happens yet, but  | ||||
|       eventually I might implement something. | ||||
|  | ||||
|     Keybindings for things like maximize window, vertical maximize, | ||||
|     etc. can be bound, but may not all exist by default. See | ||||
|     metacity.schemas. | ||||
|  | ||||
|  - Window mouse bindings: | ||||
|  | ||||
|     Clicking anywhere on frame with button 1 will raise/focus window | ||||
|      | ||||
|     If you click a window control, such as the close button, then the  | ||||
|      control will activate on button release if you are still over it | ||||
|      on release (as with most GUI toolkits) | ||||
|  | ||||
|     If you click and drag borders with button 1 it resizes the window | ||||
|      | ||||
|     If you click and drag the titlebar with button 1 it moves the  | ||||
|      window. | ||||
|  | ||||
|     If you click anywhere on the frame with button 2 it lowers the  | ||||
|      window. | ||||
|  | ||||
|     If you click anywhere on the frame with button 3 it shows the  | ||||
|      window menu. | ||||
|  | ||||
|     If you hold down Super (windows key) and click inside a window, it | ||||
|      will move the window (buttons 1 and 2) or show menu (button 3). | ||||
|      Or you can configure a different modifier for this. | ||||
|  | ||||
|     If you pick up a window with button 1 and then switch workspaces | ||||
|      the window will come with you to the new workspace, this is  | ||||
|      a feature copied from Enlightenment. | ||||
|  | ||||
|     If you hold down Shift while moving a window, the window snaps | ||||
|      to edges of other windows and the screen. | ||||
|  | ||||
|  - Session management: | ||||
|  | ||||
|     Mutter connects to the session manager and will set itself up to | ||||
|      be respawned. It theoretically restores sizes/positions/workspace | ||||
|      for session-aware applications. | ||||
|  | ||||
|  - Mutter implements much of the EWMH window manager specification | ||||
|    from freedesktop.org, as well as the older ICCCM.  Please refer to | ||||
|    the COMPLIANCE file for information on mutter compliance with | ||||
|    these standards. | ||||
|  | ||||
|  - Uses Pango to render text, so has cool i18n capabilities.  | ||||
|    Supports UTF-8 window titles and such. | ||||
|  | ||||
|  - There are simple animations for actions such as minimization,  | ||||
|    to help users see what is happening. Should probably  | ||||
|    have a few more of these and make them nicer. | ||||
|  | ||||
|  - if you have the proper X setup, set the GDK_USE_XFT=1  | ||||
|    environment variable to get antialiased window titles. | ||||
|  | ||||
|  - considers the panel when placing windows and maximizing | ||||
|    them. | ||||
|  | ||||
|  - handles the window manager selection from the ICCCM. Will exit if | ||||
|    another WM claims it, and can claim it from another WM if you pass | ||||
|    the --replace argument. So if you're running another | ||||
|    ICCCM-compliant WM, you can run "mutter --replace" to replace it | ||||
|    with Metacity. | ||||
|  | ||||
|  - does basic colormap handling | ||||
|  | ||||
|  - and much more! well, maybe not a lot more. | ||||
|  | ||||
| HOW TO ADD EXTERNAL FEATURES | ||||
| === | ||||
|  | ||||
| You can write a mutter "plugin" such as a pager, window list, icon | ||||
| box, task menu, or even things like "window matching" using the | ||||
| Extended Window Manager Hints. See http://www.freedesktop.org for the | ||||
| EWMH specification. An easy-to-use library called "libwnck" is | ||||
| available that uses the EWMH and is specifically designed for writing | ||||
| WM accessories. | ||||
|  | ||||
| You might be interested in existing accessories such as "Devil's Pie" | ||||
| by Ross Burton, which add features to Mutter (or other | ||||
| EWMH-compliant WMs). | ||||
|  | ||||
| MUTTER BUGS, NON-FEATURES, AND CAVEATS | ||||
| === | ||||
|  | ||||
| See bugzilla: http://bugzilla.gnome.org/query.cgi | ||||
|  | ||||
| FAQ | ||||
| === | ||||
|  | ||||
| Q: Will you add my feature? | ||||
|  | ||||
| A: If it makes sense to turn on unconditionally, or is genuinely a | ||||
|    harmless preference that I would not be embarrassed to put in a | ||||
|    simple, uncluttered, user-friendly configuration dialog. | ||||
|  | ||||
|    If the only rationale for your feature is that other window | ||||
|    managers have it, or that you are personally used to it, or | ||||
|    something like that, then I will not be impressed. Metacity is | ||||
|    firmly in the "choose good defaults" camp rather than the "offer 6 | ||||
|    equally broken ways to do it, and let the user pick one" camp. | ||||
|  | ||||
|    This is part of a "no crackrock" policy, despite some exceptions | ||||
|    I'm mildly embarrassed about. For example, multiple workspaces | ||||
|    probably constitute crackrock, they confuse most users and really | ||||
|    are not that useful if you have a decent tasklist and so on. But I | ||||
|    am too used to them to turn them off.  Or alternatively | ||||
|    iconification/tasklist is crack, and workspaces/pager are good. But | ||||
|    having both is certainly a bit wrong.  Sloppy focus is probably | ||||
|    crackrock too. | ||||
|  | ||||
|    But don't think unlimited crack is OK just because I slipped up a | ||||
|    little. No slippery slope here. | ||||
|  | ||||
|    Don't let this discourage patches and fixes - I love those. ;-) | ||||
|    Just be prepared to hear the above objections if your patch adds | ||||
|    some crack-ridden configuration option. | ||||
|  | ||||
|    http://pobox.com/~hp/free-software-ui.html | ||||
|    http://pobox.com/~hp/features.html    | ||||
|  | ||||
| Q: Will Mutter be part of GNOME? | ||||
|  | ||||
| A: It is not officially part of GNOME as of GNOME 2.27. We are | ||||
|    hoping to have mutter officially included as of GNOME 2.28.  | ||||
|  | ||||
| Q: Why does Mutter remember the workspace/position of some apps  | ||||
|    but not others across logout/login? | ||||
|  | ||||
| A: Mutter only stores sizes/positions for apps that are session | ||||
|    managed. As far as I can determine, there is no way to attempt to | ||||
|    remember workspace/position for non-session-aware apps without | ||||
|    causing a lot of weird effects. | ||||
|  | ||||
|    The reason is that you don't know which non-SM-aware apps were | ||||
|    launched by the session. When you initially log in, Metacity sees a | ||||
|    bunch of new windows appear. But it can't distinguish between | ||||
|    windows that were stored in your session, or windows you just | ||||
|    launched after logging in. If Metacity tried to guess that a window | ||||
|    was from the session, it could e.g. end up maximizing a dialog, or | ||||
|    put a window you just launched on another desktop or in a weird | ||||
|    place. And in fact I see a lot of bugs like this in window managers | ||||
|    that try to handle non-session-aware apps. | ||||
|  | ||||
|    However, for session-aware apps, Mutter can tell that the | ||||
|    application instance is from the session and thus restore it | ||||
|    reliably, assuming the app properly restores the windows it had  | ||||
|    open on session save. | ||||
|     | ||||
|    So the correct way to fix the situation is to make apps | ||||
|    session-aware. libSM has come with X for years, it's very | ||||
|    standardized, it's shared by GNOME and KDE - even twm is | ||||
|    session-aware. So anyone who won't take a patch to add SM is more | ||||
|    archaic than twm - and you should flame them. ;-) | ||||
|  | ||||
|    Docs on session management: | ||||
|     http://www.fifi.org/doc/xspecs/xsmp.txt.gz | ||||
|     http://www.fifi.org/doc/xspecs/SMlib.txt.gz | ||||
|  | ||||
|    See also the ICCCM section on SM. For GNOME apps, use the | ||||
|    GnomeClient object. For a simple example of using libSM directly, | ||||
|    twm/session.c in the twm source code is pretty easy to understand. | ||||
|  | ||||
| Q: How about adding viewports in addition to workspaces? | ||||
|  | ||||
| A: I could conceivably be convinced to use viewports _instead_ of | ||||
|    workspaces, though currently I'm not thinking that. But I don't | ||||
|    think it makes any sense to have both; it's just confusing. They | ||||
|    are functionally equivalent. | ||||
|  | ||||
|    You may think this means that you won't have certain keybindings,  | ||||
|    or something like that. This is a misconception. The only  | ||||
|    _fundamental_ difference between viewports and workspaces is that  | ||||
|    with viewports, windows can "overlap" and appear partially on  | ||||
|    one and partially on another. All other differences that | ||||
|    traditionally exist in other window managers are accidental -  | ||||
|    the features commonly associated with viewports can be implemented | ||||
|    for workspaces, and vice versa. | ||||
|  | ||||
|    So I don't want to have two kinds of | ||||
|    workspace/desktop/viewport/whatever, but I'm willing to add | ||||
|    features traditionally associated with either kind if those | ||||
|    features make sense. | ||||
|  | ||||
| Q: Why is the panel always on top? | ||||
|  | ||||
| A: Because it's a better user interface, and until we made this not | ||||
|    configurable a bunch of apps were not getting fixed (the app | ||||
|    authors were just saying "put your panel on the bottom" instead of | ||||
|    properly supporting fullscreen mode, and such). | ||||
|  | ||||
|    rationales.txt has the bugzilla URL for some flamefesting on this, | ||||
|    if you want to go back and relive the glory. | ||||
|    Read these and the bugzilla stuff before asking/commenting: | ||||
|      http://pobox.com/~hp/free-software-ui.html | ||||
|      http://pobox.com/~hp/features.html    | ||||
|  | ||||
| Q: Why is there no edge flipping? | ||||
|  | ||||
| A: This one is also in rationales.txt. Because "ouija board" UI, where | ||||
|    you just move the mouse around and the computer guesses what you | ||||
|    mean, has a lot of issues. This includes mouse focus, shade-hover | ||||
|    mode, edge flipping, autoraise, etc. Metacity has mouse focus and | ||||
|    autoraise as a compromise, but these features are all confusing for | ||||
|    many users, and cause problems with accessibility, fitt's law, and | ||||
|    so on. | ||||
|  | ||||
|    Read these and the bugzilla stuff before asking/commenting: | ||||
|      http://pobox.com/~hp/free-software-ui.html | ||||
|      http://pobox.com/~hp/features.html    | ||||
|  | ||||
| Q: Why does wireframe move/resize suck? | ||||
|  | ||||
| A: You can turn it on with the reduced_resources setting. | ||||
|  | ||||
|    But: it has low usability, and is a pain | ||||
|    to implement, and there's no reason opaque move/resize should be a | ||||
|    problem on any setup that can run a modern desktop worth a darn to | ||||
|    begin with. | ||||
|  | ||||
|    Read these and the bugzilla stuff before asking/commenting: | ||||
|      http://pobox.com/~hp/free-software-ui.html | ||||
|      http://pobox.com/~hp/features.html    | ||||
|  | ||||
|    The reason we had to add wireframe anyway was broken  | ||||
|    proprietary apps that can't handle lots of resize events. | ||||
|  | ||||
| Q: Why no XYZ? | ||||
|  | ||||
| A: You are probably getting the idea by now - check rationales.txt, | ||||
|    query/search bugzilla, and read http://pobox.com/~hp/features.html | ||||
|    and http://pobox.com/~hp/free-software-ui.html | ||||
|  | ||||
|    Then sit down and answer the question for yourself.  Is the feature | ||||
|    good? What's the rationale for it? Answer "why" not just "why not." | ||||
|    Justify in terms of users as a whole, not just users like | ||||
|    yourself. How else can you solve the same problem? etc. If that | ||||
|    leads you to a strong opinion, then please, post the rationale for | ||||
|    discussion to an appropriate bugzilla bug, or to | ||||
|    usability@gnome.org. | ||||
|  | ||||
|    Please don't just "me too!" on bugzilla bugs, please don't think | ||||
|    flames will get you anywhere, and please don't repeat rationale | ||||
|    that's already been offered. | ||||
|  | ||||
| Q: Your dumb web pages you made me read talk about solving problems in | ||||
|    fundamental ways instead of adding preferences or workarounds. | ||||
|    What are some examples where metacity has done this? | ||||
|  | ||||
| A: There are quite a few, though many opportunities remain.  Sometimes | ||||
|    the real fix involves application changes. The metacity approach is | ||||
|    that it's OK to require apps to change, though there are also | ||||
|    plenty of workarounds in metacity for battles considered too hard | ||||
|    to fight. | ||||
|  | ||||
|    Here are some examples: | ||||
|  | ||||
|    - fullscreen mode was introduced to allow position constraints, | ||||
|      panel-on-top, and other such things to apply to normal windows | ||||
|      while still allowing video players etc. to "just work" | ||||
|  | ||||
|    - "whether to include minimized windows in Alt+Tab" was solved  | ||||
|      by putting minimized windows at the *end* of the tab order.  | ||||
|  | ||||
|    - Whether to pop up a feedback display during Alt+Tab was solved by | ||||
|      having both Alt+Tab and Alt+Esc | ||||
|  | ||||
|    - Whether to have a "kill" feature was solved by automatically | ||||
|      detecting and offering to kill stuck apps. Better, metacity | ||||
|      actually does "kill -9" on the process, it doesn't just | ||||
|      disconnect the process from the X server. You'll appreciate this | ||||
|      if you ever did a "kill" on Netscape 4, and watched it keep | ||||
|      eating 100% CPU even though the X server had booted it. | ||||
|  | ||||
|    - The workspaces vs. viewports mess was avoided by adding | ||||
|      directional navigation and such to workspaces, see discussion | ||||
|      earlier in this file. | ||||
|  | ||||
|    - Instead of configurable placement algorithms, there's just one  | ||||
|      that works fairly well most of the time. | ||||
|  | ||||
|    - To avoid excess CPU use during opaque move/resize, we rate limit | ||||
|      the updates to the application window's size. | ||||
|  | ||||
|    - Instead of configurable "show size of window while resizing," | ||||
|      it's only shown for windows where it matters, such as terminals. | ||||
|      (Only use-case given for all windows is for web designers | ||||
|      choosing their web browser size, but there are web sites and | ||||
|      desktop backgrounds that do this for you.) | ||||
|  | ||||
|    - Using startup notification, applications open on the workspace | ||||
|      where you launched them, not the active workspace when their | ||||
|      window is opened. | ||||
|  | ||||
|    - and much more. | ||||
|  | ||||
| Q: I think mutter sucks. | ||||
|  | ||||
| A: Feel free to use any WM you like. The reason metacity follows the | ||||
|    ICCCM and EWMH specifications is that it makes metacity a modular, | ||||
|    interchangeable part in the desktop. libwnck-based apps such as the | ||||
|    GNOME window list will work just fine with any EWMH-compliant WM. | ||||
|  | ||||
| Q: Did you spend a lot of time on this? | ||||
|  | ||||
| A: Originally the answer was no. Sadly the answer is now yes. | ||||
|  | ||||
| Q: How can you claim that you are anti-crack, while still  | ||||
|    writing a window manager? | ||||
|  | ||||
| A: I have no comment on that. | ||||
| @@ -1,11 +1,11 @@ | ||||
| #!/bin/bash | ||||
| #!/bin/sh | ||||
| # Run this to generate all the initial makefiles, etc. | ||||
|  | ||||
| srcdir=`dirname $0` | ||||
| test -z "$srcdir" && srcdir=. | ||||
|  | ||||
| PKG_NAME="mutter" | ||||
| REQUIRED_AUTOMAKE_VERSION=1.13 | ||||
| REQUIRED_AUTOMAKE_VERSION=1.10 | ||||
|  | ||||
| (test -f $srcdir/configure.ac \ | ||||
|   && test -d $srcdir/src) || { | ||||
|   | ||||
							
								
								
									
										15
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								configure.ac
									
									
									
									
									
								
							| @@ -3,7 +3,7 @@ AC_CONFIG_MACRO_DIR([m4]) | ||||
|  | ||||
| m4_define([mutter_major_version], [3]) | ||||
| m4_define([mutter_minor_version], [11]) | ||||
| m4_define([mutter_micro_version], [1]) | ||||
| m4_define([mutter_micro_version], [92]) | ||||
|  | ||||
| m4_define([mutter_version], | ||||
|           [mutter_major_version.mutter_minor_version.mutter_micro_version]) | ||||
| @@ -78,8 +78,8 @@ MUTTER_PC_MODULES=" | ||||
|    cairo >= 1.10.0 | ||||
|    gsettings-desktop-schemas >= 3.7.3 | ||||
|    xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0 | ||||
|    $CLUTTER_PACKAGE >= 1.15.94 | ||||
|    cogl-1.0 >= 1.13.3 | ||||
|    $CLUTTER_PACKAGE >= 1.17.5 | ||||
|    cogl-1.0 >= 1.17.1 | ||||
|    upower-glib >= 0.99.0 | ||||
|    gnome-desktop-3.0 | ||||
| " | ||||
| @@ -142,11 +142,6 @@ AM_GLIB_GNU_GETTEXT | ||||
| PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0) | ||||
| PKG_CHECK_MODULES(MUTTER_LAUNCH, libdrm libsystemd-login) | ||||
|  | ||||
| saved_LIBS="$LIBS" | ||||
| LIBS="$LIBS $MUTTER_LAUNCH" | ||||
| AC_CHECK_FUNCS([sd_session_get_vt]) | ||||
| LIBS="$saved_LIBS" | ||||
|  | ||||
| # Unconditionally use this dir to avoid a circular dep with gnomecc | ||||
| GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings" | ||||
| AC_SUBST(GNOME_KEYBINDINGS_KEYSDIR) | ||||
| @@ -212,9 +207,6 @@ fi | ||||
|  | ||||
| MUTTER_PC_MODULES="$MUTTER_PC_MODULES xcursor" | ||||
|  | ||||
| # We always build with wayland enabled | ||||
| AC_DEFINE(HAVE_WAYLAND, , [Building with Wayland support]) | ||||
|  | ||||
| AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no]) | ||||
| AS_IF([test "x$WAYLAND_SCANNER" = "xno"], | ||||
|   AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols])) | ||||
| @@ -461,7 +453,6 @@ doc/reference/meta-docs.sgml | ||||
| src/Makefile | ||||
| src/libmutter-wayland.pc | ||||
| src/compositor/plugins/Makefile | ||||
| protocol/Makefile | ||||
| po/Makefile.in | ||||
| ]) | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| SUBDIRS = man reference | ||||
|  | ||||
| EXTRA_DIST=theme-format.txt dialogs.txt code-overview.txt \ | ||||
| 	how-to-get-focus-right.txt | ||||
| 	how-to-get-focus-right.txt rationales.txt | ||||
|   | ||||
| @@ -49,8 +49,8 @@ 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 | ||||
| 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 | ||||
|   | ||||
| @@ -96,8 +96,6 @@ meta_compositor_hide_window | ||||
| meta_compositor_switch_workspace | ||||
| meta_compositor_maximize_window | ||||
| meta_compositor_unmaximize_window | ||||
| meta_compositor_window_mapped | ||||
| meta_compositor_window_unmapped | ||||
| meta_compositor_sync_window_geometry | ||||
| meta_compositor_set_updates_frozen | ||||
| meta_compositor_queue_frame_drawn | ||||
| @@ -388,6 +386,23 @@ 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 | ||||
| @@ -541,7 +556,10 @@ meta_window_is_override_redirect | ||||
| meta_window_is_skip_taskbar | ||||
| meta_window_get_rect | ||||
| meta_window_get_input_rect | ||||
| meta_window_get_frame_rect | ||||
| meta_window_get_outer_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 | ||||
|   | ||||
| @@ -16,11 +16,11 @@ src/core/monitor.c | ||||
| src/core/mutter.c | ||||
| src/core/prefs.c | ||||
| src/core/screen.c | ||||
| src/core/session.c | ||||
| src/x11/session.c | ||||
| src/core/util.c | ||||
| src/core/window.c | ||||
| src/core/window-props.c | ||||
| src/core/xprops.c | ||||
| src/x11/window-props.c | ||||
| src/x11/xprops.c | ||||
| src/mutter-wayland.desktop.in | ||||
| src/org.gnome.mutter.gschema.xml.in | ||||
| src/org.gnome.mutter.wayland.gschema.xml.in | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| EXTRA_DIST = xserver.xml | ||||
| @@ -29,6 +29,18 @@ | ||||
| 	<KeyListEntry name="move-to-workspace-down" | ||||
| 	              _description="Move window one workspace down" /> | ||||
|  | ||||
| 	<KeyListEntry name="move-to-monitor-left" | ||||
| 	              _description="Move window one monitor to the left" /> | ||||
|  | ||||
| 	<KeyListEntry name="move-to-monitor-right" | ||||
| 	              _description="Move window one monitor to the right" /> | ||||
|  | ||||
| 	<KeyListEntry name="move-to-monitor-up" | ||||
| 	              _description="Move window one monitor up" /> | ||||
|  | ||||
| 	<KeyListEntry name="move-to-monitor-down" | ||||
| 	              _description="Move window one monitor down" /> | ||||
|  | ||||
| 	<KeyListEntry name="switch-applications" | ||||
| 	              _description="Switch applications"/> | ||||
|  | ||||
|   | ||||
| @@ -6,6 +6,7 @@ lib_LTLIBRARIES = libmutter-wayland.la | ||||
| SUBDIRS=compositor/plugins | ||||
|  | ||||
| INCLUDES=								\ | ||||
| 	-DCLUTTER_ENABLE_COMPOSITOR_API					\ | ||||
| 	-DCLUTTER_ENABLE_EXPERIMENTAL_API				\ | ||||
| 	-DCOGL_ENABLE_EXPERIMENTAL_API					\ | ||||
| 	-DCOGL_ENABLE_EXPERIMENTAL_2_0_API                              \ | ||||
| @@ -28,11 +29,7 @@ INCLUDES=								\ | ||||
| 	-DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION)	\ | ||||
| 	-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\"				\ | ||||
| 	-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\"			\ | ||||
| 	-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" | ||||
|  | ||||
| INCLUDES += \ | ||||
| 	-I$(srcdir)/wayland						\ | ||||
| 	-I$(builddir)/wayland						\ | ||||
| 	-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"			\ | ||||
| 	-DXWAYLAND_PATH='"@XWAYLAND_PATH@"' | ||||
|  | ||||
| mutter_built_sources = \ | ||||
| @@ -40,16 +37,20 @@ mutter_built_sources = \ | ||||
| 	$(dbus_xrandr_built_sources)		\ | ||||
| 	mutter-enum-types.h 			\ | ||||
| 	mutter-enum-types.c			\ | ||||
| 	wayland/gtk-shell-protocol.c		\ | ||||
| 	wayland/gtk-shell-server-protocol.h	\ | ||||
| 	wayland/gtk-shell-client-protocol.h	\ | ||||
| 	wayland/xserver-protocol.c		\ | ||||
| 	wayland/xserver-server-protocol.h	\ | ||||
| 	wayland/xserver-client-protocol.h | ||||
| 	gtk-shell-protocol.c			\ | ||||
| 	gtk-shell-server-protocol.h		\ | ||||
| 	xdg-shell-protocol.c			\ | ||||
| 	xdg-shell-server-protocol.h		\ | ||||
| 	xserver-protocol.c			\ | ||||
| 	xserver-server-protocol.h | ||||
|  | ||||
| wayland_protocols = \ | ||||
| 	wayland/protocol/gtk-shell.xml		\ | ||||
| 	wayland/protocol/xdg-shell.xml		\ | ||||
| 	wayland/protocol/xserver.xml | ||||
|  | ||||
| libmutter_wayland_la_SOURCES =			\ | ||||
| 	core/async-getprop.c			\ | ||||
| 	core/async-getprop.h			\ | ||||
| 	core/above-tab-keycode.c		\ | ||||
| 	core/barrier.c				\ | ||||
| 	meta/barrier.h				\ | ||||
| 	core/bell.c				\ | ||||
| @@ -67,7 +68,8 @@ libmutter_wayland_la_SOURCES =			\ | ||||
| 	compositor/meta-background-actor.c	\ | ||||
| 	compositor/meta-background-actor-private.h	\ | ||||
| 	compositor/meta-background-group.c	\ | ||||
| 	compositor/meta-background-group-private.h	\ | ||||
| 	compositor/meta-cullable.c		\ | ||||
| 	compositor/meta-cullable.h		\ | ||||
| 	compositor/meta-module.c		\ | ||||
| 	compositor/meta-module.h		\ | ||||
| 	compositor/meta-plugin.c		\ | ||||
| @@ -77,6 +79,12 @@ libmutter_wayland_la_SOURCES =			\ | ||||
| 	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-surface-actor-wayland.c	\ | ||||
| 	compositor/meta-surface-actor-wayland.h	\ | ||||
| 	compositor/meta-texture-rectangle.c	\ | ||||
| 	compositor/meta-texture-rectangle.h	\ | ||||
| 	compositor/meta-texture-tower.c		\ | ||||
| @@ -97,7 +105,6 @@ libmutter_wayland_la_SOURCES =			\ | ||||
| 	meta/meta-shadow-factory.h		\ | ||||
| 	meta/meta-window-actor.h		\ | ||||
| 	meta/compositor-mutter.h 		\ | ||||
| 	core/above-tab-keycode.c		\ | ||||
| 	core/constraints.c			\ | ||||
| 	core/constraints.h			\ | ||||
| 	core/core.c				\ | ||||
| @@ -105,8 +112,6 @@ libmutter_wayland_la_SOURCES =			\ | ||||
| 	core/display.c				\ | ||||
| 	core/display-private.h			\ | ||||
| 	meta/display.h				\ | ||||
| 	ui/draw-workspace.c			\ | ||||
| 	ui/draw-workspace.h			\ | ||||
| 	core/edge-resistance.c			\ | ||||
| 	core/edge-resistance.h			\ | ||||
| 	core/edid-parse.c			\ | ||||
| @@ -117,13 +122,6 @@ libmutter_wayland_la_SOURCES =			\ | ||||
| 	core/frame.h				\ | ||||
| 	ui/gradient.c				\ | ||||
| 	meta/gradient.h				\ | ||||
| 	core/group-private.h			\ | ||||
| 	core/group-props.c			\ | ||||
| 	core/group-props.h			\ | ||||
| 	core/group.c				\ | ||||
| 	meta/group.h				\ | ||||
| 	core/iconcache.c			\ | ||||
| 	core/iconcache.h			\ | ||||
| 	core/keybindings.c			\ | ||||
| 	core/keybindings-private.h		\ | ||||
| 	core/main.c				\ | ||||
| @@ -146,8 +144,6 @@ libmutter_wayland_la_SOURCES =			\ | ||||
| 	core/screen-private.h			\ | ||||
| 	meta/screen.h				\ | ||||
| 	meta/types.h				\ | ||||
| 	core/session.c				\ | ||||
| 	core/session.h				\ | ||||
| 	core/stack.c				\ | ||||
| 	core/stack.h				\ | ||||
| 	core/stack-tracker.c			\ | ||||
| @@ -155,15 +151,11 @@ libmutter_wayland_la_SOURCES =			\ | ||||
| 	core/util.c				\ | ||||
| 	meta/util.h				\ | ||||
| 	core/util-private.h			\ | ||||
| 	core/window-props.c			\ | ||||
| 	core/window-props.h			\ | ||||
| 	core/window.c				\ | ||||
| 	core/window-private.h			\ | ||||
| 	meta/window.h				\ | ||||
| 	core/workspace.c			\ | ||||
| 	core/workspace-private.h		\ | ||||
| 	core/xprops.c				\ | ||||
| 	core/xprops.h				\ | ||||
| 	meta/common.h				\ | ||||
| 	core/core.h				\ | ||||
| 	ui/ui.h					\ | ||||
| @@ -175,19 +167,31 @@ libmutter_wayland_la_SOURCES =			\ | ||||
| 	ui/metaaccellabel.h			\ | ||||
| 	ui/resizepopup.c			\ | ||||
| 	ui/resizepopup.h			\ | ||||
| 	ui/tabpopup.c				\ | ||||
| 	ui/tabpopup.h				\ | ||||
| 	ui/tile-preview.c			\ | ||||
| 	ui/tile-preview.h			\ | ||||
| 	ui/theme-parser.c			\ | ||||
| 	ui/theme.c				\ | ||||
| 	meta/theme.h				\ | ||||
| 	ui/theme-private.h			\ | ||||
| 	ui/ui.c					\ | ||||
| 	$(mutter_built_sources) | ||||
|  | ||||
| libmutter_wayland_la_SOURCES +=			\ | ||||
| 	x11/iconcache.c				\ | ||||
| 	x11/iconcache.h				\ | ||||
| 	x11/async-getprop.c			\ | ||||
| 	x11/async-getprop.h			\ | ||||
| 	x11/group-private.h			\ | ||||
| 	x11/group-props.c			\ | ||||
| 	x11/group-props.h			\ | ||||
| 	x11/group.c				\ | ||||
| 	meta/group.h				\ | ||||
| 	x11/session.c				\ | ||||
| 	x11/session.h				\ | ||||
| 	x11/window-props.c			\ | ||||
| 	x11/window-props.h			\ | ||||
| 	x11/window-x11.c			\ | ||||
| 	x11/window-x11.h			\ | ||||
| 	x11/window-x11-private.h		\ | ||||
| 	x11/xprops.c				\ | ||||
| 	x11/xprops.h				\ | ||||
| 	wayland/meta-wayland.c			\ | ||||
| 	wayland/meta-wayland.h			\ | ||||
| 	wayland/meta-wayland-private.h		\ | ||||
| 	wayland/meta-xwayland-private.h		\ | ||||
| 	wayland/meta-xwayland.c			\ | ||||
| @@ -208,6 +212,9 @@ libmutter_wayland_la_SOURCES +=			\ | ||||
| 	wayland/meta-weston-launch.c		\ | ||||
| 	wayland/meta-weston-launch.h | ||||
|  | ||||
| nodist_libmutter_wayland_la_SOURCES =		\ | ||||
| 	$(mutter_built_sources) | ||||
|  | ||||
| libmutter_wayland_la_LDFLAGS = -no-undefined | ||||
| libmutter_wayland_la_LIBADD  = $(MUTTER_LIBS) | ||||
|  | ||||
| @@ -297,14 +304,14 @@ Meta-$(api_version).gir: libmutter-wayland.la | ||||
| @META_GIR@_FILES =				\ | ||||
| 	mutter-enum-types.h			\ | ||||
| 	$(libmutterinclude_base_headers)	\ | ||||
| 	$(filter %.c,$(libmutter_wayland_la_SOURCES)) | ||||
| 	$(filter %.c,$(libmutter_wayland_la_SOURCES) $(nodist_libmutter_wayland_la_SOURCES)) | ||||
| @META_GIR@_SCANNERFLAGS = --warn-all --warn-error | ||||
|  | ||||
| endif | ||||
|  | ||||
| testboxes_SOURCES = core/testboxes.c | ||||
| testgradient_SOURCES = ui/testgradient.c | ||||
| testasyncgetprop_SOURCES = core/testasyncgetprop.c | ||||
| testasyncgetprop_SOURCES = x11/testasyncgetprop.c | ||||
|  | ||||
| noinst_PROGRAMS=testboxes testgradient testasyncgetprop | ||||
|  | ||||
| @@ -355,6 +362,7 @@ EXTRA_DIST=$(desktopfiles_files) 	\ | ||||
| 	$(desktopfiles_in_files)	\ | ||||
| 	$(wmproperties_in_files)	\ | ||||
| 	$(xml_in_files)			\ | ||||
| 	$(wayland_protocols)		\ | ||||
| 	org.gnome.mutter.gschema.xml.in \ | ||||
| 	org.gnome.mutter.wayland.gschema.xml.in \ | ||||
| 	mutter-schemas.convert \ | ||||
| @@ -404,12 +412,7 @@ $(dbus_idle_built_sources) : Makefile.am idle-monitor.xml | ||||
| 		--c-generate-object-manager						\ | ||||
| 		$(srcdir)/idle-monitor.xml | ||||
|  | ||||
| wayland/%-protocol.c : $(top_builddir)/protocol/%.xml | ||||
| 	mkdir -p wayland | ||||
| %-protocol.c : $(srcdir)/wayland/protocol/%.xml | ||||
| 	$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@ | ||||
| wayland/%-server-protocol.h : $(top_builddir)/protocol/%.xml | ||||
| 	mkdir -p wayland | ||||
| %-server-protocol.h : $(srcdir)/wayland/protocol/%.xml | ||||
| 	$(AM_V_GEN)$(WAYLAND_SCANNER) server-header < $< > $@ | ||||
| wayland/%-client-protocol.h : $(top_builddir)/protocol/%.xml | ||||
| 	mkdir -p wayland | ||||
| 	$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@ | ||||
|   | ||||
| @@ -16,9 +16,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include "clutter-utils.h" | ||||
| @@ -95,8 +93,10 @@ meta_actor_vertices_are_untransformed (ClutterVertex *verts, | ||||
|       v3x != v1x || v3y != v2y) | ||||
|     return FALSE; | ||||
|  | ||||
|   *x_origin = x; | ||||
|   *y_origin = y; | ||||
|   if (x_origin) | ||||
|     *x_origin = x; | ||||
|   if (y_origin) | ||||
|     *y_origin = y; | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|   | ||||
| @@ -15,9 +15,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef __META_CLUTTER_UTILS_H__ | ||||
|   | ||||
| @@ -16,9 +16,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
|   | ||||
| @@ -15,9 +15,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef __META_COGL_UTILS_H__ | ||||
|   | ||||
| @@ -17,20 +17,12 @@ struct _MetaCompositor | ||||
| { | ||||
|   MetaDisplay    *display; | ||||
|  | ||||
|   Atom            atom_x_root_pixmap; | ||||
|   Atom            atom_net_wm_window_opacity; | ||||
|   guint           repaint_func_id; | ||||
|  | ||||
|   ClutterActor   *shadow_src; | ||||
|  | ||||
|   MetaPlugin     *modal_plugin; | ||||
|  | ||||
|   gint64          server_time_query_time; | ||||
|   gint64          server_time_offset; | ||||
|  | ||||
|   guint           server_time_is_monotonic_time : 1; | ||||
|   guint           show_redraw : 1; | ||||
|   guint           debug       : 1; | ||||
|   guint           no_mipmaps  : 1; | ||||
| }; | ||||
|  | ||||
| @@ -38,21 +30,17 @@ struct _MetaCompScreen | ||||
| { | ||||
|   MetaScreen            *screen; | ||||
|  | ||||
|   ClutterActor          *stage, *window_group, *top_window_group, *overlay_group; | ||||
|   ClutterActor          *stage, *window_group, *top_window_group; | ||||
|   ClutterActor          *background_actor; | ||||
|   GList                 *windows; | ||||
|   GHashTable            *windows_by_xid; | ||||
|   Window                 output; | ||||
|  | ||||
|   CoglOnscreen          *onscreen; | ||||
|   CoglFrameClosure      *frame_closure; | ||||
|  | ||||
|   /* Used for unredirecting fullscreen windows */ | ||||
|   guint                   disable_unredirect_count; | ||||
|   MetaWindowActor             *unredirected_window; | ||||
|  | ||||
|   /* Before we create the output window */ | ||||
|   XserverRegion     pending_input_region; | ||||
|   guint                  disable_unredirect_count; | ||||
|   MetaWindow            *unredirected_window; | ||||
|  | ||||
|   gint                   switch_workspace_in_progress; | ||||
|  | ||||
| @@ -75,6 +63,4 @@ void     meta_end_modal_for_plugin   (MetaScreen       *screen, | ||||
| gint64 meta_compositor_monotonic_time_to_server_time (MetaDisplay *display, | ||||
|                                                       gint64       monotonic_time); | ||||
|  | ||||
| void meta_check_end_modal (MetaScreen *screen); | ||||
|  | ||||
| #endif /* META_COMPOSITOR_PRIVATE_H */ | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -6,9 +6,6 @@ | ||||
| #include <meta/screen.h> | ||||
| #include <meta/meta-background-actor.h> | ||||
|  | ||||
| void meta_background_actor_set_clip_region  (MetaBackgroundActor *self, | ||||
|                                              cairo_region_t      *clip_region); | ||||
|  | ||||
| cairo_region_t *meta_background_actor_get_clip_region (MetaBackgroundActor *self); | ||||
|  | ||||
| #endif /* META_BACKGROUND_ACTOR_PRIVATE_H */ | ||||
|   | ||||
| @@ -14,9 +14,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Portions adapted from gnome-shell/src/shell-global.c | ||||
|  */ | ||||
| @@ -41,20 +39,35 @@ | ||||
| #include <meta/errors.h> | ||||
| #include <meta/meta-background.h> | ||||
| #include "meta-background-actor-private.h" | ||||
| #include "meta-cullable.h" | ||||
|  | ||||
| struct _MetaBackgroundActorPrivate | ||||
| { | ||||
|   cairo_region_t *clip_region; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (MetaBackgroundActor, meta_background_actor, CLUTTER_TYPE_ACTOR); | ||||
| static void cullable_iface_init (MetaCullableInterface *iface); | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_CODE (MetaBackgroundActor, meta_background_actor, CLUTTER_TYPE_ACTOR, | ||||
|                          G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)); | ||||
|  | ||||
| static void | ||||
| set_clip_region (MetaBackgroundActor *self, | ||||
|                  cairo_region_t      *clip_region) | ||||
| { | ||||
|   MetaBackgroundActorPrivate *priv = self->priv; | ||||
|  | ||||
|   g_clear_pointer (&priv->clip_region, (GDestroyNotify) cairo_region_destroy); | ||||
|   if (clip_region) | ||||
|     priv->clip_region = cairo_region_copy (clip_region); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_background_actor_dispose (GObject *object) | ||||
| { | ||||
|   MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object); | ||||
|  | ||||
|   meta_background_actor_set_clip_region (self, NULL); | ||||
|   set_clip_region (self, NULL); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_background_actor_parent_class)->dispose (object); | ||||
| } | ||||
| @@ -104,26 +117,6 @@ meta_background_actor_get_preferred_height (ClutterActor *actor, | ||||
|     *natural_height_p = height; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_background_actor_get_paint_volume (ClutterActor       *actor, | ||||
|                                         ClutterPaintVolume *volume) | ||||
| { | ||||
|   ClutterContent *content; | ||||
|   gfloat width, height; | ||||
|  | ||||
|   content = clutter_actor_get_content (actor); | ||||
|  | ||||
|   if (!content) | ||||
|     return FALSE; | ||||
|  | ||||
|   clutter_content_get_preferred_size (content, &width, &height); | ||||
|  | ||||
|   clutter_paint_volume_set_width (volume, width); | ||||
|   clutter_paint_volume_set_height (volume, height); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_background_actor_class_init (MetaBackgroundActorClass *klass) | ||||
| { | ||||
| @@ -136,7 +129,6 @@ meta_background_actor_class_init (MetaBackgroundActorClass *klass) | ||||
|  | ||||
|   actor_class->get_preferred_width = meta_background_actor_get_preferred_width; | ||||
|   actor_class->get_preferred_height = meta_background_actor_get_preferred_height; | ||||
|   actor_class->get_paint_volume = meta_background_actor_get_paint_volume; | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -166,31 +158,27 @@ meta_background_actor_new (void) | ||||
|   return CLUTTER_ACTOR (self); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_background_actor_set_clip_region: | ||||
|  * @self: a #MetaBackgroundActor | ||||
|  * @clip_region: (allow-none): the area of the actor (in allocate-relative | ||||
|  *   coordinates) that is visible. | ||||
|  * | ||||
|  * Sets the area of the background that is unobscured by overlapping windows. | ||||
|  * This is used to optimize and only paint the visible portions. | ||||
|  */ | ||||
| void | ||||
| meta_background_actor_set_clip_region (MetaBackgroundActor *self, | ||||
|                                        cairo_region_t      *clip_region) | ||||
| static void | ||||
| meta_background_actor_cull_out (MetaCullable   *cullable, | ||||
|                                 cairo_region_t *unobscured_region, | ||||
|                                 cairo_region_t *clip_region) | ||||
| { | ||||
|   MetaBackgroundActorPrivate *priv; | ||||
|   MetaBackgroundActor *self = META_BACKGROUND_ACTOR (cullable); | ||||
|   set_clip_region (self, clip_region); | ||||
| } | ||||
|  | ||||
|   g_return_if_fail (META_IS_BACKGROUND_ACTOR (self)); | ||||
| static void | ||||
| meta_background_actor_reset_culling (MetaCullable *cullable) | ||||
| { | ||||
|   MetaBackgroundActor *self = META_BACKGROUND_ACTOR (cullable); | ||||
|   set_clip_region (self, NULL); | ||||
| } | ||||
|  | ||||
|   priv = self->priv; | ||||
|  | ||||
|   g_clear_pointer (&priv->clip_region, | ||||
|                    (GDestroyNotify) | ||||
|                    cairo_region_destroy); | ||||
|  | ||||
|   if (clip_region) | ||||
|     priv->clip_region = cairo_region_copy (clip_region); | ||||
| static void | ||||
| cullable_iface_init (MetaCullableInterface *iface) | ||||
| { | ||||
|   iface->cull_out = meta_background_actor_cull_out; | ||||
|   iface->reset_culling = meta_background_actor_reset_culling; | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -1,11 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| #ifndef META_BACKGROUND_GROUP_PRIVATE_H | ||||
| #define META_BACKGROUND_GROUP_PRIVATE_H | ||||
|  | ||||
| #include <meta/screen.h> | ||||
| #include <meta/meta-background-group.h> | ||||
|  | ||||
| void meta_background_group_set_clip_region  (MetaBackgroundGroup *self, | ||||
|                                              cairo_region_t      *visible_region); | ||||
| #endif /* META_BACKGROUND_GROUP_PRIVATE_H */ | ||||
| @@ -16,87 +16,43 @@ | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #include "compositor-private.h" | ||||
| #include "clutter-utils.h" | ||||
| #include "meta-background-actor-private.h" | ||||
| #include "meta-background-group-private.h" | ||||
| #include <meta/meta-background-group.h> | ||||
| #include "meta-cullable.h" | ||||
|  | ||||
| G_DEFINE_TYPE (MetaBackgroundGroup, meta_background_group, CLUTTER_TYPE_ACTOR); | ||||
| static void cullable_iface_init (MetaCullableInterface *iface); | ||||
|  | ||||
| struct _MetaBackgroundGroupPrivate | ||||
| { | ||||
|   gpointer dummy; | ||||
| }; | ||||
|  | ||||
| static void | ||||
| meta_background_group_dispose (GObject *object) | ||||
| { | ||||
|   G_OBJECT_CLASS (meta_background_group_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_background_group_get_paint_volume (ClutterActor       *actor, | ||||
|                                         ClutterPaintVolume *volume) | ||||
| { | ||||
|   return clutter_paint_volume_set_from_allocation (volume, actor); | ||||
| } | ||||
| G_DEFINE_TYPE_WITH_CODE (MetaBackgroundGroup, meta_background_group, CLUTTER_TYPE_ACTOR, | ||||
|                          G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)); | ||||
|  | ||||
| static void | ||||
| meta_background_group_class_init (MetaBackgroundGroupClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
| } | ||||
|  | ||||
|   actor_class->get_paint_volume = meta_background_group_get_paint_volume; | ||||
|   object_class->dispose = meta_background_group_dispose; | ||||
| static void | ||||
| meta_background_group_cull_out (MetaCullable   *cullable, | ||||
|                                 cairo_region_t *unobscured_region, | ||||
|                                 cairo_region_t *clip_region) | ||||
| { | ||||
|   meta_cullable_cull_out_children (cullable, unobscured_region, clip_region); | ||||
| } | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (MetaBackgroundGroupPrivate)); | ||||
| static void | ||||
| meta_background_group_reset_culling (MetaCullable *cullable) | ||||
| { | ||||
|   meta_cullable_reset_culling_children (cullable); | ||||
| } | ||||
|  | ||||
| static void | ||||
| cullable_iface_init (MetaCullableInterface *iface) | ||||
| { | ||||
|   iface->cull_out = meta_background_group_cull_out; | ||||
|   iface->reset_culling = meta_background_group_reset_culling; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_background_group_init (MetaBackgroundGroup *self) | ||||
| { | ||||
|   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, | ||||
|                                             META_TYPE_BACKGROUND_GROUP, | ||||
|                                             MetaBackgroundGroupPrivate); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_background_group_set_clip_region: | ||||
|  * @self: a #MetaBackgroundGroup | ||||
|  * @region: (allow-none): the parts of the background to paint | ||||
|  * | ||||
|  * Sets the area of the backgrounds that is unobscured by overlapping windows. | ||||
|  * This is used to optimize and only paint the visible portions. | ||||
|  */ | ||||
| void | ||||
| meta_background_group_set_clip_region (MetaBackgroundGroup *self, | ||||
|                                        cairo_region_t      *region) | ||||
| { | ||||
|   GList *children, *l; | ||||
|  | ||||
|   children = clutter_actor_get_children (CLUTTER_ACTOR (self)); | ||||
|   for (l = children; l; l = l->next) | ||||
|     { | ||||
|       ClutterActor *actor = l->data; | ||||
|  | ||||
|       if (META_IS_BACKGROUND_ACTOR (actor)) | ||||
|         { | ||||
|           meta_background_actor_set_clip_region (META_BACKGROUND_ACTOR (actor), region); | ||||
|         } | ||||
|       else if (META_IS_BACKGROUND_GROUP (actor)) | ||||
|         { | ||||
|           int x, y; | ||||
|  | ||||
|           if (!meta_actor_is_untransformed (actor, &x, &y)) | ||||
|             continue; | ||||
|  | ||||
|           cairo_region_translate (region, -x, -y); | ||||
|           meta_background_group_set_clip_region (META_BACKGROUND_GROUP (actor), region); | ||||
|           cairo_region_translate (region, x, y); | ||||
|         } | ||||
|     } | ||||
|   g_list_free (children); | ||||
| } | ||||
|  | ||||
| ClutterActor * | ||||
|   | ||||
| @@ -14,9 +14,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|   | ||||
							
								
								
									
										201
									
								
								src/compositor/meta-cullable.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								src/compositor/meta-cullable.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,201 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * Copyright (C) 2013 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, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Owen Taylor <otaylor@redhat.com> | ||||
|  *     Ray Strode <rstrode@redhat.com> | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
| #include "meta-cullable.h" | ||||
| #include "clutter-utils.h" | ||||
|  | ||||
| G_DEFINE_INTERFACE (MetaCullable, meta_cullable, CLUTTER_TYPE_ACTOR); | ||||
|  | ||||
| /** | ||||
|  * SECTION:meta-cullable | ||||
|  * @title: MetaCullable | ||||
|  * @short_description: CPU culling operations for efficient drawing | ||||
|  * | ||||
|  * When we are painting a stack of 5-10 large actors, the standard | ||||
|  * bottom-to-top method of drawing every actor results in a tremendous | ||||
|  * amount of overdraw. If these actors are painting textures like | ||||
|  * windows, it can easily max out the available memory bandwidth on a | ||||
|  * low-end graphics chipset. It's even worse if window textures are | ||||
|  * being accessed over the AGP bus. | ||||
|  * | ||||
|  * #MetaCullable is our solution. The basic technique applied here is to | ||||
|  * do a pre-pass before painting where we walk each actor from top to bottom | ||||
|  * and ask each actor to "cull itself out". We pass in a region it can copy | ||||
|  * to clip its drawing to, and the actor can subtract its fully opaque pixels | ||||
|  * so that actors underneath know not to draw there as well. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * meta_cullable_cull_out_children: | ||||
|  * @cullable: The #MetaCullable | ||||
|  * @unobscured_region: The unobscured region, as passed into cull_out() | ||||
|  * @clip_region: The clip region, as passed into cull_out() | ||||
|  * | ||||
|  * This is a helper method for actors that want to recurse over their | ||||
|  * child actors, and cull them out. | ||||
|  * | ||||
|  * See #MetaCullable and meta_cullable_cull_out() for more details. | ||||
|  */ | ||||
| void | ||||
| meta_cullable_cull_out_children (MetaCullable   *cullable, | ||||
|                                  cairo_region_t *unobscured_region, | ||||
|                                  cairo_region_t *clip_region) | ||||
| { | ||||
|   ClutterActor *actor = CLUTTER_ACTOR (cullable); | ||||
|   ClutterActor *child; | ||||
|   ClutterActorIter iter; | ||||
|  | ||||
|   clutter_actor_iter_init (&iter, actor); | ||||
|   while (clutter_actor_iter_prev (&iter, &child)) | ||||
|     { | ||||
|       float x, y; | ||||
|       gboolean needs_culling; | ||||
|  | ||||
|       if (!META_IS_CULLABLE (child)) | ||||
|         continue; | ||||
|  | ||||
|       needs_culling = (unobscured_region != NULL && clip_region != NULL); | ||||
|  | ||||
|       if (needs_culling && !CLUTTER_ACTOR_IS_VISIBLE (child)) | ||||
|         needs_culling = FALSE; | ||||
|  | ||||
|       /* If an actor has effects applied, then that can change the area | ||||
|        * it paints and the opacity, so we no longer can figure out what | ||||
|        * portion of the actor is obscured and what portion of the screen | ||||
|        * it obscures, so we skip the actor. | ||||
|        * | ||||
|        * This has a secondary beneficial effect: if a ClutterOffscreenEffect | ||||
|        * is applied to an actor, then our clipped redraws interfere with the | ||||
|        * caching of the FBO - even if we only need to draw a small portion | ||||
|        * of the window right now, ClutterOffscreenEffect may use other portions | ||||
|        * of the FBO later. So, skipping actors with effects applied also | ||||
|        * prevents these bugs. | ||||
|        * | ||||
|        * Theoretically, we should check clutter_actor_get_offscreen_redirect() | ||||
|        * as well for the same reason, but omitted for simplicity in the | ||||
|        * hopes that no-one will do that. | ||||
|        */ | ||||
|       if (needs_culling && clutter_actor_has_effects (child)) | ||||
|         needs_culling = FALSE; | ||||
|  | ||||
|       if (needs_culling && !meta_actor_is_untransformed (child, NULL, NULL)) | ||||
|         needs_culling = FALSE; | ||||
|  | ||||
|       if (needs_culling) | ||||
|         { | ||||
|           clutter_actor_get_position (child, &x, &y); | ||||
|  | ||||
|           /* Temporarily move to the coordinate system of the actor */ | ||||
|           cairo_region_translate (unobscured_region, - x, - y); | ||||
|           cairo_region_translate (clip_region, - x, - y); | ||||
|  | ||||
|           meta_cullable_cull_out (META_CULLABLE (child), unobscured_region, clip_region); | ||||
|  | ||||
|           cairo_region_translate (unobscured_region, x, y); | ||||
|           cairo_region_translate (clip_region, x, y); | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           meta_cullable_cull_out (META_CULLABLE (child), NULL, NULL); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_cullable_reset_culling_children: | ||||
|  * @cullable: The #MetaCullable | ||||
|  * | ||||
|  * This is a helper method for actors that want to recurse over their | ||||
|  * child actors, and cull them out. | ||||
|  * | ||||
|  * See #MetaCullable and meta_cullable_reset_culling() for more details. | ||||
|  */ | ||||
| void | ||||
| meta_cullable_reset_culling_children (MetaCullable *cullable) | ||||
| { | ||||
|   ClutterActor *actor = CLUTTER_ACTOR (cullable); | ||||
|   ClutterActor *child; | ||||
|   ClutterActorIter iter; | ||||
|  | ||||
|   clutter_actor_iter_init (&iter, actor); | ||||
|   while (clutter_actor_iter_next (&iter, &child)) | ||||
|     { | ||||
|       if (!META_IS_CULLABLE (child)) | ||||
|         continue; | ||||
|  | ||||
|       meta_cullable_reset_culling (META_CULLABLE (child)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cullable_default_init (MetaCullableInterface *iface) | ||||
| { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_cullable_cull_out: | ||||
|  * @cullable: The #MetaCullable | ||||
|  * @unobscured_region: The unobscured region, in @cullable's space. | ||||
|  * @clip_region: The clip region, in @cullable's space. | ||||
|  * | ||||
|  * When #MetaWindowGroup is painted, we walk over its direct cullable | ||||
|  * children from top to bottom and ask themselves to "cull out". Cullables | ||||
|  * can use @unobscured_region and @clip_region to clip their drawing. Actors | ||||
|  * interested in eliminating overdraw should copy the @clip_region and only | ||||
|  * paint those parts, as everything else has been obscured by actors above it. | ||||
|  * | ||||
|  * Actors that may have fully opaque parts should also subtract out a region | ||||
|  * that is fully opaque from @unobscured_region and @clip_region. | ||||
|  * | ||||
|  * @unobscured_region and @clip_region are extremely similar. The difference | ||||
|  * is that @clip_region starts off with the stage's clip, if Clutter detects | ||||
|  * that we're doing a clipped redraw. @unobscured_region, however, starts off | ||||
|  * with the full stage size, so actors that may want to record what parts of | ||||
|  * their window are unobscured for e.g. scheduling repaints can do so. | ||||
|  * | ||||
|  * Actors that have children can also use the meta_cullable_cull_out_children() | ||||
|  * helper method to do a simple cull across all their children. | ||||
|  */ | ||||
| void | ||||
| meta_cullable_cull_out (MetaCullable   *cullable, | ||||
|                         cairo_region_t *unobscured_region, | ||||
|                         cairo_region_t *clip_region) | ||||
| { | ||||
|   META_CULLABLE_GET_IFACE (cullable)->cull_out (cullable, unobscured_region, clip_region); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_cullable_reset_culling: | ||||
|  * @cullable: The #MetaCullable | ||||
|  * | ||||
|  * Actors that copied data in their cull_out() implementation can now | ||||
|  * reset their data, as the paint is now over. Additional paints may be | ||||
|  * done by #ClutterClone or similar, and they should not be affected by | ||||
|  * the culling operation. | ||||
|  */ | ||||
| void | ||||
| meta_cullable_reset_culling (MetaCullable *cullable) | ||||
| { | ||||
|   META_CULLABLE_GET_IFACE (cullable)->reset_culling (cullable); | ||||
| } | ||||
							
								
								
									
										66
									
								
								src/compositor/meta-cullable.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/compositor/meta-cullable.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2013 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, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Owen Taylor <otaylor@redhat.com> | ||||
|  *     Ray Strode <rstrode@redhat.com> | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #ifndef __META_CULLABLE_H__ | ||||
| #define __META_CULLABLE_H__ | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define META_TYPE_CULLABLE             (meta_cullable_get_type ()) | ||||
| #define META_CULLABLE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CULLABLE, MetaCullable)) | ||||
| #define META_IS_CULLABLE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CULLABLE)) | ||||
| #define META_CULLABLE_GET_IFACE(obj)   (G_TYPE_INSTANCE_GET_INTERFACE ((obj),  META_TYPE_CULLABLE, MetaCullableInterface)) | ||||
|  | ||||
| typedef struct _MetaCullable MetaCullable; | ||||
| typedef struct _MetaCullableInterface MetaCullableInterface; | ||||
|  | ||||
| struct _MetaCullableInterface | ||||
| { | ||||
|   GTypeInterface g_iface; | ||||
|  | ||||
|   void (* cull_out)      (MetaCullable   *cullable, | ||||
|                           cairo_region_t *unobscured_region, | ||||
|                           cairo_region_t *clip_region); | ||||
|   void (* reset_culling) (MetaCullable  *cullable); | ||||
| }; | ||||
|  | ||||
| GType meta_cullable_get_type (void); | ||||
|  | ||||
| void meta_cullable_cull_out (MetaCullable   *cullable, | ||||
|                              cairo_region_t *unobscured_region, | ||||
|                              cairo_region_t *clip_region); | ||||
| void meta_cullable_reset_culling (MetaCullable *cullable); | ||||
|  | ||||
| /* Utility methods for implementations */ | ||||
| void meta_cullable_cull_out_children (MetaCullable   *cullable, | ||||
|                                       cairo_region_t *unobscured_region, | ||||
|                                       cairo_region_t *clip_region); | ||||
| void meta_cullable_reset_culling_children (MetaCullable *cullable); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __META_CULLABLE_H__ */ | ||||
|  | ||||
| @@ -16,9 +16,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include <meta/meta-plugin.h> | ||||
|   | ||||
| @@ -16,9 +16,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef META_MODULE_H_ | ||||
|   | ||||
| @@ -16,9 +16,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
| @@ -102,7 +100,9 @@ meta_plugin_manager_new (MetaScreen *screen) | ||||
|  | ||||
|   plugin_mgr = g_new0 (MetaPluginManager, 1); | ||||
|   plugin_mgr->screen = screen; | ||||
|   plugin_mgr->plugin = plugin = g_object_new (plugin_type, "screen", screen, NULL); | ||||
|   plugin_mgr->plugin = plugin = g_object_new (plugin_type, NULL); | ||||
|  | ||||
|   _meta_plugin_set_screen (plugin, screen); | ||||
|  | ||||
|   klass = META_PLUGIN_GET_CLASS (plugin); | ||||
|  | ||||
| @@ -167,8 +167,6 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr, | ||||
|           retval = TRUE; | ||||
|           meta_plugin_manager_kill_window_effects (plugin_mgr, | ||||
|                                                    actor); | ||||
|  | ||||
|           _meta_plugin_effect_started (plugin); | ||||
|           klass->minimize (plugin, actor); | ||||
|         } | ||||
|       break; | ||||
| @@ -178,8 +176,6 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr, | ||||
|           retval = TRUE; | ||||
|           meta_plugin_manager_kill_window_effects (plugin_mgr, | ||||
|                                                    actor); | ||||
|  | ||||
|           _meta_plugin_effect_started (plugin); | ||||
|           klass->map (plugin, actor); | ||||
|         } | ||||
|       break; | ||||
| @@ -187,7 +183,6 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr, | ||||
|       if (klass->destroy) | ||||
|         { | ||||
|           retval = TRUE; | ||||
|           _meta_plugin_effect_started (plugin); | ||||
|           klass->destroy (plugin, actor); | ||||
|         } | ||||
|       break; | ||||
| @@ -232,8 +227,6 @@ meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr, | ||||
|           retval = TRUE; | ||||
|           meta_plugin_manager_kill_window_effects (plugin_mgr, | ||||
|                                                    actor); | ||||
|  | ||||
|           _meta_plugin_effect_started (plugin); | ||||
|           klass->maximize (plugin, actor, | ||||
|                            target_x, target_y, | ||||
|                            target_width, target_height); | ||||
| @@ -245,8 +238,6 @@ meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr, | ||||
|           retval = TRUE; | ||||
|           meta_plugin_manager_kill_window_effects (plugin_mgr, | ||||
|                                                    actor); | ||||
|  | ||||
|           _meta_plugin_effect_started (plugin); | ||||
|           klass->unmaximize (plugin, actor, | ||||
|                              target_x, target_y, | ||||
|                              target_width, target_height); | ||||
| @@ -285,8 +276,6 @@ meta_plugin_manager_switch_workspace (MetaPluginManager   *plugin_mgr, | ||||
|     { | ||||
|       retval = TRUE; | ||||
|       meta_plugin_manager_kill_switch_workspace (plugin_mgr); | ||||
|  | ||||
|       _meta_plugin_effect_started (plugin); | ||||
|       klass->switch_workspace (plugin, from, to, direction); | ||||
|     } | ||||
|  | ||||
| @@ -326,3 +315,44 @@ meta_plugin_manager_confirm_display_change (MetaPluginManager *plugin_mgr) | ||||
|   else | ||||
|     return meta_plugin_complete_display_change (plugin, TRUE); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_plugin_manager_show_tile_preview (MetaPluginManager *plugin_mgr, | ||||
|                                        MetaWindow        *window, | ||||
|                                        MetaRectangle     *tile_rect, | ||||
|                                        int                tile_monitor_number) | ||||
| { | ||||
|   MetaPlugin *plugin = plugin_mgr->plugin; | ||||
|   MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); | ||||
|   MetaDisplay *display  = meta_screen_get_display (plugin_mgr->screen); | ||||
|  | ||||
|   if (display->display_opening) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (klass->show_tile_preview) | ||||
|     { | ||||
|       klass->show_tile_preview (plugin, window, tile_rect, tile_monitor_number); | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_plugin_manager_hide_tile_preview (MetaPluginManager *plugin_mgr) | ||||
| { | ||||
|   MetaPlugin *plugin = plugin_mgr->plugin; | ||||
|   MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); | ||||
|   MetaDisplay *display  = meta_screen_get_display (plugin_mgr->screen); | ||||
|  | ||||
|   if (display->display_opening) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (klass->hide_tile_preview) | ||||
|     { | ||||
|       klass->hide_tile_preview (plugin); | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|   | ||||
| @@ -16,9 +16,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef META_PLUGIN_MANAGER_H_ | ||||
| @@ -77,4 +75,9 @@ gboolean _meta_plugin_xevent_filter (MetaPlugin *plugin, | ||||
|  | ||||
| void     meta_plugin_manager_confirm_display_change (MetaPluginManager *mgr); | ||||
|  | ||||
| gboolean meta_plugin_manager_show_tile_preview (MetaPluginManager *mgr, | ||||
|                                                 MetaWindow        *window, | ||||
|                                                 MetaRectangle     *tile_rect, | ||||
|                                                 int                tile_monitor_number); | ||||
| gboolean meta_plugin_manager_hide_tile_preview (MetaPluginManager *mgr); | ||||
| #endif | ||||
|   | ||||
| @@ -16,9 +16,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
| @@ -32,6 +30,7 @@ | ||||
| #include "meta-plugin-manager.h" | ||||
| #include <meta/screen.h> | ||||
| #include <meta/display.h> | ||||
| #include <meta/util.h> | ||||
|  | ||||
| #include <string.h> | ||||
| #include <X11/Xlib.h> | ||||
| @@ -48,91 +47,15 @@ G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT); | ||||
| #define META_PLUGIN_GET_PRIVATE(obj) \ | ||||
| (G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_PLUGIN, MetaPluginPrivate)) | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|   PROP_SCREEN, | ||||
|   PROP_DEBUG_MODE, | ||||
| }; | ||||
|  | ||||
| struct _MetaPluginPrivate | ||||
| { | ||||
|   MetaScreen   *screen; | ||||
|  | ||||
|   gint          running; | ||||
|   gboolean      debug    : 1; | ||||
|   MetaScreen *screen; | ||||
| }; | ||||
|  | ||||
| static void | ||||
| meta_plugin_set_property (GObject      *object, | ||||
|                           guint         prop_id, | ||||
|                           const GValue *value, | ||||
|                           GParamSpec   *pspec) | ||||
| { | ||||
|   MetaPluginPrivate *priv = META_PLUGIN (object)->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_SCREEN: | ||||
|       priv->screen = g_value_get_object (value); | ||||
|       break; | ||||
|     case PROP_DEBUG_MODE: | ||||
|       priv->debug = g_value_get_boolean (value); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_plugin_get_property (GObject    *object, | ||||
|                           guint       prop_id, | ||||
|                           GValue     *value, | ||||
|                           GParamSpec *pspec) | ||||
| { | ||||
|   MetaPluginPrivate *priv = META_PLUGIN (object)->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_SCREEN: | ||||
|       g_value_set_object (value, priv->screen); | ||||
|       break; | ||||
|     case PROP_DEBUG_MODE: | ||||
|       g_value_set_boolean (value, priv->debug); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| meta_plugin_class_init (MetaPluginClass *klass) | ||||
| { | ||||
|   GObjectClass      *gobject_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   gobject_class->set_property    = meta_plugin_set_property; | ||||
|   gobject_class->get_property    = meta_plugin_get_property; | ||||
|  | ||||
|   g_object_class_install_property (gobject_class, | ||||
|                                    PROP_SCREEN, | ||||
|                                    g_param_spec_object ("screen", | ||||
|                                                         "MetaScreen", | ||||
|                                                         "MetaScreen", | ||||
|                                                         META_TYPE_SCREEN, | ||||
|                                                         G_PARAM_READWRITE)); | ||||
|  | ||||
|   g_object_class_install_property (gobject_class, | ||||
| 				   PROP_DEBUG_MODE, | ||||
| 				   g_param_spec_boolean ("debug-mode", | ||||
|                                                       "Debug Mode", | ||||
|                                                       "Debug Mode", | ||||
|                                                       FALSE, | ||||
|                                                       G_PARAM_READABLE)); | ||||
|  | ||||
|   g_type_class_add_private (gobject_class, sizeof (MetaPluginPrivate)); | ||||
|   g_type_class_add_private (klass, sizeof (MetaPluginPrivate)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -141,22 +64,6 @@ meta_plugin_init (MetaPlugin *self) | ||||
|   self->priv = META_PLUGIN_GET_PRIVATE (self); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_plugin_running  (MetaPlugin *plugin) | ||||
| { | ||||
|   MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv; | ||||
|  | ||||
|   return (priv->running > 0); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_plugin_debug_mode (MetaPlugin *plugin) | ||||
| { | ||||
|   MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv; | ||||
|  | ||||
|   return priv->debug; | ||||
| } | ||||
|  | ||||
| const MetaPluginInfo * | ||||
| meta_plugin_get_info (MetaPlugin *plugin) | ||||
| { | ||||
| @@ -168,21 +75,6 @@ meta_plugin_get_info (MetaPlugin *plugin) | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * _meta_plugin_effect_started: | ||||
|  * @plugin: the plugin | ||||
|  * | ||||
|  * Mark that an effect has started for the plugin. This is called | ||||
|  * internally by MetaPluginManager. | ||||
|  */ | ||||
| void | ||||
| _meta_plugin_effect_started (MetaPlugin *plugin) | ||||
| { | ||||
|   MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv; | ||||
|  | ||||
|   priv->running++; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| _meta_plugin_xevent_filter (MetaPlugin *plugin, | ||||
|                             XEvent     *xev) | ||||
| @@ -209,15 +101,8 @@ void | ||||
| meta_plugin_switch_workspace_completed (MetaPlugin *plugin) | ||||
| { | ||||
|   MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv; | ||||
|  | ||||
|   MetaScreen *screen = priv->screen; | ||||
|  | ||||
|   if (priv->running-- < 0) | ||||
|     { | ||||
|       g_warning ("Error in running effect accounting, adjusting."); | ||||
|       priv->running = 0; | ||||
|     } | ||||
|  | ||||
|   meta_switch_workspace_completed (screen); | ||||
| } | ||||
|  | ||||
| @@ -226,26 +111,6 @@ meta_plugin_window_effect_completed (MetaPlugin      *plugin, | ||||
|                                      MetaWindowActor *actor, | ||||
|                                      unsigned long    event) | ||||
| { | ||||
|   MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv; | ||||
|  | ||||
|   if (priv->running-- < 0) | ||||
|     { | ||||
|       g_warning ("Error in running effect accounting, adjusting."); | ||||
|       priv->running = 0; | ||||
|     } | ||||
|  | ||||
|   if (!actor) | ||||
|     { | ||||
|       const MetaPluginInfo *info; | ||||
|       const gchar            *name = NULL; | ||||
|  | ||||
|       if (plugin && (info = meta_plugin_get_info (plugin))) | ||||
|         name = info->name; | ||||
|  | ||||
|       g_warning ("Plugin [%s] passed NULL for actor!", | ||||
|                  name ? name : "unknown"); | ||||
|     } | ||||
|  | ||||
|   meta_window_actor_effect_completed (actor, event); | ||||
| } | ||||
|  | ||||
| @@ -340,9 +205,7 @@ meta_plugin_end_modal (MetaPlugin *plugin, | ||||
|  * meta_plugin_get_screen: | ||||
|  * @plugin: a #MetaPlugin | ||||
|  * | ||||
|  * Gets the #MetaScreen corresponding to a plugin. Each plugin instance | ||||
|  * is associated with exactly one screen; if Metacity is managing | ||||
|  * multiple screens, multiple plugin instances will be created. | ||||
|  * Gets the #MetaScreen corresponding to a plugin. | ||||
|  * | ||||
|  * Return value: (transfer none): the #MetaScreen for the plugin | ||||
|  */ | ||||
| @@ -354,6 +217,15 @@ meta_plugin_get_screen (MetaPlugin *plugin) | ||||
|   return priv->screen; | ||||
| } | ||||
|  | ||||
| void | ||||
| _meta_plugin_set_screen (MetaPlugin *plugin, | ||||
|                          MetaScreen *screen) | ||||
| { | ||||
|   MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv; | ||||
|  | ||||
|   priv->screen = screen; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_plugin_complete_display_change (MetaPlugin *plugin, | ||||
|                                      gboolean    ok) | ||||
|   | ||||
| @@ -17,9 +17,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef __META_SHADOW_FACTORY_PRIVATE_H__ | ||||
|   | ||||
| @@ -13,9 +13,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -28,17 +28,12 @@ | ||||
| #define __META_SHAPED_TEXTURE_PRIVATE_H__ | ||||
|  | ||||
| #include <meta/meta-shaped-texture.h> | ||||
| #include "meta-wayland-private.h" | ||||
|  | ||||
| ClutterActor *meta_shaped_texture_new_with_xwindow (Window xwindow); | ||||
| ClutterActor *meta_shaped_texture_new_with_wayland_surface  (MetaWaylandSurface *surface); | ||||
| void meta_shaped_texture_set_wayland_surface                (MetaShapedTexture  *stex, | ||||
|                                                              MetaWaylandSurface *surface); | ||||
| MetaWaylandSurface *meta_shaped_texture_get_wayland_surface (MetaShapedTexture *stex); | ||||
|  | ||||
| void meta_shaped_texture_set_pixmap (MetaShapedTexture *stex, | ||||
|                                      Pixmap             pixmap); | ||||
| void meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture  *stex, | ||||
|                                                 MetaWaylandBuffer  *buffer); | ||||
| ClutterActor *meta_shaped_texture_new (void); | ||||
| void meta_shaped_texture_set_texture (MetaShapedTexture *stex, | ||||
|                                       CoglTexture       *texture); | ||||
| gboolean meta_shaped_texture_get_unobscured_bounds (MetaShapedTexture     *stex, | ||||
|                                                     cairo_rectangle_int_t *unobscured_bounds); | ||||
| gboolean meta_shaped_texture_is_obscured (MetaShapedTexture *self); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -16,9 +16,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
| @@ -35,19 +33,16 @@ | ||||
| #include "meta-texture-tower.h" | ||||
|  | ||||
| #include "meta-shaped-texture-private.h" | ||||
| #include "meta-wayland-private.h" | ||||
| #include <cogl/cogl-wayland-server.h> | ||||
| #include "meta-window-actor-private.h" | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
| #include <cogl/cogl.h> | ||||
| #include <cogl/cogl-texture-pixmap-x11.h> | ||||
| #include <gdk/gdk.h> /* for gdk_rectangle_intersect() */ | ||||
| #include "meta-cullable.h" | ||||
|  | ||||
| static void meta_shaped_texture_dispose  (GObject    *object); | ||||
|  | ||||
| static void meta_shaped_texture_paint (ClutterActor       *actor); | ||||
| static void meta_shaped_texture_pick  (ClutterActor       *actor, | ||||
| 				       const ClutterColor *color); | ||||
|  | ||||
| static void meta_shaped_texture_get_preferred_width (ClutterActor *self, | ||||
|                                                      gfloat        for_height, | ||||
| @@ -61,15 +56,10 @@ static void meta_shaped_texture_get_preferred_height (ClutterActor *self, | ||||
|  | ||||
| static gboolean meta_shaped_texture_get_paint_volume (ClutterActor *self, ClutterPaintVolume *volume); | ||||
|  | ||||
| typedef enum _MetaShapedTextureType | ||||
| { | ||||
|   META_SHAPED_TEXTURE_TYPE_X11_PIXMAP, | ||||
|   META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE, | ||||
| } MetaShapedTextureType; | ||||
| static void cullable_iface_init (MetaCullableInterface *iface); | ||||
|  | ||||
|  | ||||
| G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture, | ||||
|                CLUTTER_TYPE_ACTOR); | ||||
| G_DEFINE_TYPE_WITH_CODE (MetaShapedTexture, meta_shaped_texture, CLUTTER_TYPE_ACTOR, | ||||
|                          G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)); | ||||
|  | ||||
| #define META_SHAPED_TEXTURE_GET_PRIVATE(obj) \ | ||||
|   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_SHAPED_TEXTURE, \ | ||||
| @@ -79,24 +69,16 @@ struct _MetaShapedTexturePrivate | ||||
| { | ||||
|   MetaTextureTower *paint_tower; | ||||
|  | ||||
|   MetaShapedTextureType type; | ||||
|   union { | ||||
|     struct { | ||||
|       Pixmap pixmap; | ||||
|     } x11; | ||||
|     struct { | ||||
|       MetaWaylandSurface *surface; | ||||
|     } wayland; | ||||
|   }; | ||||
|  | ||||
|   CoglTexture *texture; | ||||
|  | ||||
|   CoglTexture *mask_texture; | ||||
|  | ||||
|   cairo_region_t *clip_region; | ||||
|   cairo_region_t *input_shape_region; | ||||
|   /* The region containing only fully opaque pixels */ | ||||
|   cairo_region_t *opaque_region; | ||||
|  | ||||
|   /* MetaCullable regions, see that documentation for more details */ | ||||
|   cairo_region_t *clip_region; | ||||
|   cairo_region_t *unobscured_region; | ||||
|  | ||||
|   guint tex_width, tex_height; | ||||
|  | ||||
|   guint create_mipmaps : 1; | ||||
| @@ -113,7 +95,6 @@ meta_shaped_texture_class_init (MetaShapedTextureClass *klass) | ||||
|   actor_class->get_preferred_width = meta_shaped_texture_get_preferred_width; | ||||
|   actor_class->get_preferred_height = meta_shaped_texture_get_preferred_height; | ||||
|   actor_class->paint = meta_shaped_texture_paint; | ||||
|   actor_class->pick = meta_shaped_texture_pick; | ||||
|   actor_class->get_paint_volume = meta_shaped_texture_get_paint_volume; | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (MetaShapedTexturePrivate)); | ||||
| @@ -128,13 +109,37 @@ meta_shaped_texture_init (MetaShapedTexture *self) | ||||
|  | ||||
|   priv->paint_tower = meta_texture_tower_new (); | ||||
|  | ||||
|   priv->type = META_SHAPED_TEXTURE_TYPE_X11_PIXMAP; | ||||
|   priv->texture = NULL; | ||||
|  | ||||
|   priv->mask_texture = NULL; | ||||
|   priv->create_mipmaps = TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_unobscured_region (MetaShapedTexture *self, | ||||
|                        cairo_region_t    *unobscured_region) | ||||
| { | ||||
|   MetaShapedTexturePrivate *priv = self->priv; | ||||
|  | ||||
|   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 }; | ||||
|       priv->unobscured_region = cairo_region_copy (unobscured_region); | ||||
|       cairo_region_intersect_rectangle (priv->unobscured_region, &bounds); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_clip_region (MetaShapedTexture *self, | ||||
|                  cairo_region_t    *clip_region) | ||||
| { | ||||
|   MetaShapedTexturePrivate *priv = self->priv; | ||||
|  | ||||
|   g_clear_pointer (&priv->clip_region, (GDestroyNotify) cairo_region_destroy); | ||||
|   if (clip_region) | ||||
|     priv->clip_region = cairo_region_copy (clip_region); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_shaped_texture_dispose (GObject *object) | ||||
| { | ||||
| @@ -149,7 +154,8 @@ meta_shaped_texture_dispose (GObject *object) | ||||
|   g_clear_pointer (&priv->opaque_region, cairo_region_destroy); | ||||
|  | ||||
|   meta_shaped_texture_set_mask_texture (self, NULL); | ||||
|   meta_shaped_texture_set_clip_region (self, NULL); | ||||
|   set_unobscured_region (self, NULL); | ||||
|   set_clip_region (self, NULL); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object); | ||||
| } | ||||
| @@ -220,10 +226,8 @@ paint_clipped_rectangle (CoglFramebuffer       *fb, | ||||
|   cogl_framebuffer_draw_multitextured_rectangle (fb, pipeline, | ||||
|                                                  x1, y1, x2, y2, | ||||
|                                                  &coords[0], 8); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| set_cogl_texture (MetaShapedTexture *stex, | ||||
|                   CoglTexture       *cogl_tex) | ||||
| @@ -238,10 +242,11 @@ set_cogl_texture (MetaShapedTexture *stex, | ||||
|   if (priv->texture) | ||||
|     cogl_object_unref (priv->texture); | ||||
|  | ||||
|   priv->texture = cogl_object_ref (cogl_tex); | ||||
|   priv->texture = cogl_tex; | ||||
|  | ||||
|   if (cogl_tex != NULL) | ||||
|     { | ||||
|       cogl_object_ref (cogl_tex); | ||||
|       width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex)); | ||||
|       height = cogl_texture_get_height (COGL_TEXTURE (cogl_tex)); | ||||
|  | ||||
| @@ -266,6 +271,9 @@ set_cogl_texture (MetaShapedTexture *stex, | ||||
|    * know how much of the buffer has changed with respect to the | ||||
|    * previous buffer. We only queue a redraw in response to surface | ||||
|    * damage. */ | ||||
|  | ||||
|   if (priv->create_mipmaps) | ||||
|     meta_texture_tower_set_base_texture (priv->paint_tower, cogl_tex); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -324,15 +332,8 @@ meta_shaped_texture_paint (ClutterActor *actor) | ||||
|  | ||||
|   filter = COGL_PIPELINE_FILTER_LINEAR; | ||||
|  | ||||
|   if (!clutter_actor_is_in_clone_paint (actor)) | ||||
|     { | ||||
|       int x_origin, y_origin; | ||||
|  | ||||
|       if (meta_actor_is_untransformed (actor, | ||||
|                                        &x_origin, | ||||
|                                        &y_origin)) | ||||
|         filter = COGL_PIPELINE_FILTER_NEAREST; | ||||
|     } | ||||
|   if (!clutter_actor_is_in_clone_paint (actor) && meta_actor_is_untransformed (actor, NULL, NULL)) | ||||
|     filter = COGL_PIPELINE_FILTER_NEAREST; | ||||
|  | ||||
|   ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|   fb = cogl_get_draw_framebuffer (); | ||||
| @@ -458,71 +459,6 @@ meta_shaped_texture_paint (ClutterActor *actor) | ||||
|     cairo_region_destroy (blended_region); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_shaped_texture_pick (ClutterActor       *actor, | ||||
| 			  const ClutterColor *color) | ||||
| { | ||||
|   MetaShapedTexture *stex = (MetaShapedTexture *) actor; | ||||
|   MetaShapedTexturePrivate *priv = stex->priv; | ||||
|  | ||||
|   if (!clutter_actor_should_pick_paint (actor) || | ||||
|       (priv->clip_region && cairo_region_is_empty (priv->clip_region))) | ||||
|     return; | ||||
|  | ||||
|   /* If there is no region then use the regular pick */ | ||||
|   if (priv->input_shape_region == NULL) | ||||
|     CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)->pick (actor, color); | ||||
|   else | ||||
|     { | ||||
|       int n_rects; | ||||
|       float *rectangles; | ||||
|       int i; | ||||
|       CoglPipeline *pipeline; | ||||
|       CoglContext *ctx; | ||||
|       CoglFramebuffer *fb; | ||||
|       CoglColor cogl_color; | ||||
|  | ||||
|       /* Note: We don't bother trying to intersect the pick and clip regions | ||||
|        * since needing to copy the region, do the intersection, and probably | ||||
|        * increase the number of rectangles seems more likely to have a negative | ||||
|        * effect. | ||||
|        * | ||||
|        * NB: Most of the time when just using rectangles for picking then | ||||
|        * picking shouldn't involve any rendering, and minimizing the number of | ||||
|        * rectangles has more benefit than reducing the area of the pick | ||||
|        * region. | ||||
|        */ | ||||
|  | ||||
|       n_rects = cairo_region_num_rectangles (priv->input_shape_region); | ||||
|       rectangles = g_alloca (sizeof (float) * 4 * n_rects); | ||||
|  | ||||
|       for (i = 0; i < n_rects; i++) | ||||
|         { | ||||
|           cairo_rectangle_int_t rect; | ||||
|           int pos = i * 4; | ||||
|  | ||||
|           cairo_region_get_rectangle (priv->input_shape_region, i, &rect); | ||||
|  | ||||
|           rectangles[pos] = rect.x; | ||||
|           rectangles[pos + 1] = rect.y; | ||||
|           rectangles[pos + 2] = rect.x + rect.width; | ||||
|           rectangles[pos + 3] = rect.y + rect.height; | ||||
|         } | ||||
|  | ||||
|       ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|       fb = cogl_get_draw_framebuffer (); | ||||
|  | ||||
|       cogl_color_init_from_4ub (&cogl_color, color->red, color->green, color->blue, color->alpha); | ||||
|  | ||||
|       pipeline = cogl_pipeline_new (ctx); | ||||
|       cogl_pipeline_set_color (pipeline, &cogl_color); | ||||
|  | ||||
|       cogl_framebuffer_draw_rectangles (fb, pipeline, | ||||
|                                         rectangles, n_rects); | ||||
|       cogl_object_unref (pipeline); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_shaped_texture_get_preferred_width (ClutterActor *self, | ||||
|                                          gfloat        for_height, | ||||
| @@ -562,52 +498,37 @@ meta_shaped_texture_get_preferred_height (ClutterActor *self, | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_shaped_texture_get_paint_volume (ClutterActor *self, | ||||
| meta_shaped_texture_get_paint_volume (ClutterActor *actor, | ||||
|                                       ClutterPaintVolume *volume) | ||||
| { | ||||
|   return clutter_paint_volume_set_from_allocation (volume, self); | ||||
| } | ||||
|   MetaShapedTexture *self = META_SHAPED_TEXTURE (actor); | ||||
|   cairo_rectangle_int_t unobscured_bounds; | ||||
|  | ||||
| ClutterActor * | ||||
| meta_shaped_texture_new_with_wayland_surface (MetaWaylandSurface *surface) | ||||
| { | ||||
|   ClutterActor *actor = g_object_new (META_TYPE_SHAPED_TEXTURE, NULL); | ||||
|   MetaShapedTexturePrivate *priv = META_SHAPED_TEXTURE (actor)->priv; | ||||
|   if (!clutter_paint_volume_set_from_allocation (volume, actor)) | ||||
|     return FALSE; | ||||
|  | ||||
|   /* XXX: it could probably be better to have a "type" construct-only | ||||
|    * property or create wayland/x11 subclasses */ | ||||
|   priv->type = META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE; | ||||
|   if (meta_shaped_texture_get_unobscured_bounds (self, &unobscured_bounds)) | ||||
|     { | ||||
|       ClutterVertex origin; | ||||
|       cairo_rectangle_int_t bounds; | ||||
|  | ||||
|   meta_shaped_texture_set_wayland_surface (META_SHAPED_TEXTURE (actor), | ||||
|                                            surface); | ||||
|       /* I hate ClutterPaintVolume so much... */ | ||||
|       clutter_paint_volume_get_origin (volume, &origin); | ||||
|       bounds.x = origin.x; | ||||
|       bounds.y = origin.y; | ||||
|       bounds.width = clutter_paint_volume_get_width (volume); | ||||
|       bounds.height = clutter_paint_volume_get_height (volume); | ||||
|  | ||||
|   return actor; | ||||
| } | ||||
|       gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds); | ||||
|  | ||||
| void | ||||
| meta_shaped_texture_set_wayland_surface (MetaShapedTexture *stex, | ||||
|                                          MetaWaylandSurface *surface) | ||||
| { | ||||
|   MetaShapedTexturePrivate *priv = stex->priv; | ||||
|       origin.x = bounds.x; | ||||
|       origin.y = bounds.y; | ||||
|       clutter_paint_volume_set_origin (volume, &origin); | ||||
|       clutter_paint_volume_set_width (volume, bounds.width); | ||||
|       clutter_paint_volume_set_height (volume, bounds.height); | ||||
|     } | ||||
|  | ||||
|   priv->wayland.surface = surface; | ||||
|  | ||||
|   if (surface && surface->buffer_ref.buffer) | ||||
|     meta_shaped_texture_attach_wayland_buffer (stex, | ||||
|                                                surface->buffer_ref.buffer); | ||||
| } | ||||
|  | ||||
| MetaWaylandSurface * | ||||
| meta_shaped_texture_get_wayland_surface (MetaShapedTexture *stex) | ||||
| { | ||||
|   MetaShapedTexturePrivate *priv = stex->priv; | ||||
|   return priv->wayland.surface; | ||||
| } | ||||
|  | ||||
| ClutterActor * | ||||
| meta_shaped_texture_new_with_xwindow (Window xwindow) | ||||
| { | ||||
|   return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL); | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -652,110 +573,48 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex, | ||||
|   clutter_actor_queue_redraw (CLUTTER_ACTOR (stex)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| wayland_surface_update_area (MetaShapedTexture *stex, | ||||
|                              int                x, | ||||
|                              int                y, | ||||
|                              int                width, | ||||
|                              int                height) | ||||
| static cairo_region_t * | ||||
| effective_unobscured_region (MetaShapedTexture *self) | ||||
| { | ||||
|   MetaShapedTexturePrivate *priv; | ||||
|   MetaWaylandBuffer *buffer; | ||||
|   MetaShapedTexturePrivate *priv = self->priv; | ||||
|   ClutterActor *parent = clutter_actor_get_parent (CLUTTER_ACTOR (self)); | ||||
|  | ||||
|   priv = stex->priv; | ||||
|   if (clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self))) | ||||
|     return NULL; | ||||
|  | ||||
|   g_return_if_fail (priv->type == META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE); | ||||
|   g_return_if_fail (priv->texture != NULL); | ||||
|   while (parent && !META_IS_WINDOW_ACTOR (parent)) | ||||
|     parent = clutter_actor_get_parent (parent); | ||||
|  | ||||
|   buffer = priv->wayland.surface->buffer_ref.buffer; | ||||
|   if (parent && clutter_actor_has_mapped_clones (parent)) | ||||
|     return NULL; | ||||
|  | ||||
|   if (buffer) | ||||
|     { | ||||
|       struct wl_resource *resource = buffer->resource; | ||||
|       struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource); | ||||
|  | ||||
|       if (shm_buffer) | ||||
|         { | ||||
|           CoglPixelFormat format; | ||||
|  | ||||
|           switch (wl_shm_buffer_get_format (shm_buffer)) | ||||
|             { | ||||
| #if G_BYTE_ORDER == G_BIG_ENDIAN | ||||
|             case WL_SHM_FORMAT_ARGB8888: | ||||
|               format = COGL_PIXEL_FORMAT_ARGB_8888_PRE; | ||||
|               break; | ||||
|             case WL_SHM_FORMAT_XRGB8888: | ||||
|               format = COGL_PIXEL_FORMAT_ARGB_8888; | ||||
|               break; | ||||
| #elif G_BYTE_ORDER == G_LITTLE_ENDIAN | ||||
|             case WL_SHM_FORMAT_ARGB8888: | ||||
|               format = COGL_PIXEL_FORMAT_BGRA_8888_PRE; | ||||
|               break; | ||||
|             case WL_SHM_FORMAT_XRGB8888: | ||||
|               format = COGL_PIXEL_FORMAT_BGRA_8888; | ||||
|               break; | ||||
| #endif | ||||
|             default: | ||||
|               g_warn_if_reached (); | ||||
|               format = COGL_PIXEL_FORMAT_ARGB_8888; | ||||
|             } | ||||
|  | ||||
|           cogl_texture_set_region (priv->texture, | ||||
|                                    x, y, | ||||
|                                    x, y, | ||||
|                                    width, height, | ||||
|                                    width, height, | ||||
|                                    format, | ||||
|                                    wl_shm_buffer_get_stride (shm_buffer), | ||||
|                                    wl_shm_buffer_get_data (shm_buffer)); | ||||
|         } | ||||
|     } | ||||
|   return priv->unobscured_region; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| get_clip (MetaShapedTexture *stex, | ||||
|           int x, | ||||
|           int y, | ||||
|           int width, | ||||
|           int height, | ||||
|           cairo_rectangle_int_t *clip) | ||||
| gboolean | ||||
| meta_shaped_texture_get_unobscured_bounds (MetaShapedTexture     *self, | ||||
|                                            cairo_rectangle_int_t *unobscured_bounds) | ||||
| { | ||||
|   ClutterActor *self = CLUTTER_ACTOR (stex); | ||||
|   MetaShapedTexturePrivate *priv; | ||||
|   ClutterActorBox allocation; | ||||
|   float scale_x; | ||||
|   float scale_y; | ||||
|   cairo_region_t *unobscured_region = effective_unobscured_region (self); | ||||
|  | ||||
|   /* NB: clutter_actor_queue_redraw_with_clip expects a box in the actor's | ||||
|    * coordinate space so we need to convert from surface coordinates to | ||||
|    * actor coordinates... | ||||
|    */ | ||||
|  | ||||
|   /* Calling clutter_actor_get_allocation_box() is enormously expensive | ||||
|    * if the actor has an out-of-date allocation, since it triggers | ||||
|    * a full redraw. clutter_actor_queue_redraw_with_clip() would redraw | ||||
|    * the whole stage anyways in that case, so just go ahead and do | ||||
|    * it here. | ||||
|    */ | ||||
|   if (!clutter_actor_has_allocation (self)) | ||||
|   if (unobscured_region) | ||||
|     { | ||||
|       cairo_region_get_extents (unobscured_region, unobscured_bounds); | ||||
|       return TRUE; | ||||
|     } | ||||
|   else | ||||
|     return FALSE; | ||||
| } | ||||
|  | ||||
|   priv = stex->priv; | ||||
| gboolean | ||||
| meta_shaped_texture_is_obscured (MetaShapedTexture *self) | ||||
| { | ||||
|   cairo_region_t *unobscured_region = effective_unobscured_region (self); | ||||
|  | ||||
|   if (priv->tex_width == 0 || priv->tex_height == 0) | ||||
|   if (unobscured_region) | ||||
|     return cairo_region_is_empty (unobscured_region); | ||||
|   else | ||||
|     return FALSE; | ||||
|  | ||||
|   clutter_actor_get_allocation_box (self, &allocation); | ||||
|  | ||||
|   scale_x = (allocation.x2 - allocation.x1) / priv->tex_width; | ||||
|   scale_y = (allocation.y2 - allocation.y1) / priv->tex_height; | ||||
|  | ||||
|   clip->x = x * scale_x; | ||||
|   clip->y = y * scale_y; | ||||
|   clip->width = width * scale_x; | ||||
|   clip->height = height * scale_y; | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -765,14 +624,9 @@ get_clip (MetaShapedTexture *stex, | ||||
|  * @y: the y coordinate of the damaged area | ||||
|  * @width: the width of the damaged area | ||||
|  * @height: the height of the damaged area | ||||
|  * @unobscured_region: The unobscured region of the window or %NULL if | ||||
|  * there is no valid one (like when the actor is transformed or | ||||
|  * has a mapped clone) | ||||
|  * | ||||
|  * Repairs the damaged area indicated by @x, @y, @width and @height | ||||
|  * and queues a redraw for the intersection @visibible_region and | ||||
|  * the damage area. If @visibible_region is %NULL a redraw will always | ||||
|  * get queued. | ||||
|  * and potentially queues a redraw. | ||||
|  * | ||||
|  * Return value: Whether a redraw have been queued or not | ||||
|  */ | ||||
| @@ -781,33 +635,20 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, | ||||
| 				 int                x, | ||||
| 				 int                y, | ||||
| 				 int                width, | ||||
| 				 int                height, | ||||
| 				 cairo_region_t    *unobscured_region) | ||||
| 				 int                height) | ||||
| { | ||||
|   MetaShapedTexturePrivate *priv; | ||||
|   cairo_rectangle_int_t clip; | ||||
|   gboolean has_clip; | ||||
|   cairo_region_t *unobscured_region; | ||||
|   const cairo_rectangle_int_t clip = { x, y, width, height }; | ||||
|  | ||||
|   priv = stex->priv; | ||||
|  | ||||
|   if (priv->texture == NULL) | ||||
|     return FALSE; | ||||
|  | ||||
|   switch (priv->type) | ||||
|     { | ||||
|     case META_SHAPED_TEXTURE_TYPE_X11_PIXMAP: | ||||
|       cogl_texture_pixmap_x11_update_area (COGL_TEXTURE_PIXMAP_X11 (priv->texture), | ||||
|                                            x, y, width, height); | ||||
|       break; | ||||
|     case META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE: | ||||
|       wayland_surface_update_area (stex, x, y, width, height); | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|   meta_texture_tower_update_area (priv->paint_tower, x, y, width, height); | ||||
|  | ||||
|   has_clip = get_clip (stex, x, y, width, height, &clip); | ||||
|  | ||||
|   unobscured_region = effective_unobscured_region (stex); | ||||
|   if (unobscured_region) | ||||
|     { | ||||
|       cairo_region_t *intersection; | ||||
| @@ -816,8 +657,7 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, | ||||
|         return FALSE; | ||||
|  | ||||
|       intersection = cairo_region_copy (unobscured_region); | ||||
|       if (has_clip) | ||||
| 	cairo_region_intersect_rectangle (intersection, &clip); | ||||
|       cairo_region_intersect_rectangle (intersection, &clip); | ||||
|  | ||||
|       if (!cairo_region_is_empty (intersection)) | ||||
|         { | ||||
| @@ -825,84 +665,31 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, | ||||
|           cairo_region_get_extents (intersection, &damage_rect); | ||||
|           clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &damage_rect); | ||||
|           cairo_region_destroy (intersection); | ||||
|  | ||||
|           return TRUE; | ||||
|         } | ||||
|  | ||||
|       cairo_region_destroy (intersection); | ||||
|  | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   if (has_clip) | ||||
|     clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip); | ||||
|   else | ||||
|     clutter_actor_queue_redraw (CLUTTER_ACTOR (stex)); | ||||
|  | ||||
|   return TRUE; | ||||
|     { | ||||
|       clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip); | ||||
|       return TRUE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_shaped_texture_set_pixmap: | ||||
|  * meta_shaped_texture_set_texture: | ||||
|  * @stex: The #MetaShapedTexture | ||||
|  * @pixmap: The pixmap you want the stex to assume | ||||
|  * @pixmap: The #CoglTexture to display | ||||
|  */ | ||||
| void | ||||
| meta_shaped_texture_set_pixmap (MetaShapedTexture *stex, | ||||
|                                 Pixmap             pixmap) | ||||
| meta_shaped_texture_set_texture (MetaShapedTexture *stex, | ||||
|                                  CoglTexture       *texture) | ||||
| { | ||||
|   MetaShapedTexturePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); | ||||
|  | ||||
|   priv = stex->priv; | ||||
|  | ||||
|   if (priv->x11.pixmap == pixmap) | ||||
|     return; | ||||
|  | ||||
|   priv->x11.pixmap = pixmap; | ||||
|  | ||||
|   if (pixmap != None) | ||||
|     { | ||||
|       CoglContext *ctx = | ||||
|         clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|       CoglTexture *texture = | ||||
|         COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, pixmap, FALSE, NULL)); | ||||
|       set_cogl_texture (stex, texture); | ||||
|     } | ||||
|   else | ||||
|     set_cogl_texture (stex, NULL); | ||||
|  | ||||
|   if (priv->create_mipmaps) | ||||
|     meta_texture_tower_set_base_texture (priv->paint_tower, | ||||
|                                          COGL_TEXTURE (priv->texture)); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture  *stex, | ||||
|                                            MetaWaylandBuffer  *buffer) | ||||
| { | ||||
|   MetaShapedTexturePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); | ||||
|  | ||||
|   priv = stex->priv; | ||||
|  | ||||
|   /* TODO: we should change this api to be something like | ||||
|    * meta_shaped_texture_notify_buffer_attach() since we now maintain | ||||
|    * a reference to the MetaWaylandSurface where we can access the | ||||
|    * buffer without it being explicitly passed as an argument. | ||||
|    */ | ||||
|   g_return_if_fail (priv->wayland.surface->buffer_ref.buffer == buffer); | ||||
|  | ||||
|   if (buffer) | ||||
|     set_cogl_texture (stex, buffer->texture); | ||||
|   else | ||||
|     set_cogl_texture (stex, NULL); | ||||
|  | ||||
|   if (priv->create_mipmaps) | ||||
|     meta_texture_tower_set_base_texture (priv->paint_tower, | ||||
|                                          COGL_TEXTURE (priv->texture)); | ||||
|   set_cogl_texture (stex, texture); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -918,74 +705,6 @@ meta_shaped_texture_get_texture (MetaShapedTexture *stex) | ||||
|   return COGL_TEXTURE (stex->priv->texture); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_shaped_texture_set_input_shape_region: | ||||
|  * @stex: a #MetaShapedTexture | ||||
|  * @shape_region: the region of the texture that should respond to | ||||
|  *    input. | ||||
|  * | ||||
|  * Determines what region of the texture should accept input. For | ||||
|  * X based windows this is defined by the ShapeInput region of the | ||||
|  * window. | ||||
|  */ | ||||
| void | ||||
| meta_shaped_texture_set_input_shape_region (MetaShapedTexture *stex, | ||||
|                                             cairo_region_t    *shape_region) | ||||
| { | ||||
|   MetaShapedTexturePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); | ||||
|  | ||||
|   priv = stex->priv; | ||||
|  | ||||
|   if (priv->input_shape_region != NULL) | ||||
|     { | ||||
|       cairo_region_destroy (priv->input_shape_region); | ||||
|       priv->input_shape_region = NULL; | ||||
|     } | ||||
|  | ||||
|   if (shape_region != NULL) | ||||
|     { | ||||
|       cairo_region_reference (shape_region); | ||||
|       priv->input_shape_region = shape_region; | ||||
|     } | ||||
|  | ||||
|   clutter_actor_queue_redraw (CLUTTER_ACTOR (stex)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_shaped_texture_set_clip_region: | ||||
|  * @stex: a #MetaShapedTexture | ||||
|  * @clip_region: the region of the texture that is visible and | ||||
|  *   should be painted. | ||||
|  * | ||||
|  * Provides a hint to the texture about what areas of the texture | ||||
|  * are not completely obscured and thus need to be painted. This | ||||
|  * is an optimization and is not supposed to have any effect on | ||||
|  * the output. | ||||
|  * | ||||
|  * Typically a parent container will set the clip region before | ||||
|  * painting its children, and then unset it afterwards. | ||||
|  */ | ||||
| void | ||||
| meta_shaped_texture_set_clip_region (MetaShapedTexture *stex, | ||||
| 				     cairo_region_t    *clip_region) | ||||
| { | ||||
|   MetaShapedTexturePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); | ||||
|  | ||||
|   priv = stex->priv; | ||||
|  | ||||
|   if (priv->clip_region) | ||||
|     cairo_region_destroy (priv->clip_region); | ||||
|  | ||||
|   if (clip_region) | ||||
|     priv->clip_region = cairo_region_copy (clip_region); | ||||
|   else | ||||
|     priv->clip_region = NULL; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_shaped_texture_set_opaque_region: | ||||
|  * @stex: a #MetaShapedTexture | ||||
| @@ -1113,3 +832,46 @@ meta_shaped_texture_get_image (MetaShapedTexture     *stex, | ||||
|  | ||||
|   return surface; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_shaped_texture_cull_out (MetaCullable   *cullable, | ||||
|                               cairo_region_t *unobscured_region, | ||||
|                               cairo_region_t *clip_region) | ||||
| { | ||||
|   MetaShapedTexture *self = META_SHAPED_TEXTURE (cullable); | ||||
|   MetaShapedTexturePrivate *priv = self->priv; | ||||
|  | ||||
|   set_unobscured_region (self, unobscured_region); | ||||
|   set_clip_region (self, clip_region); | ||||
|  | ||||
|   if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (self)) == 0xff) | ||||
|     { | ||||
|       if (priv->opaque_region) | ||||
|         { | ||||
|           if (unobscured_region) | ||||
|             cairo_region_subtract (unobscured_region, priv->opaque_region); | ||||
|           if (clip_region) | ||||
|             cairo_region_subtract (clip_region, priv->opaque_region); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_shaped_texture_reset_culling (MetaCullable *cullable) | ||||
| { | ||||
|   MetaShapedTexture *self = META_SHAPED_TEXTURE (cullable); | ||||
|   set_clip_region (self, NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| cullable_iface_init (MetaCullableInterface *iface) | ||||
| { | ||||
|   iface->cull_out = meta_shaped_texture_cull_out; | ||||
|   iface->reset_culling = meta_shaped_texture_reset_culling; | ||||
| } | ||||
|  | ||||
| ClutterActor * | ||||
| meta_shaped_texture_new (void) | ||||
| { | ||||
|   return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL); | ||||
| } | ||||
|   | ||||
							
								
								
									
										165
									
								
								src/compositor/meta-surface-actor-wayland.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								src/compositor/meta-surface-actor-wayland.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,165 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2013 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-surface-actor-wayland.h" | ||||
|  | ||||
| #include <cogl/cogl-wayland-server.h> | ||||
| #include "meta-shaped-texture-private.h" | ||||
|  | ||||
| #include "wayland/meta-wayland-private.h" | ||||
|  | ||||
| struct _MetaSurfaceActorWaylandPrivate | ||||
| { | ||||
|   MetaWaylandSurface *surface; | ||||
|   MetaWaylandBuffer *buffer; | ||||
| }; | ||||
| typedef struct _MetaSurfaceActorWaylandPrivate MetaSurfaceActorWaylandPrivate; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorWayland, meta_surface_actor_wayland, META_TYPE_SURFACE_ACTOR) | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor, | ||||
|                                            int x, int y, int width, int height) | ||||
| { | ||||
|   MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor); | ||||
|   MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); | ||||
|  | ||||
|   struct wl_resource *resource = priv->buffer->resource; | ||||
|   struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource); | ||||
|  | ||||
|   if (shm_buffer) | ||||
|     { | ||||
|       CoglTexture2D *texture = COGL_TEXTURE_2D (priv->buffer->texture); | ||||
|       cogl_wayland_texture_set_region_from_shm_buffer (texture, x, y, width, height, shm_buffer, x, y, 0, NULL); | ||||
|     } | ||||
|  | ||||
|   meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_wayland_pre_paint (MetaSurfaceActor *actor) | ||||
| { | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_surface_actor_wayland_is_argb32 (MetaSurfaceActor *actor) | ||||
| { | ||||
|   /* XXX -- look at the SHM buffer format. */ | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_surface_actor_wayland_is_visible (MetaSurfaceActor *actor) | ||||
| { | ||||
|   /* TODO: ensure that the buffer isn't NULL, implement | ||||
|    * wayland mapping semantics */ | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_surface_actor_wayland_should_unredirect (MetaSurfaceActor *actor) | ||||
| { | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_wayland_set_unredirected (MetaSurfaceActor *actor, | ||||
|                                              gboolean          unredirected) | ||||
| { | ||||
|   /* Do nothing. In the future, we'll use KMS to set this | ||||
|    * up as a hardware overlay or something. */ | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor) | ||||
| { | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static MetaWindow * | ||||
| meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor) | ||||
| { | ||||
|   MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (META_SURFACE_ACTOR_WAYLAND (actor)); | ||||
|  | ||||
|   return priv->surface->window; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass) | ||||
| { | ||||
|   MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass); | ||||
|  | ||||
|   surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage; | ||||
|   surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint; | ||||
|   surface_actor_class->is_argb32 = meta_surface_actor_wayland_is_argb32; | ||||
|   surface_actor_class->is_visible = meta_surface_actor_wayland_is_visible; | ||||
|  | ||||
|   surface_actor_class->should_unredirect = meta_surface_actor_wayland_should_unredirect; | ||||
|   surface_actor_class->set_unredirected = meta_surface_actor_wayland_set_unredirected; | ||||
|   surface_actor_class->is_unredirected = meta_surface_actor_wayland_is_unredirected; | ||||
|  | ||||
|   surface_actor_class->get_window = meta_surface_actor_wayland_get_window; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_wayland_init (MetaSurfaceActorWayland *self) | ||||
| { | ||||
| } | ||||
|  | ||||
| MetaSurfaceActor * | ||||
| meta_surface_actor_wayland_new (MetaWaylandSurface *surface) | ||||
| { | ||||
|   MetaSurfaceActorWayland *self = g_object_new (META_TYPE_SURFACE_ACTOR_WAYLAND, NULL); | ||||
|   MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); | ||||
|  | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|  | ||||
|   priv->surface = surface; | ||||
|  | ||||
|   return META_SURFACE_ACTOR (self); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self, | ||||
|                                        MetaWaylandBuffer       *buffer) | ||||
| { | ||||
|   MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); | ||||
|   MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); | ||||
|  | ||||
|   priv->buffer = buffer; | ||||
|  | ||||
|   if (buffer) | ||||
|     meta_shaped_texture_set_texture (stex, buffer->texture); | ||||
|   else | ||||
|     meta_shaped_texture_set_texture (stex, NULL); | ||||
| } | ||||
|  | ||||
| MetaWaylandSurface * | ||||
| meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self) | ||||
| { | ||||
|   MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); | ||||
|   return priv->surface; | ||||
| } | ||||
							
								
								
									
										66
									
								
								src/compositor/meta-surface-actor-wayland.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/compositor/meta-surface-actor-wayland.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2013 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #ifndef __META_SURFACE_ACTOR_WAYLAND_H__ | ||||
| #define __META_SURFACE_ACTOR_WAYLAND_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| #include "meta-surface-actor.h" | ||||
|  | ||||
| #include "wayland/meta-wayland.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define META_TYPE_SURFACE_ACTOR_WAYLAND            (meta_surface_actor_wayland_get_type ()) | ||||
| #define META_SURFACE_ACTOR_WAYLAND(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWayland)) | ||||
| #define META_SURFACE_ACTOR_WAYLAND_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass)) | ||||
| #define META_IS_SURFACE_ACTOR_WAYLAND(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND)) | ||||
| #define META_IS_SURFACE_ACTOR_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_SURFACE_ACTOR_WAYLAND)) | ||||
| #define META_SURFACE_ACTOR_WAYLAND_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass)) | ||||
|  | ||||
| typedef struct _MetaSurfaceActorWayland      MetaSurfaceActorWayland; | ||||
| typedef struct _MetaSurfaceActorWaylandClass MetaSurfaceActorWaylandClass; | ||||
|  | ||||
| struct _MetaSurfaceActorWayland | ||||
| { | ||||
|   MetaSurfaceActor parent; | ||||
| }; | ||||
|  | ||||
| struct _MetaSurfaceActorWaylandClass | ||||
| { | ||||
|   MetaSurfaceActorClass parent_class; | ||||
| }; | ||||
|  | ||||
| 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_set_buffer (MetaSurfaceActorWayland *self, | ||||
|                                             MetaWaylandBuffer         *buffer); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */ | ||||
							
								
								
									
										486
									
								
								src/compositor/meta-surface-actor-x11.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										486
									
								
								src/compositor/meta-surface-actor-x11.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,486 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2013 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: | ||||
|  *     Owen Taylor <otaylor@redhat.com> | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-surface-actor-x11.h" | ||||
|  | ||||
| #include <X11/extensions/Xcomposite.h> | ||||
| #include <X11/extensions/Xrender.h> | ||||
| #include <cogl/cogl-texture-pixmap-x11.h> | ||||
|  | ||||
| #include <meta/errors.h> | ||||
| #include "window-private.h" | ||||
| #include "meta-shaped-texture-private.h" | ||||
| #include "meta-cullable.h" | ||||
|  | ||||
| struct _MetaSurfaceActorX11Private | ||||
| { | ||||
|   MetaWindow *window; | ||||
|  | ||||
|   MetaDisplay *display; | ||||
|  | ||||
|   CoglTexture *texture; | ||||
|   Pixmap pixmap; | ||||
|   Damage damage; | ||||
|  | ||||
|   int last_width; | ||||
|   int last_height; | ||||
|  | ||||
|   /* This is used to detect fullscreen windows that need to be unredirected */ | ||||
|   guint full_damage_frames_count; | ||||
|   guint does_full_damage  : 1; | ||||
|  | ||||
|   /* Other state... */ | ||||
|   guint argb32 : 1; | ||||
|   guint received_damage : 1; | ||||
|   guint size_changed : 1; | ||||
|  | ||||
|   guint unredirected   : 1; | ||||
| }; | ||||
| typedef struct _MetaSurfaceActorX11Private MetaSurfaceActorX11Private; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorX11, meta_surface_actor_x11, META_TYPE_SURFACE_ACTOR) | ||||
|  | ||||
| static void | ||||
| free_damage (MetaSurfaceActorX11 *self) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|   MetaDisplay *display = priv->display; | ||||
|   Display *xdisplay = meta_display_get_xdisplay (display); | ||||
|  | ||||
|   if (priv->damage == None) | ||||
|     return; | ||||
|  | ||||
|   meta_error_trap_push (display); | ||||
|   XDamageDestroy (xdisplay, priv->damage); | ||||
|   priv->damage = None; | ||||
|   meta_error_trap_pop (display); | ||||
| } | ||||
|  | ||||
| static void | ||||
| detach_pixmap (MetaSurfaceActorX11 *self) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|   MetaDisplay *display = priv->display; | ||||
|   Display *xdisplay = meta_display_get_xdisplay (display); | ||||
|   MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); | ||||
|  | ||||
|   if (priv->pixmap == None) | ||||
|     return; | ||||
|  | ||||
|   /* Get rid of all references to the pixmap before freeing it; it's unclear whether | ||||
|    * you are supposed to be able to free a GLXPixmap after freeing the underlying | ||||
|    * pixmap, but it certainly doesn't work with current DRI/Mesa | ||||
|    */ | ||||
|   meta_shaped_texture_set_texture (stex, NULL); | ||||
|   cogl_flush (); | ||||
|  | ||||
|   meta_error_trap_push (display); | ||||
|   XFreePixmap (xdisplay, priv->pixmap); | ||||
|   priv->pixmap = None; | ||||
|   meta_error_trap_pop (display); | ||||
|  | ||||
|   cogl_object_unref (priv->texture); | ||||
|   priv->texture = NULL; | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_pixmap (MetaSurfaceActorX11 *self, | ||||
|             Pixmap               pixmap) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|  | ||||
|   CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|   MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); | ||||
|   CoglTexture *texture; | ||||
|  | ||||
|   g_assert (priv->pixmap == None); | ||||
|   priv->pixmap = pixmap; | ||||
|  | ||||
|   texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, priv->pixmap, FALSE, NULL)); | ||||
|  | ||||
|   if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture)))) | ||||
|     g_warning ("NOTE: Not using GLX TFP!\n"); | ||||
|  | ||||
|   priv->texture = texture; | ||||
|   meta_shaped_texture_set_texture (stex, texture); | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_pixmap (MetaSurfaceActorX11 *self) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|   MetaDisplay *display = priv->display; | ||||
|   Display *xdisplay = meta_display_get_xdisplay (display); | ||||
|  | ||||
|   if (priv->size_changed) | ||||
|     { | ||||
|       detach_pixmap (self); | ||||
|       priv->size_changed = FALSE; | ||||
|     } | ||||
|  | ||||
|   if (priv->pixmap == None) | ||||
|     { | ||||
|       Pixmap new_pixmap; | ||||
|       Window xwindow = meta_window_get_toplevel_xwindow (priv->window); | ||||
|  | ||||
|       meta_error_trap_push (display); | ||||
|       new_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow); | ||||
|  | ||||
|       if (meta_error_trap_pop_with_return (display) != Success) | ||||
|         { | ||||
|           /* Probably a BadMatch if the window isn't viewable; we could | ||||
|            * GrabServer/GetWindowAttributes/NameWindowPixmap/UngrabServer/Sync | ||||
|            * to avoid this, but there's no reason to take two round trips | ||||
|            * when one will do. (We need that Sync if we want to handle failures | ||||
|            * for any reason other than !viewable. That's unlikely, but maybe | ||||
|            * we'll BadAlloc or something.) | ||||
|            */ | ||||
|           new_pixmap = None; | ||||
|         } | ||||
|  | ||||
|       if (new_pixmap == None) | ||||
|         { | ||||
|           meta_verbose ("Unable to get named pixmap for %s\n", | ||||
|                         meta_window_get_description (priv->window)); | ||||
|           return; | ||||
|         } | ||||
|  | ||||
|       set_pixmap (self, new_pixmap); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| is_visible (MetaSurfaceActorX11 *self) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|   return (priv->pixmap != None) && !priv->unredirected; | ||||
| } | ||||
|  | ||||
| static void | ||||
| damage_area (MetaSurfaceActorX11 *self, | ||||
|              int x, int y, int width, int height) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|  | ||||
|   if (!is_visible (self)) | ||||
|     return; | ||||
|  | ||||
|   cogl_texture_pixmap_x11_update_area (priv->texture, x, y, width, height); | ||||
|   meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor, | ||||
|                                        int x, int y, int width, int height) | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|  | ||||
|   priv->received_damage = TRUE; | ||||
|  | ||||
|   if (meta_window_is_fullscreen (priv->window) && !priv->unredirected && !priv->does_full_damage) | ||||
|     { | ||||
|       MetaRectangle window_rect; | ||||
|       meta_window_get_frame_rect (priv->window, &window_rect); | ||||
|  | ||||
|       if (window_rect.x == x && | ||||
|           window_rect.y == y && | ||||
|           window_rect.width == width && | ||||
|           window_rect.height == height) | ||||
|         priv->full_damage_frames_count++; | ||||
|       else | ||||
|         priv->full_damage_frames_count = 0; | ||||
|  | ||||
|       if (priv->full_damage_frames_count >= 100) | ||||
|         priv->does_full_damage = TRUE; | ||||
|     } | ||||
|  | ||||
|   /* Drop damage event for unredirected windows */ | ||||
|   if (priv->unredirected) | ||||
|     return; | ||||
|  | ||||
|   damage_area (self, x, y, width, height); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor) | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|   MetaDisplay *display = priv->display; | ||||
|   Display *xdisplay = meta_display_get_xdisplay (display); | ||||
|  | ||||
|   if (priv->received_damage) | ||||
|     { | ||||
|       meta_error_trap_push (display); | ||||
|       XDamageSubtract (xdisplay, priv->damage, None, None); | ||||
|       meta_error_trap_pop (display); | ||||
|  | ||||
|       /* We need to make sure that any X drawing that happens before the | ||||
|        * XDamageSubtract() 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. | ||||
|        * | ||||
|        * Xorg and open source driver specifics: | ||||
|        * | ||||
|        * The X server makes sure to flush drawing to the kernel before | ||||
|        * sending out damage events, but since we use DamageReportBoundingBox | ||||
|        * there may be drawing between the last damage event and the | ||||
|        * XDamageSubtract() that needs to be flushed as well. | ||||
|        * | ||||
|        * Xorg always makes sure that drawing is flushed to the kernel | ||||
|        * before writing events or responses to the client, so any round trip | ||||
|        * request at this point is sufficient to flush the GLX buffers. | ||||
|        */ | ||||
|       XSync (xdisplay, False); | ||||
|  | ||||
|       priv->received_damage = FALSE; | ||||
|     } | ||||
|  | ||||
|   update_pixmap (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_is_argb32 (MetaSurfaceActorX11 *self) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|   MetaDisplay *display = priv->display; | ||||
|   Display *xdisplay = meta_display_get_xdisplay (display); | ||||
|  | ||||
|   XRenderPictFormat *format; | ||||
|   format = XRenderFindVisualFormat (xdisplay, priv->window->xvisual); | ||||
|  | ||||
|   priv->argb32 = (format && format->type == PictTypeDirect && format->direct.alphaMask); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_surface_actor_x11_is_argb32 (MetaSurfaceActor *actor) | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|  | ||||
|   return priv->argb32; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_surface_actor_x11_is_visible (MetaSurfaceActor *actor) | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); | ||||
|   return is_visible (self); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_surface_actor_x11_should_unredirect (MetaSurfaceActor *actor) | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|  | ||||
|   MetaWindow *window = priv->window; | ||||
|  | ||||
|   if (meta_window_requested_dont_bypass_compositor (window)) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (window->opacity != 0xFF) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (window->shape_region != NULL) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (priv->argb32 && !meta_window_requested_bypass_compositor (window)) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (!meta_window_is_monitor_sized (window)) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (meta_window_requested_bypass_compositor (window)) | ||||
|     return TRUE; | ||||
|  | ||||
|   if (meta_window_is_override_redirect (window)) | ||||
|     return TRUE; | ||||
|  | ||||
|   if (priv->does_full_damage) | ||||
|     return TRUE; | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| sync_unredirected (MetaSurfaceActorX11 *self) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|   MetaDisplay *display = priv->display; | ||||
|   Display *xdisplay = meta_display_get_xdisplay (display); | ||||
|   Window xwindow = meta_window_get_toplevel_xwindow (priv->window); | ||||
|  | ||||
|   meta_error_trap_push (display); | ||||
|  | ||||
|   if (priv->unredirected) | ||||
|     { | ||||
|       detach_pixmap (self); | ||||
|       XCompositeUnredirectWindow (xdisplay, xwindow, CompositeRedirectManual); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       XCompositeRedirectWindow (xdisplay, xwindow, CompositeRedirectManual); | ||||
|     } | ||||
|  | ||||
|   meta_error_trap_pop (display); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_x11_set_unredirected (MetaSurfaceActor *actor, | ||||
|                                          gboolean          unredirected) | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|  | ||||
|   if (priv->unredirected == unredirected) | ||||
|     return; | ||||
|  | ||||
|   priv->unredirected = unredirected; | ||||
|   sync_unredirected (self); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_surface_actor_x11_is_unredirected (MetaSurfaceActor *actor) | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|  | ||||
|   return priv->unredirected; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_x11_dispose (GObject *object) | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (object); | ||||
|  | ||||
|   detach_pixmap (self); | ||||
|   free_damage (self); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_surface_actor_x11_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static MetaWindow * | ||||
| meta_surface_actor_x11_get_window (MetaSurfaceActor *actor) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (META_SURFACE_ACTOR_X11 (actor)); | ||||
|  | ||||
|   return priv->window; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_x11_class_init (MetaSurfaceActorX11Class *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|   MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass); | ||||
|  | ||||
|   object_class->dispose = meta_surface_actor_x11_dispose; | ||||
|  | ||||
|   surface_actor_class->process_damage = meta_surface_actor_x11_process_damage; | ||||
|   surface_actor_class->pre_paint = meta_surface_actor_x11_pre_paint; | ||||
|   surface_actor_class->is_argb32 = meta_surface_actor_x11_is_argb32; | ||||
|   surface_actor_class->is_visible = meta_surface_actor_x11_is_visible; | ||||
|  | ||||
|   surface_actor_class->should_unredirect = meta_surface_actor_x11_should_unredirect; | ||||
|   surface_actor_class->set_unredirected = meta_surface_actor_x11_set_unredirected; | ||||
|   surface_actor_class->is_unredirected = meta_surface_actor_x11_is_unredirected; | ||||
|  | ||||
|   surface_actor_class->get_window = meta_surface_actor_x11_get_window; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_x11_init (MetaSurfaceActorX11 *self) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|  | ||||
|   priv->last_width = -1; | ||||
|   priv->last_height = -1; | ||||
| } | ||||
|  | ||||
| static void | ||||
| create_damage (MetaSurfaceActorX11 *self) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|   Display *xdisplay = meta_display_get_xdisplay (priv->display); | ||||
|   Window xwindow = meta_window_get_toplevel_xwindow (priv->window); | ||||
|  | ||||
|   priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox); | ||||
| } | ||||
|  | ||||
| static void | ||||
| window_decorated_notify (MetaWindow *window, | ||||
|                          GParamSpec *pspec, | ||||
|                          gpointer    user_data) | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (user_data); | ||||
|  | ||||
|   free_damage (self); | ||||
|   create_damage (self); | ||||
| } | ||||
|  | ||||
| MetaSurfaceActor * | ||||
| meta_surface_actor_x11_new (MetaWindow *window) | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = g_object_new (META_TYPE_SURFACE_ACTOR_X11, NULL); | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|   MetaDisplay *display = meta_window_get_display (window); | ||||
|  | ||||
|   g_assert (!meta_is_wayland_compositor ()); | ||||
|  | ||||
|   priv->window = window; | ||||
|   priv->display = display; | ||||
|  | ||||
|   create_damage (self); | ||||
|   g_signal_connect_object (priv->window, "notify::decorated", | ||||
|                            G_CALLBACK (window_decorated_notify), self, 0); | ||||
|  | ||||
|   update_is_argb32 (self); | ||||
|  | ||||
|   priv->unredirected = FALSE; | ||||
|   sync_unredirected (self); | ||||
|  | ||||
|   clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE); | ||||
|   return META_SURFACE_ACTOR (self); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self, | ||||
|                                  int width, int height) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|  | ||||
|   if (priv->last_width == width && | ||||
|       priv->last_height == height) | ||||
|     return; | ||||
|  | ||||
|   priv->size_changed = TRUE; | ||||
|   priv->last_width = width; | ||||
|   priv->last_height = height; | ||||
| } | ||||
							
								
								
									
										69
									
								
								src/compositor/meta-surface-actor-x11.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/compositor/meta-surface-actor-x11.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2013 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: | ||||
|  *     Owen Taylor <otaylor@redhat.com> | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #ifndef __META_SURFACE_ACTOR_X11_H__ | ||||
| #define __META_SURFACE_ACTOR_X11_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| #include "meta-surface-actor.h" | ||||
|  | ||||
| #include <X11/extensions/Xdamage.h> | ||||
|  | ||||
| #include <meta/display.h> | ||||
| #include <meta/window.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define META_TYPE_SURFACE_ACTOR_X11            (meta_surface_actor_x11_get_type ()) | ||||
| #define META_SURFACE_ACTOR_X11(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11)) | ||||
| #define META_SURFACE_ACTOR_X11_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class)) | ||||
| #define META_IS_SURFACE_ACTOR_X11(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR_X11)) | ||||
| #define META_IS_SURFACE_ACTOR_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_SURFACE_ACTOR_X11)) | ||||
| #define META_SURFACE_ACTOR_X11_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class)) | ||||
|  | ||||
| typedef struct _MetaSurfaceActorX11      MetaSurfaceActorX11; | ||||
| typedef struct _MetaSurfaceActorX11Class MetaSurfaceActorX11Class; | ||||
|  | ||||
| struct _MetaSurfaceActorX11 | ||||
| { | ||||
|   MetaSurfaceActor parent; | ||||
| }; | ||||
|  | ||||
| struct _MetaSurfaceActorX11Class | ||||
| { | ||||
|   MetaSurfaceActorClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType meta_surface_actor_x11_get_type (void); | ||||
|  | ||||
| MetaSurfaceActor * meta_surface_actor_x11_new (MetaWindow *window); | ||||
|  | ||||
| void meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self, | ||||
|                                       int width, int height); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __META_SURFACE_ACTOR_X11_H__ */ | ||||
							
								
								
									
										319
									
								
								src/compositor/meta-surface-actor.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										319
									
								
								src/compositor/meta-surface-actor.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,319 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:meta-surface-actor | ||||
|  * @title: MetaSurfaceActor | ||||
|  * @short_description: An actor representing a surface in the scene graph | ||||
|  * | ||||
|  * A surface can be either a shaped texture, or a group of shaped texture, | ||||
|  * used to draw the content of a window. | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #include "meta-surface-actor.h" | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
| #include <meta/meta-shaped-texture.h> | ||||
| #include "meta-cullable.h" | ||||
| #include "meta-shaped-texture-private.h" | ||||
|  | ||||
| struct _MetaSurfaceActorPrivate | ||||
| { | ||||
|   MetaShapedTexture *texture; | ||||
|  | ||||
|   cairo_region_t *input_region; | ||||
|  | ||||
|   /* Freeze/thaw accounting */ | ||||
|   guint needs_damage_all : 1; | ||||
|   guint frozen : 1; | ||||
| }; | ||||
|  | ||||
| static void cullable_iface_init (MetaCullableInterface *iface); | ||||
|  | ||||
| G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR, | ||||
|                                   G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)); | ||||
|  | ||||
| enum { | ||||
|   REPAINT_SCHEDULED, | ||||
|  | ||||
|   LAST_SIGNAL, | ||||
| }; | ||||
|  | ||||
| static guint signals[LAST_SIGNAL]; | ||||
|  | ||||
| gboolean | ||||
| meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor      *self, | ||||
|                                           cairo_rectangle_int_t *unobscured_bounds) | ||||
| { | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|   return meta_shaped_texture_get_unobscured_bounds (priv->texture, unobscured_bounds); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_pick (ClutterActor       *actor, | ||||
|                          const ClutterColor *color) | ||||
| { | ||||
|   MetaSurfaceActor *self = META_SURFACE_ACTOR (actor); | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|  | ||||
|   if (!clutter_actor_should_pick_paint (actor)) | ||||
|     return; | ||||
|  | ||||
|   /* If there is no region then use the regular pick */ | ||||
|   if (priv->input_region == NULL) | ||||
|     CLUTTER_ACTOR_CLASS (meta_surface_actor_parent_class)->pick (actor, color); | ||||
|   else | ||||
|     { | ||||
|       int n_rects; | ||||
|       float *rectangles; | ||||
|       int i; | ||||
|       CoglPipeline *pipeline; | ||||
|       CoglContext *ctx; | ||||
|       CoglFramebuffer *fb; | ||||
|       CoglColor cogl_color; | ||||
|  | ||||
|       n_rects = cairo_region_num_rectangles (priv->input_region); | ||||
|       rectangles = g_alloca (sizeof (float) * 4 * n_rects); | ||||
|  | ||||
|       for (i = 0; i < n_rects; i++) | ||||
|         { | ||||
|           cairo_rectangle_int_t rect; | ||||
|           int pos = i * 4; | ||||
|  | ||||
|           cairo_region_get_rectangle (priv->input_region, i, &rect); | ||||
|  | ||||
|           rectangles[pos + 0] = rect.x; | ||||
|           rectangles[pos + 1] = rect.y; | ||||
|           rectangles[pos + 2] = rect.x + rect.width; | ||||
|           rectangles[pos + 3] = rect.y + rect.height; | ||||
|         } | ||||
|  | ||||
|       ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|       fb = cogl_get_draw_framebuffer (); | ||||
|  | ||||
|       cogl_color_init_from_4ub (&cogl_color, color->red, color->green, color->blue, color->alpha); | ||||
|  | ||||
|       pipeline = cogl_pipeline_new (ctx); | ||||
|       cogl_pipeline_set_color (pipeline, &cogl_color); | ||||
|       cogl_framebuffer_draw_rectangles (fb, pipeline, rectangles, n_rects); | ||||
|       cogl_object_unref (pipeline); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_dispose (GObject *object) | ||||
| { | ||||
|   MetaSurfaceActor *self = META_SURFACE_ACTOR (object); | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|  | ||||
|   g_clear_pointer (&priv->input_region, cairo_region_destroy); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_surface_actor_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_class_init (MetaSurfaceActorClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|  | ||||
|   object_class->dispose = meta_surface_actor_dispose; | ||||
|   actor_class->pick = meta_surface_actor_pick; | ||||
|  | ||||
|   signals[REPAINT_SCHEDULED] = g_signal_new ("repaint-scheduled", | ||||
|                                              G_TYPE_FROM_CLASS (object_class), | ||||
|                                              G_SIGNAL_RUN_LAST, | ||||
|                                              0, | ||||
|                                              NULL, NULL, NULL, | ||||
|                                              G_TYPE_NONE, 0); | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (MetaSurfaceActorPrivate)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_cull_out (MetaCullable   *cullable, | ||||
|                              cairo_region_t *unobscured_region, | ||||
|                              cairo_region_t *clip_region) | ||||
| { | ||||
|   meta_cullable_cull_out_children (cullable, unobscured_region, clip_region); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_reset_culling (MetaCullable *cullable) | ||||
| { | ||||
|   meta_cullable_reset_culling_children (cullable); | ||||
| } | ||||
|  | ||||
| static void | ||||
| cullable_iface_init (MetaCullableInterface *iface) | ||||
| { | ||||
|   iface->cull_out = meta_surface_actor_cull_out; | ||||
|   iface->reset_culling = meta_surface_actor_reset_culling; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_init (MetaSurfaceActor *self) | ||||
| { | ||||
|   MetaSurfaceActorPrivate *priv; | ||||
|  | ||||
|   priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, | ||||
|                                                    META_TYPE_SURFACE_ACTOR, | ||||
|                                                    MetaSurfaceActorPrivate); | ||||
|  | ||||
|   priv->texture = META_SHAPED_TEXTURE (meta_shaped_texture_new ()); | ||||
|   clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->texture)); | ||||
| } | ||||
|  | ||||
| cairo_surface_t * | ||||
| meta_surface_actor_get_image (MetaSurfaceActor      *self, | ||||
|                               cairo_rectangle_int_t *clip) | ||||
| { | ||||
|   return meta_shaped_texture_get_image (self->priv->texture, clip); | ||||
| } | ||||
|  | ||||
| MetaShapedTexture * | ||||
| meta_surface_actor_get_texture (MetaSurfaceActor *self) | ||||
| { | ||||
|   return self->priv->texture; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_surface_actor_update_area (MetaSurfaceActor *self, | ||||
|                                 int x, int y, int width, int height) | ||||
| { | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|  | ||||
|   if (meta_shaped_texture_update_area (priv->texture, x, y, width, height)) | ||||
|     g_signal_emit (self, signals[REPAINT_SCHEDULED], 0); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_surface_actor_is_obscured (MetaSurfaceActor *self) | ||||
| { | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|   return meta_shaped_texture_is_obscured (priv->texture); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_surface_actor_set_input_region (MetaSurfaceActor *self, | ||||
|                                      cairo_region_t   *region) | ||||
| { | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|  | ||||
|   if (priv->input_region) | ||||
|     cairo_region_destroy (priv->input_region); | ||||
|  | ||||
|   if (region) | ||||
|     priv->input_region = cairo_region_reference (region); | ||||
|   else | ||||
|     priv->input_region = NULL; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_surface_actor_set_opaque_region (MetaSurfaceActor *self, | ||||
|                                       cairo_region_t   *region) | ||||
| { | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|   meta_shaped_texture_set_opaque_region (priv->texture, region); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| is_frozen (MetaSurfaceActor *self) | ||||
| { | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|   return priv->frozen; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_surface_actor_process_damage (MetaSurfaceActor *self, | ||||
|                                    int x, int y, int width, int height) | ||||
| { | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|  | ||||
|   if (is_frozen (self)) | ||||
|     { | ||||
|       /* The window is frozen due to an effect in progress: we ignore damage | ||||
|        * here on the off chance that this will stop the corresponding | ||||
|        * texture_from_pixmap from being update. | ||||
|        * | ||||
|        * needs_damage_all tracks that some unknown damage happened while the | ||||
|        * window was frozen so that when the window becomes unfrozen we can | ||||
|        * issue a full window update to cover any lost damage. | ||||
|        * | ||||
|        * It should be noted that this is an unreliable mechanism since it's | ||||
|        * quite likely that drivers will aim to provide a zero-copy | ||||
|        * implementation of the texture_from_pixmap extension and in those cases | ||||
|        * any drawing done to the window is always immediately reflected in the | ||||
|        * texture regardless of damage event handling. | ||||
|        */ | ||||
|       priv->needs_damage_all = TRUE; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   META_SURFACE_ACTOR_GET_CLASS (self)->process_damage (self, x, y, width, height); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_surface_actor_pre_paint (MetaSurfaceActor *self) | ||||
| { | ||||
|   META_SURFACE_ACTOR_GET_CLASS (self)->pre_paint (self); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_surface_actor_is_argb32 (MetaSurfaceActor *self) | ||||
| { | ||||
|   return META_SURFACE_ACTOR_GET_CLASS (self)->is_argb32 (self); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_surface_actor_is_visible (MetaSurfaceActor *self) | ||||
| { | ||||
|   return META_SURFACE_ACTOR_GET_CLASS (self)->is_visible (self); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_surface_actor_set_frozen (MetaSurfaceActor *self, | ||||
|                                gboolean          frozen) | ||||
| { | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|  | ||||
|   priv->frozen = frozen; | ||||
|  | ||||
|   if (!frozen && priv->needs_damage_all) | ||||
|     { | ||||
|       /* Since we ignore damage events while a window is frozen for certain effects | ||||
|        * we may need to issue an update_area() covering the whole pixmap if we | ||||
|        * don't know what real damage has happened. */ | ||||
|  | ||||
|       meta_surface_actor_process_damage (self, 0, 0, | ||||
|                                          clutter_actor_get_width (CLUTTER_ACTOR (priv->texture)), | ||||
|                                          clutter_actor_get_height (CLUTTER_ACTOR (priv->texture))); | ||||
|       priv->needs_damage_all = FALSE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_surface_actor_should_unredirect (MetaSurfaceActor *self) | ||||
| { | ||||
|   return META_SURFACE_ACTOR_GET_CLASS (self)->should_unredirect (self); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_surface_actor_set_unredirected (MetaSurfaceActor *self, | ||||
|                                      gboolean          unredirected) | ||||
| { | ||||
|   META_SURFACE_ACTOR_GET_CLASS (self)->set_unredirected (self, unredirected); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_surface_actor_is_unredirected (MetaSurfaceActor *self) | ||||
| { | ||||
|   return META_SURFACE_ACTOR_GET_CLASS (self)->is_unredirected (self); | ||||
| } | ||||
|  | ||||
| MetaWindow * | ||||
| meta_surface_actor_get_window (MetaSurfaceActor *self) | ||||
| { | ||||
|   return META_SURFACE_ACTOR_GET_CLASS (self)->get_window (self); | ||||
| } | ||||
							
								
								
									
										86
									
								
								src/compositor/meta-surface-actor.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/compositor/meta-surface-actor.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| #ifndef META_SURFACE_ACTOR_PRIVATE_H | ||||
| #define META_SURFACE_ACTOR_PRIVATE_H | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #include <meta/meta-shaped-texture.h> | ||||
| #include <meta/window.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define META_TYPE_SURFACE_ACTOR            (meta_surface_actor_get_type()) | ||||
| #define META_SURFACE_ACTOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR, MetaSurfaceActor)) | ||||
| #define META_SURFACE_ACTOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SURFACE_ACTOR, MetaSurfaceActorClass)) | ||||
| #define META_IS_SURFACE_ACTOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR)) | ||||
| #define META_IS_SURFACE_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SURFACE_ACTOR)) | ||||
| #define META_SURFACE_ACTOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SURFACE_ACTOR, MetaSurfaceActorClass)) | ||||
|  | ||||
| typedef struct _MetaSurfaceActor        MetaSurfaceActor; | ||||
| typedef struct _MetaSurfaceActorClass   MetaSurfaceActorClass; | ||||
| typedef struct _MetaSurfaceActorPrivate MetaSurfaceActorPrivate; | ||||
|  | ||||
| struct _MetaSurfaceActorClass | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActorClass parent_class; | ||||
|  | ||||
|   void     (* process_damage)    (MetaSurfaceActor *actor, | ||||
|                                   int x, int y, int width, int height); | ||||
|   void     (* pre_paint)         (MetaSurfaceActor *actor); | ||||
|   gboolean (* is_argb32)         (MetaSurfaceActor *actor); | ||||
|   gboolean (* is_visible)        (MetaSurfaceActor *actor); | ||||
|  | ||||
|   gboolean (* should_unredirect) (MetaSurfaceActor *actor); | ||||
|   void     (* set_unredirected)  (MetaSurfaceActor *actor, | ||||
|                                   gboolean          unredirected); | ||||
|   gboolean (* is_unredirected)   (MetaSurfaceActor *actor); | ||||
|  | ||||
|   MetaWindow *(* get_window)      (MetaSurfaceActor *actor); | ||||
| }; | ||||
|  | ||||
| struct _MetaSurfaceActor | ||||
| { | ||||
|   ClutterActor            parent; | ||||
|  | ||||
|   MetaSurfaceActorPrivate *priv; | ||||
| }; | ||||
|  | ||||
| GType meta_surface_actor_get_type (void); | ||||
|  | ||||
| cairo_surface_t *meta_surface_actor_get_image (MetaSurfaceActor      *self, | ||||
|                                                cairo_rectangle_int_t *clip); | ||||
|  | ||||
| MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self); | ||||
| MetaWindow        *meta_surface_actor_get_window  (MetaSurfaceActor *self); | ||||
|  | ||||
| gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self); | ||||
| gboolean meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor      *self, | ||||
|                                                    cairo_rectangle_int_t *unobscured_bounds); | ||||
|  | ||||
| void meta_surface_actor_set_input_region (MetaSurfaceActor *self, | ||||
|                                           cairo_region_t   *region); | ||||
| void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self, | ||||
|                                            cairo_region_t   *region); | ||||
|  | ||||
| void meta_surface_actor_update_area (MetaSurfaceActor *actor, | ||||
|                                      int x, int y, int width, int height); | ||||
|  | ||||
| void meta_surface_actor_process_damage (MetaSurfaceActor *actor, | ||||
|                                         int x, int y, int width, int height); | ||||
| void meta_surface_actor_pre_paint (MetaSurfaceActor *actor); | ||||
| gboolean meta_surface_actor_is_argb32 (MetaSurfaceActor *actor); | ||||
| gboolean meta_surface_actor_is_visible (MetaSurfaceActor *actor); | ||||
|  | ||||
| void meta_surface_actor_set_frozen (MetaSurfaceActor *actor, | ||||
|                                     gboolean          frozen); | ||||
|  | ||||
| gboolean meta_surface_actor_should_unredirect (MetaSurfaceActor *actor); | ||||
| void meta_surface_actor_set_unredirected (MetaSurfaceActor *actor, | ||||
|                                           gboolean          unredirected); | ||||
| gboolean meta_surface_actor_is_unredirected (MetaSurfaceActor *actor); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* META_SURFACE_ACTOR_PRIVATE_H */ | ||||
| @@ -18,9 +18,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
| @@ -28,41 +26,6 @@ | ||||
| #include <clutter/clutter.h> | ||||
| #include "meta-texture-rectangle.h" | ||||
|  | ||||
| CoglTexture * | ||||
| meta_texture_rectangle_new (unsigned int width, | ||||
|                             unsigned int height, | ||||
|                             CoglPixelFormat format, | ||||
|                             CoglPixelFormat internal_format, | ||||
|                             unsigned int rowstride, | ||||
|                             const guint8 *data, | ||||
|                             GError **error) | ||||
| { | ||||
|   ClutterBackend *backend = | ||||
|     clutter_get_default_backend (); | ||||
|   CoglContext *context = | ||||
|     clutter_backend_get_cogl_context (backend); | ||||
|   CoglTextureRectangle *tex_rect; | ||||
|  | ||||
|   tex_rect = cogl_texture_rectangle_new_with_size (context, | ||||
|                                                    width, height, | ||||
|                                                    internal_format, | ||||
|                                                    error); | ||||
|   if (tex_rect == NULL) | ||||
|     return NULL; | ||||
|  | ||||
|   if (data) | ||||
|     cogl_texture_set_region (COGL_TEXTURE (tex_rect), | ||||
|                              0, 0, /* src_x/y */ | ||||
|                              0, 0, /* dst_x/y */ | ||||
|                              width, height, /* dst_width/height */ | ||||
|                              width, height, /* width/height */ | ||||
|                              format, | ||||
|                              rowstride, | ||||
|                              data); | ||||
|  | ||||
|   return COGL_TEXTURE (tex_rect); | ||||
| } | ||||
|  | ||||
| static void | ||||
| texture_rectangle_check_cb (CoglTexture *sub_texture, | ||||
|                             const float *sub_texture_coords, | ||||
|   | ||||
| @@ -18,9 +18,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef __META_TEXTURE_RECTANGLE_H__ | ||||
| @@ -30,15 +28,6 @@ | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| CoglTexture * | ||||
| meta_texture_rectangle_new (unsigned int width, | ||||
|                             unsigned int height, | ||||
|                             CoglPixelFormat format, | ||||
|                             CoglPixelFormat internal_format, | ||||
|                             unsigned int rowstride, | ||||
|                             const guint8 *data, | ||||
|                             GError **error); | ||||
|  | ||||
| gboolean | ||||
| meta_texture_rectangle_check (CoglTexture *texture); | ||||
|  | ||||
|   | ||||
| @@ -17,9 +17,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include <math.h> | ||||
| @@ -357,18 +355,10 @@ texture_tower_create_texture (MetaTextureTower *tower, | ||||
|   if ((!is_power_of_two (width) || !is_power_of_two (height)) && | ||||
|       meta_texture_rectangle_check (tower->textures[level - 1])) | ||||
|     { | ||||
|       tower->textures[level] = | ||||
|         meta_texture_rectangle_new (width, height, | ||||
|                                     /* data format */ | ||||
|                                     TEXTURE_FORMAT, | ||||
|                                     /* internal cogl format */ | ||||
|                                     TEXTURE_FORMAT, | ||||
|                                     /* rowstride */ | ||||
|                                     width * 4, | ||||
|                                     /* data */ | ||||
|                                     NULL, | ||||
|                                     /* error */ | ||||
|                                     NULL); | ||||
|       ClutterBackend *backend = clutter_get_default_backend (); | ||||
|       CoglContext *context = clutter_backend_get_cogl_context (backend); | ||||
|  | ||||
|       tower->textures[level] = cogl_texture_rectangle_new_with_size (context, width, height); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|   | ||||
| @@ -17,9 +17,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef __META_TEXTURE_TOWER_H__ | ||||
|   | ||||
| @@ -5,11 +5,9 @@ | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #include <wayland-server.h> | ||||
| #include <meta-wayland-private.h> | ||||
|  | ||||
| #include <X11/extensions/Xdamage.h> | ||||
| #include <meta/compositor-mutter.h> | ||||
| #include "meta-surface-actor.h" | ||||
|  | ||||
| MetaWindowActor *meta_window_actor_new (MetaWindow *window); | ||||
|  | ||||
| @@ -30,16 +28,6 @@ void meta_window_actor_unmaximize (MetaWindowActor *self, | ||||
| void meta_window_actor_process_x11_damage (MetaWindowActor    *self, | ||||
|                                            XDamageNotifyEvent *event); | ||||
|  | ||||
| void meta_window_actor_process_wayland_damage (MetaWindowActor *self, | ||||
|                                                int              x, | ||||
|                                                int              y, | ||||
|                                                int              width, | ||||
|                                                int              height); | ||||
| void meta_window_actor_set_wayland_surface    (MetaWindowActor    *self, | ||||
|                                                MetaWaylandSurface *surface); | ||||
| void meta_window_actor_attach_wayland_buffer  (MetaWindowActor   *self, | ||||
|                                                MetaWaylandBuffer *buffer); | ||||
|  | ||||
| void meta_window_actor_pre_paint      (MetaWindowActor    *self); | ||||
| void meta_window_actor_post_paint     (MetaWindowActor    *self); | ||||
| void meta_window_actor_frame_complete (MetaWindowActor    *self, | ||||
| @@ -48,13 +36,13 @@ void meta_window_actor_frame_complete (MetaWindowActor    *self, | ||||
|  | ||||
| void meta_window_actor_invalidate_shadow (MetaWindowActor *self); | ||||
|  | ||||
| void meta_window_actor_set_redirected (MetaWindowActor *self, gboolean state); | ||||
|  | ||||
| gboolean meta_window_actor_should_unredirect (MetaWindowActor *self); | ||||
|  | ||||
| void meta_window_actor_get_shape_bounds (MetaWindowActor       *self, | ||||
|                                           cairo_rectangle_int_t *bounds); | ||||
|  | ||||
| gboolean meta_window_actor_should_unredirect   (MetaWindowActor *self); | ||||
| void     meta_window_actor_set_unredirected    (MetaWindowActor *self, | ||||
|                                                 gboolean         unredirected); | ||||
|  | ||||
| gboolean meta_window_actor_effect_in_progress  (MetaWindowActor *self); | ||||
| void     meta_window_actor_sync_actor_geometry (MetaWindowActor *self, | ||||
|                                                 gboolean         did_placement); | ||||
| @@ -68,18 +56,10 @@ void     meta_window_actor_set_updates_frozen  (MetaWindowActor *self, | ||||
| void     meta_window_actor_queue_frame_drawn   (MetaWindowActor *self, | ||||
|                                                 gboolean         no_delay_frame); | ||||
|  | ||||
| cairo_region_t *meta_window_actor_get_obscured_region (MetaWindowActor *self); | ||||
|  | ||||
| void meta_window_actor_set_clip_region         (MetaWindowActor *self, | ||||
|                                                 cairo_region_t  *clip_region); | ||||
| void meta_window_actor_set_clip_region_beneath (MetaWindowActor *self, | ||||
|                                                 cairo_region_t  *beneath_region); | ||||
| void meta_window_actor_reset_clip_regions      (MetaWindowActor *self); | ||||
|  | ||||
| void meta_window_actor_set_unobscured_region      (MetaWindowActor *self, | ||||
|                                                    cairo_region_t  *unobscured_region); | ||||
|  | ||||
| void meta_window_actor_effect_completed (MetaWindowActor *actor, | ||||
|                                          gulong           event); | ||||
|  | ||||
| MetaSurfaceActor *meta_window_actor_get_surface (MetaWindowActor *self); | ||||
| void meta_window_actor_update_surface (MetaWindowActor *self); | ||||
|  | ||||
| #endif /* META_WINDOW_ACTOR_PRIVATE_H */ | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -11,9 +11,8 @@ | ||||
| #include "compositor-private.h" | ||||
| #include "meta-window-actor-private.h" | ||||
| #include "meta-window-group.h" | ||||
| #include "meta-background-actor-private.h" | ||||
| #include "meta-background-group-private.h" | ||||
| #include "window-private.h" | ||||
| #include "meta-cullable.h" | ||||
|  | ||||
| struct _MetaWindowGroupClass | ||||
| { | ||||
| @@ -27,7 +26,10 @@ struct _MetaWindowGroup | ||||
|   MetaScreen *screen; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (MetaWindowGroup, meta_window_group, CLUTTER_TYPE_ACTOR); | ||||
| static void cullable_iface_init (MetaCullableInterface *iface); | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_CODE (MetaWindowGroup, meta_window_group, CLUTTER_TYPE_ACTOR, | ||||
|                          G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)); | ||||
|  | ||||
| /* Help macros to scale from OpenGL <-1,1> coordinates system to | ||||
|  * window coordinates ranging [0,window-size]. Borrowed from clutter-utils.c | ||||
| @@ -87,34 +89,40 @@ painting_untransformed (MetaWindowGroup *window_group, | ||||
|   return meta_actor_vertices_are_untransformed (vertices, width, height, x_origin, y_origin); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_window_group_cull_out (MetaCullable   *cullable, | ||||
|                             cairo_region_t *unobscured_region, | ||||
|                             cairo_region_t *clip_region) | ||||
| { | ||||
|   meta_cullable_cull_out_children (cullable, unobscured_region, clip_region); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_window_group_reset_culling (MetaCullable *cullable) | ||||
| { | ||||
|   meta_cullable_reset_culling_children (cullable); | ||||
| } | ||||
|  | ||||
| static void | ||||
| cullable_iface_init (MetaCullableInterface *iface) | ||||
| { | ||||
|   iface->cull_out = meta_window_group_cull_out; | ||||
|   iface->reset_culling = meta_window_group_reset_culling; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_window_group_paint (ClutterActor *actor) | ||||
| { | ||||
|   cairo_region_t *clip_region; | ||||
|   cairo_region_t *unobscured_region; | ||||
|   ClutterActorIter iter; | ||||
|   ClutterActor *child; | ||||
|   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 paint_x_offset, paint_y_offset; | ||||
|  | ||||
|   MetaWindowGroup *window_group = META_WINDOW_GROUP (actor); | ||||
|   MetaCompScreen *info = meta_screen_get_compositor_data (window_group->screen); | ||||
|   ClutterActor *stage = clutter_actor_get_stage (actor); | ||||
|  | ||||
|   /* Start off by treating all windows as completely unobscured, so damage anywhere | ||||
|    * in a window queues redraws, but confine it more below. */ | ||||
|   clutter_actor_iter_init (&iter, actor); | ||||
|   while (clutter_actor_iter_next (&iter, &child)) | ||||
|     { | ||||
|       if (META_IS_WINDOW_ACTOR (child)) | ||||
|         { | ||||
|           MetaWindowActor *window_actor = META_WINDOW_ACTOR (child); | ||||
|           meta_window_actor_set_unobscured_region (window_actor, NULL); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   /* Normally we expect an actor to be drawn at it's position on the screen. | ||||
|    * However, if we're inside the paint of a ClutterClone, that won't be the | ||||
|    * case and we need to compensate. We look at the position of the window | ||||
| @@ -135,9 +143,6 @@ meta_window_group_paint (ClutterActor *actor) | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   paint_x_offset = paint_x_origin - actor_x_origin; | ||||
|   paint_y_offset = paint_y_origin - actor_y_origin; | ||||
|  | ||||
|   visible_rect.x = visible_rect.y = 0; | ||||
|   visible_rect.width = clutter_actor_get_width (CLUTTER_ACTOR (stage)); | ||||
|   visible_rect.height = clutter_actor_get_height (CLUTTER_ACTOR (stage)); | ||||
| @@ -155,138 +160,44 @@ meta_window_group_paint (ClutterActor *actor) | ||||
|  | ||||
|   clip_region = cairo_region_create_rectangle (&clip_rect); | ||||
|  | ||||
|   if (!meta_is_wayland_compositor ()) | ||||
|     { | ||||
|       info = meta_screen_get_compositor_data (window_group->screen); | ||||
|       if (info->unredirected_window != NULL) | ||||
|         { | ||||
|           cairo_rectangle_int_t unredirected_rect; | ||||
|           MetaWindow *window = meta_window_actor_get_meta_window (info->unredirected_window); | ||||
|   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); | ||||
|  | ||||
|           meta_window_get_outer_rect (window, (MetaRectangle *)&unredirected_rect); | ||||
|           cairo_region_subtract_rectangle (unobscured_region, &unredirected_rect); | ||||
|           cairo_region_subtract_rectangle (clip_region, &unredirected_rect); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   /* We walk the list from top to bottom (opposite of painting order), | ||||
|    * and subtract the opaque area of each window out of the visible | ||||
|    * region that we pass to the windows below. | ||||
|    */ | ||||
|   clutter_actor_iter_init (&iter, actor); | ||||
|   while (clutter_actor_iter_prev (&iter, &child)) | ||||
|     { | ||||
|       if (!CLUTTER_ACTOR_IS_VISIBLE (child)) | ||||
|         continue; | ||||
|  | ||||
|       if (!meta_is_wayland_compositor () && | ||||
|           info->unredirected_window != NULL && | ||||
|           child == CLUTTER_ACTOR (info->unredirected_window)) | ||||
|         continue; | ||||
|  | ||||
|       /* If an actor has effects applied, then that can change the area | ||||
|        * it paints and the opacity, so we no longer can figure out what | ||||
|        * portion of the actor is obscured and what portion of the screen | ||||
|        * it obscures, so we skip the actor. | ||||
|        * | ||||
|        * This has a secondary beneficial effect: if a ClutterOffscreenEffect | ||||
|        * is applied to an actor, then our clipped redraws interfere with the | ||||
|        * caching of the FBO - even if we only need to draw a small portion | ||||
|        * of the window right now, ClutterOffscreenEffect may use other portions | ||||
|        * of the FBO later. So, skipping actors with effects applied also | ||||
|        * prevents these bugs. | ||||
|        * | ||||
|        * Theoretically, we should check clutter_actor_get_offscreen_redirect() | ||||
|        * as well for the same reason, but omitted for simplicity in the | ||||
|        * hopes that no-one will do that. | ||||
|        */ | ||||
|       if (clutter_actor_has_effects (child)) | ||||
|         continue; | ||||
|  | ||||
|       if (META_IS_WINDOW_ACTOR (child)) | ||||
|         { | ||||
|           MetaWindowActor *window_actor = META_WINDOW_ACTOR (child); | ||||
|           int x, y; | ||||
|  | ||||
|           if (!meta_actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y)) | ||||
|             continue; | ||||
|  | ||||
|           x += paint_x_offset; | ||||
|           y += paint_y_offset; | ||||
|  | ||||
|  | ||||
|           /* Temporarily move to the coordinate system of the actor */ | ||||
|           cairo_region_translate (unobscured_region, - x, - y); | ||||
|           cairo_region_translate (clip_region, - x, - y); | ||||
|  | ||||
|           meta_window_actor_set_unobscured_region (window_actor, unobscured_region); | ||||
|           meta_window_actor_set_clip_region (window_actor, clip_region); | ||||
|  | ||||
|           if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (window_actor)) == 0xff) | ||||
|             { | ||||
|               cairo_region_t *obscured_region = meta_window_actor_get_obscured_region (window_actor); | ||||
|               if (obscured_region) | ||||
|                 { | ||||
|                   cairo_region_subtract (unobscured_region, obscured_region); | ||||
|                   cairo_region_subtract (clip_region, obscured_region); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|           meta_window_actor_set_clip_region_beneath (window_actor, clip_region); | ||||
|  | ||||
|           cairo_region_translate (unobscured_region, x, y); | ||||
|           cairo_region_translate (clip_region, x, y); | ||||
|         } | ||||
|       else if (META_IS_BACKGROUND_ACTOR (child) || | ||||
|                META_IS_BACKGROUND_GROUP (child)) | ||||
|         { | ||||
|           int x, y; | ||||
|  | ||||
|           if (!meta_actor_is_untransformed (child, &x, &y)) | ||||
|             continue; | ||||
|  | ||||
|           x += paint_x_offset; | ||||
|           y += paint_y_offset; | ||||
|  | ||||
|           cairo_region_translate (clip_region, - x, - y); | ||||
|  | ||||
|           if (META_IS_BACKGROUND_GROUP (child)) | ||||
|             meta_background_group_set_clip_region (META_BACKGROUND_GROUP (child), clip_region); | ||||
|           else | ||||
|             meta_background_actor_set_clip_region (META_BACKGROUND_ACTOR (child), clip_region); | ||||
|           cairo_region_translate (clip_region, x, y); | ||||
|         } | ||||
|     } | ||||
|   meta_cullable_cull_out (META_CULLABLE (window_group), unobscured_region, clip_region); | ||||
|  | ||||
|   cairo_region_destroy (unobscured_region); | ||||
|   cairo_region_destroy (clip_region); | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor); | ||||
|  | ||||
|   /* Now that we are done painting, unset the visible regions (they will | ||||
|    * mess up painting clones of our actors) | ||||
|    */ | ||||
|   clutter_actor_iter_init (&iter, actor); | ||||
|   while (clutter_actor_iter_next (&iter, &child)) | ||||
|     { | ||||
|       if (META_IS_WINDOW_ACTOR (child)) | ||||
|         { | ||||
|           MetaWindowActor *window_actor = META_WINDOW_ACTOR (child); | ||||
|           meta_window_actor_reset_clip_regions (window_actor); | ||||
|         } | ||||
|       else if (META_IS_BACKGROUND_ACTOR (child)) | ||||
|         { | ||||
|           MetaBackgroundActor *background_actor = META_BACKGROUND_ACTOR (child); | ||||
|           meta_background_actor_set_clip_region (background_actor, NULL); | ||||
|         } | ||||
|     } | ||||
|   meta_cullable_reset_culling (META_CULLABLE (window_group)); | ||||
| } | ||||
|  | ||||
| /* Adapted from clutter_actor_update_default_paint_volume() */ | ||||
| static gboolean | ||||
| meta_window_group_get_paint_volume (ClutterActor       *actor, | ||||
| meta_window_group_get_paint_volume (ClutterActor       *self, | ||||
|                                     ClutterPaintVolume *volume) | ||||
| { | ||||
|   return clutter_paint_volume_set_from_allocation (volume, actor); | ||||
|   ClutterActorIter iter; | ||||
|   ClutterActor *child; | ||||
|  | ||||
|   clutter_actor_iter_init (&iter, self); | ||||
|   while (clutter_actor_iter_next (&iter, &child)) | ||||
|     { | ||||
|       const ClutterPaintVolume *child_volume; | ||||
|  | ||||
|       if (!CLUTTER_ACTOR_IS_MAPPED (child)) | ||||
|         continue; | ||||
|  | ||||
|       child_volume = clutter_actor_get_transformed_paint_volume (child, self); | ||||
|       if (child_volume == NULL) | ||||
|         return FALSE; | ||||
|  | ||||
|       clutter_paint_volume_union (volume, child_volume); | ||||
|     } | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
|   | ||||
| @@ -11,29 +11,9 @@ | ||||
|  * MetaWindowGroup: | ||||
|  * | ||||
|  * This class is a subclass of ClutterActor with special handling for | ||||
|  * MetaWindowActor/MetaBackgroundActor/MetaBackgroundGroup when painting | ||||
|  * children. | ||||
|  * | ||||
|  * When we are painting a stack of 5-10 maximized windows, the | ||||
|  * standard bottom-to-top method of drawing every actor results in a | ||||
|  * tremendous amount of overdraw and can easily max out the available | ||||
|  * memory bandwidth on a low-end graphics chipset. It's even worse if | ||||
|  * window textures are being accessed over the AGP bus. | ||||
|  * | ||||
|  * The basic technique applied here is to do a pre-pass before painting | ||||
|  * where we walk window from top to bottom and compute the visible area | ||||
|  * at each step by subtracting out the windows above it. The visible | ||||
|  * area is passed to MetaWindowActor which uses it to clip the portion of | ||||
|  * the window which drawn and avoid redrawing the shadow if it is completely | ||||
|  * obscured. | ||||
|  * | ||||
|  * A caveat is that this is ineffective if applications are using ARGB | ||||
|  * visuals, since we have no way of knowing whether a window obscures | ||||
|  * the windows behind it or not. Alternate approaches using the depth | ||||
|  * or stencil buffer rather than client side regions might be able to | ||||
|  * handle alpha windows, but the combination of glAlphaFunc and stenciling | ||||
|  * tends not to be efficient except on newer cards. (And on newer cards | ||||
|  * we have lots of memory and bandwidth.) | ||||
|  * #MetaCullable when painting children. It uses code similar to | ||||
|  * meta_cullable_cull_out_children(), but also has additional special | ||||
|  * cases for the undirected window, and similar. | ||||
|  */ | ||||
|  | ||||
| #define META_TYPE_WINDOW_GROUP            (meta_window_group_get_type ()) | ||||
|   | ||||
| @@ -17,9 +17,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #include <string.h> | ||||
|  | ||||
|   | ||||
| @@ -17,9 +17,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef __META_WINDOW_SHAPE_H__ | ||||
|   | ||||
| @@ -16,9 +16,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
| @@ -34,13 +32,14 @@ | ||||
| #include <gmodule.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #define DESTROY_TIMEOUT   250 | ||||
| #define DESTROY_TIMEOUT   100 | ||||
| #define MINIMIZE_TIMEOUT  250 | ||||
| #define MAXIMIZE_TIMEOUT  250 | ||||
| #define MAP_TIMEOUT       250 | ||||
| #define SWITCH_TIMEOUT    500 | ||||
|  | ||||
| #define ACTOR_DATA_KEY "MCCP-Default-actor-data" | ||||
| #define SCREEN_TILE_PREVIEW_DATA_KEY "MCCP-Default-screen-tile-preview-data" | ||||
|  | ||||
| #define META_TYPE_DEFAULT_PLUGIN            (meta_default_plugin_get_type ()) | ||||
| #define META_DEFAULT_PLUGIN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPlugin)) | ||||
| @@ -69,6 +68,7 @@ struct _MetaDefaultPluginClass | ||||
| }; | ||||
|  | ||||
| static GQuark actor_data_quark = 0; | ||||
| static GQuark screen_tile_preview_data_quark = 0; | ||||
|  | ||||
| static void start      (MetaPlugin      *plugin); | ||||
| static void minimize   (MetaPlugin      *plugin, | ||||
| @@ -99,6 +99,12 @@ static void kill_window_effects   (MetaPlugin      *plugin, | ||||
|                                    MetaWindowActor *actor); | ||||
| static void kill_switch_workspace (MetaPlugin      *plugin); | ||||
|  | ||||
| static void show_tile_preview (MetaPlugin      *plugin, | ||||
|                                MetaWindow      *window, | ||||
|                                MetaRectangle   *tile_rect, | ||||
|                                int              tile_monitor_number); | ||||
| static void hide_tile_preview (MetaPlugin      *plugin); | ||||
|  | ||||
| static void confirm_display_change (MetaPlugin *plugin); | ||||
|  | ||||
| static const MetaPluginInfo * plugin_info (MetaPlugin *plugin); | ||||
| @@ -145,6 +151,15 @@ typedef struct | ||||
| } EffectCompleteData; | ||||
|  | ||||
|  | ||||
| typedef struct _ScreenTilePreview | ||||
| { | ||||
|   ClutterActor   *actor; | ||||
|  | ||||
|   GdkRGBA        *preview_color; | ||||
|  | ||||
|   MetaRectangle   tile_rect; | ||||
| } ScreenTilePreview; | ||||
|  | ||||
| static void | ||||
| meta_default_plugin_dispose (GObject *object) | ||||
| { | ||||
| @@ -205,6 +220,8 @@ meta_default_plugin_class_init (MetaDefaultPluginClass *klass) | ||||
|   plugin_class->unmaximize       = unmaximize; | ||||
|   plugin_class->destroy          = destroy; | ||||
|   plugin_class->switch_workspace = switch_workspace; | ||||
|   plugin_class->show_tile_preview = show_tile_preview; | ||||
|   plugin_class->hide_tile_preview = hide_tile_preview; | ||||
|   plugin_class->plugin_info      = plugin_info; | ||||
|   plugin_class->kill_window_effects   = kill_window_effects; | ||||
|   plugin_class->kill_switch_workspace = kill_switch_workspace; | ||||
| @@ -291,26 +308,13 @@ on_switch_workspace_effect_complete (ClutterTimeline *timeline, gpointer data) | ||||
|   meta_plugin_switch_workspace_completed (plugin); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| show_stage (MetaPlugin *plugin) | ||||
| { | ||||
|   MetaScreen *screen; | ||||
|   ClutterActor *stage; | ||||
|  | ||||
|   screen = meta_plugin_get_screen (plugin); | ||||
|   stage = meta_get_stage_for_screen (screen); | ||||
|  | ||||
|   clutter_actor_show (stage); | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_monitors_changed (MetaScreen *screen, | ||||
|                      MetaPlugin *plugin) | ||||
| { | ||||
|   MetaDefaultPlugin *self = META_DEFAULT_PLUGIN (plugin); | ||||
|   int i, n; | ||||
|   GRand *rand = g_rand_new_with_seed (12345); | ||||
|  | ||||
|   clutter_actor_destroy_all_children (self->priv->background_group); | ||||
|  | ||||
| @@ -333,14 +337,16 @@ on_monitors_changed (MetaScreen *screen, | ||||
|          reproducible. | ||||
|       */ | ||||
|       clutter_color_init (&color, | ||||
|                           g_random_int () % 255, | ||||
|                           g_random_int () % 255, | ||||
|                           g_random_int () % 255, | ||||
|                           g_rand_int_range (rand, 0, 255), | ||||
|                           g_rand_int_range (rand, 0, 255), | ||||
|                           g_rand_int_range (rand, 0, 255), | ||||
|                           255); | ||||
|       clutter_actor_set_background_color (background, &color); | ||||
|  | ||||
|       clutter_actor_add_child (self->priv->background_group, background); | ||||
|     } | ||||
|  | ||||
|   g_rand_free (rand); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -357,10 +363,7 @@ start (MetaPlugin *plugin) | ||||
|                     G_CALLBACK (on_monitors_changed), plugin); | ||||
|   on_monitors_changed (screen, plugin); | ||||
|  | ||||
|   meta_later_add (META_LATER_BEFORE_REDRAW, | ||||
|                   (GSourceFunc) show_stage, | ||||
|                   plugin, | ||||
|                   NULL); | ||||
|   clutter_actor_show (meta_get_stage_for_screen (screen)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -409,9 +412,11 @@ switch_workspace (MetaPlugin *plugin, | ||||
|       MetaWindowActor *window_actor = l->data; | ||||
|       ActorPrivate    *apriv	    = get_actor_private (window_actor); | ||||
|       ClutterActor    *actor	    = CLUTTER_ACTOR (window_actor); | ||||
|       MetaWorkspace   *workspace; | ||||
|       gint             win_workspace; | ||||
|  | ||||
|       win_workspace = meta_window_actor_get_workspace (window_actor); | ||||
|       workspace = meta_window_get_workspace (meta_window_actor_get_meta_window (window_actor)); | ||||
|       win_workspace = meta_workspace_index (workspace); | ||||
|  | ||||
|       if (win_workspace == to || win_workspace == from) | ||||
|         { | ||||
| @@ -483,8 +488,6 @@ on_minimize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data | ||||
|   /* FIXME - we shouldn't assume the original scale, it should be saved | ||||
|    * at the start of the effect */ | ||||
|   clutter_actor_set_scale (data->actor, 1.0, 1.0); | ||||
|   clutter_actor_move_anchor_point_from_gravity (data->actor, | ||||
|                                                 CLUTTER_GRAVITY_NORTH_WEST); | ||||
|  | ||||
|   /* Now notify the manager that we are done with this effect */ | ||||
|   meta_plugin_minimize_completed (plugin, window_actor); | ||||
| @@ -521,9 +524,6 @@ minimize (MetaPlugin *plugin, MetaWindowActor *window_actor) | ||||
|  | ||||
|       apriv->is_minimized = TRUE; | ||||
|  | ||||
|       clutter_actor_move_anchor_point_from_gravity (actor, | ||||
|                                                     CLUTTER_GRAVITY_CENTER); | ||||
|  | ||||
|       animation = clutter_actor_animate (actor, | ||||
|                                          CLUTTER_EASE_IN_SINE, | ||||
|                                          MINIMIZE_TIMEOUT, | ||||
| @@ -562,8 +562,6 @@ on_maximize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data | ||||
|  | ||||
|   /* FIXME - don't assume the original scale was 1.0 */ | ||||
|   clutter_actor_set_scale (data->actor, 1.0, 1.0); | ||||
|   clutter_actor_move_anchor_point_from_gravity (data->actor, | ||||
|                                                 CLUTTER_GRAVITY_NORTH_WEST); | ||||
|  | ||||
|   /* Now notify the manager that we are done with this effect */ | ||||
|   meta_plugin_maximize_completed (plugin, window_actor); | ||||
| @@ -588,10 +586,8 @@ maximize (MetaPlugin *plugin, | ||||
|   ClutterActor *actor = CLUTTER_ACTOR (window_actor); | ||||
|   MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor); | ||||
|  | ||||
|   gdouble  scale_x    = 1.0; | ||||
|   gdouble  scale_y    = 1.0; | ||||
|   gfloat   anchor_x   = 0; | ||||
|   gfloat   anchor_y   = 0; | ||||
|   gdouble  scale_x = 1.0; | ||||
|   gdouble  scale_y = 1.0; | ||||
|  | ||||
|   type = meta_window_get_window_type (meta_window); | ||||
|  | ||||
| @@ -615,13 +611,6 @@ maximize (MetaPlugin *plugin, | ||||
|       scale_x = (gdouble)end_width / (gdouble) width; | ||||
|       scale_y = (gdouble)end_height / (gdouble) height; | ||||
|  | ||||
|       anchor_x = (gdouble)(x - end_x)*(gdouble)width / | ||||
|         ((gdouble)(end_width - width)); | ||||
|       anchor_y = (gdouble)(y - end_y)*(gdouble)height / | ||||
|         ((gdouble)(end_height - height)); | ||||
|  | ||||
|       clutter_actor_move_anchor_point (actor, anchor_x, anchor_y); | ||||
|  | ||||
|       animation = clutter_actor_animate (actor, | ||||
|                                          CLUTTER_EASE_IN_SINE, | ||||
|                                          MAXIMIZE_TIMEOUT, | ||||
| @@ -676,9 +665,6 @@ on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data) | ||||
|  | ||||
|   apriv->tml_map = NULL; | ||||
|  | ||||
|   clutter_actor_move_anchor_point_from_gravity (data->actor, | ||||
|                                                 CLUTTER_GRAVITY_NORTH_WEST); | ||||
|  | ||||
|   /* Now notify the manager that we are done with this effect */ | ||||
|   meta_plugin_map_completed (plugin, window_actor); | ||||
|  | ||||
| @@ -704,15 +690,15 @@ map (MetaPlugin *plugin, MetaWindowActor *window_actor) | ||||
|       EffectCompleteData *data = g_new0 (EffectCompleteData, 1); | ||||
|       ActorPrivate *apriv = get_actor_private (window_actor); | ||||
|  | ||||
|       clutter_actor_move_anchor_point_from_gravity (actor, | ||||
|                                                     CLUTTER_GRAVITY_CENTER); | ||||
|  | ||||
|       clutter_actor_set_scale (actor, 0.0, 0.0); | ||||
|       clutter_actor_set_pivot_point (actor, 0.5, 0.5); | ||||
|       clutter_actor_set_opacity (actor, 0); | ||||
|       clutter_actor_set_scale (actor, 0.5, 0.5); | ||||
|       clutter_actor_show (actor); | ||||
|  | ||||
|       animation = clutter_actor_animate (actor, | ||||
|                                          CLUTTER_EASE_IN_SINE, | ||||
|                                          CLUTTER_EASE_OUT_QUAD, | ||||
|                                          MAP_TIMEOUT, | ||||
|                                          "opacity", 255, | ||||
|                                          "scale-x", 1.0, | ||||
|                                          "scale-y", 1.0, | ||||
|                                          NULL); | ||||
| @@ -764,14 +750,12 @@ destroy (MetaPlugin *plugin, MetaWindowActor *window_actor) | ||||
|       EffectCompleteData *data = g_new0 (EffectCompleteData, 1); | ||||
|       ActorPrivate *apriv = get_actor_private (window_actor); | ||||
|  | ||||
|       clutter_actor_move_anchor_point_from_gravity (actor, | ||||
|                                                     CLUTTER_GRAVITY_CENTER); | ||||
|  | ||||
|       animation = clutter_actor_animate (actor, | ||||
|                                          CLUTTER_EASE_IN_SINE, | ||||
|                                          CLUTTER_EASE_OUT_QUAD, | ||||
|                                          DESTROY_TIMEOUT, | ||||
|                                          "scale-x", 0.0, | ||||
|                                          "scale-y", 1.0, | ||||
|                                          "opacity", 0, | ||||
|                                          "scale-x", 0.8, | ||||
|                                          "scale-y", 0.8, | ||||
|                                          NULL); | ||||
|       apriv->tml_destroy = clutter_animation_get_timeline (animation); | ||||
|       data->plugin = plugin; | ||||
| @@ -784,6 +768,82 @@ destroy (MetaPlugin *plugin, MetaWindowActor *window_actor) | ||||
|     meta_plugin_destroy_completed (plugin, window_actor); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Tile preview private data accessor | ||||
|  */ | ||||
| static void | ||||
| free_screen_tile_preview (gpointer data) | ||||
| { | ||||
|   ScreenTilePreview *preview = data; | ||||
|  | ||||
|   if (G_LIKELY (preview != NULL)) { | ||||
|     clutter_actor_destroy (preview->actor); | ||||
|     g_slice_free (ScreenTilePreview, preview); | ||||
|   } | ||||
| } | ||||
|  | ||||
| static ScreenTilePreview * | ||||
| get_screen_tile_preview (MetaScreen *screen) | ||||
| { | ||||
|   ScreenTilePreview *preview = g_object_get_qdata (G_OBJECT (screen), screen_tile_preview_data_quark); | ||||
|  | ||||
|   if (G_UNLIKELY (screen_tile_preview_data_quark == 0)) | ||||
|     screen_tile_preview_data_quark = g_quark_from_static_string (SCREEN_TILE_PREVIEW_DATA_KEY); | ||||
|  | ||||
|   if (G_UNLIKELY (!preview)) | ||||
|     { | ||||
|       preview = g_slice_new0 (ScreenTilePreview); | ||||
|  | ||||
|       preview->actor = clutter_actor_new (); | ||||
|       clutter_actor_set_background_color (preview->actor, CLUTTER_COLOR_Blue); | ||||
|       clutter_actor_set_opacity (preview->actor, 100); | ||||
|  | ||||
|       clutter_actor_add_child (meta_get_window_group_for_screen (screen), preview->actor); | ||||
|       g_object_set_qdata_full (G_OBJECT (screen), | ||||
|                                screen_tile_preview_data_quark, preview, | ||||
|                                free_screen_tile_preview); | ||||
|     } | ||||
|  | ||||
|   return preview; | ||||
| } | ||||
|  | ||||
| static void | ||||
| show_tile_preview (MetaPlugin    *plugin, | ||||
|                    MetaWindow    *window, | ||||
|                    MetaRectangle *tile_rect, | ||||
|                    int            tile_monitor_number) | ||||
| { | ||||
|   MetaScreen *screen = meta_plugin_get_screen (plugin); | ||||
|   ScreenTilePreview *preview = get_screen_tile_preview (screen); | ||||
|   ClutterActor *window_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 | ||||
|       && preview->tile_rect.height == tile_rect->height) | ||||
|     return; /* nothing to do */ | ||||
|  | ||||
|   clutter_actor_set_position (preview->actor, tile_rect->x, tile_rect->y); | ||||
|   clutter_actor_set_size (preview->actor, tile_rect->width, tile_rect->height); | ||||
|  | ||||
|   clutter_actor_show (preview->actor); | ||||
|  | ||||
|   window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window)); | ||||
|   clutter_actor_lower (preview->actor, window_actor); | ||||
|  | ||||
|   preview->tile_rect = *tile_rect; | ||||
| } | ||||
|  | ||||
| static void | ||||
| hide_tile_preview (MetaPlugin *plugin) | ||||
| { | ||||
|   MetaScreen *screen = meta_plugin_get_screen (plugin); | ||||
|   ScreenTilePreview *preview = get_screen_tile_preview (screen); | ||||
|  | ||||
|   clutter_actor_hide (preview->actor); | ||||
| } | ||||
|  | ||||
| static void | ||||
| kill_switch_workspace (MetaPlugin     *plugin) | ||||
| { | ||||
|   | ||||
| @@ -15,9 +15,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include "region-utils.h" | ||||
|   | ||||
| @@ -15,9 +15,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef __META_REGION_UTILS_H__ | ||||
|   | ||||
| @@ -15,9 +15,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /* The standard cycle-windows keybinding should be the key above the | ||||
|   | ||||
| @@ -366,11 +366,25 @@ meta_barrier_fire_event (MetaBarrier    *barrier, | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_display_process_barrier_event (MetaDisplay    *display, | ||||
|                                     XIBarrierEvent *xev) | ||||
| meta_display_process_barrier_event (MetaDisplay *display, | ||||
|                                     XIEvent     *event) | ||||
| { | ||||
|   MetaBarrier *barrier; | ||||
|   XIBarrierEvent *xev; | ||||
|  | ||||
|   if (event == NULL) | ||||
|     return FALSE; | ||||
|  | ||||
|   switch (event->evtype) | ||||
|     { | ||||
|     case XI_BarrierHit: | ||||
|     case XI_BarrierLeave: | ||||
|       break; | ||||
|     default: | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   xev = (XIBarrierEvent *) event; | ||||
|   barrier = g_hash_table_lookup (display->xids, &xev->barrier); | ||||
|   if (barrier != NULL) | ||||
|     { | ||||
|   | ||||
| @@ -17,9 +17,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
| @@ -60,88 +58,6 @@ | ||||
| #include <canberra-gtk.h> | ||||
| #endif | ||||
|  | ||||
| /** | ||||
|  * bell_flash_screen: | ||||
|  * @display:  The display which owns the screen (rather redundant) | ||||
|  * @screen:   The screen to flash | ||||
|  * | ||||
|  * Flashes one entire screen.  This is done by making a window the size of the | ||||
|  * whole screen (or reusing the old one, if it's still around), mapping it, | ||||
|  * painting it white and then black, and then unmapping it. We set saveunder so | ||||
|  * that all the windows behind it come back immediately. | ||||
|  * | ||||
|  * Unlike frame flashes, we don't do fullscreen flashes with a timeout; rather, | ||||
|  * we do them in one go, because we don't have to rely on the theme code | ||||
|  * redrawing the frame for us in order to do the flash. | ||||
|  */ | ||||
| /* | ||||
|  * Bug: The way I read it, this appears not to do the flash | ||||
|  * the first time we flash a particular display. Am I wrong? | ||||
|  * | ||||
|  * Bug: This appears to destroy our current XSync status. | ||||
|  */ | ||||
| static void | ||||
| bell_flash_screen (MetaDisplay *display,  | ||||
| 			MetaScreen  *screen) | ||||
| { | ||||
|   Window root = screen->xroot; | ||||
|   int width = screen->rect.width; | ||||
|   int height = screen->rect.height; | ||||
|    | ||||
|   if (screen->flash_window == None) | ||||
|     { | ||||
|       Visual *visual = (Visual *)CopyFromParent; | ||||
|       XSetWindowAttributes xswa; | ||||
|       int depth = CopyFromParent; | ||||
|       xswa.save_under = True; | ||||
|       xswa.override_redirect = True; | ||||
|       /*  | ||||
|        * TODO: use XGetVisualInfo and determine which is an | ||||
|        * overlay, if one is present, and use the Overlay visual | ||||
|        * for this window (for performance reasons).   | ||||
|        * Not sure how to tell this yet...  | ||||
|        */ | ||||
|       screen->flash_window = XCreateWindow (display->xdisplay, root, | ||||
| 					    0, 0, width, height, | ||||
| 					    0, depth, | ||||
| 					    InputOutput, | ||||
| 					    visual, | ||||
| 				    /* note: XSun doesn't like SaveUnder here */ | ||||
| 					    CWSaveUnder | CWOverrideRedirect, | ||||
| 					    &xswa); | ||||
|       XSelectInput (display->xdisplay, screen->flash_window, ExposureMask); | ||||
|       XMapWindow (display->xdisplay, screen->flash_window); | ||||
|       XSync (display->xdisplay, False); | ||||
|       XFlush (display->xdisplay); | ||||
|       XUnmapWindow (display->xdisplay, screen->flash_window); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       /* just draw something in the window */ | ||||
|       GC gc = XCreateGC (display->xdisplay, screen->flash_window, 0, NULL); | ||||
|       XMapWindow (display->xdisplay, screen->flash_window); | ||||
|       XSetForeground (display->xdisplay, gc, | ||||
| 		      WhitePixel (display->xdisplay,  | ||||
| 				  XScreenNumberOfScreen (screen->xscreen))); | ||||
|       XFillRectangle (display->xdisplay, screen->flash_window, gc, | ||||
| 		      0, 0, width, height); | ||||
|       XSetForeground (display->xdisplay, gc, | ||||
| 		      BlackPixel (display->xdisplay,  | ||||
| 				  XScreenNumberOfScreen (screen->xscreen))); | ||||
|       XFillRectangle (display->xdisplay, screen->flash_window, gc, | ||||
| 		      0, 0, width, height); | ||||
|       XFlush (display->xdisplay); | ||||
|       XSync (display->xdisplay, False); | ||||
|       XUnmapWindow (display->xdisplay, screen->flash_window); | ||||
|       XFreeGC (display->xdisplay, gc); | ||||
|     } | ||||
|  | ||||
|   if (meta_prefs_get_focus_mode () != G_DESKTOP_FOCUS_MODE_CLICK && | ||||
|       !display->mouse_mode) | ||||
|     meta_display_increment_focus_sentinel (display); | ||||
|   XFlush (display->xdisplay); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * bell_flash_fullscreen: | ||||
|  * @display: The display the event came in on | ||||
| @@ -166,12 +82,7 @@ bell_flash_fullscreen (MetaDisplay *display, | ||||
|     { | ||||
|       screen = meta_display_screen_for_xwindow (display, xkb_bell_ev->window); | ||||
|       if (screen) | ||||
|         { | ||||
|           if (display->compositor) | ||||
|             meta_compositor_flash_screen (display->compositor, screen); | ||||
|           else | ||||
|             bell_flash_screen (display, screen); | ||||
|         } | ||||
|         meta_compositor_flash_screen (display->compositor, screen); | ||||
|     } | ||||
|   else  | ||||
|     { | ||||
| @@ -179,10 +90,7 @@ bell_flash_fullscreen (MetaDisplay *display, | ||||
|       while (screen_list)  | ||||
| 	{ | ||||
| 	  screen = (MetaScreen *) screen_list->data; | ||||
|           if (display->compositor) | ||||
|             meta_compositor_flash_screen (display->compositor, screen); | ||||
|           else | ||||
|             bell_flash_screen (display, screen); | ||||
|           meta_compositor_flash_screen (display->compositor, screen); | ||||
| 	  screen_list = screen_list->next; | ||||
| 	} | ||||
|     } | ||||
|   | ||||
| @@ -14,9 +14,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include <X11/Xlib.h> | ||||
|   | ||||
| @@ -16,9 +16,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef META_BOXES_PRIVATE_H | ||||
|   | ||||
| @@ -25,9 +25,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include "boxes-private.h" | ||||
|   | ||||
| @@ -18,9 +18,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
| @@ -118,8 +116,6 @@ typedef struct | ||||
| { | ||||
|   MetaRectangle        orig; | ||||
|   MetaRectangle        current; | ||||
|   MetaFrameBorders    *borders; | ||||
|   gboolean             must_free_borders; | ||||
|   ActionType           action_type; | ||||
|   gboolean             is_user_action; | ||||
|  | ||||
| @@ -195,7 +191,6 @@ static gboolean constrain_partially_onscreen (MetaWindow         *window, | ||||
|  | ||||
| static void setup_constraint_info        (ConstraintInfo      *info, | ||||
|                                           MetaWindow          *window, | ||||
|                                           MetaFrameBorders    *orig_borders, | ||||
|                                           MetaMoveResizeFlags  flags, | ||||
|                                           int                  resize_gravity, | ||||
|                                           const MetaRectangle *orig, | ||||
| @@ -204,13 +199,12 @@ static void place_window_if_needed       (MetaWindow     *window, | ||||
|                                           ConstraintInfo *info); | ||||
| static void update_onscreen_requirements (MetaWindow     *window, | ||||
|                                           ConstraintInfo *info); | ||||
| static void extend_by_frame              (MetaRectangle           *rect, | ||||
|                                           const MetaFrameBorders  *borders); | ||||
| static void unextend_by_frame            (MetaRectangle           *rect, | ||||
|                                           const MetaFrameBorders  *borders); | ||||
| static inline void get_size_limits       (const MetaWindow        *window, | ||||
|                                           const MetaFrameBorders  *borders, | ||||
|                                           gboolean include_frame, | ||||
| static void extend_by_frame              (MetaWindow     *window, | ||||
|                                           MetaRectangle  *rect); | ||||
| static void unextend_by_frame            (MetaWindow     *window, | ||||
|                                           MetaRectangle  *rect); | ||||
| static inline void get_size_limits       (MetaWindow    *window, | ||||
|                                           gboolean       include_frame, | ||||
|                                           MetaRectangle *min_size, | ||||
|                                           MetaRectangle *max_size); | ||||
|  | ||||
| @@ -280,7 +274,6 @@ do_all_constraints (MetaWindow         *window, | ||||
|  | ||||
| void | ||||
| meta_window_constrain (MetaWindow          *window, | ||||
|                        MetaFrameBorders    *orig_borders, | ||||
|                        MetaMoveResizeFlags  flags, | ||||
|                        int                  resize_gravity, | ||||
|                        const MetaRectangle *orig, | ||||
| @@ -303,7 +296,6 @@ meta_window_constrain (MetaWindow          *window, | ||||
|  | ||||
|   setup_constraint_info (&info, | ||||
|                          window,  | ||||
|                          orig_borders, | ||||
|                          flags, | ||||
|                          resize_gravity, | ||||
|                          orig, | ||||
| @@ -333,19 +325,11 @@ meta_window_constrain (MetaWindow          *window, | ||||
|    * if this was a user move or user move-and-resize operation. | ||||
|    */ | ||||
|   update_onscreen_requirements (window, &info); | ||||
|  | ||||
|   /* Ew, what an ugly way to do things.  Destructors (in a real OOP language, | ||||
|    * not gobject-style--gobject would be more pain than it's worth) or | ||||
|    * smart pointers would be so much nicer here.  *shrug* | ||||
|    */ | ||||
|   if (info.must_free_borders) | ||||
|     g_free (info.borders); | ||||
| } | ||||
|  | ||||
| static void | ||||
| setup_constraint_info (ConstraintInfo      *info, | ||||
|                        MetaWindow          *window, | ||||
|                        MetaFrameBorders    *orig_borders, | ||||
|                        MetaMoveResizeFlags  flags, | ||||
|                        int                  resize_gravity, | ||||
|                        const MetaRectangle *orig, | ||||
| @@ -357,18 +341,6 @@ setup_constraint_info (ConstraintInfo      *info, | ||||
|   info->orig    = *orig; | ||||
|   info->current = *new; | ||||
|  | ||||
|   /* Create a fake frame geometry if none really exists */ | ||||
|   if (orig_borders && !window->fullscreen) | ||||
|     { | ||||
|       info->borders = orig_borders; | ||||
|       info->must_free_borders = FALSE; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       info->borders = g_new0 (MetaFrameBorders, 1); | ||||
|       info->must_free_borders = TRUE; | ||||
|     } | ||||
|  | ||||
|   if (flags & META_IS_MOVE_ACTION && flags & META_IS_RESIZE_ACTION) | ||||
|     info->action_type = ACTION_MOVE_AND_RESIZE; | ||||
|   else if (flags & META_IS_RESIZE_ACTION) | ||||
| @@ -453,8 +425,9 @@ setup_constraint_info (ConstraintInfo      *info, | ||||
|    * the monitor. | ||||
|    */ | ||||
|   if (meta_prefs_get_force_fullscreen() && | ||||
|       window->client_type != META_WINDOW_CLIENT_TYPE_WAYLAND && | ||||
|       !window->hide_titlebar_when_maximized && | ||||
|       window->decorated && | ||||
|       (window->decorated || !meta_window_is_client_decorated (window)) && | ||||
|       meta_rectangle_equal (new, &monitor_info->rect) && | ||||
|       window->has_fullscreen_func && | ||||
|       !window->fullscreen) | ||||
| @@ -519,11 +492,17 @@ place_window_if_needed(MetaWindow     *window, | ||||
|       !window->minimized && | ||||
|       !window->fullscreen) | ||||
|     { | ||||
|       MetaRectangle placed_rect = info->orig; | ||||
|       MetaRectangle orig_rect; | ||||
|       MetaRectangle placed_rect; | ||||
|       MetaWorkspace *cur_workspace; | ||||
|       const MetaMonitorInfo *monitor_info; | ||||
|  | ||||
|       meta_window_place (window, info->borders, info->orig.x, info->orig.y, | ||||
|       meta_window_get_frame_rect (window, &placed_rect); | ||||
|  | ||||
|       orig_rect = info->orig; | ||||
|       extend_by_frame (window, &orig_rect); | ||||
|  | ||||
|       meta_window_place (window, orig_rect.x, orig_rect.y, | ||||
|                          &placed_rect.x, &placed_rect.y); | ||||
|       did_placement = TRUE; | ||||
|  | ||||
| @@ -541,6 +520,7 @@ place_window_if_needed(MetaWindow     *window, | ||||
|         meta_workspace_get_onmonitor_region (cur_workspace,  | ||||
|                                              monitor_info->number); | ||||
|  | ||||
|       meta_window_frame_rect_to_client_rect (window, &placed_rect, &placed_rect); | ||||
|  | ||||
|       info->current.x = placed_rect.x; | ||||
|       info->current.y = placed_rect.y; | ||||
| @@ -586,10 +566,6 @@ place_window_if_needed(MetaWindow     *window, | ||||
|                 (window->maximize_vertically_after_placement ? | ||||
|                  META_MAXIMIZE_VERTICAL : 0), &info->current); | ||||
|  | ||||
|           /* maximization may have changed frame geometry */ | ||||
|           if (!window->fullscreen) | ||||
|             meta_frame_calc_borders (window->frame, info->borders); | ||||
|  | ||||
|           if (window->fullscreen_after_placement) | ||||
|             { | ||||
|               window->saved_rect = info->current; | ||||
| @@ -649,7 +625,7 @@ update_onscreen_requirements (MetaWindow     *window, | ||||
|   /* The require onscreen/on-single-monitor and titlebar_visible | ||||
|    * stuff is relative to the outer window, not the inner | ||||
|    */ | ||||
|   extend_by_frame (&info->current, info->borders); | ||||
|   extend_by_frame (window, &info->current); | ||||
|  | ||||
|   /* Update whether we want future constraint runs to require the | ||||
|    * window to be on fully onscreen. | ||||
| @@ -682,10 +658,13 @@ update_onscreen_requirements (MetaWindow     *window, | ||||
|    */ | ||||
|   if (window->frame && window->decorated) | ||||
|     { | ||||
|       MetaFrameBorders borders; | ||||
|       MetaRectangle titlebar_rect; | ||||
|  | ||||
|       meta_frame_calc_borders (window->frame, &borders); | ||||
|  | ||||
|       titlebar_rect = info->current; | ||||
|       titlebar_rect.height = info->borders->visible.top; | ||||
|       titlebar_rect.height = borders.visible.top; | ||||
|       old = window->require_titlebar_visible; | ||||
|       window->require_titlebar_visible = | ||||
|         meta_rectangle_overlaps_with_region (info->usable_screen_region, | ||||
| @@ -698,39 +677,33 @@ update_onscreen_requirements (MetaWindow     *window, | ||||
|     } | ||||
|  | ||||
|   /* Don't forget to restore the position of the window */ | ||||
|   unextend_by_frame (&info->current, info->borders); | ||||
|   unextend_by_frame (window, &info->current); | ||||
| } | ||||
|  | ||||
| static void | ||||
| extend_by_frame (MetaRectangle           *rect, | ||||
|                  const MetaFrameBorders *borders) | ||||
| extend_by_frame (MetaWindow    *window, | ||||
|                  MetaRectangle *rect) | ||||
| { | ||||
|   rect->x -= borders->visible.left; | ||||
|   rect->y -= borders->visible.top; | ||||
|   rect->width  += borders->visible.left + borders->visible.right; | ||||
|   rect->height += borders->visible.top + borders->visible.bottom; | ||||
|   meta_window_client_rect_to_frame_rect (window, rect, rect); | ||||
| } | ||||
|  | ||||
| static void | ||||
| unextend_by_frame (MetaRectangle           *rect, | ||||
|                    const MetaFrameBorders *borders) | ||||
| unextend_by_frame (MetaWindow    *window, | ||||
|                    MetaRectangle *rect) | ||||
| { | ||||
|   rect->x += borders->visible.left; | ||||
|   rect->y += borders->visible.top; | ||||
|   rect->width  -= borders->visible.left + borders->visible.right; | ||||
|   rect->height -= borders->visible.top + borders->visible.bottom; | ||||
|   meta_window_frame_rect_to_client_rect (window, rect, rect); | ||||
| } | ||||
|  | ||||
| static inline void | ||||
| get_size_limits (const MetaWindow        *window, | ||||
|                  const MetaFrameBorders *borders, | ||||
|                  gboolean                 include_frame, | ||||
| get_size_limits (MetaWindow    *window, | ||||
|                  gboolean       include_frame, | ||||
|                  MetaRectangle *min_size, | ||||
|                  MetaRectangle *max_size) | ||||
| { | ||||
|   /* We pack the results into MetaRectangle structs just for convienience; we | ||||
|    * don't actually use the position of those rects. | ||||
|    */ | ||||
|   min_size->x = min_size->y = max_size->x = max_size->y = 0; | ||||
|   min_size->width  = window->size_hints.min_width; | ||||
|   min_size->height = window->size_hints.min_height; | ||||
|   max_size->width  = window->size_hints.max_width; | ||||
| @@ -738,22 +711,8 @@ get_size_limits (const MetaWindow        *window, | ||||
|  | ||||
|   if (include_frame) | ||||
|     { | ||||
|       int fw = borders->visible.left + borders->visible.right; | ||||
|       int fh = borders->visible.top + borders->visible.bottom; | ||||
|  | ||||
|       min_size->width  += fw; | ||||
|       min_size->height += fh; | ||||
|       /* Do check to avoid overflow (e.g. max_size->width & max_size->height | ||||
|        * may be set to G_MAXINT by meta_set_normal_hints()). | ||||
|        */ | ||||
|       if (max_size->width < (G_MAXINT - fw)) | ||||
|         max_size->width += fw; | ||||
|       else | ||||
|         max_size->width = G_MAXINT; | ||||
|       if (max_size->height < (G_MAXINT - fh)) | ||||
|         max_size->height += fh; | ||||
|       else | ||||
|         max_size->height = G_MAXINT; | ||||
|       meta_window_client_rect_to_frame_rect (window, min_size, min_size); | ||||
|       meta_window_client_rect_to_frame_rect (window, max_size, max_size); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -765,18 +724,28 @@ constrain_modal_dialog (MetaWindow         *window, | ||||
| { | ||||
|   int x, y; | ||||
|   MetaWindow *parent = meta_window_get_transient_for (window); | ||||
|   MetaRectangle child_rect, parent_rect; | ||||
|   gboolean constraint_already_satisfied; | ||||
|  | ||||
|   if (!meta_window_is_attached_dialog (window)) | ||||
|     return TRUE; | ||||
|  | ||||
|   x = parent->rect.x + (parent->rect.width / 2  - info->current.width / 2); | ||||
|   y = parent->rect.y + (parent->rect.height / 2 - info->current.height / 2); | ||||
|   if (parent->frame) | ||||
|     { | ||||
|       x += parent->frame->rect.x; | ||||
|       y += parent->frame->rect.y; | ||||
|     } | ||||
|   /* We want to center the dialog on the parent, including the decorations | ||||
|      for both of them. info->current is in client X window coordinates, so we need | ||||
|      to convert them to frame coordinates, apply the centering and then | ||||
|      convert back to client. | ||||
|   */ | ||||
|  | ||||
|   child_rect = info->current; | ||||
|   extend_by_frame (window, &child_rect); | ||||
|  | ||||
|   meta_window_get_frame_rect (parent, &parent_rect); | ||||
|  | ||||
|   child_rect.x = parent_rect.x + (parent_rect.width / 2  - child_rect.width / 2); | ||||
|   child_rect.y = parent_rect.y + (parent_rect.height / 2 - child_rect.height / 2); | ||||
|   unextend_by_frame (window, &child_rect); | ||||
|   x = child_rect.x; | ||||
|   y = child_rect.y; | ||||
|  | ||||
|   constraint_already_satisfied = (x == info->current.x) && (y == info->current.y); | ||||
|  | ||||
| @@ -841,19 +810,19 @@ constrain_maximization (MetaWindow         *window, | ||||
|       active_workspace_struts = window->screen->active_workspace->all_struts; | ||||
|  | ||||
|       target_size = info->current; | ||||
|       extend_by_frame (&target_size, info->borders); | ||||
|       extend_by_frame (window, &target_size); | ||||
|       meta_rectangle_expand_to_avoiding_struts (&target_size, | ||||
|                                                 &info->entire_monitor, | ||||
|                                                 direction, | ||||
|                                                 active_workspace_struts); | ||||
|    } | ||||
|   /* Now make target_size = maximized size of client window */ | ||||
|   unextend_by_frame (&target_size, info->borders); | ||||
|   unextend_by_frame (window, &target_size); | ||||
|  | ||||
|   /* Check min size constraints; max size constraints are ignored for maximized | ||||
|    * windows, as per bug 327543. | ||||
|    */ | ||||
|   get_size_limits (window, info->borders, FALSE, &min_size, &max_size); | ||||
|   get_size_limits (window, FALSE, &min_size, &max_size); | ||||
|   hminbad = target_size.width < min_size.width && window->maximized_horizontally; | ||||
|   vminbad = target_size.height < min_size.height && window->maximized_vertically; | ||||
|   if (hminbad || vminbad) | ||||
| @@ -907,12 +876,12 @@ constrain_tiling (MetaWindow         *window, | ||||
|    * use an external function for the actual calculation | ||||
|    */ | ||||
|   meta_window_get_current_tile_area (window, &target_size); | ||||
|   unextend_by_frame (&target_size, info->borders); | ||||
|   unextend_by_frame (window, &target_size); | ||||
|  | ||||
|   /* Check min size constraints; max size constraints are ignored as for | ||||
|    * maximized windows. | ||||
|    */ | ||||
|   get_size_limits (window, info->borders, FALSE, &min_size, &max_size); | ||||
|   get_size_limits (window, FALSE, &min_size, &max_size); | ||||
|   hminbad = target_size.width < min_size.width; | ||||
|   vminbad = target_size.height < min_size.height; | ||||
|   if (hminbad || vminbad) | ||||
| @@ -955,7 +924,7 @@ constrain_fullscreen (MetaWindow         *window, | ||||
|  | ||||
|   monitor = info->entire_monitor; | ||||
|  | ||||
|   get_size_limits (window, info->borders, FALSE, &min_size, &max_size); | ||||
|   get_size_limits (window, FALSE, &min_size, &max_size); | ||||
|   too_big =   !meta_rectangle_could_fit_rect (&monitor, &min_size); | ||||
|   too_small = !meta_rectangle_could_fit_rect (&max_size, &monitor); | ||||
|   if (too_big || too_small) | ||||
| @@ -1064,7 +1033,7 @@ constrain_size_limits (MetaWindow         *window, | ||||
|     return TRUE; | ||||
|  | ||||
|   /* Determine whether constraint is already satisfied; exit if it is */ | ||||
|   get_size_limits (window, info->borders, FALSE, &min_size, &max_size); | ||||
|   get_size_limits (window, FALSE, &min_size, &max_size); | ||||
|   /* We ignore max-size limits for maximized windows; see #327543 */ | ||||
|   if (window->maximized_horizontally) | ||||
|     max_size.width = MAX (max_size.width, info->current.width); | ||||
| @@ -1256,8 +1225,8 @@ do_screen_and_monitor_relative_constraints ( | ||||
|  | ||||
|   /* Determine whether constraint applies; exit if it doesn't */ | ||||
|   how_far_it_can_be_smushed = info->current; | ||||
|   get_size_limits (window, info->borders, TRUE, &min_size, &max_size); | ||||
|   extend_by_frame (&info->current, info->borders); | ||||
|   get_size_limits (window, TRUE, &min_size, &max_size); | ||||
|   extend_by_frame (window, &info->current); | ||||
|  | ||||
|   if (info->action_type != ACTION_MOVE) | ||||
|     { | ||||
| @@ -1277,7 +1246,7 @@ do_screen_and_monitor_relative_constraints ( | ||||
|                                         &info->current); | ||||
|   if (exit_early || constraint_satisfied || check_only) | ||||
|     { | ||||
|       unextend_by_frame (&info->current, info->borders); | ||||
|       unextend_by_frame (window, &info->current); | ||||
|       return constraint_satisfied; | ||||
|     } | ||||
|  | ||||
| @@ -1301,7 +1270,7 @@ do_screen_and_monitor_relative_constraints ( | ||||
|                                       info->fixed_directions, | ||||
|                                       &info->current); | ||||
|  | ||||
|   unextend_by_frame (&info->current, info->borders); | ||||
|   unextend_by_frame (window, &info->current); | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| @@ -1390,7 +1359,6 @@ constrain_titlebar_visible (MetaWindow         *window, | ||||
|       window->type == META_WINDOW_DOCK    || | ||||
|       window->fullscreen                  || | ||||
|       !window->require_titlebar_visible   || | ||||
|       !window->decorated                  || | ||||
|       unconstrained_user_action) | ||||
|     return TRUE; | ||||
|  | ||||
| @@ -1414,8 +1382,11 @@ constrain_titlebar_visible (MetaWindow         *window, | ||||
|    */ | ||||
|   if (window->frame) | ||||
|     { | ||||
|       bottom_amount = info->current.height + info->borders->visible.bottom; | ||||
|       vert_amount_onscreen = info->borders->visible.top; | ||||
|       MetaFrameBorders borders; | ||||
|       meta_frame_calc_borders (window->frame, &borders); | ||||
|  | ||||
|       bottom_amount = info->current.height + borders.visible.bottom; | ||||
|       vert_amount_onscreen = borders.visible.top; | ||||
|     } | ||||
|   else | ||||
|     bottom_amount = vert_amount_offscreen; | ||||
| @@ -1489,8 +1460,11 @@ constrain_partially_onscreen (MetaWindow         *window, | ||||
|    */ | ||||
|   if (window->frame) | ||||
|     { | ||||
|       bottom_amount = info->current.height + info->borders->visible.bottom; | ||||
|       vert_amount_onscreen = info->borders->visible.top; | ||||
|       MetaFrameBorders borders; | ||||
|       meta_frame_calc_borders (window->frame, &borders); | ||||
|  | ||||
|       bottom_amount = info->current.height + borders.visible.bottom; | ||||
|       vert_amount_onscreen = borders.visible.top; | ||||
|     } | ||||
|   else | ||||
|     bottom_amount = vert_amount_offscreen; | ||||
|   | ||||
| @@ -17,9 +17,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef META_CONSTRAINTS_H | ||||
| @@ -40,7 +38,6 @@ typedef enum | ||||
| } MetaMoveResizeFlags; | ||||
|  | ||||
| void meta_window_constrain (MetaWindow          *window, | ||||
|                             MetaFrameBorders    *orig_borders, | ||||
|                             MetaMoveResizeFlags  flags, | ||||
|                             int                  resize_gravity, | ||||
|                             const MetaRectangle *orig, | ||||
|   | ||||
| @@ -18,9 +18,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
| @@ -172,6 +170,7 @@ meta_core_queue_frame_resize (Display *xdisplay, | ||||
|   MetaWindow *window = get_window (xdisplay, frame_xwindow); | ||||
|  | ||||
|   meta_window_queue (window, META_QUEUE_MOVE_RESIZE); | ||||
|   meta_window_frame_size_changed (window); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -282,8 +281,7 @@ meta_core_lower_beneath_grab_window (Display *xdisplay, | ||||
|     return; | ||||
|  | ||||
|   changes.stack_mode = Below; | ||||
|   changes.sibling = grab_window->frame ? grab_window->frame->xwindow | ||||
|                                        : grab_window->xwindow; | ||||
|   changes.sibling = meta_window_get_toplevel_xwindow (grab_window); | ||||
|  | ||||
|   stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11; | ||||
|   stack_window.x11.xwindow = xwindow; | ||||
| @@ -330,8 +328,7 @@ meta_core_maximize (Display *xdisplay, | ||||
|   if (meta_prefs_get_raise_on_click ()) | ||||
|     meta_window_raise (window); | ||||
|  | ||||
|   meta_window_maximize (window,  | ||||
|                         META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL); | ||||
|   meta_window_maximize (window, META_MAXIMIZE_BOTH); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -344,11 +341,9 @@ meta_core_toggle_maximize_vertically (Display *xdisplay, | ||||
|     meta_window_raise (window); | ||||
|  | ||||
|   if (META_WINDOW_MAXIMIZED_VERTICALLY (window)) | ||||
|     meta_window_unmaximize (window,  | ||||
|                             META_MAXIMIZE_VERTICAL); | ||||
|     meta_window_unmaximize (window, META_MAXIMIZE_VERTICAL); | ||||
|   else | ||||
|     meta_window_maximize (window, | ||||
|     			    META_MAXIMIZE_VERTICAL); | ||||
|     meta_window_maximize (window, META_MAXIMIZE_VERTICAL); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -361,11 +356,9 @@ meta_core_toggle_maximize_horizontally (Display *xdisplay, | ||||
|     meta_window_raise (window); | ||||
|  | ||||
|   if (META_WINDOW_MAXIMIZED_HORIZONTALLY (window)) | ||||
|     meta_window_unmaximize (window,  | ||||
|                             META_MAXIMIZE_HORIZONTAL); | ||||
|     meta_window_unmaximize (window, META_MAXIMIZE_HORIZONTAL); | ||||
|   else | ||||
|     meta_window_maximize (window, | ||||
|     			    META_MAXIMIZE_HORIZONTAL); | ||||
|     meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -378,11 +371,9 @@ meta_core_toggle_maximize (Display *xdisplay, | ||||
|     meta_window_raise (window); | ||||
|  | ||||
|   if (META_WINDOW_MAXIMIZED (window)) | ||||
|     meta_window_unmaximize (window,  | ||||
|                             META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL); | ||||
|     meta_window_unmaximize (window, META_MAXIMIZE_BOTH); | ||||
|   else | ||||
|     meta_window_maximize (window, | ||||
|                           META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL); | ||||
|     meta_window_maximize (window, META_MAXIMIZE_BOTH); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -394,8 +385,7 @@ meta_core_unmaximize (Display *xdisplay, | ||||
|   if (meta_prefs_get_raise_on_click ()) | ||||
|     meta_window_raise (window); | ||||
|  | ||||
|   meta_window_unmaximize (window, | ||||
|                           META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL); | ||||
|   meta_window_unmaximize (window, META_MAXIMIZE_BOTH); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -728,16 +718,6 @@ meta_core_set_screen_cursor (Display *xdisplay, | ||||
|   meta_frame_set_screen_cursor (window->frame, cursor); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_core_increment_event_serial (Display *xdisplay) | ||||
| { | ||||
|   MetaDisplay *display; | ||||
|    | ||||
|   display = meta_display_for_x_display (xdisplay); | ||||
|  | ||||
|   meta_display_increment_event_serial (display); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_invalidate_default_icons (void) | ||||
| { | ||||
|   | ||||
| @@ -17,9 +17,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef META_CORE_H | ||||
| @@ -195,12 +193,6 @@ void       meta_core_set_screen_cursor (Display *xdisplay, | ||||
|                                         Window   frame_on_screen, | ||||
|                                         MetaCursor cursor); | ||||
|  | ||||
| /* Used because we ignore EnterNotify when a window is unmapped that | ||||
|  * really shouldn't cause focus changes, by comparing the event serial | ||||
|  * of the EnterNotify and the UnmapNotify. | ||||
|  */ | ||||
| void meta_core_increment_event_serial (Display *display); | ||||
|  | ||||
| void meta_invalidate_default_icons (void); | ||||
|  | ||||
| void meta_core_add_old_event_mask (Display     *xdisplay, | ||||
|   | ||||
| @@ -17,9 +17,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #define _XOPEN_SOURCE /* for kill() */ | ||||
| @@ -39,18 +37,17 @@ | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| #include "wayland/meta-wayland-surface.h" | ||||
|  | ||||
| static void meta_window_present_delete_dialog (MetaWindow *window, | ||||
|                                                guint32     timestamp); | ||||
|  | ||||
| static void | ||||
| delete_ping_reply_func (MetaDisplay *display, | ||||
|                         Window       xwindow, | ||||
| delete_ping_reply_func (MetaWindow  *window, | ||||
|                         guint32      timestamp, | ||||
|                         void        *user_data) | ||||
| { | ||||
|   meta_topic (META_DEBUG_PING, | ||||
|               "Got reply to delete ping for %s\n", | ||||
|               ((MetaWindow*)user_data)->desc); | ||||
|   meta_topic (META_DEBUG_PING, "Got reply to delete ping for %s\n", window->desc); | ||||
|  | ||||
|   /* we do nothing */ | ||||
| } | ||||
| @@ -68,12 +65,10 @@ dialog_exited (GPid pid, int status, gpointer user_data) | ||||
| } | ||||
|  | ||||
| static void | ||||
| delete_ping_timeout_func (MetaDisplay *display, | ||||
|                           Window       xwindow, | ||||
| delete_ping_timeout_func (MetaWindow  *window, | ||||
|                           guint32      timestamp, | ||||
|                           void        *user_data) | ||||
| { | ||||
|   MetaWindow *window = user_data; | ||||
|   char *window_title; | ||||
|   gchar *window_content, *tmp; | ||||
|   GPid dialog_pid; | ||||
| @@ -137,36 +132,42 @@ void | ||||
| meta_window_check_alive (MetaWindow *window, | ||||
|                          guint32     timestamp) | ||||
| { | ||||
|   meta_display_ping_window (window->display, | ||||
|                             window, | ||||
|   meta_display_ping_window (window, | ||||
|                             timestamp, | ||||
|                             delete_ping_reply_func, | ||||
|                             delete_ping_timeout_func, | ||||
|                             window); | ||||
|                             NULL); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_window_delete (MetaWindow  *window, | ||||
|                     guint32      timestamp) | ||||
| { | ||||
|   meta_error_trap_push (window->display); | ||||
|   if (window->delete_window) | ||||
|   if (window->client_type == META_WINDOW_CLIENT_TYPE_X11) | ||||
|     { | ||||
|       meta_topic (META_DEBUG_WINDOW_OPS, | ||||
|                   "Deleting %s with delete_window request\n", | ||||
|                   window->desc); | ||||
|       meta_window_send_icccm_message (window, | ||||
|                                       window->display->atom_WM_DELETE_WINDOW, | ||||
|                                       timestamp); | ||||
|       meta_error_trap_push (window->display); | ||||
|       if (window->delete_window) | ||||
|         { | ||||
|           meta_topic (META_DEBUG_WINDOW_OPS, | ||||
|                       "Deleting %s with delete_window request\n", | ||||
|                       window->desc); | ||||
|           meta_window_send_icccm_message (window, | ||||
|                                           window->display->atom_WM_DELETE_WINDOW, | ||||
|                                           timestamp); | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           meta_topic (META_DEBUG_WINDOW_OPS, | ||||
|                       "Deleting %s with explicit kill\n", | ||||
|                       window->desc); | ||||
|           XKillClient (window->display->xdisplay, window->xwindow); | ||||
|         } | ||||
|       meta_error_trap_pop (window->display); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       meta_topic (META_DEBUG_WINDOW_OPS, | ||||
|                   "Deleting %s with explicit kill\n", | ||||
|                   window->desc); | ||||
|       XKillClient (window->display->xdisplay, window->xwindow); | ||||
|       meta_wayland_surface_delete (window->surface); | ||||
|     } | ||||
|   meta_error_trap_pop (window->display); | ||||
|  | ||||
|   meta_window_check_alive (window, timestamp); | ||||
|  | ||||
| @@ -260,8 +261,7 @@ meta_window_present_delete_dialog (MetaWindow *window, guint32 timestamp) | ||||
|         { | ||||
|           MetaWindow *w = tmp->data; | ||||
|  | ||||
|           if (w->xtransient_for == window->xwindow && | ||||
|               w->res_class && | ||||
|           if (w->transient_for == window && w->res_class && | ||||
|               g_ascii_strcasecmp (w->res_class, "mutter-dialog") == 0) | ||||
|             { | ||||
|               meta_window_activate (w, timestamp); | ||||
|   | ||||
| @@ -19,9 +19,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef META_DISPLAY_PRIVATE_H | ||||
| @@ -39,6 +37,7 @@ | ||||
| #include "keybindings-private.h" | ||||
| #include <meta/prefs.h> | ||||
| #include <meta/barrier.h> | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #ifdef HAVE_STARTUP_NOTIFICATION | ||||
| #include <libsn/sn.h> | ||||
| @@ -56,10 +55,9 @@ typedef struct _MetaWindowPropHooks MetaWindowPropHooks; | ||||
|  | ||||
| typedef struct MetaEdgeResistanceData MetaEdgeResistanceData; | ||||
|  | ||||
| typedef void (* MetaWindowPingFunc) (MetaDisplay *display, | ||||
| 				     Window       xwindow, | ||||
| 				     guint32      timestamp, | ||||
| 				     gpointer     user_data); | ||||
| typedef void (* MetaWindowPingFunc) (MetaWindow  *window, | ||||
|                                      guint32      timestamp, | ||||
|                                      gpointer     user_data); | ||||
|  | ||||
| typedef enum { | ||||
|   META_LIST_DEFAULT                   = 0,      /* normal windows */ | ||||
| @@ -86,14 +84,6 @@ typedef enum { | ||||
|   META_TILE_MAXIMIZED | ||||
| } MetaTileMode; | ||||
|  | ||||
| typedef enum { | ||||
|   META_FOCUS_NONE = 0, | ||||
|   META_FOCUS_X_CLIENT = 1, | ||||
|   META_FOCUS_WAYLAND_CLIENT = 2, | ||||
|   META_FOCUS_NO_FOCUS_WINDOW = 3, | ||||
|   META_FOCUS_STAGE = 4 | ||||
| } MetaFocusType; | ||||
|  | ||||
| struct _MetaDisplay | ||||
| { | ||||
|   GObject parent_instance; | ||||
| @@ -101,6 +91,8 @@ struct _MetaDisplay | ||||
|   char *name; | ||||
|   Display *xdisplay; | ||||
|  | ||||
|   int clutter_event_filter; | ||||
|  | ||||
|   Window leader_window; | ||||
|   Window timestamp_pinging_window; | ||||
|  | ||||
| @@ -125,7 +117,6 @@ struct _MetaDisplay | ||||
|    * like the no_focus_window or the stage X window. */ | ||||
|   Window focus_xwindow; | ||||
|   gulong focus_serial; | ||||
|   MetaFocusType focus_type; | ||||
|  | ||||
|   /* last timestamp passed to XSetInputFocus */ | ||||
|   guint32 last_focus_time; | ||||
| @@ -147,6 +138,14 @@ struct _MetaDisplay | ||||
|    */ | ||||
|   guint allow_terminal_deactivation : 1; | ||||
|  | ||||
|   /* If true, server->focus_serial refers to us changing the focus; in | ||||
|    * this case, we can ignore focus events that have exactly focus_serial, | ||||
|    * since we take care to make another request immediately afterwards. | ||||
|    * But if focus is being changed by another client, we have to accept | ||||
|    * multiple events with the same serial. | ||||
|    */ | ||||
|   guint focused_by_us : 1; | ||||
|  | ||||
|   guint static_gravity_works : 1; | ||||
|    | ||||
|   /*< private-ish >*/ | ||||
| @@ -189,7 +188,7 @@ struct _MetaDisplay | ||||
|   MetaWindow* autoraise_window; | ||||
|  | ||||
|   /* Alt+click button grabs */ | ||||
|   unsigned int window_grab_modifiers; | ||||
|   ClutterModifierType window_grab_modifiers; | ||||
|    | ||||
|   /* current window operation */ | ||||
|   MetaGrabOp  grab_op; | ||||
| @@ -216,7 +215,6 @@ struct _MetaDisplay | ||||
|   gboolean    grab_threshold_movement_reached; /* raise_on_click == FALSE.    */ | ||||
|   MetaResizePopup *grab_resize_popup; | ||||
|   GTimeVal    grab_last_moveresize_time; | ||||
|   guint32     grab_motion_notify_time; | ||||
|   GList*      grab_old_window_stacking; | ||||
|   MetaEdgeResistanceData *grab_edge_resistance_data; | ||||
|   unsigned int grab_last_user_action_was_snap; | ||||
| @@ -234,8 +232,8 @@ struct _MetaDisplay | ||||
|   int	      grab_resize_timeout_id; | ||||
|  | ||||
|   /* Keybindings stuff */ | ||||
|   MetaKeyBinding *key_bindings; | ||||
|   int             n_key_bindings; | ||||
|   GHashTable     *key_bindings; | ||||
|   GHashTable     *key_bindings_index; | ||||
|   int             min_keycode; | ||||
|   int             max_keycode; | ||||
|   KeySym *keymap; | ||||
| @@ -445,14 +443,13 @@ void meta_display_retheme_all (void); | ||||
| void meta_display_set_cursor_theme (const char *theme,  | ||||
| 				    int         size); | ||||
|  | ||||
| void meta_display_ping_window      (MetaDisplay        *display, | ||||
|                                     MetaWindow         *window, | ||||
| void meta_display_ping_window      (MetaWindow         *window, | ||||
|                                     guint32             timestamp, | ||||
|                                     MetaWindowPingFunc  ping_reply_func, | ||||
|                                     MetaWindowPingFunc  ping_timeout_func, | ||||
|                                     void               *user_data); | ||||
| gboolean meta_display_window_has_pending_pings (MetaDisplay        *display, | ||||
| 						MetaWindow         *window); | ||||
| void meta_display_pong_for_serial  (MetaDisplay        *display, | ||||
|                                     guint32             serial); | ||||
|  | ||||
| int meta_resize_gravity_from_grab_op (MetaGrabOp op); | ||||
|  | ||||
| @@ -473,27 +470,22 @@ void meta_display_queue_autoraise_callback  (MetaDisplay *display, | ||||
| void meta_display_remove_autoraise_callback (MetaDisplay *display); | ||||
|  | ||||
| void meta_display_overlay_key_activate (MetaDisplay *display); | ||||
| void meta_display_accelerator_activate (MetaDisplay *display, | ||||
|                                         guint        action, | ||||
|                                         guint        deviceid, | ||||
|                                         guint        timestamp); | ||||
| void meta_display_accelerator_activate (MetaDisplay     *display, | ||||
|                                         guint            action, | ||||
|                                         ClutterKeyEvent *event); | ||||
| gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display); | ||||
|  | ||||
| /* In above-tab-keycode.c */ | ||||
| guint meta_display_get_above_tab_keycode (MetaDisplay *display); | ||||
|  | ||||
| gboolean meta_display_handle_event (MetaDisplay *display, | ||||
|                                     XEvent      *event); | ||||
|  | ||||
| #ifdef HAVE_XI23 | ||||
| gboolean meta_display_process_barrier_event (MetaDisplay    *display, | ||||
|                                              XIBarrierEvent *event); | ||||
| gboolean meta_display_process_barrier_event (MetaDisplay *display, | ||||
|                                              XIEvent     *event); | ||||
| #endif /* HAVE_XI23 */ | ||||
|  | ||||
| void meta_display_set_input_focus_xwindow (MetaDisplay   *display, | ||||
|                                            MetaScreen    *screen, | ||||
|                                            MetaFocusType  type, | ||||
|                                            Window         window, | ||||
|                                            guint32        timestamp); | ||||
| void meta_display_set_input_focus_xwindow (MetaDisplay *display, | ||||
|                                            MetaScreen  *screen, | ||||
|                                            Window       window, | ||||
|                                            guint32      timestamp); | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										2727
									
								
								src/core/display.c
									
									
									
									
									
								
							
							
						
						
									
										2727
									
								
								src/core/display.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -16,9 +16,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
| @@ -985,7 +983,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display) | ||||
|         { | ||||
|           MetaRectangle *new_rect; | ||||
|           new_rect = g_new (MetaRectangle, 1); | ||||
|           meta_window_get_outer_rect (cur_window, new_rect); | ||||
|           meta_window_get_frame_rect (cur_window, new_rect); | ||||
|           obscuring_windows = g_slist_prepend (obscuring_windows, new_rect); | ||||
|           window_stacking =  | ||||
|             g_slist_prepend (window_stacking, GINT_TO_POINTER (stack_position)); | ||||
| @@ -1010,7 +1008,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display) | ||||
|     { | ||||
|       MetaRectangle  cur_rect; | ||||
|       MetaWindow    *cur_window = cur_window_iter->data; | ||||
|       meta_window_get_outer_rect (cur_window, &cur_rect); | ||||
|       meta_window_get_frame_rect (cur_window, &cur_rect); | ||||
|  | ||||
|       /* Check if we want to use this window's edges for edge | ||||
|        * resistance (note that dock edges are considered screen edges | ||||
| @@ -1151,7 +1149,7 @@ meta_window_edge_resistance_for_move (MetaWindow  *window, | ||||
|   MetaRectangle old_outer, proposed_outer, new_outer; | ||||
|   gboolean is_resize; | ||||
|  | ||||
|   meta_window_get_outer_rect (window, &old_outer); | ||||
|   meta_window_get_frame_rect (window, &old_outer); | ||||
|  | ||||
|   proposed_outer = old_outer; | ||||
|   proposed_outer.x += (*new_x - old_x); | ||||
| @@ -1237,7 +1235,7 @@ meta_window_edge_resistance_for_resize (MetaWindow  *window, | ||||
|   int proposed_outer_width, proposed_outer_height; | ||||
|   gboolean is_resize; | ||||
|  | ||||
|   meta_window_get_outer_rect (window, &old_outer); | ||||
|   meta_window_get_frame_rect (window, &old_outer); | ||||
|   proposed_outer_width  = old_outer.width  + (*new_width  - old_width); | ||||
|   proposed_outer_height = old_outer.height + (*new_height - old_height); | ||||
|   meta_rectangle_resize_with_gravity (&old_outer,  | ||||
|   | ||||
| @@ -16,9 +16,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef META_EDGE_RESISTANCE_H | ||||
|   | ||||
| @@ -15,9 +15,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -18,9 +18,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
| @@ -52,9 +50,6 @@ meta_window_ensure_frame (MetaWindow *window) | ||||
|   if (window->frame) | ||||
|     return; | ||||
|    | ||||
|   /* See comment below for why this is required. */ | ||||
|   meta_display_grab (window->display); | ||||
|    | ||||
|   frame = g_new (MetaFrame, 1); | ||||
|  | ||||
|   frame->window = window; | ||||
| @@ -67,8 +62,8 @@ meta_window_ensure_frame (MetaWindow *window) | ||||
|   frame->right_width = 0; | ||||
|   frame->current_cursor = 0; | ||||
|  | ||||
|   frame->mapped = FALSE; | ||||
|   frame->is_flashing = FALSE; | ||||
|   frame->borders_cached = FALSE; | ||||
|    | ||||
|   meta_verbose ("Framing window %s: visual %s default, depth %d default depth %d\n", | ||||
|                 window->desc, | ||||
| @@ -119,14 +114,6 @@ meta_window_ensure_frame (MetaWindow *window) | ||||
|    | ||||
|   meta_display_register_x_window (window->display, &frame->xwindow, window); | ||||
|  | ||||
|   /* Reparent the client window; it may be destroyed, | ||||
|    * thus the error trap. We'll get a destroy notify later | ||||
|    * and free everything. Comment in FVWM source code says | ||||
|    * we need a server grab or the child can get its MapNotify | ||||
|    * before we've finished reparenting and getting the decoration | ||||
|    * window onscreen, so ensure_frame must be called with | ||||
|    * a grab. | ||||
|    */ | ||||
|   meta_error_trap_push (window->display); | ||||
|   if (window->mapped) | ||||
|     { | ||||
| @@ -170,7 +157,7 @@ meta_window_ensure_frame (MetaWindow *window) | ||||
|   /* Move keybindings to frame instead of window */ | ||||
|   meta_window_grab_keys (window); | ||||
|  | ||||
|   meta_display_ungrab (window->display); | ||||
|   meta_ui_map_frame (frame->window->screen->ui, frame->xwindow); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -334,9 +321,23 @@ meta_frame_calc_borders (MetaFrame        *frame, | ||||
|   if (frame == NULL) | ||||
|     meta_frame_borders_clear (borders); | ||||
|   else | ||||
|     meta_ui_get_frame_borders (frame->window->screen->ui, | ||||
|                                frame->xwindow, | ||||
|                                borders); | ||||
|     { | ||||
|       if (!frame->borders_cached) | ||||
|         { | ||||
|           meta_ui_get_frame_borders (frame->window->screen->ui, | ||||
|                                      frame->xwindow, | ||||
|                                      &frame->cached_borders); | ||||
|           frame->borders_cached = TRUE; | ||||
|         } | ||||
|  | ||||
|       *borders = frame->cached_borders; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_frame_clear_cached_borders (MetaFrame *frame) | ||||
| { | ||||
|   frame->borders_cached = FALSE; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
|   | ||||
| @@ -16,9 +16,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef META_FRAME_PRIVATE_H | ||||
| @@ -41,15 +39,17 @@ struct _MetaFrame | ||||
|    */ | ||||
|   MetaRectangle rect; | ||||
|  | ||||
|   MetaFrameBorders cached_borders; /* valid if borders_cached is set */ | ||||
|  | ||||
|   /* position of client, size of frame */ | ||||
|   int child_x; | ||||
|   int child_y; | ||||
|   int right_width; | ||||
|   int bottom_height; | ||||
|  | ||||
|   guint mapped : 1; | ||||
|   guint need_reapply_frame_shape : 1; | ||||
|   guint is_flashing : 1; /* used by the visual bell flash */ | ||||
|   guint borders_cached : 1; | ||||
| }; | ||||
|  | ||||
| void     meta_window_ensure_frame           (MetaWindow *window); | ||||
| @@ -68,6 +68,8 @@ gboolean meta_frame_sync_to_window (MetaFrame         *frame, | ||||
|                                     gboolean           need_move, | ||||
|                                     gboolean           need_resize); | ||||
|  | ||||
| void meta_frame_clear_cached_borders (MetaFrame *frame); | ||||
|  | ||||
| cairo_region_t *meta_frame_get_frame_bounds (MetaFrame *frame); | ||||
|  | ||||
| void meta_frame_get_mask (MetaFrame *frame, | ||||
|   | ||||
| @@ -21,9 +21,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef META_KEYBINDINGS_PRIVATE_H | ||||
| @@ -32,6 +30,7 @@ | ||||
| #include <gio/gio.h> | ||||
| #include <meta/keybindings.h> | ||||
|  | ||||
| typedef struct _MetaKeyHandler MetaKeyHandler; | ||||
| struct _MetaKeyHandler | ||||
| { | ||||
|   char *name; | ||||
| @@ -49,9 +48,48 @@ struct _MetaKeyBinding | ||||
|   KeyCode keycode; | ||||
|   unsigned int mask; | ||||
|   MetaVirtualModifier modifiers; | ||||
|   gint flags; | ||||
|   MetaKeyHandler *handler; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * MetaKeyCombo: | ||||
|  * @keysym: keysym | ||||
|  * @keycode: keycode | ||||
|  * @modifiers: modifiers | ||||
|  */ | ||||
| typedef struct _MetaKeyCombo MetaKeyCombo; | ||||
| struct _MetaKeyCombo | ||||
| { | ||||
|   unsigned int keysym; | ||||
|   unsigned int keycode; | ||||
|   MetaVirtualModifier modifiers; | ||||
| }; | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|   char *name; | ||||
|   GSettings *settings; | ||||
|  | ||||
|   MetaKeyBindingAction action; | ||||
|  | ||||
|   /* | ||||
|    * A list of MetaKeyCombos. Each of them is bound to | ||||
|    * this keypref. If one has keysym==modifiers==0, it is | ||||
|    * ignored. | ||||
|    */ | ||||
|   GSList *combos; | ||||
|  | ||||
|   /* for keybindings that can have shift or not like Alt+Tab */ | ||||
|   gboolean      add_shift:1; | ||||
|  | ||||
|   /* for keybindings that apply only to a window */ | ||||
|   gboolean      per_window:1; | ||||
|  | ||||
|   /* for keybindings not added with meta_display_add_keybinding() */ | ||||
|   gboolean      builtin:1; | ||||
| } MetaKeyPref; | ||||
|  | ||||
| void     meta_display_init_keys             (MetaDisplay *display); | ||||
| void     meta_display_shutdown_keys         (MetaDisplay *display); | ||||
| void     meta_screen_grab_keys              (MetaScreen  *screen); | ||||
| @@ -66,9 +104,9 @@ gboolean meta_window_grab_all_keys          (MetaWindow  *window, | ||||
|                                              guint32      timestamp); | ||||
| void     meta_window_ungrab_all_keys        (MetaWindow  *window, | ||||
|                                              guint32      timestamp); | ||||
| gboolean meta_display_process_key_event     (MetaDisplay   *display, | ||||
|                                              MetaWindow    *window, | ||||
|                                              XIDeviceEvent *event); | ||||
| gboolean meta_display_process_key_event     (MetaDisplay     *display, | ||||
|                                              MetaWindow      *window, | ||||
|                                              ClutterKeyEvent *event); | ||||
| void     meta_display_process_mapping_event (MetaDisplay *display, | ||||
|                                              XEvent      *event); | ||||
|  | ||||
| @@ -79,9 +117,8 @@ gboolean meta_prefs_add_keybinding          (const char           *name, | ||||
|  | ||||
| gboolean meta_prefs_remove_keybinding       (const char    *name); | ||||
|  | ||||
| GList *meta_prefs_get_keybindings (void); | ||||
| void meta_prefs_get_overlay_binding (MetaKeyCombo *combo); | ||||
| const char *meta_prefs_get_iso_next_group_option (void); | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -17,9 +17,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
| @@ -44,7 +42,7 @@ | ||||
|  */ | ||||
|  | ||||
| #define _GNU_SOURCE | ||||
| #define _SVID_SOURCE /* for putenv() and some signal-related functions */ | ||||
| #define _XOPEN_SOURCE /* for putenv() and some signal-related functions */ | ||||
|  | ||||
| #include <config.h> | ||||
| #include <meta/main.h> | ||||
| @@ -52,10 +50,8 @@ | ||||
| #include "display-private.h" | ||||
| #include <meta/errors.h> | ||||
| #include "ui.h" | ||||
| #include "session.h" | ||||
| #include <meta/prefs.h> | ||||
| #include <meta/compositor.h> | ||||
| #include "meta-wayland-private.h" | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <glib-unix.h> | ||||
| @@ -81,6 +77,10 @@ | ||||
| #include <girepository.h> | ||||
| #endif | ||||
|  | ||||
| #include "x11/session.h" | ||||
|  | ||||
| #include "wayland/meta-wayland.h" | ||||
|  | ||||
| /* | ||||
|  * The exit code we'll return to our parent process when we eventually die. | ||||
|  */ | ||||
| @@ -192,6 +192,7 @@ static gboolean  opt_replace_wm; | ||||
| static gboolean  opt_disable_sm; | ||||
| static gboolean  opt_sync; | ||||
| static gboolean  opt_wayland; | ||||
| static gboolean  opt_display_server; | ||||
|  | ||||
| static GOptionEntry meta_options[] = { | ||||
|   { | ||||
| @@ -235,6 +236,11 @@ static GOptionEntry meta_options[] = { | ||||
|     N_("Run as a wayland compositor"), | ||||
|     NULL | ||||
|   }, | ||||
|   { | ||||
|     "display-server", 0, 0, G_OPTION_ARG_NONE, | ||||
|     &opt_display_server, | ||||
|     N_("Run as a full display server, rather than nested") | ||||
|   }, | ||||
|   {NULL} | ||||
| }; | ||||
|  | ||||
| @@ -256,19 +262,8 @@ meta_get_option_context (void) | ||||
|   bindtextdomain (GETTEXT_PACKAGE, MUTTER_LOCALEDIR); | ||||
|   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); | ||||
|  | ||||
|   /* We must set the windowing backend here, because Clutter creates the backend | ||||
|      object when the first call is made. | ||||
|  | ||||
|      We consider running from mutter-launch equivalent to running from bare metal. | ||||
|   */ | ||||
|   if (getenv ("WESTON_LAUNCHER_SOCK")) | ||||
|     clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL); | ||||
|  | ||||
|   ctx = g_option_context_new (NULL); | ||||
|   g_option_context_add_main_entries (ctx, meta_options, GETTEXT_PACKAGE); | ||||
|   g_option_context_add_group (ctx, clutter_get_option_group_without_init ()); | ||||
|   g_option_context_add_group (ctx, cogl_get_option_group ()); | ||||
|  | ||||
|   return ctx; | ||||
| } | ||||
|  | ||||
| @@ -304,8 +299,12 @@ event_dispatch (GSource    *source, | ||||
|                 gpointer    user_data) | ||||
| { | ||||
|   ClutterEvent *event = clutter_event_get (); | ||||
|  | ||||
|   if (event) | ||||
|     clutter_do_event (event); | ||||
|     { | ||||
|       clutter_do_event (event); | ||||
|       clutter_event_free (event); | ||||
|     } | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
| @@ -343,16 +342,17 @@ meta_clutter_init (void) | ||||
|  * also is %NULL, use the default - :0.0 | ||||
|  */ | ||||
| static void | ||||
| meta_select_display (gchar *display_name) | ||||
| meta_select_display (char *display_arg) | ||||
| { | ||||
|   gchar *envVar = ""; | ||||
|   const char *display_name; | ||||
|  | ||||
|   if (display_arg) | ||||
|     display_name = (const char *) display_arg; | ||||
|   else | ||||
|     display_name = g_getenv ("MUTTER_DISPLAY"); | ||||
|  | ||||
|   if (display_name) | ||||
|     envVar = g_strconcat ("DISPLAY=", display_name, NULL); | ||||
|   else if (g_getenv ("MUTTER_DISPLAY")) | ||||
|     envVar = g_strconcat ("DISPLAY=", | ||||
|       g_getenv ("MUTTER_DISPLAY"), NULL); | ||||
|   /* DO NOT FREE envVar, putenv() sucks */ | ||||
|   putenv (envVar); | ||||
|     g_setenv ("DISPLAY", display_name, TRUE); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -387,7 +387,8 @@ meta_init (void) | ||||
| { | ||||
|   struct sigaction act; | ||||
|   sigset_t empty_mask; | ||||
|    | ||||
|   ClutterSettings *clutter_settings; | ||||
|  | ||||
|   sigemptyset (&empty_mask); | ||||
|   act.sa_handler = SIG_IGN; | ||||
|   act.sa_mask    = empty_mask; | ||||
| @@ -408,6 +409,9 @@ meta_init (void) | ||||
|   if (g_getenv ("MUTTER_DEBUG")) | ||||
|     meta_set_debugging (TRUE); | ||||
|  | ||||
|   if (opt_display_server) | ||||
|     clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL); | ||||
|  | ||||
|   meta_set_is_wayland_compositor (opt_wayland); | ||||
|  | ||||
|   if (g_get_home_dir ()) | ||||
| @@ -439,7 +443,7 @@ meta_init (void) | ||||
|     meta_fatal ("Can't specify both SM save file and SM client id\n"); | ||||
|    | ||||
|   meta_main_loop = g_main_loop_new (NULL, FALSE); | ||||
|    | ||||
|  | ||||
|   meta_ui_init (); | ||||
|  | ||||
|   /* If we are running with wayland then we don't wait until we have | ||||
| @@ -453,6 +457,13 @@ meta_init (void) | ||||
|        */ | ||||
|       meta_clutter_init (); | ||||
|     } | ||||
|  | ||||
|   /* | ||||
|    * XXX: We cannot handle high dpi scaling yet, so fix the scale to 1 | ||||
|    * for now. | ||||
|    */ | ||||
|   clutter_settings = clutter_settings_get_default (); | ||||
|   g_object_set (clutter_settings, "window-scaling-factor", 1, NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -493,6 +504,32 @@ meta_register_with_session (void) | ||||
|   g_free (opt_client_id); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_activate_session: | ||||
|  * | ||||
|  * Tells mutter to activate the session. When mutter is a | ||||
|  * Wayland compositor, this tells logind to switch over to | ||||
|  * the new session. | ||||
|  */ | ||||
| gboolean | ||||
| meta_activate_session (void) | ||||
| { | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     { | ||||
|       MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); | ||||
|       GError *error = NULL; | ||||
|  | ||||
|       if (!meta_wayland_compositor_activate_session (compositor, &error)) | ||||
|         { | ||||
|           g_warning ("Could not activate session: %s\n", error->message); | ||||
|           g_error_free (error); | ||||
|           return FALSE; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_run: (skip) | ||||
|  * | ||||
|   | ||||
| @@ -14,9 +14,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Author: Giovanni Campagna <gcampagn@redhat.com> | ||||
|  */ | ||||
| @@ -31,18 +29,21 @@ | ||||
| gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker, | ||||
| 					    XEvent            *xevent); | ||||
|  | ||||
| void     meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker, | ||||
|                                               MetaCursor         cursor); | ||||
| void     meta_cursor_tracker_revert_root     (MetaCursorTracker *tracker); | ||||
| void     meta_cursor_tracker_set_buffer      (MetaCursorTracker  *tracker, | ||||
|                                               struct wl_resource *buffer, | ||||
|                                               int                 hot_x, | ||||
|                                               int                 hot_y); | ||||
| void     meta_cursor_tracker_set_grab_cursor     (MetaCursorTracker  *tracker, | ||||
|                                                   MetaCursor          cursor); | ||||
| void     meta_cursor_tracker_set_window_cursor   (MetaCursorTracker  *tracker, | ||||
|                                                   struct wl_resource *buffer, | ||||
|                                                   int                 hot_x, | ||||
|                                                   int                 hot_y); | ||||
| void     meta_cursor_tracker_unset_window_cursor (MetaCursorTracker  *tracker); | ||||
| void     meta_cursor_tracker_set_root_cursor     (MetaCursorTracker  *tracker, | ||||
|                                                   MetaCursor          cursor); | ||||
|  | ||||
| void     meta_cursor_tracker_update_position (MetaCursorTracker *tracker, | ||||
| 					      int                new_x, | ||||
| 					      int                new_y); | ||||
| void     meta_cursor_tracker_paint           (MetaCursorTracker *tracker); | ||||
| void     meta_cursor_tracker_queue_redraw    (MetaCursorTracker *tracker, | ||||
| 					      ClutterActor      *stage); | ||||
|  | ||||
| void     meta_cursor_tracker_force_update (MetaCursorTracker *tracker); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -14,9 +14,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Author: Giovanni Campagna <gcampagn@redhat.com> | ||||
|  */ | ||||
| @@ -41,6 +39,7 @@ | ||||
| #include <gbm.h> | ||||
|  | ||||
| #include <gdk/gdk.h> | ||||
| #include <gdk/gdkx.h> | ||||
|  | ||||
| #include <X11/cursorfont.h> | ||||
| #include <X11/extensions/Xfixes.h> | ||||
| @@ -48,9 +47,10 @@ | ||||
|  | ||||
| #include "meta-cursor-tracker-private.h" | ||||
| #include "screen-private.h" | ||||
| #include "meta-wayland-private.h" | ||||
| #include "monitor-private.h" | ||||
|  | ||||
| #include "wayland/meta-wayland-private.h" | ||||
|  | ||||
| #define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_X 7 | ||||
| #define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_Y 4 | ||||
|  | ||||
| @@ -68,11 +68,34 @@ struct _MetaCursorTracker { | ||||
|   MetaScreen *screen; | ||||
|  | ||||
|   gboolean is_showing; | ||||
|   gboolean has_cursor; | ||||
|   gboolean has_hw_cursor; | ||||
|  | ||||
|   MetaCursorReference *sprite; | ||||
|   /* The cursor tracker stores the cursor for the current grab | ||||
|    * operation, the cursor for the window with pointer focus, and | ||||
|    * the cursor for the root window, which contains either the | ||||
|    * default arrow cursor or the 'busy' hourglass if we're launching | ||||
|    * an app. | ||||
|    * | ||||
|    * We choose the first one available -- if there's a grab cursor, | ||||
|    * we choose that cursor, if there's window cursor, we choose that, | ||||
|    * otherwise we choose the root cursor. | ||||
|    * | ||||
|    * The displayed_cursor contains the chosen cursor. | ||||
|    */ | ||||
|   MetaCursorReference *displayed_cursor; | ||||
|  | ||||
|   MetaCursorReference *grab_cursor; | ||||
|  | ||||
|   /* Wayland clients can set a NULL buffer as their cursor  | ||||
|    * explicitly, which means that we shouldn't display anything. | ||||
|    * So, we can't simply store a NULL in window_cursor to | ||||
|    * determine an unset window cursor; we need an extra boolean. | ||||
|    */ | ||||
|   gboolean has_window_cursor; | ||||
|   MetaCursorReference *window_cursor; | ||||
|  | ||||
|   MetaCursorReference *root_cursor; | ||||
|  | ||||
|   MetaCursorReference *default_cursors[META_CURSOR_LAST]; | ||||
|  | ||||
|   int current_x, current_y; | ||||
| @@ -98,12 +121,10 @@ enum { | ||||
|  | ||||
| static guint signals[LAST_SIGNAL]; | ||||
|  | ||||
| static void meta_cursor_tracker_set_sprite (MetaCursorTracker   *tracker, | ||||
|                                             MetaCursorReference *sprite); | ||||
|  | ||||
| static void meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *tracker, | ||||
|                                                         MetaCRTC          *crtc, | ||||
|                                                         gboolean           has_hw_cursor); | ||||
| static void sync_cursor (MetaCursorTracker *tracker); | ||||
|  | ||||
| static MetaCursorReference * | ||||
| meta_cursor_reference_ref (MetaCursorReference *self) | ||||
| @@ -286,7 +307,6 @@ meta_cursor_reference_from_theme (MetaCursorTracker  *tracker, | ||||
|   self->texture = cogl_texture_2d_new_from_data (cogl_context, | ||||
|                                                  width, height, | ||||
|                                                  cogl_format, | ||||
|                                                  COGL_PIXEL_FORMAT_ANY, | ||||
|                                                  rowstride, | ||||
|                                                  (uint8_t*)image->pixels, | ||||
|                                                  NULL); | ||||
| @@ -346,7 +366,7 @@ meta_cursor_reference_from_buffer (MetaCursorTracker  *tracker, | ||||
|   ClutterBackend *backend; | ||||
|   CoglContext *cogl_context; | ||||
|   MetaCursorReference *self; | ||||
|   CoglPixelFormat cogl_format, cogl_internal_format; | ||||
|   CoglPixelFormat cogl_format; | ||||
|   struct wl_shm_buffer *shm_buffer; | ||||
|   uint32_t gbm_format; | ||||
|  | ||||
| @@ -354,7 +374,7 @@ meta_cursor_reference_from_buffer (MetaCursorTracker  *tracker, | ||||
|   self->ref_count = 1; | ||||
|   self->hot_x = hot_x; | ||||
|   self->hot_y = hot_y; | ||||
|   | ||||
|  | ||||
|   backend = clutter_get_default_backend (); | ||||
|   cogl_context = clutter_backend_get_cogl_context (backend); | ||||
|  | ||||
| @@ -370,37 +390,31 @@ meta_cursor_reference_from_buffer (MetaCursorTracker  *tracker, | ||||
| #if G_BYTE_ORDER == G_BIG_ENDIAN | ||||
|           case WL_SHM_FORMAT_ARGB8888: | ||||
|             cogl_format = COGL_PIXEL_FORMAT_ARGB_8888_PRE; | ||||
|             cogl_internal_format = COGL_PIXEL_FORMAT_ANY; | ||||
|             gbm_format = GBM_FORMAT_ARGB8888; | ||||
|             break; | ||||
|           case WL_SHM_FORMAT_XRGB8888: | ||||
|             cogl_format = COGL_PIXEL_FORMAT_ARGB_8888; | ||||
|             cogl_internal_format = COGL_PIXEL_FORMAT_RGB_888; | ||||
|             gbm_format = GBM_FORMAT_XRGB8888; | ||||
|             break; | ||||
| #else | ||||
|           case WL_SHM_FORMAT_ARGB8888: | ||||
|             cogl_format = COGL_PIXEL_FORMAT_BGRA_8888_PRE; | ||||
|             cogl_internal_format = COGL_PIXEL_FORMAT_ANY; | ||||
|             gbm_format = GBM_FORMAT_ARGB8888; | ||||
|             break; | ||||
|           case WL_SHM_FORMAT_XRGB8888: | ||||
|             cogl_format = COGL_PIXEL_FORMAT_BGRA_8888; | ||||
|             cogl_internal_format = COGL_PIXEL_FORMAT_BGR_888; | ||||
|             gbm_format = GBM_FORMAT_XRGB8888; | ||||
|             break; | ||||
| #endif | ||||
|           default: | ||||
|             g_warn_if_reached (); | ||||
|             cogl_format = COGL_PIXEL_FORMAT_ARGB_8888; | ||||
|             cogl_internal_format = COGL_PIXEL_FORMAT_ANY; | ||||
|             gbm_format = GBM_FORMAT_ARGB8888; | ||||
|         } | ||||
|  | ||||
|       self->texture = cogl_texture_2d_new_from_data (cogl_context, | ||||
|                                                      width, height, | ||||
|                                                      cogl_format, | ||||
|                                                      cogl_internal_format, | ||||
|                                                      rowstride, | ||||
|                                                      wl_shm_buffer_get_data (shm_buffer), | ||||
|                                                      NULL); | ||||
| @@ -456,47 +470,10 @@ meta_cursor_reference_from_buffer (MetaCursorTracker  *tracker, | ||||
|  | ||||
|       if (tracker->gbm) | ||||
|         { | ||||
|           cogl_format = cogl_texture_get_format (COGL_TEXTURE (self->texture)); | ||||
|           switch (cogl_format) | ||||
|             { | ||||
| #if G_BYTE_ORDER == G_LITTLE_ENDIAN | ||||
|             case COGL_PIXEL_FORMAT_ARGB_8888_PRE: | ||||
|             case COGL_PIXEL_FORMAT_ARGB_8888: | ||||
|               gbm_format = GBM_FORMAT_BGRA8888; | ||||
|               break; | ||||
|             case COGL_PIXEL_FORMAT_BGRA_8888_PRE: | ||||
|             case COGL_PIXEL_FORMAT_BGRA_8888: | ||||
|               break; | ||||
|             case COGL_PIXEL_FORMAT_RGB_888: | ||||
|               break; | ||||
| #else | ||||
|             case COGL_PIXEL_FORMAT_ARGB_8888_PRE: | ||||
|             case COGL_PIXEL_FORMAT_ARGB_8888: | ||||
|               gbm_format = GBM_FORMAT_ARGB8888; | ||||
|               break; | ||||
|             case COGL_PIXEL_FORMAT_BGRA_8888_PRE: | ||||
|             case COGL_PIXEL_FORMAT_BGRA_8888: | ||||
|               gbm_format = GBM_FORMAT_BGRA8888; | ||||
|               break; | ||||
|             case COGL_PIXEL_FORMAT_RGB_888: | ||||
|               gbm_format = GBM_FORMAT_RGB888; | ||||
|               break; | ||||
| #endif | ||||
|             default: | ||||
|               meta_warning ("Unknown cogl format %d\n", cogl_format); | ||||
|               return self; | ||||
|             } | ||||
|  | ||||
|           if (gbm_device_is_format_supported (tracker->gbm, gbm_format, | ||||
|                                               GBM_BO_USE_CURSOR_64X64)) | ||||
|             { | ||||
|               self->bo = gbm_bo_import (tracker->gbm, GBM_BO_IMPORT_WL_BUFFER, | ||||
|                                         buffer, GBM_BO_USE_CURSOR_64X64); | ||||
|               if (!self->bo) | ||||
|                 meta_warning ("Importing HW cursor from wl_buffer failed\n"); | ||||
|             } | ||||
|           else | ||||
|             meta_warning ("HW cursor for format %d not supported\n", gbm_format); | ||||
|           self->bo = gbm_bo_import (tracker->gbm, GBM_BO_IMPORT_WL_BUFFER, | ||||
|                                     buffer, GBM_BO_USE_CURSOR_64X64); | ||||
|           if (!self->bo) | ||||
|             meta_warning ("Importing HW cursor from wl_buffer failed\n"); | ||||
|         } | ||||
|      } | ||||
|  | ||||
| @@ -520,8 +497,8 @@ meta_cursor_tracker_finalize (GObject *object) | ||||
|   MetaCursorTracker *self = META_CURSOR_TRACKER (object); | ||||
|   int i; | ||||
|  | ||||
|   if (self->sprite) | ||||
|     meta_cursor_reference_unref (self->sprite); | ||||
|   if (self->displayed_cursor) | ||||
|     meta_cursor_reference_unref (self->displayed_cursor); | ||||
|   if (self->root_cursor) | ||||
|     meta_cursor_reference_unref (self->root_cursor); | ||||
|  | ||||
| @@ -594,10 +571,18 @@ make_wayland_cursor_tracker (MetaScreen *screen) | ||||
|  | ||||
|   compositor = meta_wayland_compositor_get_default (); | ||||
|   compositor->seat->cursor_tracker = self; | ||||
|   meta_cursor_tracker_update_position (self, | ||||
|                                        wl_fixed_to_int (compositor->seat->pointer.x), | ||||
|                                        wl_fixed_to_int (compositor->seat->pointer.y)); | ||||
|  | ||||
|   self->drm_fd = compositor->drm_fd; | ||||
|   if (self->drm_fd >= 0) | ||||
|     self->gbm = gbm_create_device (compositor->drm_fd); | ||||
| #if defined(CLUTTER_WINDOWING_EGL) | ||||
|   if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL)) | ||||
|     { | ||||
|       CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (ctx)); | ||||
|       self->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer); | ||||
|       self->gbm = gbm_create_device (self->drm_fd); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|   monitors = meta_monitor_manager_get (); | ||||
|   g_signal_connect_object (monitors, "monitors-changed", | ||||
| @@ -635,17 +620,27 @@ meta_cursor_tracker_get_for_screen (MetaScreen *screen) | ||||
|   if (screen->cursor_tracker) | ||||
|     return screen->cursor_tracker; | ||||
|  | ||||
| #ifdef HAVE_WAYLAND | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     self = make_wayland_cursor_tracker (screen); | ||||
|   else | ||||
| #endif | ||||
|     self = make_x11_cursor_tracker (screen); | ||||
|  | ||||
|   screen->cursor_tracker = self; | ||||
|   return self; | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_window_cursor (MetaCursorTracker   *tracker, | ||||
|                    gboolean             has_cursor, | ||||
|                    MetaCursorReference *cursor) | ||||
| { | ||||
|   g_clear_pointer (&tracker->window_cursor, meta_cursor_reference_unref); | ||||
|   if (cursor) | ||||
|     tracker->window_cursor = meta_cursor_reference_ref (cursor); | ||||
|   tracker->has_window_cursor = has_cursor; | ||||
|   sync_cursor (tracker); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker, | ||||
|                                    XEvent            *xevent) | ||||
| @@ -662,8 +657,7 @@ meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker, | ||||
|   if (notify_event->subtype != XFixesDisplayCursorNotify) | ||||
|     return FALSE; | ||||
|  | ||||
|   g_clear_pointer (&tracker->sprite, meta_cursor_reference_unref); | ||||
|   g_signal_emit (tracker, signals[CURSOR_CHANGED], 0); | ||||
|   set_window_cursor (tracker, FALSE, NULL); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
| @@ -677,7 +671,7 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker) | ||||
|   gboolean free_cursor_data; | ||||
|   CoglContext *ctx; | ||||
|  | ||||
|   if (tracker->sprite) | ||||
|   if (tracker->has_window_cursor) | ||||
|     return; | ||||
|  | ||||
|   cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay); | ||||
| @@ -715,7 +709,6 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker) | ||||
|                                           cursor_image->width, | ||||
|                                           cursor_image->height, | ||||
|                                           CLUTTER_CAIRO_FORMAT_ARGB32, | ||||
|                                           COGL_PIXEL_FORMAT_ANY, | ||||
|                                           cursor_image->width * 4, /* stride */ | ||||
|                                           cursor_data, | ||||
|                                           NULL); | ||||
| @@ -725,9 +718,11 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker) | ||||
|  | ||||
|   if (sprite != NULL) | ||||
|     { | ||||
|       tracker->sprite = meta_cursor_reference_take_texture (sprite); | ||||
|       tracker->sprite->hot_x = cursor_image->xhot; | ||||
|       tracker->sprite->hot_y = cursor_image->yhot; | ||||
|       MetaCursorReference *cursor = meta_cursor_reference_take_texture (sprite); | ||||
|       cursor->hot_x = cursor_image->xhot; | ||||
|       cursor->hot_y = cursor_image->yhot; | ||||
|  | ||||
|       set_window_cursor (tracker, TRUE, cursor); | ||||
|     } | ||||
|   XFree (cursor_image); | ||||
| } | ||||
| @@ -745,8 +740,8 @@ meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker) | ||||
|   if (!meta_is_wayland_compositor ()) | ||||
|     ensure_xfixes_cursor (tracker); | ||||
|  | ||||
|   if (tracker->sprite) | ||||
|     return COGL_TEXTURE (tracker->sprite->texture); | ||||
|   if (tracker->displayed_cursor) | ||||
|     return COGL_TEXTURE (tracker->displayed_cursor->texture); | ||||
|   else | ||||
|     return NULL; | ||||
| } | ||||
| @@ -768,12 +763,13 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker, | ||||
|   if (!meta_is_wayland_compositor ()) | ||||
|     ensure_xfixes_cursor (tracker); | ||||
|  | ||||
|   if (tracker->sprite) | ||||
|   if (tracker->displayed_cursor) | ||||
|     { | ||||
|       MetaCursorReference *displayed_cursor = tracker->displayed_cursor; | ||||
|       if (x) | ||||
|         *x = tracker->sprite->hot_x; | ||||
|         *x = displayed_cursor->hot_x; | ||||
|       if (y) | ||||
|         *y = tracker->sprite->hot_y; | ||||
|         *y = displayed_cursor->hot_y; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
| @@ -788,14 +784,46 @@ static MetaCursorReference * | ||||
| ensure_wayland_cursor (MetaCursorTracker *tracker, | ||||
|                        MetaCursor         cursor) | ||||
| { | ||||
|   if (tracker->default_cursors[cursor]) | ||||
|     return tracker->default_cursors[cursor]; | ||||
|  | ||||
|   tracker->default_cursors[cursor] = meta_cursor_reference_from_theme (tracker, cursor); | ||||
|   if (!tracker->default_cursors[cursor]) | ||||
|     meta_warning ("Failed to load cursor from theme\n"); | ||||
|     { | ||||
|       tracker->default_cursors[cursor] = meta_cursor_reference_from_theme (tracker, cursor); | ||||
|       if (!tracker->default_cursors[cursor]) | ||||
|         meta_warning ("Failed to load cursor from theme\n"); | ||||
|     } | ||||
|  | ||||
|   return tracker->default_cursors[cursor]; | ||||
|   return meta_cursor_reference_ref (tracker->default_cursors[cursor]); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker, | ||||
|                                      MetaCursor         cursor) | ||||
| { | ||||
|   g_clear_pointer (&tracker->grab_cursor, meta_cursor_reference_unref); | ||||
|   if (cursor != META_CURSOR_DEFAULT) | ||||
|     tracker->grab_cursor = ensure_wayland_cursor (tracker, cursor); | ||||
|   sync_cursor (tracker); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_set_window_cursor (MetaCursorTracker  *tracker, | ||||
|                                        struct wl_resource *buffer, | ||||
|                                        int                 hot_x, | ||||
|                                        int                 hot_y) | ||||
| { | ||||
|   MetaCursorReference *cursor; | ||||
|  | ||||
|   if (buffer) | ||||
|     cursor = meta_cursor_reference_from_buffer (tracker, buffer, hot_x, hot_y); | ||||
|   else | ||||
|     cursor = NULL; | ||||
|  | ||||
|   set_window_cursor (tracker, TRUE, cursor); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker) | ||||
| { | ||||
|   set_window_cursor (tracker, FALSE, NULL); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -815,21 +843,12 @@ meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker, | ||||
|   /* Now update the real root cursor */ | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     { | ||||
|       MetaCursorReference *ref; | ||||
|  | ||||
|       ref = ensure_wayland_cursor (tracker, cursor); | ||||
|  | ||||
|       g_clear_pointer (&tracker->root_cursor, meta_cursor_reference_unref); | ||||
|       tracker->root_cursor = meta_cursor_reference_ref (ref); | ||||
|       tracker->root_cursor = ensure_wayland_cursor (tracker, cursor); | ||||
|       sync_cursor (tracker); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_revert_root (MetaCursorTracker *tracker) | ||||
| { | ||||
|   meta_cursor_tracker_set_sprite (tracker, tracker->root_cursor); | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_hw_cursor (MetaCursorTracker *tracker) | ||||
| { | ||||
| @@ -838,7 +857,7 @@ update_hw_cursor (MetaCursorTracker *tracker) | ||||
|   unsigned int i, n_crtcs; | ||||
|   gboolean enabled; | ||||
|  | ||||
|   enabled = tracker->has_cursor && tracker->sprite->bo != NULL; | ||||
|   enabled = tracker->displayed_cursor && tracker->displayed_cursor->bo != NULL; | ||||
|   tracker->has_hw_cursor = enabled; | ||||
|  | ||||
|   monitors = meta_monitor_manager_get (); | ||||
| @@ -884,105 +903,51 @@ move_hw_cursor (MetaCursorTracker *tracker) | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_set_buffer (MetaCursorTracker  *tracker, | ||||
|                                 struct wl_resource *buffer, | ||||
|                                 int                 hot_x, | ||||
|                                 int                 hot_y) | ||||
| static MetaCursorReference * | ||||
| get_displayed_cursor (MetaCursorTracker *tracker) | ||||
| { | ||||
|   MetaCursorReference *new_cursor; | ||||
|   if (!tracker->is_showing) | ||||
|     return NULL; | ||||
|  | ||||
|   if (buffer) | ||||
|     { | ||||
|       new_cursor = meta_cursor_reference_from_buffer (tracker, buffer, hot_x, hot_y); | ||||
|       meta_cursor_tracker_set_sprite (tracker, new_cursor); | ||||
|       meta_cursor_reference_unref (new_cursor); | ||||
|     } | ||||
|   else | ||||
|     meta_cursor_tracker_set_sprite (tracker, NULL); | ||||
|   if (tracker->grab_cursor) | ||||
|     return tracker->grab_cursor; | ||||
|  | ||||
|   if (tracker->has_window_cursor) | ||||
|     return tracker->window_cursor; | ||||
|  | ||||
|   return tracker->root_cursor; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_tracker_set_sprite (MetaCursorTracker   *tracker, | ||||
|                                 MetaCursorReference *sprite) | ||||
| sync_displayed_cursor (MetaCursorTracker *tracker) | ||||
| { | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|   MetaCursorReference *displayed_cursor = get_displayed_cursor (tracker); | ||||
|  | ||||
|   if (sprite == tracker->sprite) | ||||
|   if (tracker->displayed_cursor == displayed_cursor) | ||||
|     return; | ||||
|  | ||||
|   g_clear_pointer (&tracker->sprite, meta_cursor_reference_unref); | ||||
|   g_clear_pointer (&tracker->displayed_cursor, meta_cursor_reference_unref); | ||||
|   if (displayed_cursor) | ||||
|     tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor); | ||||
|  | ||||
|   if (sprite) | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     { | ||||
|       tracker->sprite = meta_cursor_reference_ref (sprite); | ||||
|       cogl_pipeline_set_layer_texture (tracker->pipeline, 0, COGL_TEXTURE (tracker->sprite->texture)); | ||||
|     } | ||||
|   else | ||||
|     cogl_pipeline_set_layer_texture (tracker->pipeline, 0, NULL); | ||||
|       if (displayed_cursor) | ||||
|         cogl_pipeline_set_layer_texture (tracker->pipeline, 0, COGL_TEXTURE (displayed_cursor->texture)); | ||||
|       else | ||||
|         cogl_pipeline_set_layer_texture (tracker->pipeline, 0, NULL); | ||||
|  | ||||
|   tracker->has_cursor = tracker->sprite != NULL && tracker->is_showing; | ||||
|   update_hw_cursor (tracker); | ||||
|       update_hw_cursor (tracker); | ||||
|     } | ||||
|  | ||||
|   g_signal_emit (tracker, signals[CURSOR_CHANGED], 0); | ||||
|  | ||||
|   meta_cursor_tracker_update_position (tracker, tracker->current_x, tracker->current_y); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_update_position (MetaCursorTracker *tracker, | ||||
|                                      int                new_x, | ||||
|                                      int                new_y) | ||||
| { | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|  | ||||
|   tracker->current_x = new_x; | ||||
|   tracker->current_y = new_y; | ||||
|  | ||||
|   if (tracker->sprite) | ||||
|     { | ||||
|       tracker->current_rect.x = tracker->current_x - tracker->sprite->hot_x; | ||||
|       tracker->current_rect.y = tracker->current_y - tracker->sprite->hot_y; | ||||
|       tracker->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (tracker->sprite->texture)); | ||||
|       tracker->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (tracker->sprite->texture)); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       tracker->current_rect.x = 0; | ||||
|       tracker->current_rect.y = 0; | ||||
|       tracker->current_rect.width = 0; | ||||
|       tracker->current_rect.height = 0; | ||||
|     } | ||||
|  | ||||
|   if (tracker->has_hw_cursor) | ||||
|     move_hw_cursor (tracker); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_paint (MetaCursorTracker *tracker) | ||||
| { | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|  | ||||
|   if (tracker->has_hw_cursor || !tracker->has_cursor) | ||||
|     return; | ||||
|  | ||||
|   cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (), | ||||
|                                    tracker->pipeline, | ||||
|                                    tracker->current_rect.x, | ||||
|                                    tracker->current_rect.y, | ||||
|                                    tracker->current_rect.x + | ||||
|                                    tracker->current_rect.width, | ||||
|                                    tracker->current_rect.y + | ||||
|                                    tracker->current_rect.height); | ||||
|  | ||||
|   tracker->previous_rect = tracker->current_rect; | ||||
|   tracker->previous_is_valid = TRUE; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker, | ||||
|                                   ClutterActor      *stage) | ||||
| static void | ||||
| meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker) | ||||
| { | ||||
|   MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); | ||||
|   ClutterActor *stage = compositor->stage; | ||||
|   cairo_rectangle_int_t clip; | ||||
|  | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
| @@ -999,7 +964,7 @@ meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker, | ||||
|       tracker->previous_is_valid = FALSE; | ||||
|     } | ||||
|  | ||||
|   if (tracker->has_hw_cursor || !tracker->has_cursor) | ||||
|   if (tracker->has_hw_cursor || !tracker->displayed_cursor) | ||||
|     return; | ||||
|  | ||||
|   clip.x = tracker->current_rect.x; | ||||
| @@ -1009,6 +974,72 @@ meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker, | ||||
|   clutter_actor_queue_redraw_with_clip (stage, &clip); | ||||
| } | ||||
|  | ||||
| static void | ||||
| sync_cursor (MetaCursorTracker *tracker) | ||||
| { | ||||
|   MetaCursorReference *displayed_cursor; | ||||
|  | ||||
|   sync_displayed_cursor (tracker); | ||||
|   displayed_cursor = tracker->displayed_cursor; | ||||
|  | ||||
|   if (displayed_cursor) | ||||
|     { | ||||
|       tracker->current_rect.x = tracker->current_x - displayed_cursor->hot_x; | ||||
|       tracker->current_rect.y = tracker->current_y - displayed_cursor->hot_y; | ||||
|       tracker->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (displayed_cursor->texture)); | ||||
|       tracker->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (displayed_cursor->texture)); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       tracker->current_rect.x = 0; | ||||
|       tracker->current_rect.y = 0; | ||||
|       tracker->current_rect.width = 0; | ||||
|       tracker->current_rect.height = 0; | ||||
|     } | ||||
|  | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     { | ||||
|       if (tracker->has_hw_cursor) | ||||
|         move_hw_cursor (tracker); | ||||
|       else | ||||
|         meta_cursor_tracker_queue_redraw (tracker); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_update_position (MetaCursorTracker *tracker, | ||||
|                                      int                new_x, | ||||
|                                      int                new_y) | ||||
| { | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|  | ||||
|   tracker->current_x = new_x; | ||||
|   tracker->current_y = new_y; | ||||
|  | ||||
|   sync_cursor (tracker); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_paint (MetaCursorTracker *tracker) | ||||
| { | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|  | ||||
|   if (tracker->has_hw_cursor || !tracker->displayed_cursor) | ||||
|     return; | ||||
|  | ||||
|   cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (), | ||||
|                                    tracker->pipeline, | ||||
|                                    tracker->current_rect.x, | ||||
|                                    tracker->current_rect.y, | ||||
|                                    tracker->current_rect.x + | ||||
|                                    tracker->current_rect.width, | ||||
|                                    tracker->current_rect.y + | ||||
|                                    tracker->current_rect.height); | ||||
|  | ||||
|   tracker->previous_rect = tracker->current_rect; | ||||
|   tracker->previous_is_valid = TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *tracker, | ||||
|                                             MetaCRTC          *crtc, | ||||
| @@ -1016,15 +1047,16 @@ meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *tracker, | ||||
| { | ||||
|   if (has) | ||||
|     { | ||||
|       MetaCursorReference *displayed_cursor = tracker->displayed_cursor; | ||||
|       union gbm_bo_handle handle; | ||||
|       int width, height; | ||||
|       int hot_x, hot_y; | ||||
|  | ||||
|       handle = gbm_bo_get_handle (tracker->sprite->bo); | ||||
|       width = gbm_bo_get_width (tracker->sprite->bo); | ||||
|       height = gbm_bo_get_height (tracker->sprite->bo); | ||||
|       hot_x = tracker->sprite->hot_x; | ||||
|       hot_y = tracker->sprite->hot_y; | ||||
|       handle = gbm_bo_get_handle (displayed_cursor->bo); | ||||
|       width = gbm_bo_get_width (displayed_cursor->bo); | ||||
|       height = gbm_bo_get_height (displayed_cursor->bo); | ||||
|       hot_x = displayed_cursor->hot_x; | ||||
|       hot_y = displayed_cursor->hot_y; | ||||
|  | ||||
|       drmModeSetCursor2 (tracker->drm_fd, crtc->crtc_id, handle.u32, | ||||
|                          width, height, hot_x, hot_y); | ||||
| @@ -1047,12 +1079,13 @@ get_pointer_position_gdk (int         *x, | ||||
|   GdkScreen *gscreen; | ||||
|  | ||||
|   gmanager = gdk_display_get_device_manager (gdk_display_get_default ()); | ||||
|   gdevice = gdk_device_manager_get_client_pointer (gmanager); | ||||
|   gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID); | ||||
|  | ||||
|   gdk_device_get_position (gdevice, &gscreen, x, y); | ||||
|   gdk_device_get_state (gdevice, | ||||
|                         gdk_screen_get_root_window (gscreen), | ||||
|                         NULL, (GdkModifierType*)mods); | ||||
|   if (mods) | ||||
|     gdk_device_get_state (gdevice, | ||||
|                           gdk_screen_get_root_window (gscreen), | ||||
|                           NULL, (GdkModifierType*)mods); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -1068,9 +1101,12 @@ get_pointer_position_clutter (int         *x, | ||||
|   cdevice = clutter_device_manager_get_core_device (cmanager, CLUTTER_POINTER_DEVICE); | ||||
|  | ||||
|   clutter_input_device_get_coords (cdevice, NULL, &point); | ||||
|   *x = point.x; | ||||
|   *y = point.y; | ||||
|   *mods = clutter_input_device_get_modifier_state (cdevice); | ||||
|   if (x) | ||||
|     *x = point.x; | ||||
|   if (y) | ||||
|     *y = point.y; | ||||
|   if (mods) | ||||
|     *mods = clutter_input_device_get_modifier_state (cdevice); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -1100,13 +1136,7 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker, | ||||
|  | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     { | ||||
|       MetaWaylandCompositor *compositor; | ||||
|  | ||||
|       compositor = meta_wayland_compositor_get_default (); | ||||
|  | ||||
|       tracker->has_cursor = tracker->sprite != NULL && visible; | ||||
|       update_hw_cursor (tracker); | ||||
|       meta_cursor_tracker_queue_redraw (tracker, compositor->stage); | ||||
|       sync_cursor (tracker); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
| @@ -1118,3 +1148,12 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker, | ||||
|                           tracker->screen->xroot); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_force_update (MetaCursorTracker *tracker) | ||||
| { | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|  | ||||
|   update_hw_cursor (tracker); | ||||
|   sync_cursor (tracker); | ||||
| } | ||||
|   | ||||
| @@ -14,9 +14,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Adapted from gnome-session/gnome-session/gs-idle-monitor.c and | ||||
|  *         from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c | ||||
|   | ||||
| @@ -14,9 +14,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Adapted from gnome-session/gnome-session/gs-idle-monitor.c and | ||||
|  *         from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c | ||||
| @@ -537,7 +535,7 @@ make_watch (MetaIdleMonitor           *monitor, | ||||
|           watch->timeout_source = source; | ||||
|         } | ||||
|     } | ||||
|   else | ||||
|   else if (monitor->user_active_alarm != None) | ||||
|     { | ||||
|       if (timeout_msec != 0) | ||||
|         { | ||||
| @@ -655,8 +653,10 @@ meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor, | ||||
| { | ||||
|   g_return_if_fail (META_IS_IDLE_MONITOR (monitor)); | ||||
|  | ||||
|   g_object_ref (monitor); | ||||
|   g_hash_table_remove (monitor->watches, | ||||
|                        GUINT_TO_POINTER (id)); | ||||
|   g_object_unref (monitor); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -949,6 +949,8 @@ on_bus_acquired (GDBusConnection *connection, | ||||
|   for (iter = devices; iter; iter = iter->next) | ||||
|     on_device_added (device_manager, iter->data, manager); | ||||
|  | ||||
|   g_slist_free (devices); | ||||
|  | ||||
|   g_signal_connect_object (device_manager, "device-added", | ||||
|                            G_CALLBACK (on_device_added), manager, 0); | ||||
|   g_signal_connect_object (device_manager, "device-removed", | ||||
|   | ||||
| @@ -13,9 +13,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /* This file is shared between mutter (src/core/meta-xrandr-shared.h) | ||||
|   | ||||
| @@ -20,9 +20,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
| @@ -817,6 +815,22 @@ meta_monitor_config_match_current (MetaMonitorConfig  *self, | ||||
|   return ok; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager) | ||||
| { | ||||
|   MetaOutput *outputs; | ||||
|   unsigned n_outputs; | ||||
|   unsigned int i; | ||||
|  | ||||
|   outputs = meta_monitor_manager_get_outputs (manager, &n_outputs); | ||||
|  | ||||
|   for (i = 0; i < n_outputs; i++) | ||||
|     if (outputs[i].hotplug_mode_update) | ||||
|       return TRUE; | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static MetaConfiguration * | ||||
| meta_monitor_config_get_stored (MetaMonitorConfig *self, | ||||
| 				MetaOutput        *outputs, | ||||
|   | ||||
| @@ -111,8 +111,7 @@ make_output_name (drmModeConnector *connector) | ||||
|   }; | ||||
|   const char *connector_type_name; | ||||
|  | ||||
|   if (connector->connector_type >= 0 && | ||||
|       connector->connector_type < G_N_ELEMENTS (connector_type_names)) | ||||
|   if (connector->connector_type < G_N_ELEMENTS (connector_type_names)) | ||||
|     connector_type_name = connector_type_names[connector->connector_type]; | ||||
|   else | ||||
|     connector_type_name = "unknown"; | ||||
| @@ -651,7 +650,7 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager, | ||||
|     state = DRM_MODE_DPMS_SUSPEND; | ||||
|     break; | ||||
|   case META_POWER_SAVE_OFF: | ||||
|     state = DRM_MODE_DPMS_SUSPEND; | ||||
|     state = DRM_MODE_DPMS_OFF; | ||||
|     break; | ||||
|   default: | ||||
|     return; | ||||
|   | ||||
| @@ -29,9 +29,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef META_MONITOR_PRIVATE_H | ||||
| @@ -44,9 +42,7 @@ | ||||
| #include <meta/screen.h> | ||||
| #include "stack-tracker.h" | ||||
| #include "ui.h" | ||||
| #ifdef HAVE_WAYLAND | ||||
| #include <wayland-server.h> | ||||
| #endif | ||||
| #include "meta-xrandr-shared.h" | ||||
|  | ||||
| #include "meta-dbus-xrandr.h" | ||||
| @@ -56,19 +52,6 @@ typedef struct _MetaMonitorManager         MetaMonitorManager; | ||||
| typedef struct _MetaMonitorConfigClass    MetaMonitorConfigClass; | ||||
| typedef struct _MetaMonitorConfig         MetaMonitorConfig; | ||||
|  | ||||
| #ifndef HAVE_WAYLAND | ||||
| enum wl_output_transform { | ||||
|   WL_OUTPUT_TRANSFORM_NORMAL, | ||||
|   WL_OUTPUT_TRANSFORM_90, | ||||
|   WL_OUTPUT_TRANSFORM_180, | ||||
|   WL_OUTPUT_TRANSFORM_270, | ||||
|   WL_OUTPUT_TRANSFORM_FLIPPED, | ||||
|   WL_OUTPUT_TRANSFORM_FLIPPED_90, | ||||
|   WL_OUTPUT_TRANSFORM_FLIPPED_180, | ||||
|   WL_OUTPUT_TRANSFORM_FLIPPED_270 | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| typedef struct _MetaOutput MetaOutput; | ||||
| typedef struct _MetaCRTC MetaCRTC; | ||||
| typedef struct _MetaMonitorMode MetaMonitorMode; | ||||
| @@ -119,6 +102,9 @@ struct _MetaOutput | ||||
|  | ||||
|   gpointer driver_private; | ||||
|   GDestroyNotify driver_notify; | ||||
|  | ||||
|   /* get a new preferred mode on hotplug events, to handle dynamic guest resizing */ | ||||
|   gboolean hotplug_mode_update; | ||||
| }; | ||||
|  | ||||
| struct _MetaCRTC | ||||
| @@ -407,6 +393,7 @@ void               meta_monitor_manager_free_output_array (MetaOutput *old_outpu | ||||
|                                                            int         n_old_outputs); | ||||
| void               meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes, | ||||
|                                                          int              n_old_modes); | ||||
| gboolean           meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager); | ||||
|  | ||||
| /* Returns true if transform causes width and height to be inverted | ||||
|    This is true for the odd transforms in the enum */ | ||||
|   | ||||
| @@ -20,9 +20,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
| @@ -311,6 +309,29 @@ read_output_edid (MetaMonitorManagerXrandr *manager_xrandr, | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr, | ||||
|                                 XID                       output_id) | ||||
| { | ||||
|   MetaDisplay *display = meta_get_display (); | ||||
|   XRRPropertyInfo *info; | ||||
|   gboolean result = FALSE; | ||||
|  | ||||
|   meta_error_trap_push (display); | ||||
|   info = XRRQueryOutputProperty (manager_xrandr->xdisplay, output_id, | ||||
|                                  display->atom_hotplug_mode_update); | ||||
|   meta_error_trap_pop (display); | ||||
|  | ||||
|   if (info) | ||||
|     { | ||||
|       result = TRUE; | ||||
|       XFree (info); | ||||
|     } | ||||
|  | ||||
|   return result; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager) | ||||
| { | ||||
| @@ -430,8 +451,10 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager) | ||||
|       XRRFreeCrtcInfo (crtc); | ||||
|     } | ||||
|  | ||||
|   meta_error_trap_push (meta_get_display ()); | ||||
|   primary_output = XRRGetOutputPrimary (manager_xrandr->xdisplay, | ||||
| 					DefaultRootWindow (manager_xrandr->xdisplay)); | ||||
|   meta_error_trap_pop (meta_get_display ()); | ||||
|  | ||||
|   n_actual_outputs = 0; | ||||
|   for (i = 0; i < (unsigned)resources->noutput; i++) | ||||
| @@ -484,6 +507,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager) | ||||
| 	  meta_output->width_mm = output->mm_width; | ||||
| 	  meta_output->height_mm = output->mm_height; | ||||
| 	  meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN; | ||||
|           meta_output->hotplug_mode_update = | ||||
|               output_get_hotplug_mode_update (manager_xrandr, meta_output->output_id); | ||||
|  | ||||
| 	  meta_output->n_modes = output->nmode; | ||||
| 	  meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes); | ||||
| @@ -666,10 +691,11 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager, | ||||
| 						 unsigned int         n_outputs) | ||||
| { | ||||
|   MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); | ||||
|   MetaDisplay *display = meta_get_display (); | ||||
|   unsigned i; | ||||
|   int width, height, width_mm, height_mm; | ||||
|  | ||||
|   meta_display_grab (meta_get_display ()); | ||||
|   meta_display_grab (display); | ||||
|  | ||||
|   /* First compute the new size of the screen (framebuffer) */ | ||||
|   width = 0; height = 0; | ||||
| @@ -763,10 +789,10 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager, | ||||
|    */ | ||||
|   width_mm = (width / DPI_FALLBACK) * 25.4 + 0.5; | ||||
|   height_mm = (height / DPI_FALLBACK) * 25.4 + 0.5; | ||||
|   meta_error_trap_push (meta_get_display ()); | ||||
|   meta_error_trap_push (display); | ||||
|   XRRSetScreenSize (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay), | ||||
|                     width, height, width_mm, height_mm); | ||||
|   meta_error_trap_pop (meta_get_display ()); | ||||
|   meta_error_trap_pop (display); | ||||
|  | ||||
|   for (i = 0; i < n_crtcs; i++) | ||||
|     { | ||||
| @@ -823,7 +849,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager, | ||||
|               goto next; | ||||
|             } | ||||
|  | ||||
|           meta_error_trap_push (meta_get_display ()); | ||||
|           meta_error_trap_push (display); | ||||
|           ok = XRRSetCrtcConfig (manager_xrandr->xdisplay, | ||||
|                                  manager_xrandr->resources, | ||||
|                                  (XID)crtc->crtc_id, | ||||
| @@ -832,7 +858,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager, | ||||
|                                  (XID)mode->mode_id, | ||||
|                                  wl_transform_to_xrandr (crtc_info->transform), | ||||
|                                  outputs, n_outputs); | ||||
|           meta_error_trap_pop (meta_get_display ()); | ||||
|           meta_error_trap_pop (display); | ||||
|  | ||||
|           if (ok != Success) | ||||
|             { | ||||
| @@ -873,9 +899,11 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager, | ||||
|  | ||||
|       if (output_info->is_primary) | ||||
|         { | ||||
|           meta_error_trap_push (display); | ||||
|           XRRSetOutputPrimary (manager_xrandr->xdisplay, | ||||
|                                DefaultRootWindow (manager_xrandr->xdisplay), | ||||
|                                (XID)output_info->output->output_id); | ||||
|           meta_error_trap_pop (display); | ||||
|         } | ||||
|  | ||||
|       output_set_presentation_xrandr (manager_xrandr, | ||||
| @@ -901,7 +929,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager, | ||||
|       output->is_primary = FALSE; | ||||
|     } | ||||
|  | ||||
|   meta_display_ungrab (meta_get_display ()); | ||||
|   meta_display_ungrab (display); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -969,6 +997,16 @@ meta_monitor_manager_xrandr_set_crtc_gamma (MetaMonitorManager *manager, | ||||
|   XRRFreeGamma (gamma); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_xrandr_rebuild_derived (MetaMonitorManager *manager) | ||||
| { | ||||
|   /* This will be a no-op if the change was from our side, as | ||||
|      we already called it in the DBus method handler */ | ||||
|   meta_monitor_config_update_current (manager->config, manager); | ||||
|  | ||||
|   meta_monitor_manager_rebuild_derived (manager); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager, | ||||
| 					   XEvent             *event) | ||||
| @@ -978,6 +1016,7 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager, | ||||
|   MetaCRTC *old_crtcs; | ||||
|   MetaMonitorMode *old_modes; | ||||
|   unsigned int n_old_outputs, n_old_modes; | ||||
|   gboolean new_config; | ||||
|  | ||||
|   if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify) | ||||
|     return FALSE; | ||||
| @@ -994,31 +1033,36 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager, | ||||
|   manager->serial++; | ||||
|   meta_monitor_manager_xrandr_read_current (manager); | ||||
|  | ||||
|   /* Check if the current intended configuration has the same outputs | ||||
|      as the new real one, or if the event is a result of an XRandR call. | ||||
|      If so, we can go straight to rebuild the logical config and tell | ||||
|      the outside world. | ||||
|      Otherwise, this event was caused by hotplug, so give a chance to | ||||
|      MetaMonitorConfig. | ||||
|   new_config = manager_xrandr->resources->timestamp >= | ||||
|     manager_xrandr->resources->configTimestamp; | ||||
|   if (meta_monitor_manager_has_hotplug_mode_update (manager)) | ||||
|  | ||||
|      Note that we need to check both the timestamps and the list of | ||||
|      outputs, because the X server might emit spurious events with | ||||
|      new configTimestamps (bug 702804), and the driver may have | ||||
|      changed the EDID for some other reason (old broken qxl and vbox | ||||
|      drivers...). | ||||
|   */ | ||||
|   if (manager_xrandr->resources->timestamp >= manager_xrandr->resources->configTimestamp || | ||||
|       meta_monitor_config_match_current (manager->config, manager)) | ||||
|     { | ||||
|       /* This will be a no-op if the change was from our side, as | ||||
|          we already called it in the DBus method handler */ | ||||
|       meta_monitor_config_update_current (manager->config, manager); | ||||
|  | ||||
|       meta_monitor_manager_rebuild_derived (manager); | ||||
|       /* Check if the current intended configuration is a result of an | ||||
|          XRandR call.  Otherwise, hotplug_mode_update tells us to get | ||||
|          a new preferred mode on hotplug events to handle dynamic | ||||
|          guest resizing. */ | ||||
|       if (new_config) | ||||
|         meta_monitor_manager_xrandr_rebuild_derived (manager); | ||||
|       else | ||||
|         meta_monitor_config_make_default (manager->config, manager); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       if (!meta_monitor_config_apply_stored (manager->config, manager)) | ||||
|       /* Check if the current intended configuration has the same outputs | ||||
|          as the new real one, or if the event is a result of an XRandR call. | ||||
|          If so, we can go straight to rebuild the logical config and tell | ||||
|          the outside world. | ||||
|          Otherwise, this event was caused by hotplug, so give a chance to | ||||
|          MetaMonitorConfig. | ||||
|  | ||||
|          Note that we need to check both the timestamps and the list of | ||||
|          outputs, because the X server might emit spurious events with new | ||||
|          configTimestamps (bug 702804), and the driver may have changed | ||||
|          the EDID for some other reason (old qxl and vbox drivers). */ | ||||
|       if (new_config || meta_monitor_config_match_current (manager->config, manager)) | ||||
|         meta_monitor_manager_xrandr_rebuild_derived (manager); | ||||
|       else if (!meta_monitor_config_apply_stored (manager->config, manager)) | ||||
|         meta_monitor_config_make_default (manager->config, manager); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -20,9 +20,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
| @@ -36,7 +34,6 @@ | ||||
| #include "util-private.h" | ||||
| #include <meta/errors.h> | ||||
| #include "monitor-private.h" | ||||
| #include "meta-wayland-private.h" | ||||
|  | ||||
| #include "meta-dbus-xrandr.h" | ||||
|  | ||||
| @@ -290,7 +287,7 @@ make_logical_config (MetaMonitorManager *manager) | ||||
|  | ||||
|       for (j = 0; j < monitor_infos->len; j++) | ||||
|         { | ||||
|           MetaMonitorInfo *info = &g_array_index (monitor_infos, MetaMonitorInfo, i); | ||||
|           MetaMonitorInfo *info = &g_array_index (monitor_infos, MetaMonitorInfo, j); | ||||
|           if (meta_rectangle_equal (&crtc->rect, | ||||
|                                     &info->rect)) | ||||
|             { | ||||
| @@ -358,19 +355,35 @@ make_logical_config (MetaMonitorManager *manager) | ||||
| static GType | ||||
| get_default_backend (void) | ||||
| { | ||||
|   if (meta_is_wayland_compositor ()) | ||||
| #if defined(CLUTTER_WINDOWING_EGL) | ||||
|   if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL)) | ||||
|     return META_TYPE_MONITOR_MANAGER_KMS; | ||||
| #endif | ||||
|  | ||||
| #if defined(CLUTTER_WINDOWING_X11) | ||||
|   if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11)) | ||||
|     { | ||||
|       MetaWaylandCompositor *compositor; | ||||
|  | ||||
|       compositor = meta_wayland_compositor_get_default (); | ||||
|  | ||||
|       if (meta_wayland_compositor_is_native (compositor)) | ||||
|         return META_TYPE_MONITOR_MANAGER_KMS; | ||||
|       else | ||||
|       /* 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 META_TYPE_MONITOR_MANAGER; | ||||
|       else | ||||
|         return META_TYPE_MONITOR_MANAGER_XRANDR; | ||||
|     } | ||||
|   else | ||||
|     return META_TYPE_MONITOR_MANAGER_XRANDR; | ||||
| #endif | ||||
|  | ||||
| #if defined(CLUTTER_WINDOWING_WAYLAND) | ||||
|   if (clutter_check_windowing_backend (CLUTTER_WINDOWING_WAYLAND)) | ||||
|     { | ||||
|       /* Use the dummy implementation on Wayland for now. | ||||
|        * In the future, we should support wl_fullscreen_output | ||||
|        * which will have CRTC management in the protocol. */ | ||||
|       return META_TYPE_MONITOR_MANAGER; | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|   g_assert_not_reached (); | ||||
| } | ||||
|  | ||||
| static MetaMonitorManager * | ||||
| @@ -614,46 +627,60 @@ static char * | ||||
| make_display_name (MetaMonitorManager *manager, | ||||
|                    MetaOutput         *output) | ||||
| { | ||||
|   char *inches = NULL; | ||||
|   char *vendor_name = NULL; | ||||
|   char *ret; | ||||
|  | ||||
|   if (g_str_has_prefix (output->name, "LVDS") || | ||||
|       g_str_has_prefix (output->name, "eDP")) | ||||
|     return g_strdup (_("Built-in display")); | ||||
|     { | ||||
|       ret = g_strdup (_("Built-in display")); | ||||
|       goto out; | ||||
|     } | ||||
|  | ||||
|   if (output->width_mm != -1 && output->height_mm != -1) | ||||
|   if (output->width_mm > 0 && output->height_mm > 0) | ||||
|     { | ||||
|       double d = sqrt (output->width_mm * output->width_mm + | ||||
|                        output->height_mm * output->height_mm); | ||||
|       char *inches = diagonal_to_str (d / 25.4); | ||||
|       char *vendor_name; | ||||
|       char *ret; | ||||
|       inches = diagonal_to_str (d / 25.4); | ||||
|     } | ||||
|  | ||||
|       if (g_strcmp0 (output->vendor, "unknown") != 0) | ||||
|         { | ||||
|           if (!manager->pnp_ids) | ||||
|             manager->pnp_ids = gnome_pnp_ids_new (); | ||||
|   if (g_strcmp0 (output->vendor, "unknown") != 0) | ||||
|     { | ||||
|       if (!manager->pnp_ids) | ||||
|         manager->pnp_ids = gnome_pnp_ids_new (); | ||||
|  | ||||
|           vendor_name = gnome_pnp_ids_get_pnp_id (manager->pnp_ids, | ||||
|                                                   output->vendor); | ||||
|       vendor_name = gnome_pnp_ids_get_pnp_id (manager->pnp_ids, | ||||
|                                               output->vendor); | ||||
|  | ||||
|           ret = g_strdup_printf ("%s %s", vendor_name, inches); | ||||
|  | ||||
|           g_free (vendor_name); | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           /* TRANSLATORS: this is a monitor name (in case we don't know | ||||
|              the vendor), it's Unknown followed by a size in inches, | ||||
|              like 'Unknown 15"' | ||||
|           */ | ||||
|           ret = g_strdup_printf (_("Unknown %s"), inches); | ||||
|         } | ||||
|  | ||||
|       g_free (inches); | ||||
|       return ret; | ||||
|       if (!vendor_name) | ||||
|         vendor_name = g_strdup (output->vendor); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       return g_strdup (output->vendor); | ||||
|       if (inches != NULL) | ||||
|         vendor_name = g_strdup (_("Unknown")); | ||||
|       else | ||||
|         vendor_name = g_strdup (_("Unknown Display")); | ||||
|     } | ||||
|  | ||||
|   if (inches != NULL) | ||||
|     { | ||||
|       /* 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); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       ret = g_strdup (vendor_name); | ||||
|     } | ||||
|  | ||||
|  out: | ||||
|   g_free (inches); | ||||
|   g_free (vendor_name); | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
|   | ||||
| @@ -14,9 +14,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|   | ||||
							
								
								
									
										324
									
								
								src/core/place.c
									
									
									
									
									
								
							
							
						
						
									
										324
									
								
								src/core/place.c
									
									
									
									
									
								
							| @@ -19,9 +19,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
| @@ -47,34 +45,18 @@ northwestcmp (gconstpointer a, gconstpointer b) | ||||
| { | ||||
|   MetaWindow *aw = (gpointer) a; | ||||
|   MetaWindow *bw = (gpointer) b; | ||||
|   MetaRectangle a_frame; | ||||
|   MetaRectangle b_frame; | ||||
|   int from_origin_a; | ||||
|   int from_origin_b; | ||||
|   int ax, ay, bx, by; | ||||
|  | ||||
|   /* we're interested in the frame position for cascading, | ||||
|    * not meta_window_get_position() | ||||
|    */ | ||||
|   if (aw->frame) | ||||
|     { | ||||
|       ax = aw->frame->rect.x; | ||||
|       ay = aw->frame->rect.y; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       ax = aw->rect.x; | ||||
|       ay = aw->rect.y; | ||||
|     } | ||||
|  | ||||
|   if (bw->frame) | ||||
|     { | ||||
|       bx = bw->frame->rect.x; | ||||
|       by = bw->frame->rect.y; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       bx = bw->rect.x; | ||||
|       by = bw->rect.y; | ||||
|     } | ||||
|   meta_window_get_frame_rect (aw, &a_frame); | ||||
|   meta_window_get_frame_rect (bw, &b_frame); | ||||
|   ax = a_frame.x; | ||||
|   ay = a_frame.y; | ||||
|   bx = b_frame.x; | ||||
|   by = b_frame.y; | ||||
|    | ||||
|   /* probably there's a fast good-enough-guess we could use here. */ | ||||
|   from_origin_a = sqrt (ax * ax + ay * ay); | ||||
| @@ -90,7 +72,6 @@ northwestcmp (gconstpointer a, gconstpointer b) | ||||
|  | ||||
| static void | ||||
| find_next_cascade (MetaWindow *window, | ||||
|                    MetaFrameBorders *borders, | ||||
|                    /* visible windows on relevant workspaces */ | ||||
|                    GList      *windows, | ||||
|                    int         x, | ||||
| @@ -102,6 +83,7 @@ find_next_cascade (MetaWindow *window, | ||||
|   GList *sorted; | ||||
|   int cascade_x, cascade_y; | ||||
|   int x_threshold, y_threshold; | ||||
|   MetaRectangle frame_rect; | ||||
|   int window_width, window_height; | ||||
|   int cascade_stage; | ||||
|   MetaRectangle work_area; | ||||
| @@ -120,10 +102,13 @@ find_next_cascade (MetaWindow *window, | ||||
|    * manually cascade. | ||||
|    */ | ||||
| #define CASCADE_FUZZ 15 | ||||
|   if (borders) | ||||
|   if (window->frame) | ||||
|     { | ||||
|       x_threshold = MAX (borders->visible.left, CASCADE_FUZZ); | ||||
|       y_threshold = MAX (borders->visible.top, CASCADE_FUZZ); | ||||
|       MetaFrameBorders borders; | ||||
|  | ||||
|       meta_frame_calc_borders (window->frame, &borders); | ||||
|       x_threshold = MAX (borders.visible.left, CASCADE_FUZZ); | ||||
|       y_threshold = MAX (borders.visible.top, CASCADE_FUZZ); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
| @@ -143,30 +128,25 @@ find_next_cascade (MetaWindow *window, | ||||
|   cascade_y = MAX (0, work_area.y); | ||||
|    | ||||
|   /* Find first cascade position that's not used. */ | ||||
|    | ||||
|   window_width = window->frame ? window->frame->rect.width : window->rect.width; | ||||
|   window_height = window->frame ? window->frame->rect.height : window->rect.height; | ||||
|  | ||||
|   meta_window_get_frame_rect (window, &frame_rect); | ||||
|   window_width = frame_rect.width; | ||||
|   window_height = frame_rect.height; | ||||
|    | ||||
|   cascade_stage = 0; | ||||
|   tmp = sorted; | ||||
|   while (tmp != NULL) | ||||
|     { | ||||
|       MetaWindow *w; | ||||
|       MetaRectangle w_frame_rect; | ||||
|       int wx, wy; | ||||
|        | ||||
|       w = tmp->data; | ||||
|  | ||||
|       /* we want frame position, not window position */ | ||||
|       if (w->frame) | ||||
|         { | ||||
|           wx = w->frame->rect.x; | ||||
|           wy = w->frame->rect.y; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           wx = w->rect.x; | ||||
|           wy = w->rect.y; | ||||
|         } | ||||
|       meta_window_get_frame_rect (w, &w_frame_rect); | ||||
|       wx = w_frame_rect.x; | ||||
|       wy = w_frame_rect.y; | ||||
|        | ||||
|       if (ABS (wx - cascade_x) < x_threshold && | ||||
|           ABS (wy - cascade_y) < y_threshold) | ||||
| @@ -223,22 +203,12 @@ find_next_cascade (MetaWindow *window, | ||||
|    | ||||
|   g_list_free (sorted); | ||||
|  | ||||
|   /* Convert coords to position of window, not position of frame. */ | ||||
|   if (borders == NULL) | ||||
|     { | ||||
|       *new_x = cascade_x; | ||||
|       *new_y = cascade_y; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       *new_x = cascade_x + borders->visible.left; | ||||
|       *new_y = cascade_y + borders->visible.top; | ||||
|     } | ||||
|   *new_x = cascade_x; | ||||
|   *new_y = cascade_y; | ||||
| } | ||||
|  | ||||
| static void | ||||
| find_most_freespace (MetaWindow *window, | ||||
|                      MetaFrameBorders *borders, | ||||
|                      /* visible windows on relevant workspaces */ | ||||
|                      MetaWindow *focus_window, | ||||
|                      int         x, | ||||
| @@ -250,29 +220,25 @@ find_most_freespace (MetaWindow *window, | ||||
|   int max_area; | ||||
|   int max_width, max_height, left, right, top, bottom; | ||||
|   int left_space, right_space, top_space, bottom_space; | ||||
|   int frame_size_left, frame_size_top; | ||||
|   MetaRectangle work_area; | ||||
|   MetaRectangle avoid; | ||||
|   MetaRectangle outer; | ||||
|  | ||||
|   frame_size_left = borders ? borders->visible.left : 0; | ||||
|   frame_size_top  = borders ? borders->visible.top : 0; | ||||
|   MetaRectangle frame_rect; | ||||
|  | ||||
|   meta_window_get_work_area_current_monitor (focus_window, &work_area); | ||||
|   meta_window_get_outer_rect (focus_window, &avoid); | ||||
|   meta_window_get_outer_rect (window, &outer); | ||||
|   meta_window_get_frame_rect (focus_window, &avoid); | ||||
|   meta_window_get_frame_rect (window, &frame_rect); | ||||
|  | ||||
|   /* Find the areas of choosing the various sides of the focus window */ | ||||
|   max_width  = MIN (avoid.width, outer.width); | ||||
|   max_height = MIN (avoid.height, outer.height); | ||||
|   max_width  = MIN (avoid.width, frame_rect.width); | ||||
|   max_height = MIN (avoid.height, frame_rect.height); | ||||
|   left_space   = avoid.x - work_area.x; | ||||
|   right_space  = work_area.width - (avoid.x + avoid.width - work_area.x); | ||||
|   top_space    = avoid.y - work_area.y; | ||||
|   bottom_space = work_area.height - (avoid.y + avoid.height - work_area.y); | ||||
|   left   = MIN (left_space,   outer.width); | ||||
|   right  = MIN (right_space,  outer.width); | ||||
|   top    = MIN (top_space,    outer.height); | ||||
|   bottom = MIN (bottom_space, outer.height); | ||||
|   left   = MIN (left_space,   frame_rect.width); | ||||
|   right  = MIN (right_space,  frame_rect.width); | ||||
|   top    = MIN (top_space,    frame_rect.height); | ||||
|   bottom = MIN (bottom_space, frame_rect.height); | ||||
|  | ||||
|   /* Find out which side of the focus_window can show the most of the window */ | ||||
|   side = META_LEFT; | ||||
| @@ -304,39 +270,56 @@ find_most_freespace (MetaWindow *window, | ||||
|   switch (side) | ||||
|     { | ||||
|     case META_LEFT: | ||||
|       *new_y = avoid.y + frame_size_top; | ||||
|       if (left_space > outer.width) | ||||
|         *new_x = avoid.x - outer.width + frame_size_left; | ||||
|       *new_y = avoid.y; | ||||
|       if (left_space > frame_rect.width) | ||||
|         *new_x = avoid.x - frame_rect.width; | ||||
|       else | ||||
|         *new_x = work_area.x + frame_size_left; | ||||
|         *new_x = work_area.x; | ||||
|       break; | ||||
|     case META_RIGHT: | ||||
|       *new_y = avoid.y + frame_size_top; | ||||
|       if (right_space > outer.width) | ||||
|         *new_x = avoid.x + avoid.width + frame_size_left; | ||||
|       *new_y = avoid.y; | ||||
|       if (right_space > frame_rect.width) | ||||
|         *new_x = avoid.x + avoid.width; | ||||
|       else | ||||
|         *new_x = work_area.x + work_area.width - outer.width + frame_size_left; | ||||
|         *new_x = work_area.x + work_area.width - frame_rect.width; | ||||
|       break; | ||||
|     case META_TOP: | ||||
|       *new_x = avoid.x + frame_size_left; | ||||
|       if (top_space > outer.height) | ||||
|         *new_y = avoid.y - outer.height + frame_size_top; | ||||
|       *new_x = avoid.x; | ||||
|       if (top_space > frame_rect.height) | ||||
|         *new_y = avoid.y - frame_rect.height; | ||||
|       else | ||||
|         *new_y = work_area.y + frame_size_top; | ||||
|         *new_y = work_area.y; | ||||
|       break; | ||||
|     case META_BOTTOM: | ||||
|       *new_x = avoid.x + frame_size_left; | ||||
|       if (bottom_space > outer.height) | ||||
|         *new_y = avoid.y + avoid.height + frame_size_top; | ||||
|       *new_x = avoid.x; | ||||
|       if (bottom_space > frame_rect.height) | ||||
|         *new_y = avoid.y + avoid.height; | ||||
|       else | ||||
|         *new_y = work_area.y + work_area.height - outer.height + frame_size_top; | ||||
|         *new_y = work_area.y + work_area.height - frame_rect.height; | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| window_overlaps_focus_window (MetaWindow *window) | ||||
| { | ||||
|   MetaWindow *focus_window; | ||||
|   MetaRectangle window_frame, focus_frame, overlap; | ||||
|  | ||||
|   focus_window = window->display->focus_window; | ||||
|   if (focus_window == NULL) | ||||
|     return FALSE; | ||||
|  | ||||
|   meta_window_get_frame_rect (window, &window_frame); | ||||
|   meta_window_get_frame_rect (focus_window, &focus_frame); | ||||
|  | ||||
|   return meta_rectangle_intersect (&window_frame, | ||||
|                                    &focus_frame, | ||||
|                                    &overlap); | ||||
| } | ||||
|  | ||||
| static void | ||||
| avoid_being_obscured_as_second_modal_dialog (MetaWindow *window, | ||||
|                                              MetaFrameBorders *borders, | ||||
|                                              int        *x, | ||||
|                                              int        *y) | ||||
| { | ||||
| @@ -355,18 +338,17 @@ avoid_being_obscured_as_second_modal_dialog (MetaWindow *window, | ||||
|    */ | ||||
|  | ||||
|   MetaWindow *focus_window; | ||||
|   MetaRectangle overlap; | ||||
|  | ||||
|   focus_window = window->display->focus_window; | ||||
|  | ||||
|   /* denied_focus_and_not_transient is only set when focus_window != NULL */ | ||||
|  | ||||
|   if (window->denied_focus_and_not_transient && | ||||
|       window->wm_state_modal && /* FIXME: Maybe do this for all transients? */ | ||||
|       window->type == META_WINDOW_MODAL_DIALOG && | ||||
|       meta_window_same_application (window, focus_window) && | ||||
|       meta_rectangle_intersect (&window->rect, | ||||
|                                 &focus_window->rect, | ||||
|                                 &overlap)) | ||||
|       window_overlaps_focus_window (window)) | ||||
|     { | ||||
|       find_most_freespace (window, borders, focus_window, *x, *y, x, y); | ||||
|       find_most_freespace (window, focus_window, *x, *y, x, y); | ||||
|       meta_topic (META_DEBUG_PLACEMENT, | ||||
|                   "Dialog window %s was denied focus but may be modal " | ||||
|                   "to the focus window; had to move it to avoid the " | ||||
| @@ -409,7 +391,7 @@ rectangle_overlaps_some_window (MetaRectangle *rect, | ||||
|         case META_WINDOW_UTILITY: | ||||
|         case META_WINDOW_TOOLBAR: | ||||
|         case META_WINDOW_MENU: | ||||
|           meta_window_get_outer_rect (other, &other_rect); | ||||
|           meta_window_get_frame_rect (other, &other_rect); | ||||
|            | ||||
|           if (meta_rectangle_intersect (rect, &other_rect, &dest)) | ||||
|             return TRUE; | ||||
| @@ -427,20 +409,14 @@ leftmost_cmp (gconstpointer a, gconstpointer b) | ||||
| { | ||||
|   MetaWindow *aw = (gpointer) a; | ||||
|   MetaWindow *bw = (gpointer) b; | ||||
|   MetaRectangle a_frame; | ||||
|   MetaRectangle b_frame; | ||||
|   int ax, bx; | ||||
|  | ||||
|   /* we're interested in the frame position for cascading, | ||||
|    * not meta_window_get_position() | ||||
|    */ | ||||
|   if (aw->frame) | ||||
|     ax = aw->frame->rect.x; | ||||
|   else | ||||
|     ax = aw->rect.x; | ||||
|  | ||||
|   if (bw->frame) | ||||
|     bx = bw->frame->rect.x; | ||||
|   else | ||||
|     bx = bw->rect.x; | ||||
|   meta_window_get_frame_rect (aw, &a_frame); | ||||
|   meta_window_get_frame_rect (bw, &b_frame); | ||||
|   ax = a_frame.x; | ||||
|   bx = b_frame.x; | ||||
|  | ||||
|   if (ax < bx) | ||||
|     return -1; | ||||
| @@ -455,20 +431,14 @@ topmost_cmp (gconstpointer a, gconstpointer b) | ||||
| { | ||||
|   MetaWindow *aw = (gpointer) a; | ||||
|   MetaWindow *bw = (gpointer) b; | ||||
|   MetaRectangle a_frame; | ||||
|   MetaRectangle b_frame; | ||||
|   int ay, by; | ||||
|  | ||||
|   /* we're interested in the frame position for cascading, | ||||
|    * not meta_window_get_position() | ||||
|    */ | ||||
|   if (aw->frame) | ||||
|     ay = aw->frame->rect.y; | ||||
|   else | ||||
|     ay = aw->rect.y; | ||||
|  | ||||
|   if (bw->frame) | ||||
|     by = bw->frame->rect.y; | ||||
|   else | ||||
|     by = bw->rect.y; | ||||
|   meta_window_get_frame_rect (aw, &a_frame); | ||||
|   meta_window_get_frame_rect (bw, &b_frame); | ||||
|   ay = a_frame.y; | ||||
|   by = b_frame.y; | ||||
|  | ||||
|   if (ay < by) | ||||
|     return -1; | ||||
| @@ -506,7 +476,6 @@ center_tile_rect_in_area (MetaRectangle *rect, | ||||
|  */ | ||||
| static gboolean | ||||
| find_first_fit (MetaWindow *window, | ||||
|                 MetaFrameBorders *borders, | ||||
|                 /* visible windows on relevant workspaces */ | ||||
|                 GList      *windows, | ||||
| 		int         monitor, | ||||
| @@ -540,15 +509,8 @@ find_first_fit (MetaWindow *window, | ||||
|   right_sorted = g_list_copy (windows); | ||||
|   right_sorted = g_list_sort (right_sorted, topmost_cmp); | ||||
|   right_sorted = g_list_sort (right_sorted, leftmost_cmp); | ||||
|    | ||||
|   rect.width = window->rect.width; | ||||
|   rect.height = window->rect.height; | ||||
|    | ||||
|   if (borders) | ||||
|     { | ||||
|       rect.width += borders->visible.left + borders->visible.right; | ||||
|       rect.height += borders->visible.top + borders->visible.bottom; | ||||
|     } | ||||
|  | ||||
|   meta_window_get_frame_rect (window, &rect); | ||||
|  | ||||
| #ifdef WITH_VERBOSE_MODE | ||||
|     { | ||||
| @@ -570,11 +532,6 @@ find_first_fit (MetaWindow *window, | ||||
|       { | ||||
|         *new_x = rect.x; | ||||
|         *new_y = rect.y; | ||||
|         if (borders) | ||||
|           { | ||||
|             *new_x += borders->visible.left; | ||||
|             *new_y += borders->visible.top; | ||||
|           } | ||||
|      | ||||
|         retval = TRUE; | ||||
|         | ||||
| @@ -586,23 +543,18 @@ find_first_fit (MetaWindow *window, | ||||
|     while (tmp != NULL) | ||||
|       { | ||||
|         MetaWindow *w = tmp->data; | ||||
|         MetaRectangle outer_rect; | ||||
|         MetaRectangle frame_rect; | ||||
|  | ||||
|         meta_window_get_outer_rect (w, &outer_rect); | ||||
|         meta_window_get_frame_rect (w, &frame_rect); | ||||
|        | ||||
|         rect.x = outer_rect.x; | ||||
|         rect.y = outer_rect.y + outer_rect.height; | ||||
|         rect.x = frame_rect.x; | ||||
|         rect.y = frame_rect.y + frame_rect.height; | ||||
|        | ||||
|         if (meta_rectangle_contains_rect (&work_area, &rect) && | ||||
|             !rectangle_overlaps_some_window (&rect, below_sorted)) | ||||
|           { | ||||
|             *new_x = rect.x; | ||||
|             *new_y = rect.y; | ||||
|             if (borders) | ||||
|               { | ||||
|                 *new_x += borders->visible.left; | ||||
|                 *new_y += borders->visible.top; | ||||
|               } | ||||
|            | ||||
|             retval = TRUE; | ||||
|            | ||||
| @@ -617,23 +569,18 @@ find_first_fit (MetaWindow *window, | ||||
|     while (tmp != NULL) | ||||
|       { | ||||
|         MetaWindow *w = tmp->data; | ||||
|         MetaRectangle outer_rect; | ||||
|         MetaRectangle frame_rect; | ||||
|     | ||||
|         meta_window_get_outer_rect (w, &outer_rect); | ||||
|         meta_window_get_frame_rect (w, &frame_rect); | ||||
|       | ||||
|         rect.x = outer_rect.x + outer_rect.width; | ||||
|         rect.y = outer_rect.y; | ||||
|         rect.x = frame_rect.x + frame_rect.width; | ||||
|         rect.y = frame_rect.y; | ||||
|     | ||||
|         if (meta_rectangle_contains_rect (&work_area, &rect) && | ||||
|             !rectangle_overlaps_some_window (&rect, right_sorted)) | ||||
|           { | ||||
|             *new_x = rect.x; | ||||
|             *new_y = rect.y; | ||||
|             if (borders) | ||||
|               { | ||||
|                 *new_x += borders->visible.left; | ||||
|                 *new_y += borders->visible.top; | ||||
|               } | ||||
|          | ||||
|             retval = TRUE; | ||||
|         | ||||
| @@ -652,7 +599,6 @@ find_first_fit (MetaWindow *window, | ||||
|  | ||||
| void | ||||
| meta_window_place (MetaWindow        *window, | ||||
|                    MetaFrameBorders  *borders, | ||||
|                    int                x, | ||||
|                    int                y, | ||||
|                    int               *new_x, | ||||
| @@ -661,17 +607,10 @@ meta_window_place (MetaWindow        *window, | ||||
|   GList *windows; | ||||
|   const MetaMonitorInfo *xi; | ||||
|  | ||||
|   /* frame member variables should NEVER be used in here, only | ||||
|    * MetaFrameBorders. But remember borders == NULL | ||||
|    * for undecorated windows. Also, this function should | ||||
|    * NEVER have side effects other than computing the | ||||
|    * placement coordinates. | ||||
|    */ | ||||
|  | ||||
|   meta_topic (META_DEBUG_PLACEMENT, "Placing window %s\n", window->desc); | ||||
|  | ||||
|   windows = NULL; | ||||
|    | ||||
|  | ||||
|   switch (window->type) | ||||
|     { | ||||
|       /* Run placement algorithm on these. */ | ||||
| @@ -699,7 +638,7 @@ meta_window_place (MetaWindow        *window, | ||||
|     case META_WINDOW_OVERRIDE_OTHER: | ||||
|       goto done_no_constraints; | ||||
|     } | ||||
|    | ||||
|  | ||||
|   if (meta_prefs_get_disable_workarounds ()) | ||||
|     { | ||||
|       switch (window->type) | ||||
| @@ -756,48 +695,39 @@ meta_window_place (MetaWindow        *window, | ||||
|         { | ||||
|           meta_topic (META_DEBUG_PLACEMENT, | ||||
|                       "Not placing window with PPosition or USPosition set\n"); | ||||
|           avoid_being_obscured_as_second_modal_dialog (window, borders, &x, &y); | ||||
|           avoid_being_obscured_as_second_modal_dialog (window, &x, &y); | ||||
|           goto done_no_constraints; | ||||
|         } | ||||
|     } | ||||
|    | ||||
|   if ((window->type == META_WINDOW_DIALOG || | ||||
|        window->type == META_WINDOW_MODAL_DIALOG) && | ||||
|       window->xtransient_for != None) | ||||
|     { | ||||
|       /* Center horizontally, at top of parent vertically */ | ||||
|  | ||||
|       MetaWindow *parent; | ||||
|            | ||||
|       parent = | ||||
|         meta_display_lookup_x_window (window->display, | ||||
|                                       window->xtransient_for); | ||||
|   if (window->type == META_WINDOW_DIALOG || | ||||
|       window->type == META_WINDOW_MODAL_DIALOG) | ||||
|     { | ||||
|       MetaWindow *parent = meta_window_get_transient_for (window); | ||||
|  | ||||
|       if (parent) | ||||
|         { | ||||
|           int w; | ||||
|           MetaRectangle frame_rect, parent_frame_rect; | ||||
|  | ||||
|           meta_window_get_position (parent, &x, &y); | ||||
|           w = parent->rect.width; | ||||
|           meta_window_get_frame_rect (window, &frame_rect); | ||||
|           meta_window_get_frame_rect (parent, &parent_frame_rect); | ||||
|  | ||||
|           y = parent_frame_rect.y; | ||||
|  | ||||
|           /* center of parent */ | ||||
|           x = x + w / 2; | ||||
|           x = parent_frame_rect.x + parent_frame_rect.width / 2; | ||||
|           /* center of child over center of parent */ | ||||
|           x -= window->rect.width / 2; | ||||
|           x -= frame_rect.width / 2; | ||||
|  | ||||
|           /* "visually" center window over parent, leaving twice as | ||||
|            * much space below as on top. | ||||
|            */ | ||||
|           y += (parent->rect.height - window->rect.height)/3; | ||||
|  | ||||
|           /* put top of child's frame, not top of child's client */ | ||||
|           if (borders) | ||||
|             y += borders->visible.top; | ||||
|           y += (parent_frame_rect.height - frame_rect.height)/3; | ||||
|  | ||||
|           meta_topic (META_DEBUG_PLACEMENT, "Centered window %s over transient parent\n", | ||||
|                       window->desc); | ||||
|            | ||||
|           avoid_being_obscured_as_second_modal_dialog (window, borders, &x, &y); | ||||
|           avoid_being_obscured_as_second_modal_dialog (window, &x, &y); | ||||
|  | ||||
|           goto done; | ||||
|         } | ||||
| @@ -813,6 +743,9 @@ meta_window_place (MetaWindow        *window, | ||||
|     { | ||||
|       /* Center on current monitor */ | ||||
|       int w, h; | ||||
|       MetaRectangle frame_rect; | ||||
|  | ||||
|       meta_window_get_frame_rect (window, &frame_rect); | ||||
|  | ||||
|       /* Warning, this function is a round trip! */ | ||||
|       xi = meta_screen_get_current_monitor_info (window->screen); | ||||
| @@ -820,8 +753,8 @@ meta_window_place (MetaWindow        *window, | ||||
|       w = xi->rect.width; | ||||
|       h = xi->rect.height; | ||||
|  | ||||
|       x = (w - window->rect.width) / 2; | ||||
|       y = (h - window->rect.height) / 2; | ||||
|       x = (w - frame_rect.width) / 2; | ||||
|       y = (h - frame_rect.height) / 2; | ||||
|  | ||||
|       x += xi->rect.x; | ||||
|       y += xi->rect.y; | ||||
| @@ -865,7 +798,7 @@ meta_window_place (MetaWindow        *window, | ||||
|   x = xi->rect.x; | ||||
|   y = xi->rect.y; | ||||
|  | ||||
|   if (find_first_fit (window, borders, windows, | ||||
|   if (find_first_fit (window, windows, | ||||
|                       xi->number, | ||||
|                       x, y, &x, &y)) | ||||
|     goto done_check_denied_focus; | ||||
| @@ -878,17 +811,17 @@ meta_window_place (MetaWindow        *window, | ||||
|       !window->fullscreen) | ||||
|     { | ||||
|       MetaRectangle workarea; | ||||
|       MetaRectangle outer; | ||||
|       MetaRectangle frame_rect; | ||||
|  | ||||
|       meta_window_get_work_area_for_monitor (window, | ||||
|                                              xi->number, | ||||
|                                              &workarea);       | ||||
|       meta_window_get_outer_rect (window, &outer); | ||||
|       meta_window_get_frame_rect (window, &frame_rect); | ||||
|        | ||||
|       /* If the window is bigger than the screen, then automaximize.  Do NOT | ||||
|        * auto-maximize the directions independently.  See #419810. | ||||
|        */ | ||||
|       if (outer.width >= workarea.width && outer.height >= workarea.height) | ||||
|       if (frame_rect.width >= workarea.width && frame_rect.height >= workarea.height) | ||||
|         { | ||||
|           window->maximize_horizontally_after_placement = TRUE; | ||||
|           window->maximize_vertically_after_placement = TRUE; | ||||
| @@ -899,7 +832,7 @@ meta_window_place (MetaWindow        *window, | ||||
|    * fully overlapping window (e.g. starting multiple terminals) | ||||
|    * */ | ||||
|   if (x == xi->rect.x && y == xi->rect.y)   | ||||
|     find_next_cascade (window, borders, windows, x, y, &x, &y); | ||||
|     find_next_cascade (window, windows, x, y, &x, &y); | ||||
|  | ||||
|  done_check_denied_focus: | ||||
|   /* If the window is being denied focus and isn't a transient of the | ||||
| @@ -909,17 +842,14 @@ meta_window_place (MetaWindow        *window, | ||||
|    */ | ||||
|   if (window->denied_focus_and_not_transient) | ||||
|     { | ||||
|       gboolean       found_fit; | ||||
|       MetaWindow    *focus_window; | ||||
|       MetaRectangle  overlap; | ||||
|       gboolean       found_fit; | ||||
|  | ||||
|       focus_window = window->display->focus_window; | ||||
|       g_assert (focus_window != NULL); | ||||
|  | ||||
|       /* No need to do anything if the window doesn't overlap at all */ | ||||
|       found_fit = !meta_rectangle_intersect (&window->rect, | ||||
|                                              &focus_window->rect, | ||||
|                                              &overlap); | ||||
|       found_fit = !window_overlaps_focus_window (window); | ||||
|  | ||||
|       /* Try to do a first fit again, this time only taking into account the | ||||
|        * focus window. | ||||
| @@ -933,7 +863,7 @@ meta_window_place (MetaWindow        *window, | ||||
|           x = xi->rect.x; | ||||
|           y = xi->rect.y; | ||||
|  | ||||
|           found_fit = find_first_fit (window, borders, focus_window_list, | ||||
|           found_fit = find_first_fit (window, focus_window_list, | ||||
|                                       xi->number, | ||||
|                                       x, y, &x, &y); | ||||
|           g_list_free (focus_window_list); | ||||
| @@ -943,7 +873,7 @@ meta_window_place (MetaWindow        *window, | ||||
|        * as possible. | ||||
|        */ | ||||
|       if (!found_fit) | ||||
|         find_most_freespace (window, borders, focus_window, x, y, &x, &y); | ||||
|         find_most_freespace (window, focus_window, x, y, &x, &y); | ||||
|     } | ||||
|    | ||||
|  done: | ||||
|   | ||||
| @@ -16,9 +16,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef META_PLACE_H | ||||
| @@ -28,7 +26,6 @@ | ||||
| #include "frame.h" | ||||
|  | ||||
| void meta_window_place (MetaWindow *window, | ||||
|                         MetaFrameBorders *borders, | ||||
|                         int         x, | ||||
|                         int         y, | ||||
|                         int        *new_x, | ||||
|   | ||||
| @@ -17,9 +17,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
| @@ -59,7 +57,6 @@ | ||||
|  | ||||
| #define KEY_OVERLAY_KEY "overlay-key" | ||||
| #define KEY_WORKSPACES_ONLY_ON_PRIMARY "workspaces-only-on-primary" | ||||
| #define KEY_NO_TAB_POPUP "no-tab-popup" | ||||
|  | ||||
| /* These are the different schemas we are keeping | ||||
|  * a GSettings instance for */ | ||||
| @@ -114,8 +111,6 @@ static char **workspace_names = NULL; | ||||
|  | ||||
| static gboolean workspaces_only_on_primary = FALSE; | ||||
|  | ||||
| static gboolean no_tab_popup = FALSE; | ||||
|  | ||||
| static char *iso_next_group_option = NULL; | ||||
|  | ||||
| static void handle_preference_update_enum (GSettings *settings, | ||||
| @@ -367,13 +362,6 @@ static MetaBoolPreference preferences_bool[] = | ||||
|       }, | ||||
|       &workspaces_only_on_primary, | ||||
|     }, | ||||
|     { | ||||
|       { KEY_NO_TAB_POPUP, | ||||
|         SCHEMA_MUTTER, | ||||
|         META_PREF_NO_TAB_POPUP, | ||||
|       }, | ||||
|       &no_tab_popup, | ||||
|     }, | ||||
|     { | ||||
|       { "auto-maximize", | ||||
|         SCHEMA_MUTTER, | ||||
| @@ -1815,9 +1803,6 @@ meta_preference_to_string (MetaPreference pref) | ||||
|     case META_PREF_WORKSPACES_ONLY_ON_PRIMARY: | ||||
|       return "WORKSPACES_ONLY_ON_PRIMARY"; | ||||
|  | ||||
|     case META_PREF_NO_TAB_POPUP: | ||||
|       return "NO_TAB_POPUP"; | ||||
|  | ||||
|     case META_PREF_DRAGGABLE_BORDER_WIDTH: | ||||
|       return "DRAGGABLE_BORDER_WIDTH"; | ||||
|  | ||||
| @@ -1871,7 +1856,7 @@ init_bindings (void) | ||||
|   pref = g_new0 (MetaKeyPref, 1); | ||||
|   pref->name = g_strdup ("overlay-key"); | ||||
|   pref->action = META_KEYBINDING_ACTION_OVERLAY_KEY; | ||||
|   pref->bindings = g_slist_prepend (pref->bindings, &overlay_key_combo); | ||||
|   pref->combos = g_slist_prepend (pref->combos, &overlay_key_combo); | ||||
|   pref->builtin = 1; | ||||
|  | ||||
|   g_hash_table_insert (key_bindings, g_strdup ("overlay-key"), pref); | ||||
| @@ -1881,7 +1866,7 @@ static gboolean | ||||
| update_binding (MetaKeyPref *binding, | ||||
|                 gchar      **strokes) | ||||
| { | ||||
|   GSList *old_bindings, *a, *b; | ||||
|   GSList *old_combos, *a, *b; | ||||
|   gboolean changed; | ||||
|   unsigned int keysym; | ||||
|   unsigned int keycode; | ||||
| @@ -1893,8 +1878,8 @@ update_binding (MetaKeyPref *binding, | ||||
|               "Binding \"%s\" has new GSettings value\n", | ||||
|               binding->name); | ||||
|  | ||||
|   old_bindings = binding->bindings; | ||||
|   binding->bindings = NULL; | ||||
|   old_combos = binding->combos; | ||||
|   binding->combos = NULL; | ||||
|  | ||||
|   for (i = 0; strokes && strokes[i]; i++) | ||||
|     { | ||||
| @@ -1935,17 +1920,17 @@ update_binding (MetaKeyPref *binding, | ||||
|       combo->keysym = keysym; | ||||
|       combo->keycode = keycode; | ||||
|       combo->modifiers = mods; | ||||
|       binding->bindings = g_slist_prepend (binding->bindings, combo); | ||||
|       binding->combos = g_slist_prepend (binding->combos, combo); | ||||
|  | ||||
|       meta_topic (META_DEBUG_KEYBINDINGS, | ||||
|                       "New keybinding for \"%s\" is keysym = 0x%x keycode = 0x%x mods = 0x%x\n", | ||||
|                       binding->name, keysym, keycode, mods); | ||||
|     } | ||||
|  | ||||
|   binding->bindings = g_slist_reverse (binding->bindings); | ||||
|   binding->combos = g_slist_reverse (binding->combos); | ||||
|  | ||||
|   a = old_bindings; | ||||
|   b = binding->bindings; | ||||
|   a = old_combos; | ||||
|   b = binding->combos; | ||||
|   while (TRUE) | ||||
|     { | ||||
|       if ((!a && b) || (a && !b)) | ||||
| @@ -1970,7 +1955,7 @@ update_binding (MetaKeyPref *binding, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   g_slist_free_full (old_bindings, g_free); | ||||
|   g_slist_free_full (old_combos, g_free); | ||||
|  | ||||
|   return changed; | ||||
| } | ||||
| @@ -2105,7 +2090,7 @@ meta_prefs_add_keybinding (const char           *name, | ||||
|   pref->name = g_strdup (name); | ||||
|   pref->settings = g_object_ref (settings); | ||||
|   pref->action = action; | ||||
|   pref->bindings = NULL; | ||||
|   pref->combos = NULL; | ||||
|   pref->add_shift = (flags & META_KEY_BINDING_REVERSES) != 0; | ||||
|   pref->per_window = (flags & META_KEY_BINDING_PER_WINDOW) != 0; | ||||
|   pref->builtin = (flags & META_KEY_BINDING_BUILTIN) != 0; | ||||
| @@ -2169,11 +2154,6 @@ meta_prefs_remove_keybinding (const char *name) | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_prefs_get_keybindings: | ||||
|  * | ||||
|  * Returns: (element-type MetaKeyPref) (transfer container): | ||||
|  */ | ||||
| GList * | ||||
| meta_prefs_get_keybindings () | ||||
| { | ||||
| @@ -2274,7 +2254,7 @@ meta_prefs_get_window_binding (const char          *name, | ||||
|  | ||||
|   if (pref->per_window) | ||||
|     { | ||||
|       GSList *s = pref->bindings; | ||||
|       GSList *s = pref->combos; | ||||
|  | ||||
|       while (s) | ||||
|         { | ||||
| @@ -2322,25 +2302,6 @@ meta_prefs_get_workspaces_only_on_primary (void) | ||||
|   return workspaces_only_on_primary; | ||||
| } | ||||
|  | ||||
|  | ||||
| gboolean | ||||
| meta_prefs_get_no_tab_popup (void) | ||||
| { | ||||
|   return no_tab_popup; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_prefs_set_no_tab_popup (gboolean whether) | ||||
| { | ||||
|   MetaBasePreference *pref; | ||||
|  | ||||
|   if (find_pref (preferences_bool, sizeof(MetaBoolPreference), | ||||
|                  KEY_NO_TAB_POPUP, &pref)) | ||||
|     { | ||||
|       g_settings_set_boolean (SETTINGS (pref->schema), KEY_NO_TAB_POPUP, whether); | ||||
|     } | ||||
| } | ||||
|  | ||||
| int | ||||
| meta_prefs_get_draggable_border_width (void) | ||||
| { | ||||
|   | ||||
| @@ -25,9 +25,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef META_SCREEN_PRIVATE_H | ||||
| @@ -66,8 +64,6 @@ struct _MetaScreen | ||||
|   Visual *default_xvisual; | ||||
|   MetaRectangle rect;  /* Size of screen; rect.x & rect.y are always 0 */ | ||||
|   MetaUI *ui; | ||||
|   MetaTabPopup *tab_popup, *ws_popup; | ||||
|   MetaTilePreview *tile_preview; | ||||
|  | ||||
|   guint tile_preview_timeout_id; | ||||
|  | ||||
| @@ -153,25 +149,9 @@ void          meta_screen_foreach_window      (MetaScreen                 *scree | ||||
|  | ||||
| void          meta_screen_update_cursor       (MetaScreen                 *screen); | ||||
|  | ||||
| void          meta_screen_tab_popup_create       (MetaScreen              *screen, | ||||
|                                                   MetaTabList              list_type, | ||||
|                                                   MetaTabShowType          show_type, | ||||
|                                                   MetaWindow              *initial_window); | ||||
| void          meta_screen_tab_popup_forward      (MetaScreen              *screen); | ||||
| void          meta_screen_tab_popup_backward     (MetaScreen              *screen); | ||||
| MetaWindow*   meta_screen_tab_popup_get_selected (MetaScreen              *screen); | ||||
| void          meta_screen_tab_popup_destroy      (MetaScreen              *screen); | ||||
|  | ||||
| void          meta_screen_workspace_popup_create       (MetaScreen    *screen, | ||||
|                                                         MetaWorkspace *initial_selection); | ||||
| void          meta_screen_workspace_popup_select       (MetaScreen    *screen, | ||||
|                                                         MetaWorkspace *workspace); | ||||
| MetaWorkspace*meta_screen_workspace_popup_get_selected (MetaScreen    *screen); | ||||
| void          meta_screen_workspace_popup_destroy      (MetaScreen    *screen); | ||||
|  | ||||
| void          meta_screen_tile_preview_update          (MetaScreen    *screen, | ||||
| void          meta_screen_update_tile_preview          (MetaScreen    *screen, | ||||
|                                                         gboolean       delay); | ||||
| void          meta_screen_tile_preview_hide            (MetaScreen    *screen); | ||||
| void          meta_screen_hide_tile_preview            (MetaScreen    *screen); | ||||
|  | ||||
| MetaWindow*   meta_screen_get_mouse_window     (MetaScreen                 *screen, | ||||
|                                                 MetaWindow                 *not_this_one); | ||||
| @@ -243,7 +223,7 @@ void     meta_screen_workspace_switched (MetaScreen         *screen, | ||||
|  | ||||
| void meta_screen_set_active_workspace_hint (MetaScreen *screen); | ||||
|  | ||||
| Window   meta_screen_create_guard_window (Display *xdisplay, MetaScreen *screen); | ||||
| void meta_screen_create_guard_window (MetaScreen *screen); | ||||
|  | ||||
| gboolean meta_screen_handle_xevent (MetaScreen *screen, | ||||
|                                     XEvent     *xevent); | ||||
|   | ||||
| @@ -19,9 +19,7 @@ | ||||
|  * 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. | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
| @@ -41,11 +39,9 @@ | ||||
| #include "workspace-private.h" | ||||
| #include "keybindings-private.h" | ||||
| #include "stack.h" | ||||
| #include "xprops.h" | ||||
| #include <meta/compositor.h> | ||||
| #include "mutter-enum-types.h" | ||||
| #include "core.h" | ||||
| #include "meta-wayland-private.h" | ||||
| #include "meta-cursor-tracker-private.h" | ||||
|  | ||||
| #include <X11/extensions/Xinerama.h> | ||||
| @@ -56,6 +52,8 @@ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include "x11/xprops.h" | ||||
|  | ||||
| static char* get_screen_name (MetaDisplay *display, | ||||
|                               int          number); | ||||
|  | ||||
| @@ -310,6 +308,8 @@ set_supported_hint (MetaScreen *screen) | ||||
| #include <meta/atomnames.h> | ||||
| #undef item | ||||
| #undef EWMH_ATOMS_ONLY | ||||
|  | ||||
|     screen->display->atom__GTK_FRAME_EXTENTS, | ||||
|   }; | ||||
|  | ||||
|   XChangeProperty (screen->display->xdisplay, screen->xroot, | ||||
| @@ -391,6 +391,8 @@ int | ||||
| meta_screen_monitor_index_to_xinerama_index (MetaScreen *screen, | ||||
|                                              int         index) | ||||
| { | ||||
|   g_return_val_if_fail (index >= 0 && index < screen->n_monitor_infos, -1); | ||||
|  | ||||
|   meta_screen_ensure_xinerama_indices (screen); | ||||
|  | ||||
|   return screen->monitor_infos[index].xinerama_index; | ||||
| @@ -447,17 +449,16 @@ reload_monitor_infos (MetaScreen *screen) | ||||
|  * should effectively be forwarded to events on the background actor, | ||||
|  * providing that the scene graph is set up correctly. | ||||
|  */ | ||||
| Window | ||||
| meta_screen_create_guard_window (Display *xdisplay, MetaScreen *screen) | ||||
| static Window | ||||
| create_guard_window (Display *xdisplay, MetaScreen *screen) | ||||
| { | ||||
|   XSetWindowAttributes attributes; | ||||
|   Window guard_window; | ||||
|   gulong create_serial; | ||||
|   MetaStackWindow stack_window; | ||||
|    | ||||
|  | ||||
|   attributes.event_mask = NoEventMask; | ||||
|   attributes.override_redirect = True; | ||||
|   attributes.background_pixel = BlackPixel (xdisplay, screen->number); | ||||
|  | ||||
|   /* We have to call record_add() after we have the new window ID, | ||||
|    * so save the serial for the CreateWindow request until then */ | ||||
| @@ -470,10 +471,10 @@ meta_screen_create_guard_window (Display *xdisplay, MetaScreen *screen) | ||||
| 		   screen->rect.width, | ||||
| 		   screen->rect.height, | ||||
| 		   0, /* border width */ | ||||
| 		   CopyFromParent, /* depth */ | ||||
| 		   CopyFromParent, /* class */ | ||||
| 		   0, /* depth */ | ||||
| 		   InputOnly, /* class */ | ||||
| 		   CopyFromParent, /* visual */ | ||||
| 		   CWEventMask|CWOverrideRedirect|CWBackPixel, | ||||
| 		   CWEventMask|CWOverrideRedirect, | ||||
| 		   &attributes); | ||||
|  | ||||
|   { | ||||
| @@ -761,10 +762,6 @@ meta_screen_new (MetaDisplay *display, | ||||
|   screen->ui = meta_ui_new (screen->display->xdisplay, | ||||
|                             screen->xscreen); | ||||
|  | ||||
|   screen->tab_popup = NULL; | ||||
|   screen->ws_popup = NULL; | ||||
|   screen->tile_preview = NULL; | ||||
|  | ||||
|   screen->tile_preview_timeout_id = 0; | ||||
|  | ||||
|   screen->stack = meta_stack_new (screen); | ||||
| @@ -812,11 +809,8 @@ meta_screen_free (MetaScreen *screen, | ||||
|    | ||||
|   meta_display_grab (display); | ||||
|  | ||||
|   if (screen->display->compositor) | ||||
|     { | ||||
|       meta_compositor_unmanage_screen (screen->display->compositor, | ||||
| 				       screen); | ||||
|     } | ||||
|   meta_compositor_unmanage_screen (screen->display->compositor, | ||||
|                                    screen); | ||||
|    | ||||
|   meta_display_unmanage_windows_for_screen (display, screen, timestamp); | ||||
|    | ||||
| @@ -859,9 +853,9 @@ meta_screen_free (MetaScreen *screen, | ||||
|                   screen->wm_sn_selection_window); | ||||
|    | ||||
|   if (screen->work_area_later != 0) | ||||
|     g_source_remove (screen->work_area_later); | ||||
|     meta_later_remove (screen->work_area_later); | ||||
|   if (screen->check_fullscreen_later != 0) | ||||
|     g_source_remove (screen->check_fullscreen_later); | ||||
|     meta_later_remove (screen->check_fullscreen_later); | ||||
|  | ||||
|   if (screen->monitor_infos) | ||||
|     g_free (screen->monitor_infos); | ||||
| @@ -869,9 +863,6 @@ meta_screen_free (MetaScreen *screen, | ||||
|   if (screen->tile_preview_timeout_id) | ||||
|     g_source_remove (screen->tile_preview_timeout_id); | ||||
|  | ||||
|   if (screen->tile_preview) | ||||
|     meta_tile_preview_free (screen->tile_preview); | ||||
|    | ||||
|   g_free (screen->screen_name); | ||||
|  | ||||
|   g_object_unref (screen); | ||||
| @@ -880,83 +871,34 @@ meta_screen_free (MetaScreen *screen, | ||||
|   meta_display_ungrab (display); | ||||
| } | ||||
|  | ||||
| typedef struct | ||||
| void | ||||
| meta_screen_create_guard_window (MetaScreen *screen) | ||||
| { | ||||
|   Window		xwindow; | ||||
|   XWindowAttributes	attrs; | ||||
| } WindowInfo; | ||||
|  | ||||
| static GList * | ||||
| list_windows (MetaScreen *screen) | ||||
| { | ||||
|   Window ignored1, ignored2; | ||||
|   Window *children; | ||||
|   guint n_children, i; | ||||
|   GList *result; | ||||
|  | ||||
|   XQueryTree (screen->display->xdisplay, | ||||
|               screen->xroot, | ||||
|               &ignored1, &ignored2, &children, &n_children); | ||||
|  | ||||
|   result = NULL; | ||||
|   for (i = 0; i < n_children; ++i) | ||||
|     { | ||||
|       WindowInfo *info = g_new0 (WindowInfo, 1); | ||||
|  | ||||
|       meta_error_trap_push_with_return (screen->display); | ||||
|        | ||||
|       XGetWindowAttributes (screen->display->xdisplay, | ||||
|                             children[i], &info->attrs); | ||||
|  | ||||
|       if (meta_error_trap_pop_with_return (screen->display)) | ||||
| 	{ | ||||
|           meta_verbose ("Failed to get attributes for window 0x%lx\n", | ||||
|                         children[i]); | ||||
| 	  g_free (info); | ||||
|         } | ||||
|       else | ||||
|         { | ||||
| 	  info->xwindow = children[i]; | ||||
| 	} | ||||
|  | ||||
|       result = g_list_prepend (result, info); | ||||
|     } | ||||
|  | ||||
|   if (children) | ||||
|     XFree (children); | ||||
|  | ||||
|   return g_list_reverse (result); | ||||
|   if (screen->guard_window == None) | ||||
|     screen->guard_window = create_guard_window (screen->display->xdisplay, screen); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_screen_manage_all_windows (MetaScreen *screen) | ||||
| { | ||||
|   GList *windows; | ||||
|   GList *list; | ||||
|  | ||||
|   meta_display_grab (screen->display); | ||||
|  | ||||
|   if (screen->guard_window == None) | ||||
|     screen->guard_window = | ||||
|       meta_screen_create_guard_window (screen->display->xdisplay, screen); | ||||
|  | ||||
|   windows = list_windows (screen); | ||||
|   MetaStackWindow *_children; | ||||
|   MetaStackWindow *children; | ||||
|   int n_children, i; | ||||
|  | ||||
|   meta_stack_freeze (screen->stack); | ||||
|   for (list = windows; list != NULL; list = list->next) | ||||
|   meta_stack_tracker_get_stack (screen->stack_tracker, &_children, &n_children); | ||||
|  | ||||
|   /* Copy the stack as it will be modified as part of the loop */ | ||||
|   children = g_memdup (_children, sizeof (MetaStackWindow) * n_children); | ||||
|  | ||||
|   for (i = 0; i < n_children; ++i) | ||||
|     { | ||||
|       WindowInfo *info = list->data; | ||||
|  | ||||
|       meta_window_new_with_attrs (screen->display, info->xwindow, TRUE, | ||||
|                                   META_COMP_EFFECT_NONE, | ||||
|                                   &info->attrs); | ||||
|       meta_window_x11_new (screen->display, children[i].x11.xwindow, TRUE, | ||||
|                            META_COMP_EFFECT_NONE); | ||||
|     } | ||||
|  | ||||
|   g_free (children); | ||||
|   meta_stack_thaw (screen->stack); | ||||
|  | ||||
|   g_list_foreach (windows, (GFunc)g_free, NULL); | ||||
|   g_list_free (windows); | ||||
|  | ||||
|   meta_display_ungrab (screen->display); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -1482,255 +1424,8 @@ meta_screen_update_cursor (MetaScreen *screen) | ||||
|                                        screen->current_cursor); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_screen_tab_popup_create (MetaScreen      *screen, | ||||
|                               MetaTabList      list_type, | ||||
|                               MetaTabShowType  show_type, | ||||
|                               MetaWindow      *initial_selection) | ||||
| { | ||||
|   MetaTabEntry *entries; | ||||
|   GList *tab_list; | ||||
|   GList *tmp; | ||||
|   int len; | ||||
|   int i; | ||||
|  | ||||
|   if (screen->tab_popup) | ||||
|     return; | ||||
|  | ||||
|   tab_list = meta_display_get_tab_list (screen->display, | ||||
|                                         list_type, | ||||
|                                         screen, | ||||
|                                         screen->active_workspace); | ||||
|  | ||||
|   len = g_list_length (tab_list); | ||||
|  | ||||
|   entries = g_new (MetaTabEntry, len + 1); | ||||
|   entries[len].key = NULL; | ||||
|   entries[len].title = NULL; | ||||
|   entries[len].icon = NULL; | ||||
|  | ||||
|   i = 0; | ||||
|   tmp = tab_list; | ||||
|   while (i < len) | ||||
|     { | ||||
|       MetaWindow *window; | ||||
|       MetaRectangle r; | ||||
|  | ||||
|       window = tmp->data; | ||||
|  | ||||
|       entries[i].key = (MetaTabEntryKey) window; | ||||
|       entries[i].title = window->title; | ||||
|       entries[i].icon = g_object_ref (window->icon); | ||||
|       entries[i].blank = FALSE; | ||||
|       entries[i].hidden = !meta_window_showing_on_its_workspace (window); | ||||
|       entries[i].demands_attention = window->wm_state_demands_attention; | ||||
|  | ||||
|       if (show_type == META_TAB_SHOW_INSTANTLY || | ||||
|           !entries[i].hidden                   || | ||||
|           !meta_window_get_icon_geometry (window, &r)) | ||||
|         meta_window_get_outer_rect (window, &r); | ||||
|  | ||||
|       entries[i].rect = r; | ||||
|  | ||||
|       /* Find inside of highlight rectangle to be used when window is | ||||
|        * outlined for tabbing.  This should be the size of the | ||||
|        * east/west frame, and the size of the south frame, on those | ||||
|        * sides.  On the top it should be the size of the south frame | ||||
|        * edge. | ||||
|        */ | ||||
| #define OUTLINE_WIDTH 5 | ||||
|       /* Top side */ | ||||
|       if (!entries[i].hidden && | ||||
|           window->frame && window->frame->bottom_height > 0 && | ||||
|           window->frame->child_y >= window->frame->bottom_height) | ||||
|         entries[i].inner_rect.y = window->frame->bottom_height; | ||||
|       else | ||||
|         entries[i].inner_rect.y = OUTLINE_WIDTH; | ||||
|  | ||||
|       /* Bottom side */ | ||||
|       if (!entries[i].hidden && | ||||
|           window->frame && window->frame->bottom_height != 0) | ||||
|         entries[i].inner_rect.height = r.height | ||||
|           - entries[i].inner_rect.y - window->frame->bottom_height; | ||||
|       else | ||||
|         entries[i].inner_rect.height = r.height | ||||
|           - entries[i].inner_rect.y - OUTLINE_WIDTH; | ||||
|  | ||||
|       /* Left side */ | ||||
|       if (!entries[i].hidden && window->frame && window->frame->child_x != 0) | ||||
|         entries[i].inner_rect.x = window->frame->child_x; | ||||
|       else | ||||
|         entries[i].inner_rect.x = OUTLINE_WIDTH; | ||||
|  | ||||
|       /* Right side */ | ||||
|       if (!entries[i].hidden && | ||||
|           window->frame && window->frame->right_width != 0) | ||||
|         entries[i].inner_rect.width = r.width | ||||
|           - entries[i].inner_rect.x - window->frame->right_width; | ||||
|       else | ||||
|         entries[i].inner_rect.width = r.width | ||||
|           - entries[i].inner_rect.x - OUTLINE_WIDTH; | ||||
|  | ||||
|       ++i; | ||||
|       tmp = tmp->next; | ||||
|     } | ||||
|  | ||||
|   if (!meta_prefs_get_no_tab_popup ()) | ||||
|     screen->tab_popup = meta_ui_tab_popup_new (entries, | ||||
|                                                screen->number, | ||||
|                                                len, | ||||
|                                                5, /* FIXME */ | ||||
|                                                TRUE); | ||||
|  | ||||
|   for (i = 0; i < len; i++) | ||||
|     g_object_unref (entries[i].icon); | ||||
|  | ||||
|   g_free (entries); | ||||
|  | ||||
|   g_list_free (tab_list); | ||||
|  | ||||
|   meta_ui_tab_popup_select (screen->tab_popup, | ||||
|                             (MetaTabEntryKey) initial_selection); | ||||
|  | ||||
|   if (show_type != META_TAB_SHOW_INSTANTLY) | ||||
|     meta_ui_tab_popup_set_showing (screen->tab_popup, TRUE); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_screen_tab_popup_forward (MetaScreen *screen) | ||||
| { | ||||
|   g_return_if_fail (screen->tab_popup != NULL); | ||||
|  | ||||
|   meta_ui_tab_popup_forward (screen->tab_popup); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_screen_tab_popup_backward (MetaScreen *screen) | ||||
| { | ||||
|   g_return_if_fail (screen->tab_popup != NULL); | ||||
|  | ||||
|   meta_ui_tab_popup_backward (screen->tab_popup); | ||||
| } | ||||
|  | ||||
| MetaWindow * | ||||
| meta_screen_tab_popup_get_selected (MetaScreen *screen) | ||||
| { | ||||
|   g_return_val_if_fail (screen->tab_popup != NULL, NULL); | ||||
|  | ||||
|   return (MetaWindow *) meta_ui_tab_popup_get_selected (screen->tab_popup); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_screen_tab_popup_destroy (MetaScreen *screen) | ||||
| { | ||||
|   if (screen->tab_popup) | ||||
|     { | ||||
|       meta_ui_tab_popup_free (screen->tab_popup); | ||||
|       screen->tab_popup = NULL; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_screen_workspace_popup_create (MetaScreen    *screen, | ||||
|                                     MetaWorkspace *initial_selection) | ||||
| { | ||||
|   MetaTabEntry *entries; | ||||
|   int len; | ||||
|   int i; | ||||
|   MetaWorkspaceLayout layout; | ||||
|   int n_workspaces; | ||||
|   int current_workspace; | ||||
|  | ||||
|   if (screen->ws_popup || meta_prefs_get_no_tab_popup ()) | ||||
|     return; | ||||
|  | ||||
|   current_workspace = meta_workspace_index (screen->active_workspace); | ||||
|   n_workspaces = meta_screen_get_n_workspaces (screen); | ||||
|  | ||||
|   meta_screen_calc_workspace_layout (screen, n_workspaces, | ||||
|                                      current_workspace, &layout); | ||||
|  | ||||
|   len = layout.grid_area; | ||||
|    | ||||
|   entries = g_new (MetaTabEntry, len + 1); | ||||
|   entries[len].key = NULL; | ||||
|   entries[len].title = NULL; | ||||
|   entries[len].icon = NULL; | ||||
|  | ||||
|   i = 0; | ||||
|   while (i < len) | ||||
|     { | ||||
|       if (layout.grid[i] >= 0) | ||||
|         { | ||||
|           MetaWorkspace *workspace; | ||||
|            | ||||
|           workspace = meta_screen_get_workspace_by_index (screen, | ||||
|                                                           layout.grid[i]); | ||||
|            | ||||
|           entries[i].key = (MetaTabEntryKey) workspace; | ||||
|           entries[i].title = meta_workspace_get_name (workspace); | ||||
|           entries[i].icon = NULL; | ||||
|           entries[i].blank = FALSE; | ||||
|            | ||||
|           g_assert (entries[i].title != NULL); | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           entries[i].key = NULL; | ||||
|           entries[i].title = NULL; | ||||
|           entries[i].icon = NULL; | ||||
|           entries[i].blank = TRUE; | ||||
|         } | ||||
|       entries[i].hidden = FALSE; | ||||
|       entries[i].demands_attention = FALSE; | ||||
|  | ||||
|       ++i; | ||||
|     } | ||||
|  | ||||
|   screen->ws_popup = meta_ui_tab_popup_new (entries, | ||||
|                                             screen->number, | ||||
|                                             len, | ||||
|                                             layout.cols, | ||||
|                                             FALSE); | ||||
|  | ||||
|   g_free (entries); | ||||
|   meta_screen_free_workspace_layout (&layout); | ||||
|  | ||||
|   meta_ui_tab_popup_select (screen->ws_popup, | ||||
|                             (MetaTabEntryKey) initial_selection); | ||||
|   meta_ui_tab_popup_set_showing (screen->ws_popup, TRUE); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_screen_workspace_popup_select (MetaScreen    *screen, | ||||
|                                     MetaWorkspace *workspace) | ||||
| { | ||||
|   g_return_if_fail (screen->ws_popup != NULL); | ||||
|  | ||||
|   meta_ui_tab_popup_select (screen->ws_popup, | ||||
|                             (MetaTabEntryKey) workspace); | ||||
| } | ||||
|  | ||||
| MetaWorkspace * | ||||
| meta_screen_workspace_popup_get_selected (MetaScreen *screen) | ||||
| { | ||||
|   g_return_val_if_fail (screen->ws_popup != NULL, NULL); | ||||
|  | ||||
|   return (MetaWorkspace *) meta_ui_tab_popup_get_selected (screen->ws_popup); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_screen_workspace_popup_destroy (MetaScreen *screen) | ||||
| { | ||||
|   if (screen->ws_popup) | ||||
|     { | ||||
|       meta_ui_tab_popup_free (screen->ws_popup); | ||||
|       screen->ws_popup = NULL; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_screen_tile_preview_update_timeout (gpointer data) | ||||
| meta_screen_update_tile_preview_timeout (gpointer data) | ||||
| { | ||||
|   MetaScreen *screen = data; | ||||
|   MetaWindow *window = screen->display->grab_window; | ||||
| @@ -1738,22 +1433,6 @@ meta_screen_tile_preview_update_timeout (gpointer data) | ||||
|  | ||||
|   screen->tile_preview_timeout_id = 0; | ||||
|  | ||||
|   if (!screen->tile_preview) | ||||
|     { | ||||
|       Window xwindow; | ||||
|       gulong create_serial; | ||||
|       MetaStackWindow stack_window; | ||||
|  | ||||
|       screen->tile_preview = meta_tile_preview_new (screen->number); | ||||
|       xwindow = meta_tile_preview_get_xwindow (screen->tile_preview, | ||||
|                                                &create_serial); | ||||
|       stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11; | ||||
|       stack_window.x11.xwindow = xwindow; | ||||
|       meta_stack_tracker_record_add (screen->stack_tracker, | ||||
|                                      &stack_window, | ||||
|                                      create_serial); | ||||
|     } | ||||
|  | ||||
|   if (window) | ||||
|     { | ||||
|       switch (window->tile_mode) | ||||
| @@ -1778,12 +1457,16 @@ meta_screen_tile_preview_update_timeout (gpointer data) | ||||
|   if (needs_preview) | ||||
|     { | ||||
|       MetaRectangle tile_rect; | ||||
|       int monitor; | ||||
|  | ||||
|       monitor = meta_window_get_current_tile_monitor_number (window); | ||||
|       meta_window_get_current_tile_area (window, &tile_rect); | ||||
|       meta_tile_preview_show (screen->tile_preview, &tile_rect); | ||||
|       meta_compositor_show_tile_preview (screen->display->compositor, | ||||
|                                          screen, window, &tile_rect, monitor); | ||||
|     } | ||||
|   else | ||||
|     meta_tile_preview_hide (screen->tile_preview); | ||||
|     meta_compositor_hide_tile_preview (screen->display->compositor, | ||||
|                                        screen); | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
| @@ -1791,7 +1474,7 @@ meta_screen_tile_preview_update_timeout (gpointer data) | ||||
| #define TILE_PREVIEW_TIMEOUT_MS 200 | ||||
|  | ||||
| void | ||||
| meta_screen_tile_preview_update (MetaScreen *screen, | ||||
| meta_screen_update_tile_preview (MetaScreen *screen, | ||||
|                                  gboolean    delay) | ||||
| { | ||||
|   if (delay) | ||||
| @@ -1801,7 +1484,7 @@ meta_screen_tile_preview_update (MetaScreen *screen, | ||||
|  | ||||
|       screen->tile_preview_timeout_id = | ||||
|         g_timeout_add (TILE_PREVIEW_TIMEOUT_MS, | ||||
|                        meta_screen_tile_preview_update_timeout, | ||||
|                        meta_screen_update_tile_preview_timeout, | ||||
|                        screen); | ||||
|     } | ||||
|   else | ||||
| @@ -1809,18 +1492,18 @@ meta_screen_tile_preview_update (MetaScreen *screen, | ||||
|       if (screen->tile_preview_timeout_id > 0) | ||||
|         g_source_remove (screen->tile_preview_timeout_id); | ||||
|  | ||||
|       meta_screen_tile_preview_update_timeout ((gpointer)screen); | ||||
|       meta_screen_update_tile_preview_timeout ((gpointer)screen); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_screen_tile_preview_hide (MetaScreen *screen) | ||||
| meta_screen_hide_tile_preview (MetaScreen *screen) | ||||
| { | ||||
|   if (screen->tile_preview_timeout_id > 0) | ||||
|     g_source_remove (screen->tile_preview_timeout_id); | ||||
|  | ||||
|   if (screen->tile_preview) | ||||
|     meta_tile_preview_hide (screen->tile_preview); | ||||
|   meta_compositor_hide_tile_preview (screen->display->compositor, | ||||
|                                      screen); | ||||
| } | ||||
|  | ||||
| MetaWindow* | ||||
| @@ -1828,38 +1511,19 @@ meta_screen_get_mouse_window (MetaScreen  *screen, | ||||
|                               MetaWindow  *not_this_one) | ||||
| { | ||||
|   MetaWindow *window; | ||||
|   Window root_return, child_return; | ||||
|   double root_x_return, root_y_return; | ||||
|   double win_x_return, win_y_return; | ||||
|   XIButtonState buttons; | ||||
|   XIModifierState mods; | ||||
|   XIGroupState group; | ||||
|   int x, y; | ||||
|  | ||||
|   if (not_this_one) | ||||
|     meta_topic (META_DEBUG_FOCUS, | ||||
|                 "Focusing mouse window excluding %s\n", not_this_one->desc); | ||||
|  | ||||
|   meta_error_trap_push (screen->display); | ||||
|   XIQueryPointer (screen->display->xdisplay, | ||||
|                   META_VIRTUAL_CORE_POINTER_ID, | ||||
|                   screen->xroot, | ||||
|                   &root_return, | ||||
|                   &child_return, | ||||
|                   &root_x_return, | ||||
|                   &root_y_return, | ||||
|                   &win_x_return, | ||||
|                   &win_y_return, | ||||
|                   &buttons, | ||||
|                   &mods, | ||||
|                   &group); | ||||
|   meta_error_trap_pop (screen->display); | ||||
|   free (buttons.mask); | ||||
|   meta_cursor_tracker_get_pointer (screen->cursor_tracker, | ||||
|                                    &x, &y, NULL); | ||||
|  | ||||
|   window = meta_stack_get_default_focus_window_at_point (screen->stack, | ||||
|                                                          screen->active_workspace, | ||||
|                                                          not_this_one, | ||||
|                                                          root_x_return, | ||||
|                                                          root_y_return); | ||||
|                                                          x, y); | ||||
|  | ||||
|   return window; | ||||
| } | ||||
| @@ -1914,7 +1578,7 @@ meta_screen_get_monitor_for_window (MetaScreen *screen, | ||||
| { | ||||
|   MetaRectangle window_rect; | ||||
|    | ||||
|   meta_window_get_outer_rect (window, &window_rect); | ||||
|   meta_window_get_frame_rect (window, &window_rect); | ||||
|  | ||||
|   return meta_screen_get_monitor_for_rect (screen, &window_rect); | ||||
| } | ||||
| @@ -2141,28 +1805,11 @@ meta_screen_get_current_monitor (MetaScreen *screen) | ||||
|    | ||||
|   if (screen->display->monitor_cache_invalidated) | ||||
|     { | ||||
|       Window root_return, child_return; | ||||
|       double win_x_return, win_y_return; | ||||
|       double root_x_return, root_y_return; | ||||
|       XIButtonState buttons; | ||||
|       XIModifierState mods; | ||||
|       XIGroupState group; | ||||
|       int x, y; | ||||
|  | ||||
|       XIQueryPointer (screen->display->xdisplay, | ||||
|                       META_VIRTUAL_CORE_POINTER_ID, | ||||
|                       screen->xroot, | ||||
|                       &root_return, | ||||
|                       &child_return, | ||||
|                       &root_x_return, | ||||
|                       &root_y_return, | ||||
|                       &win_x_return, | ||||
|                       &win_y_return, | ||||
|                       &buttons, | ||||
|                       &mods, | ||||
|                       &group); | ||||
|       free (buttons.mask); | ||||
|  | ||||
|       meta_screen_get_current_monitor_for_pos (screen, root_x_return, root_y_return); | ||||
|       meta_cursor_tracker_get_pointer (screen->cursor_tracker, | ||||
|                                        &x, &y, NULL); | ||||
|       meta_screen_get_current_monitor_for_pos (screen, x, y); | ||||
|     } | ||||
|  | ||||
|   return screen->last_monitor_index; | ||||
| @@ -2873,10 +2520,9 @@ on_monitors_changed (MetaMonitorManager *manager, | ||||
|                        &changes); | ||||
|     } | ||||
|  | ||||
|   if (screen->display->compositor) | ||||
|     meta_compositor_sync_screen_size (screen->display->compositor, | ||||
| 				      screen, | ||||
|                                       screen->rect.width, screen->rect.height); | ||||
|   meta_compositor_sync_screen_size (screen->display->compositor, | ||||
|                                     screen, | ||||
|                                     screen->rect.width, screen->rect.height); | ||||
|  | ||||
|   /* Queue a resize on all the windows */ | ||||
|   meta_screen_foreach_window (screen, meta_screen_resize_func, 0); | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user